Commit Graph

82 Commits

Author SHA1 Message Date
Shirona1337 8f53eda70e feat(loader): randomize injector window title and jitter its size
Anti-fingerprint hardening for the loader window:

- The OS-level window title (read by GetWindowTextW / window scanners) is
  now a fresh random alphanumeric string on every launch instead of the
  fixed "OpenZen Loader" text. The visible custom title bar keeps showing
  the branded name, so the UI is unchanged.
- The window size gets a per-launch random jitter of +/-10px on each axis
  (base 760x500), with the minimum size lowered by the jitter so a negative
  jitter isn't clamped.

Note: the Win32 *class* name is intentionally not randomized here — a Qt6
top-level window's class atom is fixed at CreateWindow time and Qt 6.10
exposes no hook to customize it (SetClassLongPtr cannot rename a class),
so randomizing it would require replacing the Qt window with a hand-rolled
native window. Title + size are the practical fingerprint vectors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 01:18:08 +08:00
Shirona1337 941b69203b docs: fix wrong subject in README (closes #51)
The cause clause incorrectly read "笔者惨遭家暴" (the author). The subject
of that sentence — referenced by "其" — is the 精神马来人, so correct it to
"精神马来人惨遭家暴".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 01:03:17 +08:00
Shirona1337 f59d4c121c fix(patchify): guard HEAD inject arity and correct Embeddium patch docs
Follow-up hardening for the Embeddium/Sodium XRay compat patch (#54).

- PatchTransformer.injectHead now validates a handler's parameter list
  against the forwarded (receiver, args..., CallbackInfo) sequence before
  emitting bytecode. Name-only (desc="") patches match by method name
  alone, so a handler could bind to a target with a different arity or
  primitive parameter types and produce a VerifyError at class load. Such
  mismatches are now logged and skipped instead.
- Name-only matching in apply() now resolves the target method name via
  getHandlerTargetMethodName(), covering all handler kinds instead of only
  Inject/Overwrite.
- BlockOcclusionCachePatch javadoc: drop the stale claim that registration
  is guarded by Class.forName() (it is registered unconditionally, and must
  be), and clarify that Object params only protect against type mismatches,
  not arity mismatches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 00:46:40 +08:00
Ichinomiya Shirona b76ba33ea5 Merge pull request #54 from pabukK/fix-xray-bug
fix: 修复在sodium(或sodium based)的视觉优化模组加载时xray不工作
2026-06-20 00:42:57 +08:00
Kajiki 21508a6f34 fix: 修复在sodium(或sodium based)的视觉优化模组加载时xray不工作 2026-06-19 22:45:56 +08:00
Shirona1337 55fe4699f2 docs: update qq group
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:23:58 +08:00
Shirona1337 ba0fd3b702 fix(scaffold,invmanager): stop treating cobwebs as placeable blocks
Cobwebs are BlockItems, so BlockUtil.isPlaceable treated them like
ordinary building blocks: Scaffold would select them and bridge with
them, and InventoryManager counted them toward Max Block Size, then
threw the web stack away via getWorstBlock once over the limit.
Exclude WebBlock so webs stay reserved for AutoWebPlace/manual use.

Fixes #50

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:22:27 +08:00
Shirona1337 42ca5e208c docs: update README.md 2026-06-08 20:32:28 +08:00
Shirona1337 72d5f1415c docs: update README.md 2026-06-08 17:06:06 +08:00
Ichinomiya Shirona 6c842f3033 docs: update qq group 2026-06-08 04:50:09 +08:00
Shirona1337 7576add38f docs: remove early-stage instability note and fix README typos/punctuation
- Drop the "still in early build, many features may be unavailable" note
- Fix duplicated words, a typo (Interger -> Integer) and awkward phrasing
- Normalize half-width commas/colons to full-width and fix CJK-Latin spacing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:39:26 +08:00
Shirona1337 d3e4748966 fix(render): skip shaders that fail to compile instead of crashing
ShaderProgram now logs and disables itself (valid=false) on shader compile/link failure instead of throwing IllegalStateException. The throw previously bubbled out of StencilHelper's static initializer as ExceptionInInitializerError and crashed the ClickGUI on drivers that reject legacy GLSL (Intel forward-compatible GL contexts: 'texture2D removed in Forward Compatible context').

Callers degrade gracefully when a shader is unavailable: use() is a no-op, drawRoundedRect falls back to a plain rect, drawBlurredRect disables blur for the session, and StencilHelper.applyStencil draws content directly without the rounded composite.

Closes #20, #24

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 16:00:10 +08:00
Shirona1337 07be28c11e chore(release): trigger obfuscated loader release [Release]
Touch build.gradle (a paths-filtered file) so the push runs Build Loader; HEAD carries [Release], so the workflow cuts a GitHub Release with the obfuscated jar + injector + de-obfuscation mapping. Empty commits are skipped by the workflow's paths filter, hence a real (harmless comment) change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
build-07be28c
2026-06-01 15:19:44 +08:00
Shirona1337 5b70703db5 chore(release): publish obfuscated loader [Release]
Build-time-obfuscated build — every class renamed to a fresh random 16-char name (random package + class). Ships the agent jar, the single-file injector, and the per-build de-obfuscation mapping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 15:15:24 +08:00
Shirona1337 fb681e7c83 fix(ci): repair corrupted native/vcpkg.json builtin-baseline
A stray '混淆器' had been appended to the builtin-baseline SHA, leaving the JSON string unterminated; vcpkg manifest parsing failed in CI (Unexpected EOF in middle of string). Restore the clean 40-hex baseline (tag 2026.04.27 / qtbase 6.10.2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 14:14:21 +08:00
Shirona1337 91fb65c22f feat(build): randomized build-time class-name obfuscation + pin Qt 6.10.2
Rename every shit.zen.* / asm.patchify.* class to a fresh random 16-char name in one random 16-char package on each build, via an ASM ClassRemapper pass (build.gradle ext.obfuscateJar, run after ForgeGradle reobfJar). Class names only; methods/fields preserved. Manifest Premain/Agent-Class, the DllBootstrap Class.forName string, and the native bridge name (generated_names.h OZ_BRIDGE_FQCN) are wired to the generated names. Residual original-name strings (loggers, log text, the asm.patchify.* property keys) scrubbed. Emits build/rename-mapping.txt.

Pin Qt to 6.10.2 (vcpkg builtin-baseline + CI tag 2026.04.27): MSVC 14.44 crashes building Qt 6.11.0. Build Qt single-threaded locally (VCPKG_MAX_CONCURRENCY=1, loader --parallel 1, gated off GitHub Actions) to dodge parallel-compilation compiler crashes on that toolset.

CI uploads rename-mapping.txt as an artifact and attaches it to the Release; the Release body warns that prebuilt artifacts share one fixed (blacklist-able) mapping and users should self-compile. README documents the obfuscation + the self-compile warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 14:09:28 +08:00
Shirona1337 3263b0b4cb ci(loader): pin vcpkg baseline so the Qt cache stops missing
The vcpkg install was cloned at a floating HEAD while native/vcpkg.json
carried no builtin-baseline, so every run resolved the qtbase port afresh.
Its package ABI drifted whenever upstream vcpkg moved, the restored
actions/cache entry no longer matched, and qtbase was rebuilt from source
(~31 min) on every push. Because the cache key is static (hash of
vcpkg.json, unchanged since 05-23) the rebuilt tree was never saved back
either, so the miss repeated forever.

Pin both sides to vcpkg tag 2026.05.25
(d015e31e90838a4c9dfa3eed45979bc70d9357fc, qtbase 6.11.0):
  - native/vcpkg.json: add "builtin-baseline"
  - workflow: clone --branch 2026.05.25

Adding the baseline also changes the vcpkg.json hash, so this run gets a
fresh cache key, cold-builds Qt once, and saves it; subsequent runs match
the now-deterministic ABI and skip the qtbase build entirely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 00:55:19 +08:00
Shirona1337 5b1d220280 feat(module): restore XRay with true see-through terrain patch [Release]
Restore the full XRay ore-scanner module (flood-fill vein detection,
anti-fake-ore scoring, packet-driven blind scan, wireframe ESP boxes and
on-screen tracers, ~27 settings) and add BlockPatch, which hooks
Block.shouldRenderFace so terrain turns transparent and only the target
ores render while XRay is enabled. Use @EqualsAndHashCode for BlockKey.

Closes #34

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
build-5b1d220
2026-05-31 23:42:15 +08:00
Shirona1337 8b16eb4972 fix(module): default NameProtect to off [Release]
Don't auto-enable in the constructor — opt-in only, matching every
other render module. Pairs with the onDisable fix from 9ad6a6b so the
module starts off and can be toggled freely.
build-8b16eb4
2026-05-31 16:34:58 +08:00
Shirona1337 9ad6a6b70c fix(module): allow NameProtect to be disabled (#38)
Drop the onDisable override that immediately re-enabled the module —
left-clicking the entry in the ClickGui now actually turns it off.
The constructor still defaults the module on, so the protection is
opt-out rather than opt-in.
2026-05-31 16:32:52 +08:00
Shirona1337 4958f6694c fix(gui): align panel ClickGui widget glyphs by capHeight (#37)
Reworks vertical placement in PanelClickGui / CategoryBar / ProfileWidget
/ SettingsPopup / NumberSettingRenderer so search-bar icon + placeholder,
category bar Y, role badge, dropdown header/value/arrow/items, and the
number widget label/sign/value/caret all derive their Y from CapHeight
instead of ascent+descent or hard-coded pixel offsets — fixes drift at
non-100% GUI scale.

Co-Authored-By: Koe <KoeNotPrism@proton.me>
2026-05-31 16:32:41 +08:00
Shirona1337 8d395a1d9f docs(readme): add 父子相爱相杀 subsection with xinxin screenshot
Adds a short subsection under 后门 documenting the upstream author's
QQ-group claim that another contributor used a backdoor to remotely
read user files, with the chat screenshot as evidence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 02:10:18 +08:00
Shirona1337 9dc1dcbcd5 docs(readme): inline the backdoor analysis with screenshots & traces
Promote the standalone mapping/BACKDOOR.md into the main README so the
backdoor discussion (screen capture, RCE / file download / file browse
packets, the upstream author's contradictory responses) is visible
without an extra click. Includes captured Trace screenshots, the
ToString-leaked CPacketSystemInfo class and the author's QQ-chat /
Bilibili rebuttals.

File moves:
- mapping/BACKDOOR.md       -> inlined into README
- mapping/screenshot-*.png  -> img/  (alongside the other readme assets)
- Several new images under img/  (RCE, backdoor*, CPacketSystemInfo, meme)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 02:06:05 +08:00
Shirona1337 dea5cf6270 docs(readme): replace Mod path with -javaagent, add optional UPX prereq
The Forge mod entry point no longer works in this project, so the
build section was steering people toward a path that wouldn't load.
Reframe the two delivery shapes as Java Agent jar and hot-injector
EXE, with a callout that mods/ is unsupported.

Other readme drift caught in this pass:
- UPX listed as an optional common prerequisite with install
  instructions (choco / upx.github.io) — the upxCompress task already
  no-ops when upx isn't on PATH, this just makes the option visible.
- 使用注入器 步骤 updated for the Inject-button UI (previously
  documented "double-click a row").
- 删除 stale "构建流程" 列表 in the injector section.
- 后门 段更新 + 布吉岛 段加删除线 reflecting current detection
  status (user-authored edits picked up in the same commit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 01:16:27 +08:00
Shirona1337 ecc29d4e82 build(native): enable per-TU parallel compilation (cmake --parallel + /MP)
Before: MSBuild defaulted to a single process per project, so each
vcxproj compiled its .cpp files sequentially. Local clean rebuild of
OpenZen.dll + OpenZenLoader.exe measured ~14.6 s.

After: same cold rebuild measures ~4.8 s — 3x faster — by combining

- `cmake --build --parallel <Runtime.runtime.availableProcessors()>`
  in the buildNative task, which forwards a project-level `-m:N` to
  MSBuild and gets DLL / Loader to build concurrently where the
  dependency graph allows.
- `/MP` on the MSVC compile options, which is the actual win: it lets
  cl.exe spawn one compiler process per available core within a
  single vcxproj. The DLL+Loader together have ~13 .cpp files; this
  is where the bulk of wall-time was being spent serially.

CI runners get the same speed-up for free.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 01:06:02 +08:00
Shirona1337 6529c3090b ci(loader): widen build-trigger paths + [SKIP CI] gate + case-insensitive [Release]
Three workflow ergonomics tweaks:

- Path filter now also includes build.gradle / settings.gradle /
  gradle.properties / gradle/wrapper/** / gradlew(.bat) and the
  workflow file itself, so a wrapper bump or build-script change
  still triggers CI even though only src/ and native/ files compile
  into the final artifact.
- Job-level if: skips the entire build when the push commit message
  contains [SKIP CI] (Actions' contains() is case-insensitive for
  string operands, so [skip ci] and [SKIP CI] both qualify).
  workflow_dispatch is unaffected because head_commit is null there.
- [Release] marker detection in the PowerShell publish step now uses
  StringComparison.OrdinalIgnoreCase so [release], [Release] and
  [RELEASE] all cut a release; .NET's default .Contains is case-
  sensitive which made the existing rule too brittle.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 00:52:16 +08:00
Shirona1337 5745547a37 ci(loader): gate GitHub Release publishing on [Release] commit marker
Add an opt-in publish step at the tail of the build job:

- Bump job permissions to contents: write so the workflow token can
  create releases.
- Read the HEAD commit message via `git log -1` and set an
  is_release output when it contains the literal substring [Release].
- When set, `gh release create build-<sha>` and attach the staged
  OpenZenLoader-<sha>.exe and OpenZen-<sha>.jar. Notes are piped
  through a file (--notes-file) so brackets / newlines in the commit
  message can't corrupt the CLI invocation.

Pushes without the marker keep producing only the existing per-build
artifacts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
build-5745547
2026-05-25 00:33:00 +08:00
Shirona1337 58caaef588 fix(hud): restore lost Material Icons codepoints in EventAlertHud
Cross-checked against the original obfuscated jar via Recaf. Seven PUA
codepoints in the icon string literals had been replaced with empty
strings somewhere in the deobf pipeline, which left the alert HUD with
no icons and an off-centred text layout (since titleFont.getWidth("")
returns 0, the text was being squeezed against the left edge).

Restored:
- ender_pearl glyph (U+E55E) for the projectile alert
- bolt glyph (U+EA0B) for the lightning alert + hasPathIcon
  discriminator + static-block glyph lookup
- arrow_upward / arrow_downward (U+E5D8 / U+E5DB) for the off-screen
  direction indicator + the rotated fallback case

Font sizes already matched the original (48 / 44 / 8 / 6); the apparent
"text too small" was an artefact of the zero-width icon collapsing the
row.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 22:54:06 +08:00
Shirona1337 9c4059198a fix(gui): NewClickGui hidden setting click routing & slider drag release
Cherry-picked the GUI fixes from #31 (by @Kyresn). Excluded the unrelated
.gitignore / META-INF/MANIFEST.MF / ZenClient changes from that PR:
MANIFEST.MF is generated by the jar task and must not be tracked, and
the isClientDist() guard is a no-op on a 1.20.1 client.

- Add visibility.displayable() guards on Boolean / Mode / MultiSelect
  setting elements and at the ModuleElement dispatch site so hidden
  rows (e.g. Eagle/Snap under Scaffold Telly Bridge) can no longer
  steal clicks meant for the rows below them.
- Expand BooleanSettingElement's click hitbox to the full row, matching
  OldClickGui behaviour.
- Drop the in-bounds gate on mouseReleased in ModuleElement and
  CategoryPanel so a NumberSetting slider drag that ends outside the
  panel still releases isDragging.

Co-Authored-By: Kyresn <179435327+Kyresn@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 22:17:33 +08:00
Shirona1337 0c2441f3a6 feat(loader): frameless UI with splash, custom list, inject overlay
Replace the standard QMainWindow chrome and QTableWidget with a
purpose-built Qt UI built around hand-rolled widgets and animations:

- SplashScreen: frameless translucent splash with a wordmark fade/scale,
  a sweeping scan line and a pulsing accent glow. ~950ms total cold-start
  reveal that fades out into the main window.
- TitleBar: custom title bar replaces the OS frame, owns drag-to-move,
  minimize/close buttons, and a breathing scan-status dot.
- InstanceList + InstanceRow: scrollable column of self-painted rows
  (PID, title, Inject button). Rows are not selectable, double-click
  has no special meaning - injection happens only through the button.
  Hover animates each row's tint; new pids play a slide-in/opacity
  entrance.
- InjectionOverlay: modal-style frameless overlay shown while inject()
  runs in a worker thread. Spinner ring + progress bar advance during
  injection; completion swaps to a checkmark / X, holds briefly, then
  fades out. After it closes, the main window fades and the loader
  self-quits.
- MainWindow: frameless + translucent panel painted by hand; entrance
  fade/slide on launch; uniform playExitThenQuit() shared by the close
  button and the post-injection path so every exit path gets a fade-out
  instead of a hard vanish.

Also enables Win11 rounded corners via DwmSetWindowAttribute on show.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 17:54:03 +08:00
Shirona1337 778b9980b8 ci(loader): opt v4 actions into Node 24 runtime ahead of forced flip
GitHub deprecated Node 20 for JavaScript actions on 2025-09-19; v4 of
checkout / setup-java / cache / upload-artifact and ilammy/msvc-dev-cmd
still ship a Node 20 binary in action.yml. Set
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true at job scope so the runner
executes them under Node 24 now - silences the deprecation warning and
removes a 2026-06-02 surprise when the default flips.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 17:03:19 +08:00
Shirona1337 2177f181ed ci(loader): upload loader exe + mod jar as separate sha-stamped artifacts
Stage build/dist/OpenZenLoader.exe and build/libs/hey-1.0.jar into
build/release as OpenZenLoader-<sha>.exe and OpenZen-<sha>.jar, then
publish each as its own upload-artifact entry whose name matches the
file. actions/upload-artifact always wraps a zip around the payload, so
this is as close as we can get to "no wrapper" without cutting a Release
- documented inline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:57:27 +08:00
Shirona1337 a9e3a9af0a fix(inventory): restore InventoryManager flow to match original jar
Vineflower decompiled the original into one large performInventoryAction
plus a few oddities (dead `shouldSkip` guard, dead keyJump/keyShift reads,
unused locals). The previous rewrite split the offhand handling into
several helpers, which inverted the if/else if chain and silently
changed which branch wins when multiple offhand modes match.

Re-align with the original control flow:
- onPacket: drop the `shouldSkip = false; if (shouldSkip) return;` dead
  guard; collapse the ClickPacket/ClosePacket cancel under an explicit
  externalContainerOpen short-circuit so external chests/furnaces fall
  through untouched.
- onMotion: early-return for the no-pending-packets branch and strip the
  side-effect-free keyJump/keyShift reads.
- performInventoryAction: re-merge the split handle* helpers into the
  flat if / else if chain the original jar uses.
- isUsefulItem: flatten back into the per-item return ladder.
- Drop unused imports (Screen, Iterator, ChestMenu) and add the missing
  ChatUtil import that the packet trace lines need.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:47:53 +08:00
Shirona1337 c6c20877ff ci(loader): cache vcpkg installed/ via actions/cache, drop x-gha
The previous run still rebuilt Qt from source on the second push.
vcpkg's x-gha binary cache backend relies on the v1 GitHub Actions
cache API and the ACTIONS_CACHE_URL / ACTIONS_RUNTIME_TOKEN
secrets exported via actions/github-script. On the current
windows-2022 image the v1 API is being phased out (the new
ACTIONS_RESULTS_URL is what's reachable), so x-gha quietly missed
on every run.

Switch to a path-based actions/cache@v4 entry:

  - path: vcpkg\installed + vcpkg-archives
  - key:  vcpkg-qt-${runner.os}-${hash(native/vcpkg.json)}
  - restore-keys: vcpkg-qt-${runner.os}- (warm start on a vcpkg.json bump)

vcpkg.installed is the deployed Qt tree CMake's manifest mode
inspects; if it already contains qtbase[widgets] the first vcpkg
install call is a no-op and CMake configure finishes in seconds.
vcpkg-archives gets fed via the new
VCPKG_BINARY_SOURCES=clear;files,...\vcpkg-archives,readwrite
binary source so transitive package binaries are also persisted
across runs - useful when vcpkg.json changes and only some libs
need rebuilding.

Also drop the now-unused "Export GitHub Actions cache tokens"
step (no x-gha backend, no tokens needed).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:06:02 +08:00
Shirona1337 e03d936b10 fix(noslow): drop Grim V3 paywall gate, allow free mode switch
The deobfuscated NoSlow kept the original jar's pay-role gate
around its Grim V3 mode:

  hasGrimRole() -> false stub (no auth bridge in this fork)
  checkAndFallbackMode() -> if !hasGrimRole && mode == "Grim V3":
                              mode = "NoSlow"

That made every "Grim V3" selection snap back to "NoSlow" the
next tick - reported as NoSlow Mode grimv3 cannot be enabled
in #27.

We are open source; the paywall is gone. Delete the whole gate:

  - hasGrimRole / isGrimMode / isGrimModeActive /
    checkAndFallbackMode / createModeSetting are removed.
  - The three checkAndFallbackMode call sites (ctor / onEnable /
    onTick) are removed.
  - `mode` is initialized inline with the two-option ModeSetting.
  - isGrimSlowMode / isNoSlowMode collapse to mode.is(...) one-
    liners so the rest of NoSlow still picks the right slowdown
    branch.

Closes #27

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:54:15 +08:00
Shirona1337 5024d8237b ci(loader): override pre-set VCPKG_ROOT via GITHUB_ENV
windows-2022 runners with VS Enterprise installed pre-set a
system-wide VCPKG_ROOT pointing at
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\vcpkg".
That value wins over the job-level `env: VCPKG_ROOT:` in PowerShell
expansions, so the previous run tried to git-clone into that
read-only path and failed with "destination path ... already exists
and is not an empty directory".

Drop the job-level VCPKG_ROOT and instead resolve the path to
"$GITHUB_WORKSPACE\vcpkg" inside the clone step, then write it
back via GITHUB_ENV so every later step (including Gradle's
findVcpkg / configureNative) picks up our copy. The build step
also dumps VCPKG_ROOT / JAVA_HOME / OPENZEN_BUILD_REVISION up
front for quick diagnosis if the override ever drifts again.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:00:23 +08:00
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 bfb0c0e464 fix(reflection): correct SRG fallback names for noJumpDelay / rightClickDelay
Telly Bridge Scaffold (and other paths that lean on
ReflectionUtil.setJumpDelay / setRightClickDelay) silently broke
under DLL injection because the SRG name we were trying on the
production runtime was wrong:

  noJumpDelay     was f_20889_  ->  f_20954_   (LivingEntity)
  rightClickDelay was f_91076_  ->  f_91011_   (Minecraft)

findField walks the superclass chain and tries every candidate
name, so in a dev mojmap environment the mojmap names match first
and we never noticed. In a SRG production runtime both candidates
miss, findField throws ReflectionException, the surrounding try
swallows it as "Failed to set ... field", and Telly Bridge's
jump-delay reset never lands - the scaffold then mis-times the
next placement.

The other ReflectionUtil entries (yRot/xRot/depthBufferId/
brewingStand/missTime) use SRG names that were already correct
for 1.20.1; left untouched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:55:30 +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 7f76b86c84 docs(readme): drop [WIP] tag, add Bujidao anti-cheat FAQ
- Title no longer carries the [WIP] marker now that the DLL injection
  and module restoration work has stabilised.
- Minor wording tweak in the early-build disclaimer.
- New "常见问题" section noting that Bujidao currently does not
  detect the project (verified 2026-05-23) since its anti-cheat is
  class-name blacklist based; suggest renaming classes at build time.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 10:51:33 +08:00
Shirona1337 eadd525e83 fix(modules): gate keybind toggles on mc.screen == null
Module keybinds used to fire while ChatScreen, PauseScreen or any
other UI was open, so typing a chat message or being in the pause
menu would silently toggle modules whose bind happened to match a
key in the text.

Skip the keybind scan in onKey() unless mc.screen is null, matching
vanilla's "no GUI" gating used elsewhere.

Fixes #19

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 10:16:10 +08:00
Shirona1337 2d4c941c72 chore: add QQ group to README, drop unused bootstrapForDll
- README: announce QQ group 523522206 for project discussion.
- ZenClient: remove bootstrapForDll(). The DLL path went from
  "GameLoaderBridge -> DllBootstrap.start -> new ZenClient" to just
  "DllBootstrap.start -> registerPatches + installPatchesAndRetransform"
  a few commits ago, so MinecraftPatch.onTick's existing lazy-init
  now constructs the singleton on the next tick and no external
  caller needs this helper anymore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 10:11:53 +08:00
Shirona1337 87b774563c refactor(combat,movement): restore KillAura/NoSlow from Recaf source
KillAura
  - Field set realigned with the obfuscated jar: drop rotationsMode,
    attackMode, targetHud, noUseItem, aboveTarget; keep 12 boolean /
    7 number / 3 mode + sprintCounter.
  - Settings renamed per the user's config sheet: Infinity Switch,
    Keep Sprint, Max APS, Min APS, Switch Delay (Attack Times), FoV,
    Priority. Defaults: attackMobs/multiAttack/keepSprint=true,
    aimRange=4, maxAps=12, minAps=9, Priority=FoV.
  - New Test/More Particles/Ignore skip ticks/Fake AutoBlock/Delay
    Mode settings now drive real behaviour:
      * test  -> "attack player above" branch in isValidTarget
      * ignoreSkipTicks -> attack pacing guard in onPreMotion
      * morePart -> magicCrit+crit in attackEntity
      * delayMode "1.8" smooths attacks across ticks; "1.9" uses
        sprintCounter + attackStrengthScale gating
      * fakeAutoBlock surfaces to OldHitting (see below)
  - Target ESP turned into a 4-mode ModeSetting (None/Spiral/Box/Tab)
    with the original hurt-tinted box and tab renderers wired through
    RenderUtil + EntityUtil.
  - attackEntity bridged back through ForgeHooksClient.onMouseButton*
    so Forge mouse listeners still see the synthesised swings.
  - doAttack now bails on isWebPlacing first and surfaces an
    AntiBots-skip notice via ChatUtil.print.
  - All settings + internal flags moved to inline field initializers;
    constructor only does super(...) and INSTANCE = this.

NoSlow (was FastUse)
  - Rename module, file, INSTANCE type, mods.toml-facing display name,
    and all call sites (ModuleManager, MinecraftPatch).
  - Mode option list now ("Grim V3", "NoSlow") with Grim V3 default;
    isGrimMode probes the new label.
  - User-facing settings renamed (Bow / Crossbow / Food / Potion drop
    the NoSlow suffix). Bow/Crossbow defaults flipped to false.
  - Settings + state moved to inline initializers; constructor only
    does super(...), INSTANCE = this, checkAndFallbackMode().

OldHitting
  - isKillAuraAttacking now gates on the restored fakeAutoBlock flag,
    matching the obfuscated jar's animation trigger.

ReflectionUtil-side knock-on cleanup (the SRG/mojmap remap helpers
introduced earlier) is what made these field-name swaps safe at
runtime in both dev and DLL-injected environments.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 09:48:37 +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
Shirona1337 f9068db44e fix(panel): unstick PanelClickGui layout & icons
修复 PanelClickGui 错位:
- 按 recaf 完全复刻 drawSearchBar (变量顺序/分支/常量回到原版)
- 同步精简 PanelClickGui 主体: 去掉死的 static block、Renderer.render lambda 包装、drawPanelGlow/drawSearchBar 多余的 RenderUtil.drawBlurredRect、render() 里的重复变量赋值
- ModuleListPanel 第一行起点偏移 +2*scale -> +8*scale, 解决反混淆后的 GlyphMetrics 让 GlHelper.drawText 视觉顶部高于 drawY 导致第一个 module 名字被 clip 上沿裁掉的问题; onMouseClick 命中盒同步下移
- NeverloseWatermark: 补齐 6 个 Material Icons 字形 (\ue8a6 / \ue8b8 / \uebca / \ueb66 / \ue0c8 / \ue192)
- FastUse.getTriple: keyName 由 "" 改为 null, KeyBindsHud 才会画默认 \ue9f6 key 图标

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 07:36:32 +08:00
Shirona1337 fe1fdea994 docs(github): add issue templates for bug, crash and suggest
Add YAML issue forms under .github/ISSUE_TEMPLATE/ with required
fields for bug reports (behavior, repro, expected fix), crashes
(log, repro) and suggestions. Disable blank issues via config.yml
to force template usage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 06:48:12 +08:00
Shirona1337 0a50ed3e1c fix(rotation): port Naven's LivingEntityRenderer head/pitch redirect
Replace the entity-state force-write in RotationHandler.onHeadTurn with
a render-side override that fires RotationAnimationEvent from inside
LivingEntityRenderer.render's Mth.rotLerp / Mth.lerp call sites — the
local entity's yBodyRot/yHeadRot/xRot keep doing Mojang's natural body-
follows-head lerp.

Wrap slices account for PatchApplier's loose (owner || name) && desc
matcher: head yaw is rotLerp #2, head pitch is lerp #4 (after the three
Mth.rotLerp matches that the owner-match alone pulls in).

Also surface PatchTransformer behavior so future broken targets are
visible: log every applied handler at INFO and warn whenever a wrap /
invoke / TAIL inject / ModifyLocals anchor finds no site.
2026-05-23 06:42:03 +08:00