会话与在线状态检测

基本信息

属性 值
主类 com.sintinium.oauth.login.LoginUtil
作用对象 net.minecraft.client.Minecraft#session(字段名 field_71449_j)
在线判定 Mojang MinecraftSessionService.hasJoinedServer
缓存窗口 10 秒

功能

两个职责:

  1. 在线判定 —— 多人游戏界面打开时实时检测当前 Session 是否仍被 Mojang 接受。
  2. Session 写入 —— Microsoft 登录完成后,把新 Session 反射写回 Minecraft.session,并主动触发一次在线判定刷新缓存。

在线状态判定

入口

  • GuiEventHandler.multiplayerScreenOpen 在按钮添加后启一条新线程调用 LoginUtil.isOnline()
  • 根据返回值通过 TextWidget.setText/setColor 切换显示文字与颜色

判定逻辑(isOnline())

if (!needsRefresh && now - lastCheck < 10s) return wasOnline
needsRefresh = false
lastCheck = System.currentTimeMillis()
sessionService.joinServer(uuid, session.token, randomUuid())
return sessionService.hasJoinedServer(uuid, randomUuid).isComplete()

任一异常(典型 AuthenticationException)→ wasOnline = false; return false。

视觉表现

返回值 文字 颜色
true Status: online 0x55FF55(浅绿)
false Status: offline 0xFF5555(浅红)
初次调用 Status: loading 默认白色 0xFFFFFF

注意:Status: loading 是 TextWidget 初始文本,仅在 GuiEventHandler.multiplayerScreenOpen 启动判定线程之前显示;线程结束后即被替换。

Session 写入

loginMs(MinecraftProfile profile)

把 Microsoft 链路拿到的 MinecraftProfile 包装为 net.minecraft.util.Session(Session.Type.MOJANG)然后调用 setSession(...)。accessToken 直接作为 Session.token 写入。

setSession(Session session)

  • 设 needsRefresh = true 并立即 updateOnlineStatus(),避免返回旧缓存
  • 通过 cpw.mods.fml.relauncher.ReflectionHelper.findField(Minecraft.class, "field_71449_j", "session") 定位 Session 字段
  • field.setAccessible(true) 后 field.set(Minecraft.getMinecraft(), session)
  • 失败时只 e.printStackTrace(),不通知用户

状态机

字段 含义
needsRefresh = true 下次 isOnline() 必须重算,不走缓存
needsRefresh = false 可走 10 秒缓存
wasOnline 上次真实在线判定的结果
lastCheck 上次真实判定的系统毫秒时间戳

触发刷新

  • 多人界面打开 → 自动刷新
  • setSession(...) 完成后 → 强制刷新
  • 缓存命中窗口 = 10 秒

已知限制

  • joinServer 与 hasJoinedServer 各用不同的随机 UUID(一个用 Session.func_148256_e(),一个 UUID.randomUUID())—— 调用顺序与 Mojang 标准实现一致,但每次按钮开启多人界面都会向 sessionserver.mojang.com 发起两次请求
  • 缓存命中窗口固定 10 秒,强行按按钮刷新需要 10 秒后才生效

相关条目