82 lines
2.8 KiB
C#
82 lines
2.8 KiB
C#
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<PlayerInfo> 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 { /* 异常路径,吞掉二次异常 */ }
|
||
}
|
||
}
|
||
}
|