Files
AIC-Project/Server/games-src/Fighter3D/Fighter3D.Server/FighterServerRoom.cs
T

103 lines
3.0 KiB
C#

using System.Collections.Generic;
using System.Text;
using Fighter3D.Core;
using XWorld.Framework;
using XWorld.Framework.Protocol;
namespace Fighter3D.Server
{
public sealed class FighterServerRoom : IGameServerRoom
{
public const ushort InputOpcode = 1;
public const ushort SnapshotOpcode = 100;
private readonly FighterLogic _logic = new FighterLogic();
private readonly Dictionary<int, int> _seatOfPlayer = new Dictionary<int, int>();
private readonly int[] _playerOfSeat = new int[2];
private IRoomCtx _ctx;
private FighterState _state;
private bool _ended;
public void OnRoomStart(IReadOnlyList<PlayerInfo> players, IRoomCtx ctx)
{
_ctx = ctx;
_state = _logic.CreateInitial(
new RoomConfig { GameId = "fighter3d", Version = 1, Seed = 1, PlayerCount = players.Count },
ctx.Random);
for (int i = 0; i < players.Count && i < 2; i++)
{
_seatOfPlayer[players[i].PlayerId] = i;
_playerOfSeat[i] = players[i].PlayerId;
}
Broadcast();
}
public void OnMessage(int playerId, NetMessage message)
{
if (_ended || message.Opcode != InputOpcode)
return;
if (!_seatOfPlayer.TryGetValue(playerId, out int seat))
return;
try
{
var reader = new PacketReader(message.Payload);
int axis = reader.ReadVarInt();
var buttons = (FighterButtons)reader.ReadByte();
_state = _logic.Step(_state, FighterInput.Controls(seat, axis, buttons), _ctx.Random).State;
}
catch (System.Exception ex)
{
_ctx.Logger.Error($"fighter3d input decode failed: {ex.Message}");
}
}
public void OnTick(float deltaTime)
{
if (_ended)
return;
var result = _logic.Step(_state, FighterInput.Tick(deltaTime), _ctx.Random);
_state = result.State;
Broadcast();
if (_state.Phase == FighterPhase.Finished)
EndRoomOnce();
}
public void OnRoomEnd()
{
_ctx?.Logger.Info("fighter3d room end");
}
private void Broadcast()
{
_ctx.Broadcast(new NetMessage(SnapshotOpcode, _logic.Encode(_state)));
}
private void EndRoomOnce()
{
if (_ended)
return;
_ended = true;
int winnerPid = _state.WinnerSeat >= 0 && _state.WinnerSeat < 2
? _playerOfSeat[_state.WinnerSeat]
: 0;
string text = _state.WinnerSeat == 2
? "Fighter3D draw"
: $"Fighter3D winner seat {_state.WinnerSeat}";
_ctx.EndRoom(new RoomEndResult
{
WinnerPlayerId = winnerPid,
ResultBlob = Encoding.UTF8.GetBytes(text)
});
}
}
}