feat: add minigame room player service

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ud18010
2026-07-29 12:24:58 +08:00
co-authored by Claude Opus 4.8
parent 053a95b4fb
commit 31afce6882
13 changed files with 1878 additions and 10 deletions
@@ -8,6 +8,9 @@ namespace XWorld.Framework
public int PlayerId;
public string Name;
public bool IsAI;
public int Level;
public int AppearanceType;
public int AvatarId;
}
public sealed class RoomConfig
@@ -11,6 +11,7 @@ namespace XWorld.Framework
{
IAssetLoader Assets { get; }
ILogger Logger { get; }
IRoomPlayerService Players { get; }
void Send(NetMessage message); // 发往服务端(Game 通道)
void Exit(); // 请求退出当前小游戏
}
@@ -83,6 +83,14 @@ namespace XWorld.Framework.Protocol
w.WriteString(p.Name);
w.WriteBool(p.IsAI);
}
w.WriteVarUInt((uint)Players.Count);
foreach (var p in Players)
{
w.WriteVarInt(p.PlayerId);
w.WriteVarInt(p.Level);
w.WriteVarInt(p.AppearanceType);
w.WriteVarInt(p.AvatarId);
}
return w.ToArray();
}
@@ -105,6 +113,24 @@ namespace XWorld.Framework.Protocol
IsAI = r.ReadBool(),
});
}
if (r.HasMore)
{
uint extendedCount = r.ReadVarUInt();
uint count = extendedCount < (uint)m.Players.Count ? extendedCount : (uint)m.Players.Count;
for (uint i = 0; i < extendedCount; i++)
{
int playerId = r.ReadVarInt();
int level = r.ReadVarInt();
int appearanceType = r.ReadVarInt();
int avatarId = r.ReadVarInt();
if (i < count && m.Players[(int)i].PlayerId == playerId)
{
m.Players[(int)i].Level = level;
m.Players[(int)i].AppearanceType = appearanceType;
m.Players[(int)i].AvatarId = avatarId;
}
}
}
return m;
}
}
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
namespace XWorld.Framework
{
public interface IRoomPlayerService
{
IReadOnlyList<PlayerInfo> GetRoomPlayers();
bool TryGetRoomPlayer(int playerId, out PlayerInfo player);
void RequestPlayerInfo(int playerId, Action<PlayerInfo> onLoaded);
}
public sealed class RoomPlayerService : IRoomPlayerService
{
private readonly List<PlayerInfo> _players = new List<PlayerInfo>();
private readonly Dictionary<int, PlayerInfo> _byId = new Dictionary<int, PlayerInfo>();
public void SetRoomPlayers(IEnumerable<PlayerInfo> players)
{
_players.Clear();
_byId.Clear();
if (players == null)
{
return;
}
foreach (PlayerInfo player in players)
{
if (player == null)
{
continue;
}
PlayerInfo copy = Clone(player);
_players.Add(copy);
_byId[copy.PlayerId] = copy;
}
}
public IReadOnlyList<PlayerInfo> GetRoomPlayers()
{
var copy = new List<PlayerInfo>(_players.Count);
for (int i = 0; i < _players.Count; i++)
{
copy.Add(Clone(_players[i]));
}
return copy;
}
public bool TryGetRoomPlayer(int playerId, out PlayerInfo player)
{
if (_byId.TryGetValue(playerId, out PlayerInfo cached))
{
player = Clone(cached);
return true;
}
player = null;
return false;
}
public void RequestPlayerInfo(int playerId, Action<PlayerInfo> onLoaded)
{
TryGetRoomPlayer(playerId, out PlayerInfo player);
onLoaded?.Invoke(player);
}
private static PlayerInfo Clone(PlayerInfo source)
{
return new PlayerInfo
{
PlayerId = source.PlayerId,
Name = source.Name,
IsAI = source.IsAI,
Level = source.Level,
AppearanceType = source.AppearanceType,
AvatarId = source.AvatarId,
};
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b46a69ff45443a48a1dd13fb5a8e3d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: