Files
OpenZen/paste/README.md
T
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

405 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Zen 抄袭 Naven 的源代码证据
本文档基于公开可获取的两个仓库进行**逐行 / 逐字段 / 逐字符串**对比:
- **参考实现(被抄袭方)**:[`Margele/Naven-Modern`](https://github.com/Margele/Naven-Modern)(即 Naven 客户端的简单移植版本)
- **待审项目(疑似抄袭方)**:本仓 OpenZen(Zen 客户端反混淆产物)
> Naven 仓库的包名混淆 `com.heypixel.heypixel.VcX6svVqmeT8.*` 来自 Naven 原作者本人 push 上 GitHub 的状态,不是本文档的混淆操作。Zen 这边的对应文件全部位于 `src/main/java/shit/zen/`。
---
## TL;DR
- **Zen 的"功能模块"几乎全部能在 Naven 中找到一对一对应**:要么直接同名搬运,要么把 Naven 的 `@ModuleInfo(name=...)` 内部名直接拿来当类名(最典型的是 `InventoryManager` —— Naven 的类叫 `InventoryCleaner`,但 `@ModuleInfo(name="InventoryManager")`,Zen 直接以这个内部名命名)。
- **框架层(事件 / 模块 / 设置 / 命令 / 工具)也全套搬运**:`EventBus` 是 Naven `EventManager` 的逐字段重命名;`EventPriority` 沿用 DarkMagician6 EventAPI 的特征数值;`@EventTarget value() default 2` 完全一致;`bind/toggle/config/language` 四条命令的提示串(`"Bound X to Y."`、`"Invalid module."`、`"Usage: .bind <module> [key]"`)一字不差;`ChunkUtil.getLoadedChunks` 连异常文案 `"Stream limit didn't work."` 都照搬。
- **多处遗留"反混淆指纹"**:`RotationUtil` 里那个工具类完全用不到的 `import org.antlr.v4.runtime.misc.OrderedHashSet`;`Stuck` 的魔法数 `+ 1337`;`Projectiles` 模块 RGB `(173, 12, 255)` / `(255, 238, 154)`;`InventoryManager` 的中文字面量 `"点击使用"`;都是 Naven 那边独有的特征。
- **改动方向集中在三件事**:(a)拆模块(把 Naven 的 `HUD` 拆成 `Watermark` + 一堆 `shit.zen.hud.*`);(b)扩写(`Disabler` 在 Naven 的 yaw-only 一段外面包了一整套 Grim/ACA/Themis 子模块);(c)改名(`AttackCrystal → CrystalAura`、`Aura → KillAura`、`Glow → ESP`、`NoJumpDelay → NoDelay`、`InventoryCleaner → InventoryManager`),通常**只换类名不换 Setting 文案**,所以 Setting 字符串成为最稳定的抄袭指纹。
下表是模块级的总览:
| 类别 | Naven 模块 | Zen 对应 | 抄袭程度 |
|------|-----------|---------|---------|
| Combat | `AntiBots` | `combat/AntiBots` | **逐行** |
| Combat | `Aura` (`@ModuleInfo name="KillAura"`) | `combat/KillAura` | **逐行**(最严重) |
| Combat | `AttackCrystal` (`@ModuleInfo name="CrystalAura"`) | `combat/CrystalAura` | **逐行** |
| Combat | `AntiFireball` | `combat/AntiFireball` | **逐行** |
| Combat | `AimAssist` | `misc/AimAssist` | 同名 + 部分重写 |
| Combat | `AutoClicker` | `misc/AutoClicker` | 同名 + 显著扩写 |
| Combat | `Velocity` | `combat/AntiKB` | 仅功能相近,不构成抄袭 |
| Move | `Scaffold` | `movement/Scaffold` | **逐行** + 扩展 |
| Move | `FastWeb` | `movement/FastWeb` | **逐行** |
| Move | `Sprint` | `movement/Sprint` | **逐行** |
| Move | `Stuck` | `player/Stuck` | **逐行** + 扩展 |
| Move | `AutoMLG` | `player/AutoMLG` | 重写 + 触发器抄袭 |
| Move | `SafeWalk` | `misc/SafeWalk` | **逐行**(仅改 Category) |
| Move | `Blink` | `movement/FireballBlink` | 骨架抄袭 + 场景重写 |
| Move | `NoJumpDelay` | `movement/NoDelay` | 改名(Setting label 露馅) |
| Misc | `Disabler` | `exploit/Disabler` | 核心段照搬 + 包装扩展 |
| Misc | `FastPlace` | `exploit/FastPlace` | hook 入口一致,算法换皮 |
| Misc | `AutoTools` | `world/AutoTools` | **逐行翻译** |
| Misc | `Teams` | `world/Teams` | **逐行**(加一个 Mode) |
| Misc | `ChestStealer` | `player/ChestStealer` | 核心判定段照搬 |
| Misc | `InventoryCleaner` (`@ModuleInfo name="InventoryManager"`) | `player/InventoryManager` | **逐行**(含中文字面量) |
| Render | `Glow` | `render/ESP` | 改名 + 扩展 |
| Render | `ChestESP` | `render/ChestESP` | **逐行** |
| Render | `Compass` | `render/Compass` | **逐行** |
| Render | `FullBright` | `render/FullBright` | **逐行**(仅放大范围) |
| Render | `ItemTags` | `render/ItemTags` | 同名空壳 |
| Render | `NameProtect` | `render/NameProtect` | 同算法 + 重写事件路径 |
| Render | `NameTags` | `render/NameTags` | 门面策略类(Scale=0.3/0.01 露馅) |
| Render | `NoHurtCam` | `render/NoHurtCam` | 同名空壳 |
| Render | `Projectile` | `render/Projectiles` | **逐行**(颜色/重力/算法常量全照搬) |
| Render | `HUD` | `render/Watermark` + `shit.zen.hud.*` | 拆模块 + 字段名 |
| 框架 | `EventManager` / `EventTarget` / `Priority` | `EventBus` / `EventTarget` / `EventPriority` | **逐字段** |
| 框架 | `Module` / `ModuleManager` / `Category` | 同名 | **逐行**(setEnabled、toggle 完全一致) |
| 框架 | `Value` / `ValueBuilder` / `*Value` | `Setting` / `*Setting` | **同结构**改名 |
| 框架 | `Command*` + `CommandManager` | `Command*` + `CommandManager` | **逐字符串**(命令名、提示串一致) |
| 框架 | `RotationUtils` / `ChunkUtils` / `BlockUtils` / ... | `RotationUtil` / `ChunkUtil` / `BlockUtil` / ... | **逐行** + 残留特征 import |
---
## 一、Combat 模块
### Zen `combat/AntiBots.java` vs Naven `combat/AntiBots.java`
**对应关系**:直接同名搬运。
**关键证据**:
- 五个静态 map 一一对应:`uuidDisplayNames ↔ suspectNames`、`entityIdDisplayNames ↔ confirmedBotNames`、`uuids ↔ suspectJoinTimes`、`ids ↔ confirmedBotIds`、`respawnTime ↔ playerAddTimes`,全部用 `ConcurrentHashMap` / `HashSet`。
- Setting `"Respawn Time"`:默认 2500、范围 0–10000、步长 100,完全一致。
- 方法 `isBedWarsBot(Entity)` / `isBot(Entity)` 签名和返回路径完全相同。
- **字符串字面量原样保留**:`"Fake Staff Detected! ("`、`"Bot Detected! ("`、`"Bot Removed! ("` 三条全部相同。
- 500 ms 怀疑→确认管线、`ClientboundPlayerInfoUpdatePacket / ClientboundAddPlayerPacket / ClientboundRemoveEntitiesPacket` 三段式处理同构。
### Zen `combat/KillAura.java` vs Naven `combat/Aura.java`
**对应关系**:Naven 类名 `Aura`(`@ModuleInfo(name="KillAura")`)→ Zen 直接以 `KillAura` 命名。**这是抄袭最严重的模块。**
**关键证据**:
- **12 个 BooleanSetting + 9 个 NumberSetting 与 Naven 一一对应**,名字/默认值/范围全套一致:`Attack Player / Attack Invisible / Attack Animals / Attack Mobs / Multi Attack / Prefer Baby / Target HUD / Target ESP / Attack Range(=Aim Range) / APS / Switch Size / FOV / Hurt Time`,默认 `range=5/1–6, aps=10/1–20, switchSize=1/1–5, fov=360/10–360, hurtTime=10/0–10`。
- `switchSize` 的可见性 `() -> !infSwitch.getValue()` 等价 Naven `() -> !infSwitch.getCurrentValue()`。
- `isValidTarget` 的实体类型检查链:`ArmorStand / Invisible / Player+bbWidth<0.5 || isSleeping / (Mob|Slime|Bat|AbstractGolem) / (Animal|Squid) / Villager / isSpectator`——import `Bat, AbstractGolem, Squid, Slime, Villager, ArmorStand` 完全一致。
- 主循环:`isSwitch = switchSize > 1` → `updateTargets()` → `aimingTarget = shouldPreAim/getTarget()` → 记录 `prev/lastRotationData` → `attacks >= switchAttackTimes || distance > 3` 时 round-robin `++index` → `attacks += aps/20f`。
- `getTargets()` 结尾:`possibleTargets.sort(Comparator.comparing(o -> o instanceof EndCrystal ? 0 : 1))`、`subList(0, Math.min(size, switchSize))` 限长、`preferBaby` 的 `removeIf(!isBaby)`,三处写法一对一。
- TargetESP:`200/255F, 0, 0, 60/255F` red / `0, 200/255F, 0, 60/255F` green、`AABB box = entity.getBoundingBox().move(-motionX,-motionY,-motionZ).move(partialTick*motionX,...)`、`RenderSystem.setShader(GameRenderer::getPositionShader)`、`GL_LINE_SMOOTH` 开关顺序完全照搬。
### Zen `combat/CrystalAura.java` vs Naven `combat/AttackCrystal.java`
**对应关系**:Naven 类名 `AttackCrystal`(`@ModuleInfo(name="CrystalAura")`)→ Zen 直接以 `CrystalAura` 命名。
**关键证据**:
- Setting `"Attack on Packet (Danger)"` 字符串、`boolean` 类型、`false` 默认完全一致。
- `onPacket` 7 步序列:收 `ClientboundAddEntityPacket` → `EntityType.END_CRYSTAL` → `new EndCrystal(mc.level, packet.getX/Y/Z())` → `setId(packet.getId())` → 距离阈值 `≤ 4` → `ServerboundMovePlayerPacket.PosRot` + `ServerboundUseItemPacket(MAIN_HAND)` → 暂存→改 rotation→`createAttackPacket(target, false)`→swing→还原。一一对应。
- `onTick` 中 `Optional<Entity> any = StreamSupport.stream(... entitiesForRendering ...).filter(entity instanceof EndCrystal).findAny();` 配合 `≤ 3` 阈值。
- 静态字段 `Entity entity / crystalTarget` 与 `rotations / aimRotation` 双字段同构。
### Zen `combat/AntiFireball.java` vs Naven `misc/AntiFireball.java`
**对应关系**:同名搬运(仅改 Category)。
**关键证据**:
- 流式查找一模一样:`StreamSupport.stream(mc.level.entitiesForRendering().spliterator(), …).filter(entity instanceof Fireball && mc.player.distanceTo(entity) < 6).map(...).findFirst()`,距离阈值 `6` 同。
- 早退 `if (!optional.isPresent()) return;`。
- 两行攻击代码顺序和变量名完全一致:`mc.gameMode.attack(mc.player, fireball); mc.player.swing(InteractionHand.MAIN_HAND);`。
### Zen `misc/AimAssist.java` vs Naven `combat/AimAssist.java`
**对应关系**:同名搬运 + 后续大改写。
**关键证据**:类名同;`getAngleDifference(double, double)` 静态助手同名同实现(`Mth.wrapDegrees(a-b)`);`fov` / `range` 字段语义相同(Setting label `"Fov"` / `"FoV"` 仅大小写差)。
**改动**:算法已大幅重写为 smooth/adaptive 偏移模型,事件接入 `KillAura.isValidTarget(...)`,逐行抄袭已不显著。
### Zen `misc/AutoClicker.java` vs Naven `combat/AutoClicker.java`
**对应关系**:同名搬运 + 显著扩写。
**关键证据**:核心攻击路径相同 —— `mc.options.keyAttack.isDown()` + `mc.hitResult.getType() != BLOCK` + `setMissTime(0)`(Naven 通过 `MinecraftAccessor` mixin,Zen 通过 `ReflectionUtil`) + `KeyMapping.click(mc.options.keyAttack.getKey())`。
**改动**:Zen 加 Left/Right/Both、Method/Key/Mouse、Break Block、CPS Mode 等扩展。
### Zen `combat/AntiKB.java` vs Naven `combat/Velocity.java`
**判定**:功能相近但实现路径完全不同(Zen 是 mode-dispatcher,Naven 是 packet-cancel),**不构成抄袭证据**。
---
## 二、Movement / Player 模块
### Zen `movement/Scaffold.java` vs Naven `move/Scaffold.java`
**对应关系**:同名搬运,框架翻新但核心算法逐句保留。
**关键证据**:
- `ModeSetting("Mode", "Normal", "Telly Bridge", ..., "Keep Y")` 与 Naven `mode.setModes("Normal","Telly Bridge","Keep Y")` 一一对应。
- `renderItemSpoof` 字段名、默认 `true` 一致;`advancedBlockSearch` 字段名原样保留。
- `eagle` / `snap` 的可见性 lambda `() -> mode.is("Normal")` 与 Naven `setVisibility(() -> mode.isCurrentMode("Normal"))` 是相同代码翻译。
- `getPlayerYawRotation` 中随机抖动 `RandomUtils.nextFloat(0.0f, 0.5f) - 0.25f`、yaw `-180.0F`、pitch `82F / 75.5F` 这些 magic 数原样保留。
- **`isOnBlockEdge(float)` 函数体逐字符相同**:`!mc.level.getCollisions(mc.player, mc.player.getBoundingBox().move(0.0,-0.5,0.0).inflate(-x,0.0,-x)).iterator().hasNext()`。
### Zen `movement/FastWeb.java` vs Naven `move/FastWeb.java`
**关键证据**:
- 字段 `playerInWebTick / ticksInWeb`(Naven)→ `lastWebTick / webCount`(Zen)只改名不改语义。
- `onMotion` 中 `playerInWebTick < mc.player.tickCount → ticksInWeb = 0` 的 reset 逻辑完全照搬。
- 阈值 `> 5` 与魔法向量 `new Vec3(0.88, 1.88, 0.88)` **逐字节相同**。
- 无 Setting,行为路径一致。
### Zen `movement/Sprint.java` vs Naven `move/Sprint.java`
**关键证据**:类签名一致,主体只有 `mc.options.toggleSprint().set(false)` + `keySprint` 强按下,PRE 阶段执行。
### Zen `player/Stuck.java` vs Naven `move/Stuck.java`
**关键证据**:
- 字段一一对应(仅重命名):`stage / packet / lastYaw / lastPitch / tryDisable / Queue<ServerboundPongPacket> packets` → `stuckState / capturedPacket / savedYaw / savedPitch / pendingDisable / pongQueue`。
- `setEnabled` 的 `stage==3 → disable`、否则 `tryDisable=true` 三段分支完全保留。
- **神奇位移常数 `mc.player.getX() + 1337` / `getZ() + 1337` 一字不差。**
- `onPacket` 的 `instanceof` 链顺序与分支体一致:`ServerboundMovePlayerPacket → cancel`、`ServerboundPongPacket → offer + cancel`、`ServerboundUseItemPacket || ServerboundPlayerActionPacket → capture + stage=1 + cancel`、`ClientboundPlayerPositionPacket → drain pong + stage=3 + disable`。
### Zen `player/AutoMLG.java` vs Naven `move/AutoMLG.java`
**关键证据**:
- Setting `triggerDistanceSetting = NumberSetting("Fall distance", 3.0f, 1.0f, 10.0f, 0.1f)` 与 Naven `distance = ValueBuilder("Fall Distance").setDefaultFloatValue(3).setFloatStep(0.1f)...` 默认/步进相同。
- `Items.WATER_BUCKET` 在槽 0..9 的扫描写法、`originalSlot = inventory.selected` 切换+还原模式照搬。
- pitch 强制朝下(90°)、useItem MAIN_HAND + swing 流程一致。
**Zen 自加**:Predict Ticks / Solid check / 一个拼写错误 `Recorvey`(typo,反而成为抄袭佐证)。
### Zen `misc/SafeWalk.java` vs Naven `move/SafeWalk.java`
**关键证据**:
- `isOnBlockEdge(float)` 函数体**逐字符相同**(含 `0.3F` 常量、参数 `inset` 是 `sensitivity` 的最小程度改名)。
- `onMotion` 主体一句 `mc.options.keyShift.setDown(mc.player.onGround() && isOnBlockEdge(0.3F))`。
- `onDisable` 复用 `InputConstants.isKeyDown(...) + mc.options.keyShift.setDown` 模式。
**改动**:仅改 Category(MOVEMENT → MISC)。
### Zen `movement/FireballBlink.java` vs Naven `move/Blink.java`
**对应关系**:Naven 通用 `Blink` 被改名为 `FireballBlink` 并特化场景。
**关键证据**:`LinkedBlockingQueue<Packet<?>> + ConcurrentLinkedQueue` 的"扣留发包再 flush"骨架、`flushPackets()` 在 disable 时清队列、监听 `ClientboundSetEntityMotionPacket` 玩家 ID 后入队,与 Naven 的 packet 暂存模型同构。
### Zen `movement/NoDelay.java` vs Naven `move/NoJumpDelay.java`
**关键证据**:
- Setting label `new BooleanSetting("No Jump Delay", true)` **直接抄 Naven 的 `@ModuleInfo(name="NoJumpDelay")`**。
- 字段名 `fastDig` 与开关 label 不符 —— 提示是从其它项目搬来后未对齐。
- 类本身没有事件回调,实际效果由 mixin 完成(同 Naven 的 `LivingEntityAccessor.setNoJumpDelay(0)` 思路)。
---
## 三、Misc / Exploit / Player 模块
### Zen `exploit/Disabler.java` vs Naven `misc/Disabler.java`
**对应关系**:Naven Disabler 的 `duplicateRotPlaceDisabler` 一整段被 Zen 当作 `grimDuplicateRotPlace` 子选项原样搬来,外面包了一整套扩展。
**关键证据**:
- 字段命名完全照搬:`rotated`、`lastPlacedDeltaYaw → lastPlacedYawDiff`、`lastPlacedDeltaPitch → lastPlacedPitchDiff`。
- 算法控制流逐句对应:`hasRotation()` → 算 `deltaYaw = abs(yaw - last)` → `rotated = true` → `ServerboundUseItemOnPacket` 分支 `lastPlacedDeltaYaw = deltaYaw; rotated = false`。
- **魔法常数照抄**:阈值 `deltaYaw > 2`、`xDiff < 0.0001` 完全一致。
- `Logging` BooleanSetting + `log(...)` 函数同名同语义。
**改动**:把生成新 packet 改成 `ReflectionUtil.setYRot/setXRot` 改原 packet;外加 Grim/ACA/Themis 一堆扩展子模块。原始 yaw-only 核心是 Naven 的。
### Zen `exploit/FastPlace.java` vs Naven `misc/FastPlace.java`
**判定**:算法换皮(Zen Delay 计时器,Naven CPS 累加器)但**底层 hook 点 `setRightClickDelay(0)` 完全一致**(Naven 通过 MinecraftAccessor mixin,Zen 通过 ReflectionUtil)。`BlockItem` 判定路径相同。最弱的证据。
### Zen `world/AutoTools.java` vs Naven `misc/AutoTools.java`
**对应关系**:几乎逐行翻译。
**关键证据**:
- 三个 Setting `"Check Sword"=true`、`"Switch Back"=true`、`"Silent"=true` 字符串和默认值全照搬;`Silent` 绑在 `switchBack` 可见性下也保留。
- 状态字段 `originSlot = -1` → `previousSlot = -1` 仅改名。
- `getBestTool` 算法逐行复制:`int slot=0; float dmg=1; for i in 0..9` → `isGodItem/isWeaponItem` 跳过 → `SwordItem instanceof && !(WebBlock)` 例外 → `destroySpeed > 1` 时加 `efficiencyLevel * efficiencyLevel + 1` 附魔加成 → `dmg > 1 ? slot : -1` 返回。
- `onMotion` PRE/POST 切换逻辑同形,`onUpdateHeldItem` 在 MAIN_HAND && originSlot != -1 时用 `e.setItem(...)` 同一句话。
### Zen `world/Teams.java` vs Naven `misc/Teams.java`
**关键证据**:
- `isSameTeam(Entity)` 签名、返回路径、`instanceof Player` 后调 `getTeam(player) / getTeam(mc.player)` 用 `Objects.equals` 比较——完全一致。
- `getTeam(Entity)` 函数 `mc.getConnection().getPlayerInfo(entity.getUUID()) → null 检查 → playerInfo.getTeam().getName()` 逐行对应。
**改动**:加一个 `ModeSetting("Mode", "Color", "Scoreboard")`,`Scoreboard` 分支就是 Naven 原版。
### Zen `player/ChestStealer.java` vs Naven `misc/ChestStealer.java`
**关键证据**:
- 容器标题判定一模一样:`Component.translatable("container.chest")`、`"container.chestDouble"`、`"container.enderchest"`,再 `|| title.equals("Chest")`。
- `Ender Chest` BooleanSetting 默认 `false` 同名搬过来。
- `isWorthStealing` 是 Naven `isItemUseful` 分支级翻译:`ArmorItem → protection vs BestArmorScore`、`SwordItem → damage`、`PickaxeItem / AxeItem / ShovelItem → ToolScore`、`CrossbowItem → score`、`BowItem + PunchBow / PowerBow` 两个变体、`COMPASS → !hasItem`、`WATER_BUCKET/LAVA_BUCKET >= count`、`BlockItem + isPlaceable + maxBlock`、`ARROW + maxArrow`、`FISHING_ROD >= 1`、`SNOWBALL/EGG + maxProjectile`、`ItemNameBlockItem → false` → `isCommonItemUseful`,**分支顺序与返回逻辑完全一致**。
- 容器步进算法同形:`for (slot=0; slot<chestMenu.getRowCount()*9; slot++)` + `handleInventoryMouseClick(containerId, slot, 0, ClickType.QUICK_MOVE, mc.player)`。
- 跨模块耦合:Zen `ChestStealer.isRateLimited()` 给 `InventoryManager` 用,等价 Naven `ChestStealer.isWorking()`(同样 3 tick timer)。
### Zen `player/InventoryManager.java` vs Naven `misc/InventoryCleaner.java`
**对应关系**:Naven 文件叫 `InventoryCleaner` 但 `@ModuleInfo(name="InventoryManager")`,**Zen 直接用这个内部名作为类名**。
**关键证据**:
- Setting 名几乎一比一:`"Offhand Items"`(含 `Golden Apple / Projectile / Fishing Rod / None / Block` 五选)、`"Auto Armor"`、`"Inventory Only"`、`"Throw Items"`、`"Bow Priority"`(含 `Crossbow / Power Bow / Punch Bow`)、`"Max Eggs & Snowballs Size"`、`"Max Block Size"`、`"Sword Slot" / "Axe Slot" / "Pickaxe Slot" / "Bow Slot" / "Water Bucket Slot" / "Ender Pearl Slot" / "Golden Apple Slot" / "Eggs & Snowballs Slot"`——名称、含义、Slot 1..9 范围全套照抄。
- 默认值匹配:`Max Block Size 256, step 64, 64..512`、`Max Eggs & Snowballs 64, 16..256, step 16`、`Max Arrow 256`。
- 静态 getter API 抄得一字不差:`getMaxBlockSize()`、`getMaxProjectileSize()`、`getMaxArrows()`、`getWaterBucketCount()`、`getLavaBucketCount()` 等。
- **中文字符串字面量原样保留**:Zen `itemStack.getDisplayName().getString().contains("点击使用")` 与 Naven 完全相同。这是最硬的抄袭证据之一。
- 反 GuiMove + ContainerClose 逻辑照搬:`onPacket` 中检测 `ServerboundMovePlayerPacket + isMoving → send ContainerClose`,对 `UseItemOnPacket / UseItemPacket / InteractPacket / PlayerActionPacket` 触发 close,分支顺序完全一致。
- `validateSlotConfig` / `checkConfig` 用 `Pair<Boolean, NumberSetting>` 列表 + `HashSet<Integer> usedSlots` 检测槽位冲突,连 `Pair.of` 这种 commons-lang3 的导入选型都一样。
---
## 四、Render 模块
### Zen `render/ESP.java` vs Naven `render/Glow.java`
**对应关系**:Naven `Glow` 改名为 `ESP` 并扩充为 2D 边框 + 血条。Glow 模式下保留原过滤逻辑。
**关键证据**:
- `ModeSetting("Mode", "Glow", "Outlined 2D")` —— "Glow" 模式即对应 Naven 整个 Glow 模块。
- `isGlowing(Entity)` 分支顺序 `Player → Animal → Mob → ItemEntity → Arrow` 与 Naven `shouldGlow` 的 `Player → ItemEntity → Mob → Animal → Arrow` 高度一致,仅重排。
- 字段 `playersSetting / mobsSetting / animalsSetting / itemsSetting / arrowsSetting` 对应 Naven `players / mobs / animals / items / arrows`,名字 + 类型 + 默认值(Players=true,其余 false)一一对应。
### Zen `render/ChestESP.java` vs Naven `render/ChestESP.java`
**关键证据**:
- 静态字段 `chestColor / openedChestColor` 与初始值 `{0,1,0}` / `{1,0,0}` 完全一致。
- `renderBoundingBoxes` 字段名 + `CopyOnWriteArrayList` 类型完全一致;`openedChestPositions` 仅是 Naven `openedChests` 加后缀。
- `onPacket` 中 `ClientboundBlockEventPacket` 的 `block == CHEST || block == TRAPPED_CHEST && B0 == 1 && B1 == 1` 判定与 Naven 同条件同顺序。
- `getChestAabb` / `getChestBox` 内部逻辑一一对应:`hasProperty(ChestBlock.TYPE)` 返回 null、`ChestType.LEFT` 跳过、`SINGLE` 之外用 `getConnectedDirection + min/max`。
- 着色 `RenderSystem.setShaderColor(fArray[0], fArray[1], fArray[2], 0.25f)` 的 alpha = 0.25 与 Naven `0.25F` 相同。
### Zen `render/Compass.java` vs Naven `render/Compass.java`
**关键证据**:
- 两个 BooleanSetting `"Compass Only"`(默认 true)、`"No Player Only"`(默认 true)名字、默认值完全一致。
- 字段 `spawnPosition / renderYaw / renderX / renderZ` 命名完全一致。
- `getSpawnPosition` 使用 `dimensionType().natural() ? getSharedSpawnPos() : null` 逻辑相同。
- **角度公式字面一致**:`Math.toDegrees(Math.atan2(spawn.z - renderZ, spawn.x - renderX)) - 90 - renderYaw`。
- 提前 return 顺序 `compassOnly → hasPlayer/noPlayerOnly → spawnPosition == null` 完全一致。
### Zen `render/FullBright.java` vs Naven `render/FullBright.java`
**关键证据**:唯一 Setting `"Brightness"` 名字、类型、最小值 0 与 Naven 一致;min/max/step 语义相同(仅把 0–1 缩放到 0–100)。
### Zen `render/NameTags.java` vs Naven `render/NameTags.java`
**关键证据**:模块同名、`Category.RENDER`、事件分发 `onRender / onRender2D / onPacket` 多事件订阅模式一致;`NumberSetting("Scale", 0.3, 0.1, 1.0, 0.01)` 的 **默认 0.3、step 0.01 与 Naven 完全相同**,只把 max 从 0.5 放宽到 1.0。共 6 个 Setting 数量与 Naven 同。
**改动**:把真正实现外包给 `NameTagStyle` 策略类("Opal" / "Simple"),多数 Setting 名换成新含义掩饰。`Scale` 设置的默认值/step 露馅。
### Zen `render/Projectiles.java` vs Naven `render/Projectile.java`
**关键证据**:
- 5 个 BooleanSetting **完全同名同默认**:`"Show Arrows"=true / "Show Pearls"=true / "Show Potions"=false / "Show Eggs"=false / "Show Snowballs"=false`。
- 颜色字段一一对应且 **RGB 字面量完全相同**:`ThrownEnderpearl → new Color(173, 12, 255)`、`ThrownEgg → new Color(255, 238, 154)`、`Snowball → new Color(255, 255, 255)`。
- `getProjectileGravity` 五个字面常量完全相同:`Bow/Crossbow → 0.05, Potion → 0.4, FishingRod → 0.15, Trident → 0.015, default → 0.03`。
- `isThrowable` 类型集合 9 个 Item 类型相同顺序。
- `simulateTrajectory` 与 Naven `getPath` 同算法:`1000` 步迭代、空气阻力 `0.99`、起点 `getEyeHeight - 0.1`、`bowPower = (p*p + p*2)/3 * 3`。
- `getProjectileInfos` 中 `showArrows → arrowsColor / showPotions → potionsColor / showPearls → enderPearlColor / showEggs → eggColor / showSnowballs → snowballColor` 顺序完全一致。
- 类名 `BasicProjectileData / EntityArrowData / EntityPotionData → ClassEspColor / ArrowEspColor / PotionEspColor` 是包装了一层的重命名。
### Zen `render/Watermark.java` vs Naven `render/HUD.java`
**对应关系**:Zen 把 Naven 的 `HUD` 模块拆分——`Watermark` 只保留水印部分(`Style: Neverlose / DynamicIsland`),ArrayList / Notification 部分迁去 `shit.zen.hud.*`。模块名 `"Watermark"` 直接源自 Naven 的设置名 `"Water Mark"`。
### 其他同名 / 空壳
- `NameProtect`:同算法(`StringUtils.replace`)+ 重写事件路径,加 `Random` 模式。
- `NoHurtCam`:两边都是空壳(实际功能在 mixin 中由模块名查询触发)。
- `ItemTags`:Zen 端是空壳(13 行)。
---
## 五、框架级抄袭(事件 / 模块 / 设置 / 命令 / 工具 / UI)
### 5.1 事件系统
**对应关系**:Zen `EventBus` = Naven `EventManager`(功能 1:1,DarkMagician6 EventAPI 的同源派生)。
**关键证据**:
- 两个类都用 `Map<Class<? extends Event/EventMarker>, List<...>>` 作为唯一存储,注册时 `computeIfAbsent` + `CopyOnWriteArrayList`,注册完调用 `sortListValue / sortByPriority`;Zen 把内部 `MethodData` 改成 record `ListenerEntry`,字段顺序 `source/target/priority` 完全一致。
- 排序逻辑逐行同形:外层遍历 `PRIORITIES`,内层把 `priority() == priority` 的项追加到新 `CopyOnWriteArrayList`,再 `put` 覆盖原 entry——这是 DarkMagician6 EventAPI 的特有写法。
- **优先级数值/数组顺序完全一致**:`HIGHEST=0, HIGH=1, NORMAL/MEDIUM=2, LOW=3, LOWEST=4` + `PRIORITIES = {HIGHEST, HIGH, NORMAL, LOW, LOWEST}`。Zen 仅把 `MEDIUM` 改名 `NORMAL`,类名 `Priority` 改成 `EventPriority`。
- `@EventTarget` 注解:同样 `@Documented @Target(METHOD) @Retention(RUNTIME)`,**方法签名 `byte value() default 2` 完全相同**。
- `call(...)` 分发:先取 `dataList`,判空,再 `instanceof` 取消类(Naven `EventStoppable.isStopped()`、Zen `AbstractCancellable.isCancelled()`),循环里 `break` 提前退出——分支结构、变量命名节奏完全一致。
### 5.2 Module 框架
**关键证据**:
- `Module.setEnabled(boolean)` 实现完全同构:`if (enabled)` 分支 → `this.enabled = true` → `eventManager.register(this)` → `onEnable()`;`else` 分支 → `this.enabled = false` → `eventManager.unregister(this)` → `onDisable()`。`toggle()` 都写成 `setEnabled(!enabled)`。
- 字段 `name / category / key(keyCode) / enabled` 全部存在,都用 Lombok `@Getter`。
- `ModuleManager.onKey(KeyEvent)`:`@EventTarget` 遍历 `modules`,`if (module.getKey() == e.getKey()/getKeyCode()) module.toggle()`,逻辑完全一致。
- 异常 `ModuleNotFoundException` ↔ `NoSuchModuleException` 是直译。
- `Category` enum 顺序保持 `COMBAT, MOVEMENT, ..., RENDER, ..., MISC`,`fromString` 静态方法的 `equalsIgnoreCase` + 默认返回 `COMBAT` 是 Naven 没有但典型的同源扩展。
### 5.3 设置 / 值系统
**关键证据**:
- 抽象基类 4 个字段一一对应:`name`、`value/currentValue`、`visibility (Supplier<Boolean>)`、子类持有的 `update/onChanged` 回调。
- Naven `Value.isVisible()` 检查 `visibility == null || visibility.get()`;Zen 改名 `SettingVisibility`(仍是 `() -> true` 的 functional interface),构造时 `this.visibility = () -> true`——形状一致。
- `ModeValue / ModeSetting`:都用 `String[]` 存模式列表,都提供"按字符串判断当前模式"的便捷方法(Naven `isCurrentMode`、Zen `is`),`getCurrentMode()` 写成 `values[currentValue]` / `getValue()`。
- `NumberSetting` 字段 `min/max/step` 与 `FloatValue.minValue/maxValue/step` 直接对应;构造参数顺序一致。
### 5.4 命令系统
**关键证据**:
- 命令名、别名一致:`bind / b`、`toggle / t`、`config`、`language`——四条命令的关键字与 Naven 完全相同。
- `Command` 抽象类暴露同样两个抽象方法:`onCommand(String[])` 和 `onTab(String[])`。Naven 用 `@CommandInfo` 注解填字段,Zen 改成构造函数参数,但 `name/aliases` 字段命名一致。
- **提示文案逐字符相同**:`"Bound X to Y."`、`"Unbound X."`、`"Invalid module."`、`"Invalid key."`、`"Usage: .bind <module> [key]"`。
- `onTab` 实现完全相同的一行 stream:`getModules().stream().map(Module::getName).filter(s -> s.toLowerCase().startsWith(args[0].toLowerCase())).toArray(String[]::new)`。
- `CommandManager`:前缀 `.`、匹配后 `cancel/setCancelled`、按空格切分、第一段 toLowerCase 查 `aliasMap`、再用 `System.arraycopy` 切剩余参数——同样结构。
### 5.5 工具类
**关键证据**:
- `ChunkUtil.getLoadedChunks`:与 Naven `ChunkUtils` 几乎逐行相同——`radius = max(2, render distance) + 3`、`min/max ChunkPos`、`Stream.iterate` 的 lambda(`x++ > max.x` 则 `x = min.x; z++`)、**`throw new IllegalStateException("Stream limit didn't work.")`(异常文本完全相同)**、`limit((long) diameter*diameter)`、`filter(hasChunk).map(getChunk).filter(Objects::nonNull)`。
- `BlockUtil`:`canBeClicked(pos)` 返回 `getVoxelShape(pos) != Shapes.empty()`、`getBoundingBox(pos)` 返回 `getVoxelShape(pos).bounds().move(pos)`——同名同实现。
- `RotationUtil` 保留了 Naven 独有的、对工具类而言**非常诡异的 `import org.antlr.v4.runtime.misc.OrderedHashSet`**,并实际使用 `OrderedHashSet<Vec3>`,与 Naven `RotationUtils` 一致。
- "Sensitivity GCD" 公式:Naven `getFixedRotation` 里 `f = sensitivity * 0.6F + 0.2F; gcd = f*f*f*1.2F`。Zen 把它搬到 `Rotation.snapToSensitivity`:`float scaled = sensitivity * 0.6f + 0.2f; float step = scaled*scaled*scaled*1.2f`,数值常量、运算顺序完全相同。
- `diffCalcVector / rotationTo`:都用 `Math.toDegrees(atan2(dz,dx)) - 90.0f` 求 yaw,`-Math.toDegrees(atan2(dy,diffXZ))` 求 pitch,再 `wrapDegrees`——同一公式同一写法。
### 5.6 UI(ClickGui)
**对应关系**:Zen `gui/OldClickGui` + `gui/legacy/*` ≈ Naven `ui/ClickGUI`(视觉风格不同,但同样借助上面 5 个子系统)。
**关键证据**:
- 重写 `Screen` 的同一组生命周期方法。
- `onClose` 调用 `configManager.saveAll()`——与 Naven `ClickGUI` 关闭时通过 `FileManager.save()` 持久化设置的行为对应。
- 按 `Category.values()` 枚举展开面板,构造 `CategoryPanel(x, 20, 140, 20, category)`——20/140 这种典型 GUI 尺寸常数和 Naven 默认布局一致量级。
- `ModuleButton / CategoryPanel / BooleanComponent / ModeComponent / NumberComponent` 的拆分粒度与 Naven 在 `ClickGUI` 单文件内分块渲染时的命名一致。
---
## 总结
OpenZen 的整体架构(事件总线、模块系统、设置系统、命令系统、工具类、ClickGui)几乎完全沿用 Naven 客户端的代码,外加大量同名功能模块。**改动主要集中在重命名、拆分、扩展三件事,核心逻辑、字符串字面量、魔法常数、特征 import 大量保留**——尤其是那个 `RotationUtil` 里完全用不到的 `org.antlr.v4.runtime.misc.OrderedHashSet`、`Stuck` 模块的 `+ 1337`、`Projectiles` 的颜色三元组、`InventoryManager` 的中文 `"点击使用"`、`ChunkUtil` 的 `"Stream limit didn't work."` 异常文案,这些都是无法通过功能重写解释的"抄袭指纹"。
Zen 的反混淆产物在符号层面(类/方法/字段名)经过重新命名,但**字符串字面量层面没有清洗**,这一层是构成抄袭证据最强的源头。