Files
Ragon/Ragon/Sources/Entity/Entity.cs
T

249 lines
6.8 KiB
C#
Raw Normal View History

2022-08-25 23:12:33 +04:00
using System;
2022-09-06 22:39:52 +04:00
using System.Collections.Generic;
2022-10-16 16:22:27 +04:00
using NLog;
using Ragon.Common;
2022-04-24 09:05:15 +04:00
namespace Ragon.Core;
public class Entity
{
2022-10-16 16:22:27 +04:00
private ILogger _logger = LogManager.GetCurrentClassLogger();
private GameRoom _room;
2022-08-13 18:54:02 +04:00
private static ushort _idGenerator = 0;
public ushort EntityId { get; private set; }
public ushort StaticId { get; private set; }
2022-05-08 00:40:11 +04:00
public ushort EntityType { get; private set; }
2022-08-14 12:36:12 +04:00
public ushort OwnerId { get; private set; }
2022-10-16 18:00:32 +04:00
public byte[] Payload { get; private set; }
public RagonAuthority Authority { get; private set; }
2022-10-16 16:22:27 +04:00
private List<EntityProperty> _properties;
private List<EntityEvent> _bufferedEvents;
2022-09-06 22:39:52 +04:00
2022-10-16 16:22:27 +04:00
public Entity(GameRoom room, ushort ownerId, ushort entityType, ushort staticId, RagonAuthority eventAuthority)
2022-04-24 09:05:15 +04:00
{
OwnerId = ownerId;
2022-07-13 07:56:44 +04:00
StaticId = staticId;
2022-05-08 00:40:11 +04:00
EntityType = entityType;
2022-04-24 09:05:15 +04:00
EntityId = _idGenerator++;
2022-08-25 23:12:33 +04:00
Payload = Array.Empty<byte>();
Authority = eventAuthority;
2022-10-16 16:22:27 +04:00
_room = room;
_properties = new List<EntityProperty>();
_bufferedEvents = new List<EntityEvent>();
}
public void SetPayload(byte[] payload)
{
Payload = payload;
}
public void SetOwner(ushort ownerId)
{
OwnerId = ownerId;
2022-04-24 09:05:15 +04:00
}
2022-09-04 14:43:17 +04:00
2022-10-16 16:22:27 +04:00
public void AddProperty(EntityProperty property)
{
_properties.Add(property);
}
2022-10-16 18:00:32 +04:00
2022-10-16 16:22:27 +04:00
public void ReplicateEvent(ushort peerId, ushort eventId, ReadOnlySpan<byte> payload, RagonReplicationMode eventMode, RagonTarget targetMode)
{
if (Authority == RagonAuthority.OwnerOnly && OwnerId != peerId)
{
_logger.Warn($"Player have not enought authority for event with Id {eventId}");
return;
}
if (eventMode == RagonReplicationMode.Buffered && targetMode != RagonTarget.Owner)
{
var bufferedEvent = new EntityEvent()
{
EventData = payload.ToArray(),
Target = targetMode,
EventId = eventId,
2022-10-16 17:14:32 +04:00
PeerId = peerId,
2022-10-16 16:22:27 +04:00
};
_bufferedEvents.Add(bufferedEvent);
}
var serializer = _room.GetSharedSerializer();
serializer.Clear();
serializer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
serializer.WriteUShort(eventId);
serializer.WriteUShort(peerId);
serializer.WriteByte((byte) eventMode);
serializer.WriteUShort(EntityId);
serializer.WriteData(ref payload);
var sendData = serializer.ToArray();
Send(targetMode, sendData);
}
2022-10-16 17:14:32 +04:00
public void ReadState(uint peerId, RagonSerializer serializer)
2022-10-16 16:22:27 +04:00
{
if (OwnerId != peerId)
{
_logger.Warn($"Not owner can't change properties of object {EntityId}");
return;
}
for (var i = 0; i < _properties.Count; i++)
{
if (serializer.ReadBool())
{
var property = _properties[i];
var size = property.Size;
if (!property.IsFixed)
size = serializer.ReadUShort();
if (size > property.Capacity)
{
_logger.Warn($"Property {i} payload too large, size: {size}");
continue;
}
2022-10-02 16:00:34 +04:00
2022-10-16 16:22:27 +04:00
var propertyPayload = serializer.ReadData(size);
property.Write(ref propertyPayload);
property.Size = size;
}
}
}
public void WriteProperties(RagonSerializer serializer)
2022-09-04 14:43:17 +04:00
{
serializer.WriteUShort(EntityId);
2022-10-16 16:22:27 +04:00
for (int propertyIndex = 0; propertyIndex < _properties.Count; propertyIndex++)
2022-09-04 14:43:17 +04:00
{
2022-10-16 16:22:27 +04:00
var property = _properties[propertyIndex];
2022-09-04 14:43:17 +04:00
if (property.IsDirty)
{
serializer.WriteBool(true);
var span = serializer.GetWritableData(property.Size);
var data = property.Read();
data.CopyTo(span);
property.Clear();
}
else
{
serializer.WriteBool(false);
}
}
}
2022-10-16 16:22:27 +04:00
public void WriteSnapshot(RagonSerializer serializer)
2022-09-04 14:43:17 +04:00
{
2022-10-16 16:22:27 +04:00
for (int propertyIndex = 0; propertyIndex < _properties.Count; propertyIndex++)
2022-09-04 14:43:17 +04:00
{
2022-10-16 16:22:27 +04:00
var property = _properties[propertyIndex];
2022-09-04 14:43:17 +04:00
var hasPayload = property.IsFixed || property.Size > 0 && !property.IsFixed;
if (hasPayload)
{
serializer.WriteBool(true);
var span = serializer.GetWritableData(property.Size);
var data = property.Read();
data.CopyTo(span);
}
else
{
serializer.WriteBool(false);
}
}
}
2022-10-16 16:22:27 +04:00
public void RestoreBufferedEvents(ushort peerId)
{
var serializer = _room.GetSharedSerializer();
foreach (var bufferedEvent in _bufferedEvents)
{
serializer.Clear();
serializer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
serializer.WriteUShort(bufferedEvent.EventId);
2022-10-16 17:14:32 +04:00
serializer.WriteUShort(bufferedEvent.PeerId);
2022-10-16 16:22:27 +04:00
serializer.WriteByte((byte) RagonReplicationMode.Server);
serializer.WriteUShort(EntityId);
ReadOnlySpan<byte> data = bufferedEvent.EventData.AsSpan();
serializer.WriteData(ref data);
var sendData = serializer.ToArray();
2022-10-16 17:14:32 +04:00
_room.Send(peerId, sendData, DeliveryType.Reliable);
2022-10-16 16:22:27 +04:00
}
}
2022-10-16 17:14:32 +04:00
public void Create()
2022-10-16 16:22:27 +04:00
{
var serializer = _room.GetSharedSerializer();
serializer.Clear();
serializer.WriteOperation(RagonOperation.CREATE_ENTITY);
serializer.WriteUShort(EntityType);
serializer.WriteUShort(EntityId);
serializer.WriteUShort(OwnerId);
ReadOnlySpan<byte> entityPayload = Payload.AsSpan();
serializer.WriteUShort((ushort) entityPayload.Length);
serializer.WriteData(ref entityPayload);
var sendData = serializer.ToArray();
_room.BroadcastToReady(sendData, DeliveryType.Reliable);
}
2022-10-16 17:14:32 +04:00
public void Destroy(ReadOnlySpan<byte> payload)
2022-10-16 16:22:27 +04:00
{
var serializer = _room.GetSharedSerializer();
2022-10-24 22:19:50 +04:00
2022-10-16 16:22:27 +04:00
serializer.Clear();
serializer.WriteOperation(RagonOperation.DESTROY_ENTITY);
serializer.WriteInt(EntityId);
serializer.WriteUShort((ushort) payload.Length);
serializer.WriteData(ref payload);
var sendData = serializer.ToArray();
_room.BroadcastToReady(sendData, DeliveryType.Reliable);
}
void Send(RagonTarget targetMode, byte[] sendData)
{
switch (targetMode)
{
case RagonTarget.Owner:
{
_room.Send(OwnerId, sendData, DeliveryType.Reliable);
break;
}
case RagonTarget.ExceptOwner:
{
_room.BroadcastToReady(sendData, new [] { OwnerId }, DeliveryType.Reliable);
break;
}
case RagonTarget.All:
{
_room.BroadcastToReady(sendData, DeliveryType.Reliable);
break;
}
}
}
2022-10-22 21:34:35 +04:00
public void ProcessEvent(Player player, RagonSerializer reader)
{
var eventId = reader.ReadUShort();
var eventMode = (RagonReplicationMode) reader.ReadByte();
var targetMode = (RagonTarget) reader.ReadByte();
var payloadData = reader.ReadData(reader.Size);
2022-10-24 22:19:50 +04:00
Span<byte> payloadRaw = stackalloc byte[payloadData.Length];
2022-10-22 21:34:35 +04:00
ReadOnlySpan<byte> payload = payloadRaw;
payloadData.CopyTo(payloadRaw);
if (_room.Plugin.InternalHandle(player.PeerId, EntityId, eventId, ref payload))
return;
ReplicateEvent(player.PeerId, eventId, payload, eventMode, targetMode);
}
2022-04-24 09:05:15 +04:00
}