Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using XWorld.Framework;
|
||||
using XWorld.Framework.Protocol;
|
||||
using RPS.Core;
|
||||
|
||||
namespace RPS.Server
|
||||
{
|
||||
public sealed class RpsServerRoom : IGameServerRoom
|
||||
{
|
||||
public const ushort SnapshotOpcode = 1;
|
||||
public const ushort ChoiceOpcode = 1; // 客户端出招消息 opcode
|
||||
|
||||
private readonly RpsLogic _logic = new RpsLogic();
|
||||
private IRoomCtx _ctx;
|
||||
private RpsState _state;
|
||||
private readonly Dictionary<int, int> _seatOf = new Dictionary<int, int>(); // playerId->seat
|
||||
private readonly int[] _pidOfSeat = new int[2]; // seat->playerId(结算用;AI 也有 pid)
|
||||
private bool _ended;
|
||||
|
||||
public void OnRoomStart(IReadOnlyList<PlayerInfo> players, IRoomCtx ctx)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_state = _logic.CreateInitial(new RoomConfig { GameId = "rps", Version = 1, Seed = 1, PlayerCount = players.Count }, ctx.Random);
|
||||
for (int i = 0; i < players.Count && i < 2; i++)
|
||||
{
|
||||
_seatOf[players[i].PlayerId] = i;
|
||||
_pidOfSeat[i] = players[i].PlayerId;
|
||||
_state.IsAi[i] = players[i].IsAI;
|
||||
}
|
||||
Broadcast();
|
||||
}
|
||||
|
||||
public void OnMessage(int playerId, NetMessage message)
|
||||
{
|
||||
if (message.Opcode != ChoiceOpcode) return;
|
||||
if (!_seatOf.TryGetValue(playerId, out int seat)) return;
|
||||
var r = new PacketReader(message.Payload);
|
||||
var choice = (Choice)r.ReadByte();
|
||||
_state = _logic.Step(_state, RpsInput.Choose(seat, choice), _ctx.Random).State;
|
||||
}
|
||||
|
||||
public void OnTick(float dt)
|
||||
{
|
||||
if (_ended) return;
|
||||
// Choosing 阶段:AI 座位等概率出招(不读对手),仅在尚未出招时
|
||||
if (_state.Phase == RpsPhase.Choosing)
|
||||
for (int seat = 0; seat < 2; seat++)
|
||||
if (_state.IsAi[seat] && _state.Choices[seat] == Choice.None)
|
||||
{
|
||||
var c = new[] { Choice.Rock, Choice.Paper, Choice.Scissors }[_ctx.Random.Next(3)];
|
||||
_state = _logic.Step(_state, RpsInput.Choose(seat, c), _ctx.Random).State;
|
||||
}
|
||||
|
||||
var res = _logic.Step(_state, RpsInput.Tick(dt), _ctx.Random);
|
||||
_state = res.State;
|
||||
Broadcast();
|
||||
|
||||
if (_state.Phase == RpsPhase.Finished)
|
||||
{
|
||||
_ended = true;
|
||||
int s0 = _state.Scores[0], s1 = _state.Scores[1];
|
||||
bool draw = _state.Winner == 2;
|
||||
_ctx.Logger.Info($"rps finished, winner seat={_state.Winner}, scores {s0}:{s1}");
|
||||
_ctx.EndRoom(new RoomEndResult
|
||||
{
|
||||
WinnerPlayerId = draw ? 0 : _pidOfSeat[_state.Winner],
|
||||
ResultBlob = Encoding.UTF8.GetBytes(draw ? $"平局 {s0} : {s1}" : $"最终比分 {s0} : {s1}")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void OnRoomEnd() => _ctx.Logger.Info("rps room end");
|
||||
|
||||
private void Broadcast() => _ctx.Broadcast(new NetMessage(SnapshotOpcode, _logic.Encode(_state)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user