Skip to content
KokuuWorkPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DeathBack

一个面向 Arclight 混合端(Forge + Bukkit)的轻量补丁插件:在死亡时把死亡坐标补写进 CMI, 让玩家继续用原生的 /back 就能回到死亡点。

它不新增任何命令,不接管 /back,不做任何传送逻辑 —— 只把 CMI 该拿到的死亡点交给 CMI。

它解决什么问题

在 Arclight 混合端上,CMI 的 /back 在死亡场景下会失效,玩家死后提示「没有保存的死亡地点」, 但普通的 tp / home / warp 之后的 /back 却完全正常。

根本原因(已从字节码层面证实)

CMI 的 UserEvents.onPlayerDeath(PlayerDeathEvent) 逻辑如下:

user.setDeathLoc(new CMILocation(player.getLocation()));          // 无条件写 → /dback 用

if (player.hasPermission("cmi.command.back.ondeath")) {            // ← 权限门槛!
    user.setLastTeleportLocation(player.getLocation(), false);     // → /back 用
    user.setBungeeBackLocation(null);
}
user.addForDelayedSave();

注意两点:

  1. /back 读的是 LastTeleportLocation,而它在死亡路径下只在玩家拥有 cmi.command.back.ondeath 权限时才会被写入。服务器 default 组通常只给了 cmi.command.back,缺这一条 → 死亡后 /back 永远无效。
  2. 普通传送(tp/home/warp)走的是另一条链路 UserEvents.teleportBack(PlayerTeleportEvent), 那条没有权限门槛,所以一直是好的 —— 这正是「唯独死亡不行」的原因。

此外,在 Arclight 上,深度介入死亡流程的 Forge 模组(如 Corpse 尸体模组)还可能干扰 Bukkit PlayerDeathEvent 的桥接,导致 CMI 根本收不到死亡事件。

两种解法

方案 做法 说明
正统(推荐先做) lp group default permission set cmi.command.back.ondeath true 给玩家补上权限,CMI 原生逻辑即恢复正常
兜底(本插件) 装上 DeathBack 绕过权限门槛直接补写,并能兜住「死亡事件被吞」的极端情况

两者可以同时使用:权限是正统解法,插件是保险层。

功能

  • 不注册任何命令,纯被动监听:死亡时把坐标写进 CMI 的 CMIUser
  • 写入两步,与 CMI 原生 onPlayerDeath 完全一致:
    • setDeathLoc(new CMILocation(loc)) → 供 /dback 使用
    • setLastTeleportLocation(loc, false) → 供 /back 使用
  • 三重数据源,确保拿得到死亡坐标:
    1. PlayerDeathEvent
    2. EntityDeathEvent
    3. corpse:corpse 尸体实体生成(EntitySpawnEvent)—— 兜底,即使前两个事件被吞也能读到
  • 同一玩家 3 秒内只写一次,避免重复事件把坐标覆盖成重生点
  • 全部通过反射调用 CMI,不依赖 CMI 的编译期 API

兼容性

项目 版本
服务端 Arclight(Forge + Bukkit)1.20.1,Forge 47.4.20
CMI 9.7.12.3 与 9.8.10.3 均已逐一反汇编核对,反射接口完全一致
CMILib 1.5.5.0 / 1.6.0.1
JDK 17

包含的 Arclight 适配:mod 实体在 Bukkit 侧被包装为 io.izzel.arclight.common.mod.server.entity.ArclightModEntity, 需先调 getHandle() 取出 NMS 原始实体,才能反射到 CorpseEntity.getCorpseUUID()。

安全落点

不需要插件操心 —— /back 走的是 CMI 的统一传送通道 TeleportHandler.teleportPlayer(player, loc, CMITeleportType.Back), 该通道内置:

  • getSafeLocation / getSafeTeleportationLocation —— 自动寻找安全落脚点
  • isEmptySpaceForPlayer —— 检测落脚位置是否被占据
  • needToFly —— 需要时自动开启飞行
  • setTeleportInvulnerability —— 传送后短暂无敌
  • dangerousTp —— 危险传送点记录

所以即使死亡点在岩浆里,是否安全、要不要挪位,全部由 CMI 自己判断。 本插件只负责「把坐标交给 CMI」,职责边界清晰。

安装

  1. 前往 Releases 下载 DeathBack-1.1.0.jar (或自行用 Maven 构建)
  2. 放入服务端 plugins/ 目录
  3. 重启服务器

无需任何配置,无需给玩家加权限。

验证

玩家死亡后,控制台应出现:

[DeathBack] 已补写 CMI 死亡点 <玩家名> @ <世界> x,y,z(来源:PlayerDeathEvent)

之后玩家输入 /back 即可回到死亡点。

构建

需要 JDK 17 + Maven:

mvn clean package

产物在 target/DeathBack-1.1.0.jar。

实测记录

在 Arclight 1.20.1 + CMI 9.8.10.3 的完整副本服务端上验证,全部通过:

项目 结果
直调写入 DeathLoc 与 /back 目标均写入,回读坐标精确一致
3 秒防重 连续写入不同坐标,旧值未被覆盖
非玩家死亡事件 监听器正确忽略,不产生误写入
尸体兜底链路 summon corpse:corpse 时实时读出主人 UUID

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages