WorldHandler
服务端:每秒广播下一场雨的时间
基本信息
| 属性 | 值 |
|---|---|
| 路径 | com.github.lunatrius.ingameinfo.handler.WorldHandler |
| 行数 | 32 |
| 注册方 | ServerProxy.init(:22) |
| 事件 | TickEvent.WorldTickEvent |
唯一方法 onWorldTick(:15-31)
@SubscribeEvent
public void onWorldTick(TickEvent.WorldTickEvent event) {
World world = event.world;
if (world.playerEntities.isEmpty() || world.getTotalWorldTime() % 20 != 0) return; // ①
if (event.side == Side.SERVER && event.phase == TickEvent.Phase.END) { // ②
try {
PacketHandler.INSTANCE.sendToDimension(
new MessageNextRain(world.getWorldInfo().getRainTime()),
world.provider.dimensionId); // ③
} catch (Exception ex) {
Reference.logger.error("Failed to get rain!", ex);
}
}
}
| # | 条件 / 动作 |
|---|---|
| ① | 无玩家 或 不是 20 的倍数 → 直接返回 |
| ② | 必须 Side.SERVER 且 Phase.END |
| ③ | sendToDimension 广播到该维度全部玩家 |
两个条件的语义
① 的节流:% 20
world.getTotalWorldTime() 每 tick 递增 1,
% 20 == 0 即每 20 tick 命中一次 = 每 1 秒(20 TPS)。
⚠️ 取模在 side 判定之前执行:
客户端的 WorldTickEvent 也会跑 playerEntities.isEmpty() 与取模,
然后才被 ② 挡掉。逻辑未短路,属于微小浪费(每 tick 一次取模)。
① 的空检查
world.playerEntities.isEmpty() 避免向无人维度广播。
多维度服上只有玩家所在的维度会发。
这是本 mod 唯一的持续网络流量
| 对比 | PlayerHandler | 本类 |
|---|---|---|
| 频率 | 每玩家每次登录 1 次 | 每秒(每有玩家的维度) |
| 范围 | sendTo 单人 |
sendToDimension 整维度 |
| 载荷 | long(8 字节) |
int(4 字节) |
多维度服 P 个有玩家维度: 每秒 P 条消息 × (4 字节 + FML 封包开销)。
⚠️ 客户端本可自行推算:
WorldClient 持有 WorldClient.getWorldInfo(),
getRainTime() 也在其中(虽由服务端分块同步时机决定)。
每秒广播是过度设计,属实际可优化的点。
异常处理
catch (Exception ex) → logger.error("Failed to get rain!", ex)。
失败不重试,等下一秒的 tick 自然再试。
只在服务端注册
ServerProxy(:22)注册。
客户端不注册 —— 虽然方法里有 event.side == Side.SERVER 判定
(说明作者预期它可能在客户端也被调用),
但实际只在服务端注册,该判定是冗余保险。
相关
- MessageNextRain - 发送的消息(id 1)
- PacketHandler - 通道
- ServerProxy - 注册方
- PlayerHandler - 并列的另一个服务端处理器(登录时一次)