fix(loader): packageDist NO-SOURCE on clean + relax Minecraft filter

build.gradle
  - Rewrite packageDist: drop the Copy task type and use a plain
    task with `copy { from src; into ... }` inside doLast. The
    Copy task snapshots its source set at configuration time, so
    a first `./gradlew clean dll` saw the source path before
    buildNative produced OpenZenLoader.exe and ended the task as
    NO-SOURCE. Doing the copy in doLast defers source resolution
    to after buildNative, which is when the EXE actually exists.
  - Bail with a clear GradleException if the EXE is still missing
    after buildNative instead of silently leaving build/dist
    empty, and log the packaged size on success.

native/loader/src/MainWindow.cpp
  - Loosen the in-game window filter to: title startsWith
    "Minecraft" OR window class equals "GLFW30" (case-insensitive).
    GLFW30 is the LWJGL3 window class Minecraft uses before the
    title is set, so this catches the early-startup window too.
    Drop the "Launcher" blacklist - launchers are no longer
    matched by either branch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Shirona1337
2026-05-23 22:39:13 +08:00
parent 9a72330c85
commit e4ac90b69e
2 changed files with 30 additions and 8 deletions
+12 -5
View File
@@ -21,12 +21,19 @@ QString fromW(const std::wstring& w) {
return QString::fromWCharArray(w.c_str(), static_cast<int>(w.size()));
}
bool isMinecraft(const std::wstring& title) {
bool startsWithMinecraft(const std::wstring& title) {
static const std::wstring prefix = L"Minecraft";
static const std::wstring banned = L"Launcher";
if (title.size() < prefix.size()) return false;
if (title.compare(0, prefix.size(), prefix) != 0) return false;
return title.find(banned) == std::wstring::npos;
return title.compare(0, prefix.size(), prefix) == 0;
}
bool isMinecraft(const std::wstring& title, const std::wstring& cls) {
// Either the window title starts with "Minecraft" (in-game window
// labelled e.g. "Minecraft 1.20.1"), or the window class is "GLFW30"
// (the class Minecraft's LWJGL GLFW windows always use, even before the
// title has been set).
if (startsWithMinecraft(title)) return true;
return _wcsicmp(cls.c_str(), L"GLFW30") == 0;
}
} // namespace
@@ -167,7 +174,7 @@ void MainWindow::refreshNow() {
QVector<Row> filtered;
filtered.reserve(procs.size());
for (const auto& jp : procs) {
if (!isMinecraft(jp.window_title)) continue;
if (!isMinecraft(jp.window_title, jp.window_class)) continue;
Row r{ jp.pid, fromW(jp.window_title), fromW(jp.window_class) };
filtered.push_back(std::move(r));
}