Files
Ragon/Ragon.Core/Game/Room.cs
T

169 lines
4.4 KiB
C#
Raw Normal View History

2022-12-16 00:05:46 +04:00
using Ragon.Common;
2022-12-16 23:36:51 +04:00
using Ragon.Core.Time;
2022-12-16 00:05:46 +04:00
namespace Ragon.Core.Game;
2022-12-16 23:36:51 +04:00
public class Room: IAction
2022-12-16 00:05:46 +04:00
{
public string Id { get; }
public RoomInformation Info { get; }
public RoomPlayer Owner { get; set; }
public Dictionary<ushort, RoomPlayer> Players { get; }
public List<RoomPlayer> WaitPlayersList { get; private set; }
public List<RoomPlayer> ReadyPlayersList { get; private set; }
public List<RoomPlayer> PlayerList { get; private set; }
public Dictionary<ushort, Entity> Entities { get; private set; }
public List<Entity> DynamicEntitiesList { get; private set; }
public List<Entity> StaticEntitiesList { get; private set; }
public List<Entity> EntityList { get; private set; }
private HashSet<Entity> _entitiesDirtySet;
private RagonSerializer _writer;
public RagonSerializer Writer => _writer;
2022-12-16 23:36:51 +04:00
public Room(string roomId, RoomInformation info)
2022-12-16 00:05:46 +04:00
{
Id = roomId;
Info = info;
Players = new Dictionary<ushort, RoomPlayer>(info.Max);
WaitPlayersList = new List<RoomPlayer>(info.Max);
ReadyPlayersList = new List<RoomPlayer>(info.Max);
PlayerList = new List<RoomPlayer>(info.Max);
Entities = new Dictionary<ushort, Entity>();
DynamicEntitiesList = new List<Entity>();
StaticEntitiesList = new List<Entity>();
EntityList = new List<Entity>();
_entitiesDirtySet = new HashSet<Entity>();
_writer = new RagonSerializer(512);
}
public void AttachEntity(RoomPlayer newOwner, Entity entity)
{
Entities.Add(entity.Id, entity);
EntityList.Add(entity);
if (entity.StaticId == 0)
DynamicEntitiesList.Add(entity);
else
StaticEntitiesList.Add(entity);
entity.Create();
newOwner.Entities.Add(entity);
}
public void DetachEntity(RoomPlayer currentOwner, Entity entity, byte[] payload)
{
Entities.Remove(entity.Id);
EntityList.Remove(entity);
StaticEntitiesList.Remove(entity);
DynamicEntitiesList.Remove(entity);
_entitiesDirtySet.Remove(entity);
2022-12-16 23:36:51 +04:00
entity.Destroy(payload);
2022-12-16 00:05:46 +04:00
currentOwner.Entities.Remove(entity);
}
public void Tick()
{
var entities = (ushort) _entitiesDirtySet.Count;
if (entities > 0)
{
_writer.Clear();
_writer.WriteOperation(RagonOperation.REPLICATE_ENTITY_STATE);
_writer.WriteUShort(entities);
foreach (var entity in _entitiesDirtySet)
entity.State.Write(_writer);
_entitiesDirtySet.Clear();
var sendData = _writer.ToArray();
foreach (var roomPlayer in ReadyPlayersList)
roomPlayer.Connection.UnreliableChannel.Send(sendData);
}
}
public void AddPlayer(RoomPlayer player)
{
if (Players.Count == 0)
Owner = player;
player.Attach(this);
PlayerList.Add(player);
Players.Add(player.Connection.Id, player);
}
public void RemovePlayer(RoomPlayer roomPlayer)
{
if (Players.Remove(roomPlayer.Connection.Id, out var player))
{
PlayerList.Remove(player);
{
_writer.Clear();
_writer.WriteOperation(RagonOperation.PLAYER_LEAVED);
_writer.WriteString(player.Id);
var entitiesToDelete = player.Entities.DynamicList;
_writer.WriteUShort((ushort) entitiesToDelete.Count);
foreach (var entity in entitiesToDelete)
{
_writer.WriteUShort(entity.Id);
EntityList.Remove(entity);
}
var sendData = _writer.ToArray();
Broadcast(sendData);
}
if (roomPlayer.Connection.Id == Owner.Connection.Id && PlayerList.Count > 0)
{
var nextOwner = PlayerList[0];
Owner = nextOwner;
var entitiesToUpdate = roomPlayer.Entities.StaticList;
_writer.Clear();
_writer.WriteOperation(RagonOperation.OWNERSHIP_CHANGED);
_writer.WriteString(Owner.Id);
_writer.WriteUShort((ushort) entitiesToUpdate.Count);
foreach (var entity in entitiesToUpdate)
{
_writer.WriteUShort(entity.Id);
entity.SetOwner(nextOwner);
nextOwner.Entities.Add(entity);
}
var sendData = _writer.ToArray();
Broadcast(sendData);
}
}
}
public void UpdateReadyPlayerList()
{
ReadyPlayersList = PlayerList.Where(p => p.IsLoaded).ToList();
}
public void Track(Entity entity)
{
_entitiesDirtySet.Add(entity);
}
public void Broadcast(byte[] data)
{
foreach (var readyPlayer in ReadyPlayersList)
readyPlayer.Connection.ReliableChannel.Send(data);
}
}