线程与资源生命周期
地图、队伍和玩家是服务器线程管理的可变对象。文件或 HTTP 可以在后台处理,但操作这些对象时,需要回到服务器线程。
后台任务携带什么
开始后台工作之前,复制需要的 UUID、数值和不可变集合。不要把实时 ServerTeam 或其内部映射直接交给异步编码器。
回调返回后使用服务器执行器:
future.thenAccept(result -> server.execute(() -> {
applyResult(result);
}));
这是调用结构示意:future 为已有异步任务,server 为发起任务的服务器,applyResult 是业务方法。实际应用时还应确认原地图仍存在、比赛仍是同一场、请求结果仍然有效。
避免旧结果覆盖新比赛
HTTP 请求可能在地图重置后才完成。可以给每场比赛或每次加载分配递增编号,发起请求时捕获编号,回调时比对,不匹配就丢弃旧结果。
只检查地图对象引用并不总够用,因为同一个地图实例会被复用于下一场比赛。
重置与销毁
重置比赛保留区域、队伍定义和配置,清理比分、回合计时器与比赛临时状态。销毁地图则还要解除事件监听、释放自建线程或连接,并撤销长期关联。
CapabilityMap.remove() 管理能力移除。unregisterAllFromBus() 只解除监听,不能替代组件自己的资源释放。MapTeams.shutdown(Scoreboard) 用于彻底关闭,而不是每轮初始化。
发布事件前后的状态
可取消事件通常位于操作提交前,例如开始和清理。先遵守取消结果,再执行不可回退的状态变更。
胜利通知则应在本场开始状态已关闭后发布,同时保留监听器需要的比分与名单。地图每 tick 检查胜利条件,关闭状态可以避免重复通知。具体实现见一局胜负。