Add networked Fighter3D minigame
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
<AssemblyName>Fighter3D.Core</AssemblyName>
|
||||
<RootNamespace>Fighter3D.Core</RootNamespace>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\Client\Assets\MiniGames\Fighter3D\scripts~\Core\**\*.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Framework.Shared\Framework.Shared.csproj">
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
<AssemblyName>Fighter3D.Server</AssemblyName>
|
||||
<RootNamespace>Fighter3D.Server</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Framework.Shared\Framework.Shared.csproj">
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Fighter3D.Core\Fighter3D.Core.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,102 @@
|
||||
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)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user