PlayerHandler
服务端:玩家登录时下发世界种子
基本信息
| 属性 | 值 |
|---|---|
| 路径 | com.github.lunatrius.ingameinfo.handler.PlayerHandler |
| 行数 | 25(handler 包最短) |
| 注册方 | ServerProxy.init(:21) |
| 事件 | PlayerEvent.PlayerLoggedInEvent |
唯一方法 onPlayerLogin(:14-24)
@SubscribeEvent
public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
if (event.player instanceof EntityPlayerMP) {
try {
PacketHandler.INSTANCE.sendTo(
new MessageSeed(event.player.worldObj.getSeed()),
(EntityPlayerMP) event.player);
} catch (Exception ex) {
Reference.logger.error("Failed to send the seed!", ex);
}
}
}
| 步骤 | 说明 |
|---|---|
① instanceof EntityPlayerMP |
排除客户端实体 |
② new MessageSeed(worldObj.getSeed()) |
取该玩家所在世界的种子 |
③ sendTo(msg, player) |
只发给这一个玩家 |
④ catch (Exception) |
失败只记日志 |
关键细节
worldObj 而非 theWorld
用 event.player.worldObj(玩家所在维度的 World),
不是服务器主世界。跨维度时每个维度的种子不同 ——
玩家换维度后会拿到新维度的种子。
⚠️ 但 sendTo 只在登录时发一次(PlayerLoggedInEvent),
换维度不会重新触发。
所以跨维度后 TagWorld 的 seed tag
显示的是登录时那个维度的种子。
为什么不广播
用 sendTo(单个玩家) 而非 sendToDimension,
所以 N 人在线只发 N 条 —— 每玩家每登录 1 次,开销可忽略。
对比 WorldHandler 的每秒全维度广播,
这是本 mod 网络设计里合理的一处。
种子需要网络传输的原因
World.getSeed() 在客户端 WorldClient 上不保证与服务器一致
(客户端世界由服务端分块下发,种子不随区块传输),
所以必须显式下发。
异常处理
catch (Exception ex) 覆盖 sendTo 的所有失败
(含未连接完成的 NetworkRegistry 状态),
logger.error("Failed to send the seed!", ex) 保留堆栈。
⚠️ 失败后不重试 ——
hasSeed 保持 false,TagWorld 的 seed tag
在整个会话内都拿不到值。
只在服务端注册
ServerProxy(:21)注册本类;
客户端不注册 —— 客户端不需要知道种子从哪来,只接收。
相关
- MessageSeed - 发送的消息(id 0)
- PacketHandler - 通道
- ServerProxy - 注册方
- WorldHandler - 并列的另一个服务端处理器(每秒广播)