103 lines
3.0 KiB
C#
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)
|
|
});
|
|
}
|
|
}
|
|
}
|