Commit Graph

43 Commits

Author SHA1 Message Date
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
Shirona1337 67a862499e refactor(webui): inline port literal and ship deobfuscated index.html
Drop the runtime Port / Open Browser settings — the original Zen WebUI
hard-codes :8089, and the in-game settings round-trip added no value.
Replace the placeholder panel with the deobfuscated Tailwind-based
Web Click GUI shipped by Zen.
2026-05-23 05:06:44 +08:00
Shirona1337 9f790ee492 feat(webui): implement HTTP-server-backed WebUI module
Recreate the shit.zen.network.webui handlers (categories, modules,
toggle, get/set setting, static files) from Recaf and wire them into
the WebUI module so it serves a control panel from a configurable
local port. Ships a Tailwind-based panel under resources/webui/.
2026-05-23 04:15:28 +08:00
Shirona1337 cd0bc4f27b misc: fix bad named fields 2026-05-23 03:58:30 +08:00
Shirona1337 5c3607c805 chore(client): drop always-true isOwner and tidy nametag
- Remove ZenClient.isOwner(String) -- it has been hardcoded to return
  true since the Encryption / owner-check teardown, so every caller
  was effectively a no-op. Drop the method and the only remaining
  caller in NameProtect (which was filtering out the local player
  twice via name equality, then again via isOwner, with the same
  always-true result).
- KeyBindsHud: write the keyboard / power-settings glyphs as Java
  unicode escapes ('\uE1C6' / '\uE9F6') instead of inline PUA bytes,
  so the source stays diff-friendly when editors strip non-ASCII.
- OpalNameTag: drop the 'decoded name suffix' branch (the helper it
  called is gone, leaving the suffix permanently empty), and restore
  the missing health icon glyph ('\uE87D') that had been stripped to
  an empty string -- the name-box width math no longer reserves space
  for the absent decoded suffix either.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 14:14:51 +08:00
Shirona1337 49ad2adf74 fix(combat): restore KillAura tick / attack / multi logic from Recaf
Several Recaf-side behaviors were missing or wrong in the current
KillAura, which is why the module felt 'broken':

- onTick short-circuit was too aggressive: any non-null mc.screen
  killed everything. Recaf only bails for AbstractContainerScreen and
  for the rotation-owning helpers (Helper / AntiWeb / AntiTNT /
  MidPearl / Stuck / AutoWebPlace), plus ItemUtil.hasServerItem().
  Pure UI screens (chat, F3, vanilla menus that aren't containers) now
  no longer wipe the target.
- Switch trigger used the wrong counter: it compared the float
  'attacks' accumulator against switchAttackTimes, but Recaf has a
  separate per-attack counter (attackTimes) compared against
  switchDelay. Added the missing field and swapped the predicate so
  Switch Delay actually controls how long we stay on a target.
- Attack pacing was reduced to a flat 'attacks += aps/20'. Recaf only
  feeds the accumulator in Smooth mode and uses
  MathUtil.randomDouble(switchAttackTimes, aps) / 20.0 to jitter the
  rate; Snap mode instead waits for getAttackStrengthScale >= 0.9F
  and respects a sprintCounter cooldown set from
  getCurrentItemAttackStrengthDelay(). AntiKB.NoXZMode and sprintSync
  scale the rate too.
- attackEntity() now bumps attackTimes, gates the actual attack +
  swing on (sprintTickCounter % 2 == 0) when sprintSync is on, runs
  the magicCrit + crit pair when targetHud is on, and seeds
  sprintCounter for Snap mode.
- doAttack() / multiAttack now use RotationUtil.getHitDistance along
  the active rotation rather than just closestPoint distance, which
  is what Recaf does. Dropped a defensive 'attack target if not
  hovering anyone' fallback that was not in Recaf.
- updateTargets() guards against the null getTargets() can return so
  targetList is always a usable list.
- onDisable now also clears sprintCounter and attackTimes alongside
  sprintTickCounter so re-enabling the module starts from a clean
  state.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 13:52:07 +08:00
Shirona1337 9dd2a25a1b fix(hud): restore stripped material-icon glyphs in KeyBindsHud
The header keyboard icon next to 'Hotkeys' and the toggle icon used
when a module has no bound key were both left as empty string literals
in the deobfuscated source. Recaf has them as:

  initSettings(): getStringWidth("\uE1C6", bindFont)
                  getStringWidth("\uE9F6", bindFont)
  renderRows():   drawTextWithShadow("\uE1C6", ..., bindFont, ...)  (both right- and left-aligned branches)
                  drawTextWithShadow("\uE9F6", ..., bindFont, ...)  (no-keyName branch)

\uE1C6 is the Material Icons "keyboard" glyph and \uE9F6 is
"power_settings_new". The bindFont uses materialIcons(18.0f) so the
codepoints just need to be put back as Java unicode escapes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 13:30:19 +08:00
Shirona1337 cee918fe7a fix(gui): add frosted-glass blur behind PanelClickGui panel and search bar
The panel and search-bar backgrounds were calling TextGlow.drawBackground
only, which paints two translucent rounded rects (a dark base + a thin
white overlay). The original visual is supposed to be a frosted-glass
blur of the gameplay behind it -- the blur shader was loaded and
wired up via RenderUtil.drawBlurredRect (blits the main render target
into a TextureTarget, then samples it through the 'blur' shader from
ShaderSource), but nothing was actually invoking it.

Call RenderUtil.drawBlurredRect right before TextGlow.drawBackground
in both drawPanelGlow and drawSearchBar, using the existing radius
and effective alpha so the blur fades in alongside the panel open
animation. The shader assets (blur.fsh / blur.vsh / common.glsl) are
embedded in ShaderSource enum, so no extra resource files are needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 13:05:59 +08:00
Shirona1337 2e874939d5 docs: rewrite paste/README.md with side-by-side code excerpts
Per request: drop framework-level comparison, drop arguments based on
field/class/method names (those are renamed during deobfuscation and
do not prove plagiarism by themselves). Keep only the 14 modules
listed by the user plus the utility classes, and back every claim
with actual code blocks placed side-by-side so a reader can see the
two snippets are the same thing.

Modules included: AntiBots, CrystalAura, AntiFireball, Scaffold,
FastWeb, Stuck, AutoMLG, SafeWalk, Disabler, AutoTools, ChestStealer,
InventoryManager, ChestESP, Compass, Projectiles, plus a utility-
class section (ChunkUtil, RotationUtil, BlockUtil, MovementUtil,
RayTraceUtil).

The evidence now hinges on three categories of artefacts that
deobfuscation cannot fabricate: string literals ("Fake Staff Detected!
(", "Stream limit didn't work.", "点击使用", "Normal"/"Telly Bridge"
/"Keep Y", etc.), magic constants (+1337, (0.88,1.88,0.88), > 2 &&
< 0.0001, i*i+1, 72000, 0.6/0.2/1.2, +1.62, RGB (173,12,255)...),
and signature import/dead-code fingerprints (antlr-runtime's
OrderedHashSet used in a rotation util; MovementUtil.getDirectionAngle
copied verbatim despite being a private unused method).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 02:32:14 +08:00
Shirona1337 f024a0a1ae docs: detailed Zen-vs-Naven plagiarism evidence in paste/README.md
Populate paste/README.md with a per-module / per-subsystem comparison
between OpenZen (this repo, deobfuscated from Zen client) and
Naven-Modern (github.com/Margele/Naven-Modern). Findings collected by
running parallel agents against both source trees:

- Functional modules: 30+ Zen modules trace back to a 1:1 Naven
  counterpart, either same-named or renamed (e.g. KillAura<-Aura,
  CrystalAura<-AttackCrystal, ESP<-Glow, InventoryManager<-
  InventoryCleaner using Naven's @ModuleInfo internal name). Setting
  strings, default values, ranges, RGB constants, and even Chinese
  literals like "点击使用" survive verbatim.
- Framework: EventBus/EventTarget/EventPriority are the renamed twins
  of Naven's EventManager/EventTarget/Priority (same DarkMagician6
  EventAPI shape, identical default byte priority 2). Module,
  ModuleManager, Setting/Value, CommandManager, util classes (
  RotationUtil keeps Naven's odd antlr OrderedHashSet import,
  ChunkUtil keeps "Stream limit didn't work.") all line up.
- Fingerprints that can't be hand-waved away: +1337 magic offset in
  Stuck; the typo 'Recorvey' carried over from rewrites; the
  Projectiles RGB triplets (173,12,255)/(255,238,154); identical
  sensitivity-GCD formula scaled*scaled*scaled*1.2F.

The doc also tabulates module-level severity ("line-by-line" / same-
name+rewrite / not plagiarized) so readers can skim before diving in.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 01:24:49 +08:00
Shirona1337 cd5be6b1a4 add: todo in readme.md 2026-05-22 01:03:45 +08:00
Shirona1337 03ef3f7e34 add: todo in readme.md 2026-05-22 01:02:50 +08:00
Shirona1337 85eeac4738 docs: add backlog note about Naven-derived module list
README: clarify that the deobfuscated jar is the latest one as of
2026-05-21 (rather than an old build, as some users seem to assume),
collapse a stray hard wrap, and link to a new paste/ subtree that
will track which modules were lifted from the Naven client.

Also rename KillAura.aimRange to attackRange to match the user-facing
'Attack Range' label and how the field is actually used in the in-FOV
check.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:57:42 +08:00
Shirona1337 a0ac1a8cf3 revert(gui): drop DrawContext/GuiGraphics pose sharing experiment
The earlier change had Renderer.render seed DrawContext with
GuiGraphics.pose() so PanelClickGui's pushPose+scale(0.98+0.02*eased)
would also drive the inner DrawContext draws. It did not visibly fix
the search bar — icon/query/placeholder still rendered too high
relative to the search background — and quietly mutates the shared
matrix stack while CustomFont is busy pushing its own glyph
transforms on top of it.

Restore the Recaf-equivalent behavior: Renderer.render builds a
DrawContext with its own fresh PoseStack. The PanelClickGui body
wrapping with Renderer.render is kept since that is what actually
gets ModuleListPanel's scissor to take effect in Screen-mode renders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:56:44 +08:00
Shirona1337 fc95f56fc8 fix(gui): wrap PanelClickGui body in Renderer.render so search stays aligned
The previous attempt only made Renderer.render share GuiGraphics.pose()
with DrawContext when guiGraphics was non-null. But every sub-panel
call (drawSearchBar, drawToasts, ModuleListPanel, SettingsPanel,
CategoryBar, ProfileWidget, SettingsPopup, KeybindOverlay,
ScaleSwitchOverlay) used Renderer.renderConsumer, which falls back
to Renderer.render(null, ...) when currentCanvas == null — that's
exactly the Screen.render path. With guiGraphics == null the
DrawContext still got a private new PoseStack(), so any element
rendered through DrawContext was identity-posed while the search
background drawn via guiGraphics.pose() rode along with
pushPose + scale(0.98+0.02*eased), and the two drifted apart.

Wrap the entire PanelClickGui body inside Renderer.render(
guiGraphics, ...). That sets currentCanvas to a DrawContext whose
PoseStack is GuiGraphics.pose(), so every nested renderConsumer
short-circuits into the same DrawContext and shares the same
matrix. Search icon, placeholder, query text and the blinking
cursor now sit on the same scaled pose as the search background.
Toasts get the fix for free.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:38:41 +08:00
Shirona1337 7c0eaa1018 fix(gui): make ModuleListPanel clip and search/toast pose consistent
Two related render bugs in PanelClickGui (Screen context):

1) Module list overflow when a category has more entries than fit:
   ModuleListPanel.render called Renderer.renderConsumer, which in
   the Screen context (currentCanvas == null) falls through to
   Renderer.render(null, ...). That built a DrawContext(null), and
   DrawContext.clipRect short-circuits when guiGraphics is null, so
   enableScissor was never issued. The inner clip in renderModuleList
   was also skipped, so rows past the panel bottom were drawn freely.

   Switch ModuleListPanel.render and renderSearchResults to
   Renderer.render(guiGraphics, ...). The DrawContext now has the
   live GuiGraphics, so both the outer clip and the renderModuleList
   inner clip actually call enableScissor and the list stays inside
   its panel.

2) Search bar (and other PanelClickGui inner draw lambdas) drifted
   relative to their backgrounds. Renderer.render created a
   DrawContext with a fresh "new PoseStack()" regardless of the
   GuiGraphics that was passed in. PanelClickGui wraps its render in
   pushPose + scale(0.98+0.02*eased), so primitives drawn through
   guiGraphics.pose() (search background, cursor rect, toasts) got
   the scaled pose while primitives drawn through the DrawContext
   (search icon, query text, placeholder) used identity — they
   visually drifted apart whenever scaleFactor != 1.

   Construct DrawContext with the GuiGraphics's PoseStack instead of
   a private one, so every path shares the same matrix stack and
   the search bar and toasts render coherently with the rest of
   PanelClickGui.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:31:09 +08:00
Shirona1337 70faf60fee fix(gui): restore stripped material-icon glyphs and add Misc/Ghost icons
Two related rendering regressions:

1) OldClickGui category headers — the switch in legacy CategoryPanel
   only mapped COMBAT..EXPLOIT to icon glyphs 'a'..'e' and fell back
   to '?'. The Category enum has WORLD ("Misc") and MISC ("Ghost")
   too, so those two headers rendered as a question mark. Extend the
   switch with WORLD -> 'f' and MISC -> 'g'.

2) PanelClickGui rendering — several Material Icon PUA codepoints
   had been silently stripped to empty strings during earlier source
   passes, leaving the panel without bind icon, profile-popup logo /
   close button / dropdown arrow, and the number-setting edit icon.
   Restore them per Recaf:
     - ModuleListPanel bind icon       \uE312 (2 sites)
     - SettingsPopup logo              \uE8B8
     - SettingsPopup close button      \uE5CD
     - SettingsPopup dropdown arrow    \uE313
     - NumberSettingRenderer edit pen  \uE3C9
   CategoryBar's 7 category glyphs and PanelClickGui's search icon
   already had the correct PUA bytes on disk; they were just
   invisible in tooling, so no change there.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 00:11:15 +08:00
Shirona1337 346e17a3ca fix(hud): rewrite PlayerListHud.PlayerEntry to match obfuscated semantics
The hand-written PlayerEntry never initialized widthAnim, so the
render path read 0 for entry width and drew nothing visible. Other
gaps:
- nameWidth was never measured, so item layouts collapsed.
- displayName bypassed NameProtect.replacePlayerName, leaking real
  IGNs through the streamer/anti-doxx filter.
- startRemove() flipped a flag but never triggered the slide-out or
  height-collapse animations, so isRemoveDone() (which used a custom
  alpha decay) effectively never returned true.
- tick() mutated alpha / currentY by hand instead of just ticking
  the animation timers the render code already consults.

Rewrite per Recaf's PlayerListHud$PlayerEntry:
- Constructor seeds itemStacks/cheatItems from initialItems, calls
  updateItems(...) to set displayName, nameWidth, totalWidth, then
  primes slide/height/alpha/width anims (width starts at totalWidth
  so the row is visible from frame 1, then animates if it grows).
- updateItems() recomputes displayName via NameProtect, the cached
  nameWidth via headerFont, the totalWidth from padding/head/items,
  and animates widthAnim to the new total.
- startRemove() actually slides the entry out and animates height
  to 0; isRemoveDone() defers to heightAnim.isDone().
- Drop the dead alpha / targetY / currentY / parent fields.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 23:46:32 +08:00
Shirona1337 e02133547c fix(hud): rewrite PotionEffectsHud.EffectEntry to match obfuscated semantics
The previous EffectEntry had two render-killing inversions: show()
animated heightAnim to the target row height and widthAnim to 100,
but the render loop uses heightAnim as the 0..1 alpha factor
(multiplied by 80/140/160/185) and widthAnim as the actual row
height. That made every entry render with massively saturated alpha
and a 100-pixel-tall pill. getTotalWidth() also returned the height
animation value, so the sort order was wrong too.

Rewrite to mirror Recaf's PotionEffectsHud$EffectEntry:
- show(h): heightAnim -> 1.0 (alpha), widthAnim -> h (row height).
- startRemove() animates both back to 0; isRemoveDone() checks anim
  isDone() instead of a hand-rolled alpha field.
- tick() drops the custom alpha decay and keeps the duration text
  fresh for non-instantaneous effects.
- getTotalWidth() actually measures the text (icon + name + duration
  + padding) so sort-by-width works.
- updateEffect() bumps originalDuration when the new instance has a
  longer remaining duration (stacked refresh).
- refreshDisplayText() delegates to the outer HUD for the infinity
  symbol and roman-numeral amplifier formatting.
- Rename instance -> effectInstance and update render-site reads.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 23:23:01 +08:00
Shirona1337 783273fd5c fix(hud): rewrite KeyBindRow to match obfuscated semantics
The previous KeyBindRow was a hand-written stub that left
displayName/keyName/nameWidth uninitialized, never animated entries
in/out, and had a placeholder getFittingFont that didn't compute a
key width. So module rows rendered as blank zero-width strips.

Rewrite KeyBindRow to mirror the original (per Recaf):
- The constructor calls update(entry), pulls rightAligned from the
  parent HUD and seeds slide/height/alpha animations.
- update() refreshes displayName/keyName/enabled/nameWidth and
  invalidates the cached fitting font when the key text changes.
- startRemove() actually triggers the slide-out, height and alpha
  animations; isRemoveDone() checks heightAnim/alphaAnim.isDone().
- tick() no longer mutates a custom alpha field; animations drive
  visibility.
- getFittingFont() computes a scaled font when the key text exceeds
  the slot width, caches the result, and stores cachedKeyWidth so
  getKeyWidth() returns the right value.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 23:15:11 +08:00
Shirona1337 2f3e8801e7 fix(hud): populate KeyBindRow display fields so module names render
The render path in KeyBindsHud.renderRows draws row.displayName /
row.keyName and lays out rows using row.nameWidth, but the
KeyBindRow constructor (and update()) only assigned name/key,
leaving displayName, keyName and nameWidth at their default null/0.
That's why only the 'Hotkeys' header showed up while every module
row stayed blank with zero width.

Initialize displayName, keyName, nameWidth and widthValue from name
/ key in both the constructor and update().

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 23:02:05 +08:00
Shirona1337 7659ec3bc2 feat: extract bundled cloud assets to config dir on init
Add ZenClient.extractCloudAssets() that copies panel.png, ptr.png,
lie.wav and truth.wav from /assets/zen/cloud_assets/ on the classpath
into ConfigManager.CONFIG_DIR (~/.zen/configs). Existing files are
left untouched so user-replaced assets stick around. Called from
init() right after ConfigManager is constructed, since LieDetector's
TextureUtil/SoundUtil look up these files there.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 22:57:09 +08:00
Shirona1337 b2fc280118 fix(hud): unify enabled/dragging semantics and rendering pipeline
- HudElement: drop the parallel 'visible' field and the isEnabled/
  setEnabled overrides. The dual flag was getting out of sync with
  Module.enabled, so HUD listeners never registered on the event bus
  and onTick/onPacket never fired (PlayerListHud, KeyBindsHud and
  PotionEffectsHud rendered as empty panels). The base Module.enabled
  is now the single source of truth.
- HudElement: rename hudWidth/hudHeight to width/height and let
  Lombok generate getters/setters; expose 'dragging' via @Setter so
  callers don't need a hand-written setDragging.
- ChatScreenPatch: the chat-screen drag hook was reading/writing
  isEnabled/setEnabled when it really meant dragging/setDragging,
  which is why opening the chat would silently disable any HUD you
  had on screen. Switch to isDragging/setDragging.
- Add cloud_assets/ (panel.png, ptr.png, lie.wav, truth.wav)
  needed by LieDetector.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 22:49:54 +08:00
Shirona1337 12d58168fc fix(hud): stop wiping HUD visibility on every tick
HudElement.stopDragging() was clearing the 'visible' flag via
setEnabled(false), but HudManager.onTick calls stopDragging() on
every HUD every tick whenever no screen is open. The result is that
ModuleListHud, KeyBindsHud and every other HUD got disabled one tick
after construction and never rendered.

Make stopDragging() actually stop dragging — it now just flips the
'dragging' flag. Also fix the companion bugs: mousePressed() now sets
'dragging' (not 'visible'), and the 'dragging' field defaults to
false so HUDs are not born mid-drag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 22:14:12 +08:00
Shirona1337 891b7f3745 chore: clean up debug prints and register HUD/intro on event bus
- Register HudManager and a fresh IntroAnimation on the event bus
  during ZenClient bootstrap so HUDs actually tick and the intro
  plays on first launch.
- Strip leftover System.out.println debug breadcrumbs from
  NewClickGui, CategoryPanel, ModuleElement and the unused
  BUILD_TAG print in ModuleElement.
- Drop the redundant 'initialized' static flag and the stray
  NewClickGui instance constructed in the class initializer; the
  Lombok @NonNull null check on render() was already enforced, so
  the hand-written guard goes too.
- Remove the unused NumberSettingElement.sliderX field.
- Replace Module.getBind() with a Lombok @Getter on the field.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 22:06:46 +08:00
Shirona1337 5c8f97bff5 chore: drop unused/backdoor-adjacent util classes
Remove AntiDebug, CallerTracker, GamePathLocator, SignatureUtil,
Unused1 and Unused2 from shit.zen.utils.misc — none are referenced
anywhere in the source tree. Also drop the redundant same-package
Triple import from TripleProvider.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 21:29:05 +08:00
Shirona1337 797f1f3d33 refactor: drop Encryption, fix init order, simplify shutdown
- Remove unused Encryption class (AES wrapper around shit.zen.utils)
  and its construction from ZenClient bootstrap; drop dead TimerPatch
  import.
- Defer ConfigManager.loadAll() and CommandManager.initCommands() so
  configs load only after modules are registered, fixing values that
  were silently discarded.
- Make isOwner() return true so the local user is treated as owner.
- Rename ZenClient.disconnectFromServer() to shutdown() and pin the
  MinecraftPatch close hook to At.Type.HEAD so it runs before the
  game tears down its subsystems.
- README: invite users to file issues / open PRs for missing features.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 21:23:39 +08:00
Shirona1337 38a9137691 refactor: remove unnecessary boxing and rename non-ASCII identifiers
- Drop redundant Integer/Long/Boolean/Float/Double.valueOf(literal)
  calls (~218 sites across 31 files); rely on autoboxing instead.
  One chained Double.valueOf(...).toString() in AimAssist preserved.
- Rename obfuscation residue identifiers using non-ASCII characters
  to readable names:
    * AntiWeb.Phase.{Đ,Ŀ,Ł} -> {IDLE,PLACING,RECYCLING}
    * AutoOffHand.ItemType.{Đ,Ŀ,Ł} -> {SNOWBALL,GAPPLE,NONE}
    * FastUse.UseState.{Đ,Ŀ,Ł,ŧ} -> {IDLE,WAITING,SWAPPING,USING}
    * BlurFactory.BlurType.{Đ,Ŀ,Ł,ŧ} -> {NORMAL,INNER,OUTER,SOLID}
    * Rotation.Đ -> ASSERTIONS_DISABLED
    * ESP.Pair.Đ -> of
    * KeyBindsHud.KeyBindRow.Đ -> update

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 19:43:09 +08:00
Shirona1337 41f3d972b8 refactor: rename Procyon-style locals to readable names
Rename ~2887 unreadable Procyon-decompiler locals/params (f/f2/fN,
n/n2, bl/bl2, nArray, bufferedImage, etc.) across 169 files to
context-aware camelCase identifiers (x, y, width, height, alpha,
color, sensitivity, etc.). Logic, control flow, field/method names
and method signatures (types/arity) are preserved; only local
variable and parameter names changed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 19:21:20 +08:00
Shirona1337 1baa9cb76c add: mapping & original jar, backdoor expose 2026-05-21 16:38:23 +08:00
Shirona1337 a5c7eb20bf add: readme 2026-05-21 15:49:03 +08:00
Shirona1337 157d85aa0f fix: fonts 2026-05-21 15:16:31 +08:00
Ichinomiya Shirona 956a6e515f init 2026-05-21 13:51:00 +08:00