Skip to content

[BUGFIX] 31个bug提交(8高危14中危9低危) #49

Description

@sarkewww

JustARod Bug 报告合集

作者:CrystalNeko
仓库:https://github.com/CSneko/JustARod
整理时间:2026-07-12
共同发现者:sarkewwwReturn0721


目录


🔴 Critical(3 个)

Bug 1: Intex 接口缺失导致模组无法启动

严重度: Critical
文件: src/main/resources/fabric.mod.json:48 + org/cneko/justarod/entity/Intex.java(不存在)
状态: 模组启动立即崩溃 NoClassDefFoundError

fabric.mod.jsonloom:injected_interfaces 中将 Intex 注入到 RavennEntity,但 src/main/java/org/cneko/justarod/entity/Intex.java 文件不存在:

// fabric.mod.json:48
"org/cneko/toneko/common/mod/entities/RavennEntity": [
    "org/cneko/justarod/entity/Pregnant",
    "org/cneko/justarod/entity/Sexual",
    "org/cneko/justarod/entity/Intex"   // ← 文件不存在!
]

修复: 如果不需要,删除第 48 行的 Intex 引用。如果需要,创建接口文件:

// src/main/java/org/cneko/justarod/entity/Intex.java
package org.cneko.justarod.entity;

public interface Intex {
}

Bug 2: ClientConnectionMixin 无差别踢人

严重度: Critical
文件: src/main/java/org/cneko/justarod/mixin/ClientConnectionMixin.java:19-23

任何网络异常(包括瞬态超时、延迟抖动、原版合法异常)都直接关闭连接,甚至调用了 ci.cancel() 阻止原版错误处理:

@Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true)
private void onExceptionCaught(ChannelHandlerContext context, Throwable throwable, CallbackInfo ci) {
    context.close();   // 任何异常都踢
    ci.cancel();       // 连日志都不打
}

影响: 网络波动时所有玩家被强制踢出,且日志为空,管理员完全无法排查。

修复: 移除整个 Mixin,或至少加上异常类型过滤和日志:

@Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true)
private void onExceptionCaught(ChannelHandlerContext context, Throwable throwable, CallbackInfo ci) {
    Justarod.LOGGER.warn("Client connection exception", throwable);
    // 不要无条件取消原版处理,让原版自己决定
}

Bug 3: readPregnantFromNbt Female/Male 缺少 contains → 降级玩家丢失性别

严重度: Critical
文件: src/main/java/org/cneko/justarod/entity/Pregnant.java:282-283
关联 Issue: #48

// 282-283 行
setFemale(nbt.getBoolean("Female"));  // 没有 contains 检查!
setMale(nbt.getBoolean("Male"));      // 没有 contains 检查!

影响: 原版 26.1 降级到 1.21.1 玩家的 NBT 中没有 Female/Male 键 → getBoolean 返回 false → 性别被覆盖为"无" → hasUterus() 返回 false → 无法怀孕。

修复:

if (nbt.contains("Female")) {
    setFemale(nbt.getBoolean("Female"));
}
if (nbt.contains("Male")) {
    setMale(nbt.getBoolean("Male"));
}

🟠 High(5 个)

Bug 4: EntityMixin 每 tick 强制 noClip=false

严重度: High
文件: src/main/java/org/cneko/justarod/mixin/EntityMixin.java:61

坠机系统的 fall tick 循环中,第 61 行每帧强制设置 self.noClip = false

@Inject(method = "tick", at = @At("HEAD"))
private void justARod$fallTick(CallbackInfo ci) {
    if (fallenBy != null) {
        // ...
        self.noClip = false;  // ← 每 tick 重置!同一 tick 内其他 Mixin 读到错误值
        // ...
    }
}

影响:

  1. 同一 tick 内,其他在 tick 之后执行的 Mixin 读到被强制覆盖的 noClip 值
  2. 100 tick 超时后恢复 noClip,但期间所有 noClip 逻辑(旁观者、飞行)全部失效

修复: 建议只在 setFallenBy 时设置一次,不要在 tick 循环中反复强制覆盖。如果确有需要防御其他 mod 改回,加一个 @Inject(method = "setNoClip") 拦截器。


Bug 5: FOREVER_BABY ArrayList 跨线程无同步

严重度: High
文件: src/main/java/org/cneko/justarod/entity/Pregnant.java:46

List<UUID> FOREVER_BABY = new ArrayList<>();  // 静态可变列表,无同步
线程 操作 位置
服务端线程 FOREVER_BABY.add(baby.getUuid()) Pregnant.java:194
客户端渲染线程 FOREVER_BABY.contains(id) EnderDragonRendererMixin.java:34

影响: 并发写入和读取 → ConcurrentModificationException → 客户端崩溃。

修复:

List<UUID> FOREVER_BABY = Collections.synchronizedList(new ArrayList<>());
// 或者在 contains 调用处加 synchronized(FOREVER_BABY)

Bug 6: RavennEntity 完全没有 NBT 持久化

严重度: High
文件: src/main/java/org/cneko/justarod/mixin/RavennEntityMixin.java

整个文件 243 行,定义了 20+ 个 @Unique 字段(pregnant、childrenType、menstruation、sterilization、aids、HPV、hasUterus、PCOS、brithControlling、ovarianCancer、breastCancer、syphilis 等),但:

  • 没有 writePregnantToNbt 注入
  • 没有 readPregnantFromNbt 注入
  • 没有 @InjectwriteCustomDataToNbt / readCustomDataFromNbt

影响: 区块卸载 / 重启 / 传送后,RavennEntity 的所有生理状态全部丢失。相当于这个实体类型的数据根本存不住。

修复: 参照 PlayerMixin.java:846-858 的 NBT 注入模式,在 RavennEntityMixin 中添加:

@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) {
    this.writePregnantToNbt(nbt);
}

@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) {
    this.readPregnantFromNbt(nbt);
}

Bug 7: childrenType 为 null 时保存 NPE

严重度: High
文件: src/main/java/org/cneko/justarod/entity/Pregnant.java:222

nbt.putString("ChildrenType", EntityType.getId(getChildrenType()).toString());

getChildrenType() 对从未怀孕的实体返回 nullPlayerMixin 中初始化为 null,RavennEntityMixin 初始化为 RavennEntity 但可能在其他路径中为 null)→ EntityType.getId(null) → NPE。

影响: 从未怀孕的玩家/实体保存时抛 NPE,可能中断整个保存流程。

修复:

EntityType<?> type = getChildrenType();
if (type != null) {
    nbt.putString("ChildrenType", EntityType.getId(type).toString());
}

Bug 8: CommonPlayerInteractionEvent quirk 迭代遍历错误对象

严重度: High
文件: src/main/java/org/cneko/toneko/common/mod/events/CommonPlayerInteractionEvent.java:116,124

processInteractEventcontext.entity() 提取 INeko 并迭代其 quirks(第 76-82 行):

private static <T extends EventContext> InteractionResult processInteractEvent(T context, ...) {
    INeko neko = null;
    if (context.entity() instanceof INeko n) {
        neko = n;          // ← 始终是目标实体!
    }
    for (Quirk q : neko.getQuirks()) { ... }  // ← 始终迭代目标的 quirks
}

但第 124 行调用时,期望处理的是玩家自己的 quirks

// 第 116 行:处理目标实体 quirks(正确)
InteractionResult targetResult = processInteractEvent(context, ...);  // onNekoInteraction: 目标对自己的反应

// 第 124 行:期望处理玩家 quirks,但实际处理的是目标 quirks(错误!)
InteractionResult playerResult = processInteractEvent(context, ...);  // onInteractionOther: 应该用玩家的 quirks!

影响: 玩家自身的 quirk(CCB、Yuri 等)在交互时完全不被检查。这是"使用百合交配物品不生效"的根因——玩家的 Yuri quirk 从未被调用。

修复: 需要修改 processInteractEvent 使其可以迭代指定实体的 quirks,或者新增一个以 player 为 entity 的 context。


🟡 Medium(14 个)

Bug 9: INeko NickName 读自身而非 NBT

严重度: Medium
文件: src/main/java/org/cneko/toneko/common/mod/entities/INeko.java:236

if (nbt.contains("NickName")){
    this.setNickName(this.getNickName());  // ← 读自身,永远是自己
}

修复:

if (nbt.contains("NickName")){
    this.setNickName(nbt.getString("NickName"));
}

Bug 10: INeko blockedWords 不持久化

严重度: Medium
文件: src/main/java/org/cneko/toneko/common/mod/entities/INeko.java

saveNekoNBTData 中不保存 blockedWordsloadNekoNBTData 中不读取。重启后所有封禁词丢失。


Bug 11: INeko quirks 不持久化

严重度: Medium
文件: src/main/java/org/cneko/toneko/common/mod/entities/INeko.java

saveNekoNBTData 中不保存 quirksloadNekoNBTData 中不读取。重启后 /quirk add yuri 等全部丢失。


Bug 12: CCBQuirk 返回 FAIL 阻断交互

严重度: Medium
文件: src/main/java/org/cneko/justarod/quirks/CCBQuirk.kt:31,33

if (player.bundled > 0) return InteractionResult.FAIL  // 穿束身衣→失败
if (player.getNoMatingPlz() > 0) return InteractionResult.FAIL  // 拒绝交配→失败

这些在 onInteractionOther 中返回 FAIL(消耗操作),但实际上这只是玩家穿了自己的裤子,不应该阻止他对别人的互动。


Bug 13: YuriMatingItem / CCBQuirk 成功后返回 PASS 而非 SUCCESS

严重度: Medium
文件: src/main/java/org/cneko/justarod/item/YuriMatingMatingMatingItem.kt:34
文件: src/main/java/org/cneko/justarod/quirks/CCBQuirk.kt:60

返回 InteractionResult.PASS 导致 XP 分发逻辑(xpHandler)不被触发,经验值丢失。


Bug 14: Rod 死亡必定丢失

严重度: Medium
文件: src/main/java/org/cneko/justarod/event/EntityDeathEvent.java:37 + src/main/java/org/cneko/justarod/event/EntityRespawnEvent.java:17

事件顺序:

  1. AFTER_DEATH 先触发 → setRodInside(ItemStack.EMPTY) 清空旧玩家 Rod(第 37 行)
  2. AFTER_RESPAWN 后触发 → oldPlayer.getRodInside() 读到 EMPTY(第 12 行)

结果:无论什么配置,Rod 必定丢失。

修复: 把清除逻辑移到 AFTER_RESPAWN 之后,或直接删掉 AFTER_DEATH 的清除、让 RESPAWN 复制逻辑正常工作。


Bug 15: MoufletNekoBoss VulnMult 缺少 contains 检查

严重度: Medium
文件: src/main/java/org/cneko/toneko/common/mod/entities/boss/mouflet/MoufletNekoBoss.java:238

if (compound.contains("VulnTicks")) {
    this.vulnerabilityTicks = compound.getInt("VulnTicks");
    this.vulnerabilityMultiplier = compound.getFloat("VulnMult");  // 没检查 contains!
}

旧存档没有 VulnMult 时读到 0 → Boss 免疫伤害。


Bug 16: AmmunitionEntity NBT 读取 5 个字段缺 contains

严重度: Medium
文件: src/main/java/org/cneko/justarod/entity/AmmunitionEntity.java:82-88

initialPosition、velocity、damage、owner、lifetime 全都缺 contains 检查 → 旧存档实体位置变成 (0,0,0)。


Bug 17: Sexual 性欲值逻辑缺口(50~100 + =200)

严重度: Medium
文件: src/main/java/org/cneko/justarod/entity/Sexual.java:25-36

if (getSexualDesire() > 100 && getSexualDesire() < 200) { ... }     // 101~199
else if (getSexualDesire() > 400) { ... }                           // 移除
else if (getSexualDesire() < 50) { ... }                            // 0~49
else if (getSexualDesire() > 200) { ... }                           // 201~∞
else { ... }                                                         // 50~100 + 200
  • 50~100(包含 100)和恰好 200 落入 else 随机分支,与注释"性欲大于100时减小"不符

修复:

if (getSexualDesire() >= 100 && getSexualDesire() < 200) { ... }  // >=100
else if (getSexualDesire() >= 200) { ... }                          // >=200
else if (getSexualDesire() > 400) { ... }
else { ... }  // 仅 <50

Bug 18: CommonChatEventMixin INeko 强制转换无 instanceof

严重度: Medium
文件: src/main/java/org/cneko/justarod/mixin/CommonChatEventMixin.java:43

msg = Messaging.nekoModify(msg, (INeko) sender);  // sender 可能不是 INeko!

sender.getBallMouth() > 0 通过了,但如果 toNeko 的 PlayerEntity 注入未加载,sender 就不是 INeko → ClassCastException。

修复:

if (sender instanceof INeko neko) {
    msg = Messaging.nekoModify(msg, neko);
    msg = Messaging.format(msg, neko, Messaging.getChatPrefixes(neko), ConfigUtil.getChatFormat());
}

Bug 19: LivingEntityMixin miscarry 在护甲减伤前执行

严重度: Medium
文件: src/main/java/org/cneko/justarod/mixin/LivingEntityMixin.java:72

@Inject(method = "damage", at = @At("HEAD")) → 在护甲减伤、无敌帧、Resistance 效果之前就判断 amount >= 7

影响: 原版 7 点伤害经护甲减伤后可能只剩 2 点,但仍触发流产。伤害判断应该基于实际造成伤害后再执行。


Bug 20: PlayerMixin + RavennEntity 新增 Pregnant 字段未实现

严重度: Medium
文件: src/main/java/org/cneko/justarod/mixin/PlayerMixin.java + src/main/java/org/cneko/justarod/mixin/RavennEntityMixin.java

Pregnant 接口后续新增的字段(OvarianClock、UterineThickness、Paronychia、Toxoplasmosis、MenstrualCycleSync 等)在 PlayerMixin 和 RavennEntityMixin 中缺少对应的 @Unique 字段声明。通过 fabric.mod.json 注入接口,但默认方法的数据无处存储。


Bug 21: BDSMable NBT 读取 8 个字段缺 contains

严重度: Medium
文件: src/main/java/org/cneko/justarod/entity/BDSMable.java:112-121

ballMouth、bundled、electricShock、eyePatch、earplug、handcuffed、shackled、noMatingPlz 读取时缺 contains 检查。影响较小(默认值 0 与 getInt 返回值一致),但属于不规范代码。


Bug 22: ServerPlayerMixin.copyFrom 仅复制 2 个字段

严重度: Medium
文件: src/main/java/org/cneko/justarod/mixin/ServerPlayerMixin.java:18-22

player.setSterilization(oldPlayer.isSterilization());
player.setImmune2HPV(oldPlayer.isImmune2HPV());
// 只复制了 2 个!遗漏了 50+ 个字段

影响: 玩家重生后绝育状态和 HPV 免疫保留,但性别、怀孕进度、疾病、BDSM 状态等全部丢失。


🟢 Low(9 个)

Bug 23: JRNetWorkingEvents 吞所有异常

严重度: Low
文件: src/main/java/org/cneko/justarod/event/JRNetWorkingEvents.java:55,97,124

三处 catch (Exception ignored) {} 吞咽所有异常。UUID 解析失败、实体查找失败、NPE 等全部静默。

修复: 至少加日志:

catch (Exception e) {
    Justarod.LOGGER.warn("Failed to process mating request", e);
}

Bug 24: JRScreenBuilders 翻译键拼写错误

严重度: Low
文件: src/main/java/org/cneko/justarod/client/screen/JRScreenBuilders.java:111,117

Text.translatable("misc.toneko.is_or_not.not.not")  // ← .not.not 应该是 .not

修复: 去掉多余的 .not


Bug 25: ServerPlayerMixin slowTick 无上限溢出

严重度: Low
文件: src/main/java/org/cneko/justarod/mixin/ServerPlayerMixin.java:29

slowTick++;  // int 无上限,约 596 小时后溢出为负数

Bug 26: PlayerMixin hasUterus() 缺 @OverRide

严重度: Low
文件: src/main/java/org/cneko/justarod/mixin/PlayerMixin.java:365

hasUterus() 方法缺少 @Override 注解,不影响运行但属于不规范代码。


Bug 27: NekoEnergy 写入 Double 读取 Float

严重度: Low
文件: src/main/java/org/cneko/toneko/common/mod/entities/INeko.java:180,206

// 写入
nbt.putDouble("NekoEnergy", this.getNekoEnergy());   // 行 180:写入 Double
// 读取
this.setNekoEnergy(nbt.getFloat("NekoEnergy"));       // 行 206:读取 Float

存在精度丢失。统一为一种类型。


Bug 28: 攻击 XP 分发是死代码

严重度: Low
文件: src/main/java/org/cneko/toneko/common/mod/events/CommonPlayerInteractionEvent.java:152-159

for (Quirk q : sp.getQuirks()) {
    if (q != null) {
        InteractionResult result = q.onNekoAttack(sp, level, hand, le, hitResult);
        if (result == InteractionResult.SUCCESS) {
            sp.setXpWithOwner(sp.getUUID(), q.getInteractionValue() + sp.getXpWithOwner(sp.getUUID()));
        }
    }
}
return InteractionResult.PASS;  // ← 无论 SUCCESS 还是 PASS,最后都返回 PASS

循环内可能了 XP 分发,但最后总是 return InteractionResult.PASS — 如果某个 quirk 返回 SUCCESS 应该也对外返回 SUCCESS。


Bug 29: Insertable inventoryTick 用 Integer.MIN_VALUE 作 slot

严重度: Low
文件: src/main/java/org/cneko/justarod/entity/Insertable.java:26

item.inventoryTick(stack, entity.getWorld(), entity, Integer.MIN_VALUE, false);

Integer.MIN_VALUE 作为 slot 参数传入,如果物品内部的 tick 逻辑用到 slot 值可能导致未定义行为。


Bug 30: build.gradle 中 lombok/kotlin 用了 implementation

严重度: Low
文件: build.gradle:47-50

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1"
implementation "org.projectlombok:lombok:1.18.30"

这些运行时依赖用了 implementation 而非 modImplementation。在多模组环境中可能导致 classpath 冲突。


Bug 31: PlayerMixin NBT 注入方法在 Kotlin 调用之前

严重度: Low
文件: src/main/java/org/cneko/justarod/mixin/PlayerMixin.java:846-858

writePregnantToNbt 的 NBT 写注入在 Kotlin 生成的 writeCustomDataToNbt 覆盖方法之前执行,可能导致 Kotlin 覆盖方法覆盖掉 Java 写入的内容。


修复优先级建议

优先级 Bug 修复方式
🔴 P0 #1 Intex 缺失 创建 Intex.java 或删除 fabric.mod.json 引用
🔴 P0 #2 ClientConnection 踢人 删除 Mixin
🔴 P0 #3 Female/Male 缺 contains nbt.contains()
🟠 P1 #8 quirk 迭代错误 修改 processInteractEvent 支持指定实体
🟠 P1 #6 RavennEntity NBT 添加 NBT 注入
🟠 P1 #7 childrenType NPE 空值检查
🟠 P1 #5 FOREVER_BABY 跨线程 Collections.synchronizedList
🟡 P2 #14 Rod 死亡丢失 调整事件执行顺序
🟡 P2 #10-11 blockedWords/quirks 持久化 在 save/load 中添加对应 NBT 键

(其实我们也能直接帮你修了)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions