major update

This commit is contained in:
2023-03-06 10:06:43 +04:00
parent e84511e1ae
commit cbda5e9974
174 changed files with 7441 additions and 1975 deletions
+212
View File
@@ -0,0 +1,212 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Ragon.Protocol;
namespace Ragon.Server;
public class RagonEntity
{
private static ushort _idGenerator = 100;
public ushort Id { get; private set; }
public ushort Type { get; private set; }
public ushort StaticId { get; private set; }
public ushort AttachId { get; private set; }
public RagonRoomPlayer Owner { get; private set; }
public RagonAuthority Authority { get; private set; }
public RagonPayload Payload { get; private set; }
public RagonEntityState State { get; private set; }
private readonly List<RagonEvent> _bufferedEvents;
public RagonEntity(RagonRoomPlayer owner, ushort type, ushort staticId, ushort attachId, RagonAuthority eventAuthority)
{
Owner = owner;
StaticId = staticId;
Type = type;
AttachId = attachId;
Id = _idGenerator++;
Authority = eventAuthority;
State = new RagonEntityState(this);
Payload = new RagonPayload();
_bufferedEvents = new List<RagonEvent>();
}
public void SetOwner(RagonRoomPlayer owner)
{
Owner = owner;
}
public void RestoreBufferedEvents(RagonRoomPlayer roomPlayer, RagonBuffer writer)
{
foreach (var evnt in _bufferedEvents)
{
writer.Clear();
writer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
writer.WriteUShort(evnt.EventCode);
writer.WriteUShort(evnt.Invoker.Connection.Id);
writer.WriteByte((byte)RagonReplicationMode.Server);
writer.WriteUShort(Id);
evnt.Write(writer);
var sendData = writer.ToArray();
roomPlayer.Connection.Reliable.Send(sendData);
}
}
public void Create()
{
var room = Owner.Room;
var buffer = room.Writer;
buffer.Clear();
buffer.WriteOperation(RagonOperation.CREATE_ENTITY);
buffer.WriteUShort(AttachId);
buffer.WriteUShort(Type);
buffer.WriteUShort(Id);
buffer.WriteUShort(Owner.Connection.Id);
Payload.Write(buffer);
var sendData = buffer.ToArray();
foreach (var player in room.ReadyPlayersList)
player.Connection.Reliable.Send(sendData);
}
public void Destroy()
{
var room = Owner.Room;
var buffer = room.Writer;
buffer.Clear();
buffer.WriteOperation(RagonOperation.DESTROY_ENTITY);
buffer.WriteUShort(Id);
Payload.Write(buffer);
var sendData = buffer.ToArray();
foreach (var player in room.ReadyPlayersList)
player.Connection.Reliable.Send(sendData);
}
public void Snapshot(RagonBuffer buffer)
{
buffer.WriteUShort(Type);
buffer.WriteUShort(Id);
if (StaticId != 0)
buffer.WriteUShort(StaticId);
buffer.WriteUShort(Owner.Connection.Id);
buffer.WriteUShort(Payload.Size);
Payload.Write(buffer);
State.Snapshot(buffer);
}
public void ReplicateEvent(
RagonRoomPlayer caller,
RagonEvent evnt,
RagonReplicationMode eventMode,
RagonRoomPlayer targetPlayer
)
{
var room = Owner.Room;
var buffer = room.Writer;
buffer.Clear();
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
buffer.WriteUShort(evnt.EventCode);
buffer.WriteUShort(caller.Connection.Id);
buffer.WriteByte((byte)eventMode);
buffer.WriteUShort(Id);
evnt.Write(buffer);
var sendData = buffer.ToArray();
targetPlayer.Connection.Reliable.Send(sendData);
}
public void ReplicateEvent(
RagonRoomPlayer caller,
RagonEvent evnt,
RagonReplicationMode eventMode,
RagonTarget targetMode
)
{
if (Authority == RagonAuthority.OwnerOnly &&
Owner.Connection.Id != caller.Connection.Id)
{
Console.WriteLine($"Player have not enough authority for event with Id {evnt.EventCode}");
return;
}
if (eventMode == RagonReplicationMode.Buffered && targetMode != RagonTarget.Owner)
{
_bufferedEvents.Add(evnt);
}
var room = Owner.Room;
var buffer = room.Writer;
buffer.Clear();
buffer.WriteOperation(RagonOperation.REPLICATE_ENTITY_EVENT);
buffer.WriteUShort(evnt.EventCode);
buffer.WriteUShort(caller.Connection.Id);
buffer.WriteByte((byte)eventMode);
buffer.WriteUShort(Id);
evnt.Write(buffer);
var sendData = buffer.ToArray();
switch (targetMode)
{
case RagonTarget.Owner:
{
Owner.Connection.Reliable.Send(sendData);
break;
}
case RagonTarget.ExceptOwner:
{
foreach (var roomPlayer in room.ReadyPlayersList)
{
if (roomPlayer.Connection.Id != Owner.Connection.Id)
roomPlayer.Connection.Reliable.Send(sendData);
}
break;
}
case RagonTarget.ExceptInvoker:
{
foreach (var roomPlayer in room.ReadyPlayersList)
{
if (roomPlayer.Connection.Id != caller.Connection.Id)
roomPlayer.Connection.Reliable.Send(sendData);
}
break;
}
case RagonTarget.All:
{
foreach (var roomPlayer in room.ReadyPlayersList)
roomPlayer.Connection.Reliable.Send(sendData);
break;
}
}
}
}
@@ -0,0 +1,79 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Ragon.Protocol;
namespace Ragon.Server;
public class RagonEntityState
{
private List<RagonProperty> _properties;
private RagonEntity _entity;
public RagonEntityState(RagonEntity entity, int capacity = 10)
{
_entity = entity;
_properties = new List<RagonProperty>(10);
}
public void AddProperty(RagonProperty property)
{
_properties.Add(property);
}
public void Write(RagonBuffer buffer)
{
buffer.WriteUShort(_entity.Id);
foreach (var property in _properties)
{
if (property.IsDirty)
{
buffer.WriteBool(true);
property.Write(buffer);
property.Clear();
continue;
}
buffer.WriteBool(false);
}
}
public void Read(RagonBuffer buffer)
{
foreach (var property in _properties)
{
if (buffer.ReadBool())
property.Read(buffer);
}
}
public void Snapshot(RagonBuffer buffer)
{
foreach (var property in _properties)
{
var hasPayload = property.IsFixed || !property.IsFixed && property.Size > 0;
if (hasPayload)
{
buffer.WriteBool(true);
property.Write(buffer);
continue;
}
buffer.WriteBool(false);
}
}
}
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Ragon.Protocol;
namespace Ragon.Server;
public class RagonEvent
{
public RagonRoomPlayer Invoker { get; private set; }
public ushort EventCode { get; private set; }
public ushort Size => (ushort) _size;
private uint[] _data = new uint[128];
private int _size = 0;
public RagonEvent(
RagonRoomPlayer invoker,
ushort eventCode
)
{
Invoker = invoker;
EventCode = eventCode;
}
public void Read(RagonBuffer buffer)
{
var readOnlySpan = _data.AsSpan();
_size = buffer.Capacity;
buffer.ReadSpan(ref readOnlySpan, _size);
}
public void Write(RagonBuffer buffer)
{
if (_size == 0) return;
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan();
buffer.WriteSpan(ref readOnlySpan, _size);
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Ragon.Protocol;
namespace Ragon.Server;
public class RagonPayload
{
private uint[] _data = new uint[128];
private int _size = 0;
public ushort Size => (ushort) _size;
public void Read(RagonBuffer buffer)
{
var readOnlySpan = _data.AsSpan();
_size = buffer.Capacity;
buffer.ReadSpan(ref readOnlySpan, _size);
}
public void Write(RagonBuffer buffer)
{
if (_size == 0) return;
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan();
buffer.WriteSpan(ref readOnlySpan, _size);
}
}
@@ -0,0 +1,71 @@
/*
* Copyright 2023 Eduard Kargin <kargin.eduard@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.ComponentModel;
using Ragon.Protocol;
namespace Ragon.Server;
public class RagonProperty : RagonPayload
{
public int Size { get; set; }
public bool IsDirty { get; private set; }
public bool IsFixed { get; private set; }
private uint[] _data;
public RagonProperty(int size, bool isFixed)
{
Size = size;
IsFixed = isFixed;
IsDirty = false;
_data = new uint[128];
}
public void Read(RagonBuffer buffer)
{
var readOnlySpan = _data.AsSpan();
if (IsFixed)
{
buffer.ReadSpan(ref readOnlySpan, Size);
}
else
{
Size = (int) buffer.Read();
buffer.ReadSpan(ref readOnlySpan, Size);
}
IsDirty = true;
}
public void Write(RagonBuffer buffer)
{
ReadOnlySpan<uint> readOnlySpan = _data.AsSpan();
buffer.WriteSpan(ref readOnlySpan, Size);
}
public void Clear()
{
IsDirty = false;
}
public void Dump()
{
Console.WriteLine( $"[{Size.ToString("00")}] {string.Join("", _data.Take(8).Reverse().Select(b => Convert.ToString(b, 2).PadLeft(32, '0')))}");
}
}