饥饿值支付
PaymentHandler 是 signposts 自己的默认支付处理器,也是「无经济 mod 时」的兜底实现:它不消耗任何货币,而是扣玩家的饥饿值(food level / 饱食度)。经济 mod 若存在,支付逻辑可被 IPaymentHandler 的其他实现整体替换(见 Gollorum 集成)。
支付链路
客户端点击 Atlas 上的 signPost 标记
→ JumpMessage(markerId, paymentHandlerKey)
→ 服务端 JumpMessageHandler
→ SignPostsMod.playerJump(markerId, player, paymentHandlerKey)
├─ 查 paymentHandlers.get(paymentHandlerKey)
├─ MarkerToTileMap 反查路牌坐标 / 读 TileEntity 的 jumpX/Y/Z
└─ if (creative || paymentHandler.pay(player, x, y, z)) → setPositionAndUpdate(...)
支付发生在传送之前,pay 返回 true 才执行 player.setPositionAndUpdate(jumpX, jumpY, jumpZ)。
创意模式免付费
if (player.capabilities.isCreativeMode || paymentHandler.pay(player, (int) jumpX, (int) jumpY, (int) jumpZ)) {
创造模式玩家直接短路,跳过任何 pay 调用。
扣费公式
double distance = Math.pow(Math.abs(player.posX - x), 2)
+ Math.pow(Math.abs(player.posY - y), 2)
+ Math.pow(Math.abs(player.posZ - z), 2);
int distancePerHunger = ConfigurationHandler.getDistancePerPayment(); // 默认 10000
int maximumHunger = ConfigurationHandler.getMaximumPayment(); // 默认 10
int exhaustion = (int) Math.min((Math.floor(distance / distancePerHunger)), maximumHunger);
player.getFoodStats().addStats(-1 * exhaustion, 0.0F);
return true;
| 项 | 值 |
|---|---|
| 距离度量 | 平方距离(各轴差值平方后相加,没有开方) |
| 每点饱食度对应 | distancePerPayment = 10000(平方单位) |
| 换算成直线距离 | sqrt(10000) = 100 格(单向满轴) |
| 单次上限 | maximumPayment = 10 点饱食度(饥饿条半根) |
| 实际扣除 | FoodStats.addStats(-exhaustion, 0.0F),饱和度增量固定 0.0 |
| 返回值 | 恒 true,无论玩家饱食度是否足够 |
需要注意的行为
- 永远不会支付失败。
pay无论扣多少、玩家饿到什么程度都return true,所以不会因付不起而被留在原地。原版addStats对负值只是减去 exhaustion,不会致死。 - 平方距离使远距离传送异常便宜。
maximumPayment默认 10 意味着只要平方距离 ≥ 100000(直线约 316 格),一律只扣 10 点。实际游戏中「超过 316 格」这个门槛很容易达到。 - 只能沿同维度传送。
playerJump不做维度检查,目标由路牌所在维度的MarkerToTileMap决定;但playerJump本身不校验jumpX/jumpY/jumpZ是否在玩家当前维度内。 - 同坐标即失败。
playerJump要求jumpX != 0 && jumpY != 0 && jumpZ != 0三个轴都非 0 才传送,所以刻写在主世界原点(坐标 0 轴)的路牌无法作为传送目标使用。 - 扣费坐标取整。传入
pay的是(int) jumpX, (int) jumpY, (int) jumpZ,距离计算基于取整后的整数坐标。
无权限校验
SignPostsMod.playerJump 与 JumpMessageHandler 中没有任何 OP / 权限等级检查(已 grep canPlayerEdit|CommandSender|permission|opLevel|isOp|ICommand|permissionLevel|getCommandSender,全仓库无匹配)。任何玩家都可以对任意路牌发起传送,费用对所有玩家一致(除创造模式免收)。
IPaymentHandler 接口
public interface IPaymentHandler {
public boolean pay(EntityPlayer player, int x, int y, int z);
}
| 处理器 | 注册键 | 注册条件 |
|---|---|---|
PaymentHandler |
signposts |
preInit 中无条件 addPaymentHandler(new PaymentHandler(), ID) |
GollorumPaymentHandler |
signpost |
仅当 Loader.isModLoaded("signpost") |
处理器键由客户端在 JumpMessage 中附带并由服务端查表,因此默认路径是 signposts(饥饿值)。若 Loader.isModLoaded("signpost") 成立,GollorumEventHandler 会把 Atlas 交互改指向 signpost 键,从而改用 Gollorum 的经济系统。
相关条目
- 配置项 -
distancePerPayment/maximumPayment的默认值与范围 - Gollorum 集成 - 替换支付处理器的可选路径
- 传送目标流程 -
playerJump的前置校验