Commit Graph

6 Commits

Author SHA1 Message Date
Shirona1337 4634789ae0 ci(loader): build-loader workflow + git revision stamp + UPX task
GitHub Actions (.github/workflows/build-loader.yml)
  - Runs on every push to master and on workflow_dispatch.
  - windows-2022 runner: setup-java 17 (Temurin), ilammy/msvc-dev-cmd
    for MSVC x64, clones + bootstraps microsoft/vcpkg into the
    workspace, installs UPX via choco, caches Gradle, then runs
    `gradlew --no-daemon clean dll upxCompress` with VCPKG_ROOT and
    OPENZEN_BUILD_REVISION exported.
  - vcpkg's x-gha binary cache is wired in via VCPKG_BINARY_SOURCES +
    ACTIONS_CACHE_URL / ACTIONS_RUNTIME_TOKEN, so the first run pays
    the Qt static-build cost (~30 min - 2 h) and every push after
    that pulls cached qtbase artifacts.
  - Publishes build/dist/OpenZenLoader.exe as the
    OpenZenLoader-<sha> artifact (30 day retention).

Git revision in window title
  - build.gradle: gitShortRevision() prefers OPENZEN_BUILD_REVISION
    from the environment (set by CI) and falls back to
    `git rev-parse --short=7 HEAD` for local builds.
  - configureNative passes -DOPENZEN_BUILD_REVISION=<sha> to CMake
    and logs the resolved value.
  - native/loader/CMakeLists.txt forwards it as a compile definition.
  - MainWindow.buildUi sets the window title to
    "OpenZen Loader (build abc1234)" when the macro is defined, plain
    "OpenZen Loader" otherwise.

UPX compression
  - New upxCompress Gradle task: locates upx on PATH, runs
    `upx --best --lzma` on build/dist/OpenZenLoader.exe and logs the
    before/after size. Skips with a warning (not an error) when upx
    is missing so local builds keep working without it. CI's
    `gradlew clean dll upxCompress` always shrinks the artifact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 14:50:12 +08:00
Shirona1337 e4ac90b69e 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>
2026-05-23 22:39:13 +08:00
Shirona1337 9a72330c85 feat(loader): Qt6 GUI + strict wrap matcher + scaffold tweaks
Loader UI
  - Replace the Win32 ListView loader window with a Qt6 Widgets
    one. main.cpp + new MainWindow.h/cpp: QTableWidget showing
    PID / Window Title / Window Class, QTimer auto-refresh every
    1 s, double-click a row to inject. Title filter is built in
    (startsWith "Minecraft" and not containing "Launcher"), so
    HMCL / MultiMC / generic Java apps never show up.
  - Dark Fusion theme + inline QSS so the single EXE looks the
    same on any Windows version.
  - native/vcpkg.json declares qtbase[widgets] and build.gradle's
    new findVcpkg() detects VCPKG_ROOT / C:/vcpkg / D:/vcpkg /
    ~/vcpkg / D:/vcpkg-<version> and passes
    -DCMAKE_TOOLCHAIN_FILE + -DVCPKG_TARGET_TRIPLET=
    x64-windows-static so Qt is fully statically linked. Final
    OpenZenLoader.exe stays single-file (~30 MB) with no Qt6*.dll
    or vcruntime/msvcp DLL imports beyond Windows system DLLs.
  - Drop the old ui.cpp and the now-unused run_ui() entry on
    loader.h.

Patch transformer
  - asm.patchify.loader.PatchTransformer.wrapInvoke now tries a
    strict owner+name+desc match first, falling back to the
    historical (owner || name) matcher only if strict turns up
    nothing. The old loose matcher counted every Mth.*(FFF)F call
    against a wrap aimed at Mth.lerp(FFF)F, so a same-method
    sibling wrap that deleted its own site shifted later slice
    indices and made onRenderPitchLerp miss.

LivingEntityRendererPatch
  - With the strict matcher in place, onRenderPitchLerp's slice
    drops from (4,4) to (1,1) - there is exactly one
    Mth.lerp(FFF)F call site in LivingEntityRenderer.render
    (pitch lerp), as verified via javap on the runtime srg jar.
    onRenderHeadYawLerp keeps slice (2,2) (2nd of three
    Mth.rotLerp calls = head yaw). No more "no call site of
    m_14179_" warning at boot.

Scaffold
  - Rename the BooleanSetting field from advancedBlockSearch to
    sneak so the Java name matches the user-facing label ("Sneak").

README
  - Add the vcpkg / Qt prerequisites and update the injector
    usage section to describe the auto-refreshing UI + double-
    click flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:59:01 +08:00
Shirona1337 682150de48 feat(loader): manual-map injection, static CRT, filterable UI
Loader no longer touches disk: drop the LoadLibraryW path that
extracted OpenZen.dll to %TEMP%\OpenZenLoader and replace it with
an in-process PE loader that maps the embedded DLL straight into
the target Java process.

native/loader (new manual_map.cpp/.h):
  - VirtualAllocEx in the remote process for SizeOfImage,
    locally apply relocations + IAT patching (kernel32 etc. are
    KnownDLLs so local GetProcAddress addresses are valid in the
    remote), WriteProcessMemory the finished image once,
    VirtualProtectEx to match section characteristics, then run a
    minimal x64 trampoline shellcode that calls DllMain with
    DLL_PROCESS_ATTACH using the proper ABI (shadow space,
    16-byte stack alignment).
  - embedded_dll.cpp now hands back a pointer into the .rsrc
    section instead of writing the DLL out. injector.cpp shrinks
    to a 14-line shim around inject_in_memory.

native (top-level CMakeLists.txt):
  - Force /MT (CMAKE_MSVC_RUNTIME_LIBRARY = MultiThreaded) for
    both the DLL and the loader EXE. Without this the manual
    mapper's local-address import resolution trips over
    vcruntime140 / ucrtbase, which are not KnownDLLs and may have
    different bases in the target process - leading to NULL
    derefs inside msvcp140 after injection. With /MT the only
    import surface left is KERNEL32.

native/dll (jar_extract.cpp):
  - Replace FindResource/LoadResource/SizeofResource with a
    hand-rolled PE resource directory walker. FindResource paths
    through LdrFindResource_U, which depends on the PEB.Ldr table
    that manual-mapped modules are not part of, so the standard
    API returns NULL for the embedded zen.jar after injection.

native/loader UI:
  - Drop the now-pointless DLL Path edit + Browse button.
  - Add per-process "Window Class" column harvested via
    GetClassNameW alongside the existing window title.
  - Add a Minecraft Only checkbox (default on): show only rows
    whose window title startsWith "Minecraft" and does not
    contain "Launcher", filtering HMCL / MultiMC / generic Java
    apps out of the picker.

build.gradle:
  - Add cleanNative (Delete) hooked into clean so wiping the
    project also removes native/build/ and the staged
    native/zen.jar (CMake would otherwise hold onto the previous
    configure).

gradle.properties:
  - Fill in the real mod metadata (id=hey, name=OpenZen,
    authors=Shirona1337, group=io.github.openzen, description).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:47:45 +08:00
Shirona1337 18224465c2 build(loader): request UAC elevation via requireAdministrator manifest
OpenZenLoader.exe now ships with a requireAdministrator manifest
instead of asInvoker. The Windows loader prompts for UAC consent
once at launch, which:

- guarantees OpenProcess / VirtualAllocEx / CreateRemoteThread
  succeed against javaw.exe when the Minecraft launcher (HMCL,
  MultiMC) was itself started elevated,
- avoids the silent injection failure observed on locked-down
  standard user accounts.

The EXE also picks up the UAC shield overlay on its file icon.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 18:32:32 +08:00
Shirona1337 c31c6a873a feat(dll): add hot-injection DLL path with embedded GUI loader
Ship a self-contained OpenZenLoader.exe (OpenZen.dll embedded as
RCDATA) that injects into a running Minecraft 1.20.1 Forge
javaw.exe and brings up the Zen client without -javaagent or a
mods/ entry. The existing Forge mod path stays intact.

Native (native/):
  - DLL: JNI_GetCreatedJavaVMs + JVMTI late-attach via the JDK's
    instrument.dll Agent_OnAttach to obtain a real Instrumentation;
    URLClassLoader on the game loader loads a single bridge class.
  - Loader EXE: Win32 listview of javaw.exe/java.exe processes
    with window titles, CreateRemoteThread+LoadLibraryW injection,
    embedded DLL extracted to %TEMP%\OpenZenLoader at runtime.

Java:
  - shit.zen.dll.GameLoaderBridge re-defines every jar class onto
    the Forge GameClassLoader (fixed-point retry for super-class
    deps) and extracts non-class resources to
    %TEMP%\openzen-resources-<pid>, exposed via the
    openzen.resources system property.
  - shit.zen.dll.DllBootstrap only runs Bootstrap.init +
    registerPatches + installPatchesAndRetransform; ZenClient
    construction stays on MinecraftPatch.onTick lazy-init.
  - shit.zen.asm.Bootstrap parses mapping.srg, detects SRG vs
    mojmap runtime via Minecraft.tick reflection, exposes
    remapMethod/remapField used at 5 PatchTransformer match
    points and from ReflectionUtil.
  - ReflectionUtil.resolveField walks the superclass chain trying
    SRG then mojmap on each level so e.g. activeEffects on
    LocalPlayer resolves on LivingEntity.
  - shit.zen.utils.misc.Assets unifies resource lookup with a
    fallback to openzen.resources; fonts, cloud assets and WebUI
    static files route through it.
  - PatchAgent.installPatchesAndRetransform is now idempotent so
    DllBootstrap and ZenClient.init can both call it safely.

Build:
  - ./gradlew jar   forge mod jar (unchanged)
  - ./gradlew dll   single-file Loader EXE in build/dist
  - CMake auto-located via vswhere when VS 2022 ships it.
  - README documents both paths and required toolchain.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 09:06:24 +08:00