using System; using System.Collections.Generic; using XWorld.Framework; namespace XWorld.Server.Host { public sealed class Room { public string RoomId { get; } public bool IsActive { get; private set; } public bool FaultedOut { get; private set; } private readonly IGameServerRoom _logic; private readonly ManualClock _clock; private readonly RoomCtx _ctx; private readonly ILogger _logger; private bool _endRequested; public Room(string roomId, IGameServerRoom logic, ManualClock clock, RoomCtx ctx, ILogger logger) { RoomId = roomId; _logic = logic; _clock = clock; _ctx = ctx; _logger = logger; } public RoomEndResult EndResult { get; private set; } // 对外发布用的结算结果:故障房间的 EndResult 不可信(可能是故障前残留),按无结果处理 public RoomEndResult TrustedEndResult => FaultedOut ? null : EndResult; // 由 RoomCtx.EndRoom 回调(或宿主)触发;下一次 tick 末尾或 Start 后据此结束。 // 多次调用以最后一次的 result 为准。 // public:RoomHost 与测试在装配 RoomCtx 的 endRoom 回调时需引用它(跨程序集)。 public void RequestEnd() => RequestEnd(null); public void RequestEnd(RoomEndResult result) { _endRequested = true; EndResult = result; } public void Start(IReadOnlyList players) { try { _logic.OnRoomStart(players, _ctx); IsActive = true; if (_endRequested) End(); // 允许在 OnRoomStart 内即请求结束 } catch (Exception ex) { Fault("OnRoomStart", ex); } } public void Deliver(int playerId, NetMessage message) { if (!IsActive) return; try { _logic.OnMessage(playerId, message); } catch (Exception ex) { Fault("OnMessage", ex); } } public void Tick(float dt) { if (!IsActive) return; _clock.Advance(dt); try { _logic.OnTick(dt); } catch (Exception ex) { Fault("OnTick", ex); return; } if (_endRequested) End(); } public void End() { if (!IsActive) return; IsActive = false; try { _logic.OnRoomEnd(); } catch (Exception ex) { _logger.Error($"room {RoomId} OnRoomEnd 抛异常: {ex.Message}"); } } private void Fault(string where, Exception ex) { FaultedOut = true; _logger.Error($"room {RoomId} 在 {where} 故障: {ex}"); IsActive = false; try { _logic.OnRoomEnd(); } catch { /* 异常路径,吞掉二次异常 */ } } } }