This commit is contained in:
2025-01-18 17:30:03 +03:00
parent edf90b39c4
commit 2f919e4fd8
45 changed files with 1403 additions and 466 deletions
@@ -38,7 +38,7 @@ internal class AuthorizeSuccessHandler: IHandler
var playerName = reader.ReadString();
var playerPayload = reader.ReadString();
_client.SetStatus(RagonStatus.LOBBY);
_client.UpdateState(RagonState.LOBBY);
_listenerList.OnAuthorizationSuccess(playerId, playerName, playerPayload);
}
}
@@ -42,16 +42,15 @@ internal class JoinSuccessHandler : IHandler
private readonly RagonListenerList _listenerList;
private readonly RagonPlayerCache _playerCache;
private readonly RagonClient _client;
private readonly RagonRoom _room;
public JoinSuccessHandler(
RagonClient client,
RagonListenerList listenerList,
RagonPlayerCache playerCache
RagonRoom room
)
{
_client = client;
_listenerList = listenerList;
_playerCache = playerCache;
_room = room;
}
public void Handle(RagonStream reader)
@@ -59,17 +58,14 @@ internal class JoinSuccessHandler : IHandler
var roomId = reader.ReadString();
var min = reader.ReadUShort();
var max = reader.ReadUShort();
var sceneName = reader.ReadString();
var localId = reader.ReadString();
var ownerId = reader.ReadString();
var roomInfo = new RoomParameters(roomId, localId, ownerId, min, max);
_playerCache.SetOwnerAndLocal(ownerId, localId);
var roomInfo = new RoomParameters(roomId, localId, ownerId, min, max);
var room = new RagonRoom(_client, _playerCache, roomInfo);
_room.Reset(roomInfo);
_room.UserData.Read(reader);
room.UserData.Read(reader);
var playersCount = reader.ReadUShort();
RagonLog.Trace("Players: " + playersCount);
for (var i = 0; i < playersCount; i++)
@@ -79,15 +75,14 @@ internal class JoinSuccessHandler : IHandler
var playerName = reader.ReadString();
var player = _playerCache.AddPlayer(playerPeerId, playerId, playerName);
player.UserData.Read(reader);
RagonLog.Trace($"Player {playerPeerId} - {playerId} - {playerName}");
}
_client.AssignRoom(room);
_client.SetStatus(RagonStatus.ROOM);
_client.UpdateState(RagonState.ROOM);
_listenerList.OnJoined();
}
}
@@ -35,6 +35,7 @@ internal class LeaveRoomHandler : IHandler
public void Handle(RagonStream reader)
{
_listenerList.OnLeft();
_client.Room.Cleanup();
_client.Room.Clear();
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2023-2024 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.Client;
internal class RoomDataHandler: IHandler
{
private readonly RagonListenerList _listeners;
private readonly RagonPlayerCache _playerCache;
public RoomDataHandler(
RagonPlayerCache playerCache,
RagonListenerList listeners)
{
_playerCache = playerCache;
_listeners = listeners;
}
public void Handle(RagonStream reader)
{
var rawData = reader.ReadBinary(reader.Lenght);
var peerId = (ushort)(rawData[1] + (rawData[2] << 8));
RagonPlayer player = null;
if (peerId != 10000)
{
player = _playerCache.GetPlayerByPeer(peerId);
if (player == null)
{
RagonLog.Error($"Player with peerId:{peerId} not found");
_playerCache.Dump();
return;
}
}
var headerSize = 3;
var payload = new byte[rawData.Length - headerSize];
Array.Copy(rawData, headerSize, payload, 0, payload.Length);
_listeners.OnData(player, payload);
}
}
@@ -36,13 +36,13 @@ public class RoomEventHandler : IHandler
{
var eventCode = buffer.ReadUShort();
var peerId = buffer.ReadUShort();
var executionMode = (RagonReplicationMode)buffer.ReadByte();
var executionMode = (RagonReplicationMode) buffer.ReadByte();
var player = _playerCache.GetPlayerByPeer(peerId);
if (player == null)
{
RagonLog.Error($"Player with peerId:{peerId} not found as owner of event with code:{eventCode}");
_playerCache.Dump();
return;
}
@@ -16,6 +16,6 @@ public class TimestampHandler: IHandler
var timestamp1 = (uint)buffer.ReadInt();
var value = new DoubleToUInt { Int0 = timestamp0, Int1 = timestamp1 };
_client.SetTimestamp(value.Double);
_client.UpdateTimestamp(value.Double);
}
}
-1
View File
@@ -20,6 +20,5 @@ namespace Ragon.Client
{
public interface IRagonEvent: IRagonSerializable
{
}
}
@@ -22,7 +22,6 @@ namespace Ragon.Client
IRagonFailedListener,
IRagonJoinListener,
IRagonLeftListener,
IRagonSceneListener,
IRagonOwnershipChangedListener,
IRagonPlayerJoinListener,
IRagonPlayerLeftListener,
@@ -1,22 +0,0 @@
/*
* Copyright 2023-2024 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.
*/
namespace Ragon.Client;
public interface IRagonSceneListener
{
void OnSceneLoaded(RagonClient client);
}
@@ -1,6 +0,0 @@
namespace Ragon.Client;
public interface IRagonSceneRequestListener
{
void OnRequestScene(RagonClient client, string sceneName);
}
+24 -34
View File
@@ -31,7 +31,7 @@ namespace Ragon.Client
private RagonListenerList _listeners;
private RagonPlayerCache _playerCache;
private RagonEventCache _eventCache;
private RagonStatus _status;
private RagonState _state;
private double _serverTimestamp;
private float _replicationRate = 0;
@@ -39,7 +39,7 @@ namespace Ragon.Client
public double ServerTimestamp => _serverTimestamp;
public IRagonConnection Connection => _connection;
public RagonStatus Status => _status;
public RagonState State => _state;
public RagonSession Session => _session;
public RagonEventCache Event => _eventCache;
public NetworkStatistics Statistics => _stats;
@@ -64,22 +64,18 @@ namespace Ragon.Client
_replicationTime = 0;
_eventCache = new RagonEventCache();
_stats = new NetworkStatistics();
_status = RagonStatus.DISCONNECTED;
}
public void Connect(string address, ushort port, string protocol)
{
_writeBuffer = new RagonStream();
_readBuffer = new RagonStream();
_playerCache = new RagonPlayerCache();
_session = new RagonSession(this, _writeBuffer);
_room = new RagonRoom(this, _playerCache);
_stats = new NetworkStatistics();
_state = RagonState.DISCONNECTED;
_handlers = new IHandler[byte.MaxValue];
_handlers[(byte)RagonOperation.AUTHORIZED_SUCCESS] = new AuthorizeSuccessHandler(this, _listeners);
_handlers[(byte)RagonOperation.AUTHORIZED_FAILED] = new AuthorizeFailedHandler(_listeners);
_handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _listeners, _playerCache);
_handlers[(byte)RagonOperation.JOIN_SUCCESS] = new JoinSuccessHandler(this, _room);
_handlers[(byte)RagonOperation.JOIN_FAILED] = new JoinFailedHandler(_listeners);
_handlers[(byte)RagonOperation.LEAVE_ROOM] = new LeaveRoomHandler(this, _listeners);
_handlers[(byte)RagonOperation.OWNERSHIP_ROOM_CHANGED] = new OwnershipRoomHandler(_listeners, _playerCache);
@@ -87,19 +83,22 @@ namespace Ragon.Client
_handlers[(byte)RagonOperation.PLAYER_LEAVED] = new PlayerLeftHandler(_playerCache, _listeners);
_handlers[(byte)RagonOperation.REPLICATE_ROOM_EVENT] = new RoomEventHandler(this, _playerCache);
_handlers[(byte)RagonOperation.TIMESTAMP_SYNCHRONIZATION] = new TimestampHandler(this);
_handlers[(byte)RagonOperation.REPLICATE_RAW_DATA] = new RoomDataHandler(_playerCache, _listeners);
_handlers[(byte)RagonOperation.ROOM_LIST_UPDATED] = new RoomListHandler(_session, _listeners);
_handlers[(byte)RagonOperation.ROOM_DATA_UPDATED] = new RoomUserDataHandler(this, _listeners);
_handlers[(byte)RagonOperation.PLAYER_DATA_UPDATED] = new PlayerUserDataHandler(_playerCache, _listeners);
}
public void Connect(string address, ushort port, string protocol)
{
var protocolRaw = RagonVersion.Parse(protocol);
_connection.Connect(address, port, protocolRaw);
}
public void Disconnect()
{
_status = RagonStatus.DISCONNECTED;
_room?.Cleanup();
_state = RagonState.DISCONNECTED;
_room.Clear();
_connection.Disconnect();
OnDisconnected(RagonDisconnect.MANUAL);
@@ -107,14 +106,13 @@ namespace Ragon.Client
public void Update(float dt)
{
if (_status != RagonStatus.DISCONNECTED)
if (_state != RagonState.DISCONNECTED)
{
_replicationTime += dt;
if (_replicationTime >= _replicationRate)
{
_replicationTime = 0;
// _entityCache.WriteState(_writeBuffer);
SendTimestamp();
SendRoomUserData();
SendPlayerUserData();
@@ -129,9 +127,9 @@ namespace Ragon.Client
public void Dispose()
{
if (_status != RagonStatus.DISCONNECTED)
if (_state != RagonState.DISCONNECTED)
{
_status = RagonStatus.DISCONNECTED;
_state = RagonState.DISCONNECTED;
_connection.Disconnect();
}
@@ -147,7 +145,6 @@ namespace Ragon.Client
public void AddListener(IRagonOwnershipChangedListener listener) => _listeners.Add(listener);
public void AddListener(IRagonPlayerJoinListener listener) => _listeners.Add(listener);
public void AddListener(IRagonPlayerLeftListener listener) => _listeners.Add(listener);
public void AddListener(IRagonDataListener listener) => _listeners.Add(listener);
public void AddListener(IRagonRoomListListener listener) => _listeners.Add(listener);
public void AddListener(IRagonPlayerUserDataListener listener) => _listeners.Add(listener);
public void AddListener(IRagonRoomUserDataListener listener) => _listeners.Add(listener);
@@ -160,7 +157,6 @@ namespace Ragon.Client
public void RemoveListener(IRagonOwnershipChangedListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonPlayerJoinListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonPlayerLeftListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonDataListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonRoomListListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonRoomUserDataListener listener) => _listeners.Remove(listener);
public void RemoveListener(IRagonPlayerUserDataListener listener) => _listeners.Remove(listener);
@@ -168,19 +164,13 @@ namespace Ragon.Client
#endregion
#region INTERNAL
internal void AssignRoom(RagonRoom room)
internal void UpdateState(RagonState state)
{
_room?.Dispose();
_room = room;
_state = state;
}
internal void SetStatus(RagonStatus status)
{
_status = status;
}
internal void SetTimestamp(double time)
internal void UpdateTimestamp(double time)
{
_serverTimestamp = time;
}
@@ -240,7 +230,7 @@ namespace Ragon.Client
RagonLog.Trace("Connected");
_listeners.OnConnected();
_status = RagonStatus.CONNECTED;
_state = RagonState.CONNECTED;
}
private void OnDisconnected(RagonDisconnect reason)
@@ -248,7 +238,7 @@ namespace Ragon.Client
RagonLog.Trace($"Disconnected: {reason}");
_listeners.OnDisconnected(reason);
_status = RagonStatus.DISCONNECTED;
_state = RagonState.DISCONNECTED;
}
private void OnData(byte[] data)
-17
View File
@@ -29,7 +29,6 @@ namespace Ragon.Client
private readonly List<IRagonOwnershipChangedListener> _ownershipChangedListeners = new();
private readonly List<IRagonPlayerJoinListener> _playerJoinListeners = new();
private readonly List<IRagonPlayerLeftListener> _playerLeftListeners = new();
private readonly List<IRagonDataListener> _dataListeners = new();
private readonly List<IRagonRoomListListener> _roomListListeners = new();
private readonly List<IRagonRoomUserDataListener> _roomUserDataListeners = new();
private readonly List<IRagonPlayerUserDataListener> _playerUserDataListeners = new();
@@ -79,11 +78,6 @@ namespace Ragon.Client
_delayedActions.Clear();
}
public void Add(IRagonDataListener dataListener)
{
_dataListeners.Add(dataListener);
}
public void Add(IRagonAuthorizationListener listener)
{
_authorizationListeners.Add(listener);
@@ -139,11 +133,6 @@ namespace Ragon.Client
_playerUserDataListeners.Add(listener);
}
public void Remove(IRagonDataListener listener)
{
_delayedActions.Add(() => _dataListeners.Remove(listener));
}
public void Remove(IRagonAuthorizationListener listener)
{
_delayedActions.Add(() => _authorizationListeners.Remove(listener));
@@ -259,12 +248,6 @@ namespace Ragon.Client
listener.OnDisconnected(_client, disconnect);
}
public void OnData(RagonPlayer player, byte[] data)
{
foreach (var listener in _dataListeners)
listener.OnData(_client, player, data);
}
public void OnRoomList(RagonRoomInformation[] roomInfos)
{
foreach (var listListener in _roomListListeners)
+14 -33
View File
@@ -18,7 +18,7 @@ using Ragon.Protocol;
namespace Ragon.Client
{
public class RagonRoom : IDisposable
public class RagonRoom
{
private class EventSubscription : IDisposable
{
@@ -51,13 +51,12 @@ namespace Ragon.Client
private readonly RagonClient _client;
private readonly RagonPlayerCache _playerCache;
private readonly RoomParameters _parameters;
private readonly RagonUserData _userData;
private RoomParameters _parameters;
private RagonUserData _userData;
public string Id => _parameters.RoomId;
public int MinPlayers => _parameters.Min;
public int MaxPlayers => _parameters.Max;
public string Scene => "none";
public IReadOnlyList<RagonPlayer> Players => _playerCache.Players;
public RagonPlayer Local => _playerCache.Local;
@@ -69,27 +68,23 @@ namespace Ragon.Client
private readonly Dictionary<int, List<Action<RagonPlayer, IRagonEvent>>> _localListeners = new();
private readonly Dictionary<int, List<Action<RagonPlayer, IRagonEvent>>> _listeners = new();
public RagonRoom(RagonClient client,
RagonPlayerCache playerCache,
RoomParameters parameters)
public RagonRoom(RagonClient client, RagonPlayerCache playerCache)
{
_client = client;
_parameters = parameters;
_playerCache = playerCache;
_userData = new RagonUserData();
}
internal void Cleanup()
public void Reset(RoomParameters parameters)
{
Clear();
_userData = new RagonUserData();
_parameters = parameters;
_playerCache.Cleanup();
}
internal void Update(string sceneName)
{
// _scene.Update(sceneName);
}
internal void HandleEvent(ushort eventCode, RagonPlayer caller, RagonStream buffer)
{
if (_events.TryGetValue(eventCode, out var evnt))
@@ -108,7 +103,7 @@ namespace Ragon.Client
var t = new TEvent();
var eventCode = _client.Event.GetEventCode(t);
var action = (RagonPlayer player, IRagonEvent eventData) => callback.Invoke(player, (TEvent)eventData);
if (!_listeners.TryGetValue(eventCode, out var callbacks))
{
callbacks = new List<Action<RagonPlayer, IRagonEvent>>();
@@ -194,22 +189,8 @@ namespace Ragon.Client
_client.Reliable.Send(sendData);
}
public void ReplicateData(byte[] data, bool reliable)
public void Clear()
{
var sendData = new byte[data.Length + 1];
sendData[0] = (byte)RagonOperation.REPLICATE_RAW_DATA;
Array.Copy(data, 0, sendData, 1, data.Length);
if (reliable)
_client.Reliable.Send(sendData);
else
_client.Unreliable.Send(sendData);
}
public void Dispose()
{
Cleanup();
_events.Clear();
_listeners.Clear();
_localListeners.Clear();
+15 -15
View File
@@ -21,20 +21,21 @@ namespace Ragon.Client
public class RagonSession
{
private readonly RagonClient _client;
private readonly RagonStream _buffer;
private readonly RagonStream _buffer;
public RagonSession(RagonClient client, RagonStream buffer)
{
_client = client;
_buffer = buffer;
}
public void CreateOrJoin(string sceneName, int minPlayers, int maxPlayers)
public void CreateOrJoin(string sessionName, int minPlayers, int maxPlayers)
{
var parameters = new RagonRoomParameters() {Scene = sceneName, Min = minPlayers, Max = maxPlayers};
var parameters = new RagonRoomParameters() { Min = minPlayers, Max = maxPlayers };
CreateOrJoin(parameters);
}
public void CreateOrJoin(RagonRoomParameters parameters)
{
_buffer.Clear();
@@ -46,16 +47,16 @@ namespace Ragon.Client
_client.Reliable.Send(sendData);
}
public void Create(string sceneName, int minPlayers, int maxPlayers)
public void Create(string sessionName, int minPlayers, int maxPlayers)
{
Create(null, new RagonRoomParameters() {Scene = sceneName, Min = minPlayers, Max = maxPlayers});
Create(null, new RagonRoomParameters() { Min = minPlayers, Max = maxPlayers });
}
public void Create(string roomId, string sceneName, int minPlayers, int maxPlayers)
public void Create(string roomId, string sessionName, int minPlayers, int maxPlayers)
{
Create(roomId, new RagonRoomParameters() {Scene = sceneName, Min = minPlayers, Max = maxPlayers});
Create(roomId, new RagonRoomParameters() { Min = minPlayers, Max = maxPlayers });
}
public void Create(string roomId, RagonRoomParameters parameters)
{
_buffer.Clear();
@@ -76,14 +77,14 @@ namespace Ragon.Client
var sendData = _buffer.ToArray();
_client.Reliable.Send(sendData);
}
public void Leave()
public void Leave()
{
var sendData = new[] {(byte) RagonOperation.LEAVE_ROOM};
var sendData = new[] { (byte)RagonOperation.LEAVE_ROOM };
_client.Reliable.Send(sendData);
}
public void Join(string roomId)
public void Join(string roomId)
{
_buffer.Clear();
_buffer.WriteOperation(RagonOperation.JOIN_ROOM);
@@ -93,7 +94,7 @@ namespace Ragon.Client
_client.Reliable.Send(sendData);
}
public void AuthorizeWithKey(string key, string playerName, string payload = "")
public void AuthorizeWithKey(string key, string playerName, string payload = "")
{
_buffer.Clear();
_buffer.WriteOperation(RagonOperation.AUTHORIZE);
@@ -104,6 +105,5 @@ namespace Ragon.Client
var sendData = _buffer.ToArray();
_client.Reliable.Send(sendData);
}
}
}
@@ -16,7 +16,7 @@
namespace Ragon.Client
{
public enum RagonStatus
public enum RagonState
{
DISCONNECTED,
CONNECTED,