record demos as packets
This commit is contained in:
@@ -84,6 +84,11 @@ namespace Game
|
||||
Level.SceneLoaded -= OnLevelLoaded;
|
||||
//Scripting.LateUpdate -= OnLateUpdatePre;
|
||||
Scripting.LateFixedUpdate -= OnLateUpdatePre;
|
||||
|
||||
foreach (var player in Level.GetActors<PlayerActor>())
|
||||
{
|
||||
FlaxEngine.Object.Destroy(player);
|
||||
}
|
||||
}
|
||||
|
||||
private static PlayerFrame GetPlayerFrame(uint playerIndex, ulong playerFrameIndex)
|
||||
@@ -109,8 +114,8 @@ namespace Game
|
||||
try
|
||||
{
|
||||
NetworkManager.IsServer = NetworkManager.server != null;
|
||||
NetworkManager.IsClient = NetworkManager.client != null && NetworkManager.server == null;
|
||||
NetworkManager.IsLocalClient = NetworkManager.client != null && NetworkManager.server != null;
|
||||
NetworkManager.IsClient = (NetworkManager.client != null || NetworkManager.IsDemoPlaying) && NetworkManager.server == null;
|
||||
NetworkManager.IsLocalClient = (NetworkManager.client != null || NetworkManager.IsDemoPlaying) && NetworkManager.server != null;
|
||||
OnLateUpdate();
|
||||
}
|
||||
finally
|
||||
@@ -213,9 +218,9 @@ namespace Game
|
||||
clientWorldState.playerFrameHistory.Add(playerId, playerFrames);
|
||||
}
|
||||
var playerFrameHistory = clientWorldState.playerFrameHistory[playerId];
|
||||
var playerFrame = playerFrameHistory[clientWorldState.frame % 120];
|
||||
var playerFrame = playerFrameHistory[ClientFrame % 120];
|
||||
|
||||
playerFrame.frame = clientWorldState.frame;
|
||||
playerFrame.frame = ClientFrame;
|
||||
playerFrame.position = playerActor.Position;
|
||||
}
|
||||
|
||||
@@ -341,7 +346,7 @@ namespace Game
|
||||
new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle()));
|
||||
|
||||
//if (NetworkManager.IsClient)
|
||||
players[playerId].GetScript<PlayerMovement>().input.frame = clientWorldState.frame;
|
||||
players[playerId].GetScript<PlayerMovement>().input.frame = ClientFrame;
|
||||
break;
|
||||
}
|
||||
case GameModeMessageType.PlayerInput:
|
||||
@@ -547,7 +552,7 @@ namespace Game
|
||||
players.Add(playerId, null);
|
||||
players[playerId] = playerActor;
|
||||
PlayerInput playerInput = playerActor.GetScript<PlayerMovement>().input;
|
||||
playerInput.frame = (NetworkManager.IsServer) ? serverWorldState.frame : clientWorldState.frame;
|
||||
playerInput.frame = (NetworkManager.IsServer) ? serverWorldState.frame : ClientFrame;
|
||||
if (NetworkManager.IsServer)
|
||||
{
|
||||
serverWorldState.actors.Add(playerActor);
|
||||
|
||||
@@ -82,23 +82,25 @@ namespace Game
|
||||
|
||||
public static void Cleanup()
|
||||
{
|
||||
Scripting.Exit -= Cleanup;
|
||||
Scripting.FixedUpdate -= OnDemoUpdate;
|
||||
Scripting.FixedUpdate -= OnServerNetworkUpdate;
|
||||
Level.ActorSpawned -= OnServerActorSpawned;
|
||||
Scripting.FixedUpdate -= OnClientNetworkUpdate;
|
||||
Level.ActorSpawned -= OnClientActorSpawned;
|
||||
|
||||
if (server != null)
|
||||
{
|
||||
Scripting.FixedUpdate -= OnServerUpdate;
|
||||
Scripting.Exit -= Cleanup;
|
||||
Level.ActorSpawned -= OnServerActorSpawned;
|
||||
NetworkPeer.ShutdownPeer(server);
|
||||
server = null;
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
Scripting.FixedUpdate -= OnClientUpdate;
|
||||
Scripting.Exit -= Cleanup;
|
||||
Level.ActorSpawned -= OnClientActorSpawned;
|
||||
NetworkPeer.ShutdownPeer(client);
|
||||
client = null;
|
||||
}
|
||||
|
||||
LocalPlayerClientId = 0;
|
||||
|
||||
#if FLAX_EDITOR
|
||||
@@ -107,6 +109,8 @@ namespace Game
|
||||
#endif
|
||||
GameModeManager.Cleanup(); // FIXME
|
||||
|
||||
StopRecording();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
@@ -147,5 +151,7 @@ namespace Game
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -49,79 +49,96 @@ namespace Game
|
||||
return false;
|
||||
}
|
||||
|
||||
Scripting.FixedUpdate += OnClientUpdate;
|
||||
Scripting.FixedUpdate += OnClientNetworkUpdate;
|
||||
if (!listenServer)
|
||||
{
|
||||
Scripting.Exit += Cleanup;
|
||||
Level.ActorSpawned += OnClientActorSpawned;
|
||||
//Level.ActorSpawned += OnClientActorSpawned;
|
||||
}
|
||||
|
||||
string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}_v2.gdem");
|
||||
RecordDemo(demoPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void OnClientUpdate()
|
||||
private static void OnClientNetworkUpdate()
|
||||
{
|
||||
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnClientUpdate");
|
||||
using var _ = Utilities.ProfileScope("NetworkManager_OnClientNetworkUpdate");
|
||||
|
||||
while (client.PopEvent(out NetworkEvent networkEvent))
|
||||
switch (networkEvent.EventType)
|
||||
{
|
||||
RecordMessage(ref networkEvent);
|
||||
|
||||
try
|
||||
{
|
||||
case NetworkEventType.Connected:
|
||||
{
|
||||
LocalPlayerClientId = networkEvent.Sender.ConnectionId;
|
||||
Console.Print("Connected to server, ConnectionId: " + networkEvent.Sender.ConnectionId);
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Disconnected:
|
||||
{
|
||||
Console.Print("Disconnected from server, timeout.");
|
||||
LocalPlayerClientId = 0;
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Timeout:
|
||||
{
|
||||
Console.Print("Disconnected from server, connection closed.");
|
||||
LocalPlayerClientId = 0;
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Message:
|
||||
{
|
||||
try
|
||||
{
|
||||
IsLocalClient = server != null;
|
||||
IsClient = true;
|
||||
OnNetworkMessage(ref networkEvent);
|
||||
|
||||
if (networkEvent.Message.Position > 0 &&
|
||||
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||
{
|
||||
string err =
|
||||
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.";
|
||||
|
||||
networkEvent.Message.Position = 0;
|
||||
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||
}
|
||||
|
||||
string messageBytesStr = string.Join(", ",
|
||||
messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||
|
||||
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLocalClient = false;
|
||||
IsClient = false;
|
||||
client.RecycleMessage(networkEvent.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
IsLocalClient = server != null;
|
||||
IsClient = true;
|
||||
OnClientReadMessage(ref networkEvent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLocalClient = false;
|
||||
IsClient = false;
|
||||
if (networkEvent.EventType == NetworkEventType.Message)
|
||||
client.RecycleMessage(networkEvent.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnClientReadMessage(ref NetworkEvent networkEvent)
|
||||
{
|
||||
using var _ = Utilities.ProfileScope("NetworkManager_OnClientReadMessage");
|
||||
|
||||
switch (networkEvent.EventType)
|
||||
{
|
||||
case NetworkEventType.Connected:
|
||||
{
|
||||
LocalPlayerClientId = networkEvent.Sender.ConnectionId;
|
||||
Console.Print("Connected to server, ConnectionId: " + networkEvent.Sender.ConnectionId);
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Disconnected:
|
||||
{
|
||||
Console.Print("Disconnected from server, timeout.");
|
||||
LocalPlayerClientId = 0;
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Timeout:
|
||||
{
|
||||
Console.Print("Disconnected from server, connection closed.");
|
||||
LocalPlayerClientId = 0;
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Message:
|
||||
{
|
||||
OnNetworkMessage(ref networkEvent);
|
||||
|
||||
if (networkEvent.Message.Position > 0 &&
|
||||
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||
{
|
||||
string err =
|
||||
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.\n";
|
||||
|
||||
networkEvent.Message.Position = 0;
|
||||
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||
}
|
||||
|
||||
//string messageBytesStr = string.Join(", ", messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||
string messageBytesStr = string.Join("", messageBytes.Select(x => ((int)x).ToString("X2")));
|
||||
|
||||
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnClientActorSpawned(Actor actor)
|
||||
|
||||
278
Source/Game/GameMode/NetworkManager_Demo.cs
Normal file
278
Source/Game/GameMode/NetworkManager_Demo.cs
Normal file
@@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Networking;
|
||||
using Console = Game.Console;
|
||||
using Object = FlaxEngine.Object;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public static unsafe partial class NetworkManager
|
||||
{
|
||||
public const byte DemoVer = 2;
|
||||
private struct DemoNetworkEventHeader
|
||||
{
|
||||
public NetworkEventType EventType;
|
||||
public uint SenderId;
|
||||
public uint MessageId;
|
||||
public uint Length;
|
||||
}
|
||||
|
||||
private static List<NetworkEvent> buffer;
|
||||
private static IEnumerator<NetworkEvent> bufferEnumerable;
|
||||
private static GZipStream demoStream; // record
|
||||
private static FileStream demoFileStream;
|
||||
|
||||
public static bool IsRecording => demoStream != null;
|
||||
private static long flushedFrames = 0;
|
||||
|
||||
public static bool IsDemoPlaying => bufferEnumerable != null;
|
||||
|
||||
public static bool PlayDemo(string demoName)
|
||||
{
|
||||
{
|
||||
Cleanup();
|
||||
GameModeManager.Init();
|
||||
}
|
||||
|
||||
if (!ReadDemo(demoName))
|
||||
{
|
||||
Console.Print("Failed to read demo.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*if (client == null)
|
||||
{
|
||||
Console.Print("Failed to create NetworkPeer.");
|
||||
return false;
|
||||
}
|
||||
if (!client.Connect())
|
||||
{
|
||||
Console.Print("Failed to connect to the server.");
|
||||
return false;
|
||||
}*/
|
||||
|
||||
Scripting.FixedUpdate += OnDemoUpdate;
|
||||
//if (!listenServer)
|
||||
{
|
||||
Scripting.Exit += Cleanup;
|
||||
//Level.ActorSpawned += OnClientActorSpawned;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void RecordDemo(string demoPath)
|
||||
{
|
||||
if (IsRecording)
|
||||
StopRecording();
|
||||
|
||||
buffer = new List<NetworkEvent>();
|
||||
var demoFolder = Directory.GetParent(demoPath);
|
||||
if (!demoFolder.Exists)
|
||||
Directory.CreateDirectory(demoFolder.FullName);
|
||||
|
||||
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
|
||||
demoStream = new GZipStream(demoFileStream, CompressionMode.Compress);
|
||||
demoStream.WriteByte(DemoVer);
|
||||
}
|
||||
|
||||
private static void RecordMessage(ref NetworkEvent networkEvent)
|
||||
{
|
||||
if (!IsRecording)
|
||||
return;
|
||||
|
||||
NetworkEvent recordedEvent = networkEvent;
|
||||
recordedEvent.Message.Buffer = (byte*)NativeMemory.Alloc(recordedEvent.Message.Length);
|
||||
recordedEvent.Sender.ConnectionId = networkEvent.Sender.ConnectionId;
|
||||
|
||||
NativeMemory.Copy(networkEvent.Message.Buffer, recordedEvent.Message.Buffer, recordedEvent.Message.Length);
|
||||
buffer.Add(recordedEvent);
|
||||
}
|
||||
|
||||
public static void FlushDemo()
|
||||
{
|
||||
if (!IsRecording)
|
||||
return;
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
Span<byte> bytes = stackalloc byte[Unsafe.SizeOf<DemoNetworkEventHeader>()];
|
||||
foreach (ref NetworkEvent networkEvent in CollectionsMarshal.AsSpan(buffer))
|
||||
{
|
||||
DemoNetworkEventHeader header = new DemoNetworkEventHeader()
|
||||
{
|
||||
EventType = networkEvent.EventType,
|
||||
SenderId = networkEvent.Sender.ConnectionId,
|
||||
Length = networkEvent.Message.Length,
|
||||
MessageId = networkEvent.Message.MessageId,
|
||||
};
|
||||
MemoryMarshal.Write(bytes, ref header);
|
||||
demoStream.Write(bytes);
|
||||
|
||||
Span<byte> messageBytes = new Span<byte>(networkEvent.Message.Buffer, (int)networkEvent.Message.Length);
|
||||
demoStream.Write(messageBytes);
|
||||
|
||||
// TODO: free networkEvent buffer
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
flushedFrames += buffer.Count;
|
||||
buffer.Clear();
|
||||
|
||||
FlaxEngine.Debug.Write(LogType.Info, $"Wrote demo in {sw.Elapsed.TotalMilliseconds}ms, frames: {flushedFrames}");
|
||||
}
|
||||
|
||||
public static void StopRecording()
|
||||
{
|
||||
if (!IsRecording)
|
||||
return;
|
||||
|
||||
FlushDemo();
|
||||
demoStream.Close();
|
||||
demoStream = null;
|
||||
demoFileStream.Close();
|
||||
demoFileStream = null;
|
||||
}
|
||||
|
||||
private static unsafe bool ReadDemo(string demoPath)
|
||||
{
|
||||
if (!File.Exists(demoPath))
|
||||
return false;
|
||||
|
||||
buffer = new List<NetworkEvent>();
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
using FileStream fileStream = File.OpenRead(demoPath);
|
||||
using GZipStream stream = new GZipStream(fileStream, CompressionMode.Decompress);
|
||||
|
||||
int ver = stream.ReadByte();
|
||||
if (ver != DemoVer)
|
||||
{
|
||||
Console.Print($"Demo version mismatch, expected {DemoVer}, got {ver}");
|
||||
stream.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int headerSize = Unsafe.SizeOf<DemoNetworkEventHeader>();
|
||||
Span<byte> headerBuffer = stackalloc byte[headerSize];
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
int bytesLeftInBuffer = headerSize;
|
||||
do
|
||||
{
|
||||
int readBytes = stream.Read(headerBuffer.Slice(headerSize - bytesLeftInBuffer, bytesLeftInBuffer));
|
||||
if (readBytes == 0)
|
||||
break;
|
||||
bytesLeftInBuffer -= readBytes;
|
||||
} while (bytesLeftInBuffer > 0);
|
||||
|
||||
if (bytesLeftInBuffer > 0)
|
||||
break; // EOF;
|
||||
}
|
||||
|
||||
DemoNetworkEventHeader header = MemoryMarshal.Read<DemoNetworkEventHeader>(headerBuffer);
|
||||
|
||||
//buffer.Add(new NetworkEvent());
|
||||
//ref NetworkEvent networkEvent = ref buffer[buffer.Length]; // collectionmarshal
|
||||
NetworkEvent networkEvent = new NetworkEvent();
|
||||
networkEvent.EventType = header.EventType;
|
||||
networkEvent.Message.Position = 0;
|
||||
networkEvent.Message.MessageId = header.MessageId;
|
||||
networkEvent.Message.Length = networkEvent.Message.BufferSize = header.Length;
|
||||
networkEvent.Sender.ConnectionId = header.SenderId;
|
||||
|
||||
if (header.Length > 0)
|
||||
{
|
||||
networkEvent.Message.Buffer = (byte*)NativeMemory.Alloc(header.Length);
|
||||
|
||||
Span<byte> messageBufferSpan = new Span<byte>(networkEvent.Message.Buffer, (int)networkEvent.Message.BufferSize);
|
||||
{
|
||||
int bytesLeftInBuffer = (int)header.Length;
|
||||
do
|
||||
{
|
||||
int readBytes = stream.Read(messageBufferSpan.Slice((int)header.Length - bytesLeftInBuffer, bytesLeftInBuffer));
|
||||
if (readBytes == 0)
|
||||
break;
|
||||
bytesLeftInBuffer -= readBytes;
|
||||
} while (bytesLeftInBuffer > 0);
|
||||
|
||||
if (bytesLeftInBuffer > 0)
|
||||
break; // EOF;
|
||||
}
|
||||
}
|
||||
buffer.Add(networkEvent);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
bufferEnumerable = buffer.GetEnumerator();
|
||||
|
||||
Console.Print($"Demo parse time {sw.Elapsed.TotalMilliseconds}ms, frames: {buffer.Count} ");
|
||||
|
||||
DemoEndFrame(); // advances to first frame
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void DemoEndFrame()
|
||||
{
|
||||
// TODO: check if the current state frame matches the current frame number before advancing
|
||||
|
||||
/*asdf++;
|
||||
if (asdf < 8)
|
||||
return;*/
|
||||
|
||||
if (bufferEnumerable == null || !bufferEnumerable.MoveNext())
|
||||
{
|
||||
if (buffer.Any())
|
||||
{
|
||||
bufferEnumerable.Dispose();
|
||||
bufferEnumerable = null;
|
||||
buffer.Clear();
|
||||
Console.Print("Demo ended");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//var actorState = currentState.actor;
|
||||
//currentState.input = bufferEnumerable.Current;
|
||||
//frame++;
|
||||
//currentState.actor = actorState;
|
||||
}
|
||||
|
||||
private static void OnDemoUpdate()
|
||||
{
|
||||
if (!IsDemoPlaying)
|
||||
return;
|
||||
|
||||
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnDemoUpdate");
|
||||
|
||||
NetworkEvent demoEvent = bufferEnumerable.Current; // ref?
|
||||
|
||||
// TODO: change/randomize Sender.ConnectionId?
|
||||
try
|
||||
{
|
||||
IsLocalClient = server != null;
|
||||
IsClient = true;
|
||||
OnClientReadMessage(ref demoEvent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLocalClient = false;
|
||||
IsClient = false;
|
||||
//TODO: recycle event?
|
||||
}
|
||||
|
||||
DemoEndFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace Game
|
||||
return false;
|
||||
}
|
||||
|
||||
Scripting.FixedUpdate += OnServerUpdate;
|
||||
Scripting.FixedUpdate += OnServerNetworkUpdate;
|
||||
Scripting.Exit += Cleanup;
|
||||
Level.ActorSpawned += OnServerActorSpawned;
|
||||
|
||||
@@ -116,84 +116,91 @@ namespace Game
|
||||
client.EndSendMessage(channelType, message);
|
||||
}
|
||||
|
||||
private static void OnServerUpdate()
|
||||
private static void OnServerNetworkUpdate()
|
||||
{
|
||||
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnServerUpdate");
|
||||
using var _ = Utilities.ProfileScope("NetworkManager_OnServerNetworkUpdate");
|
||||
|
||||
while (server.PopEvent(out NetworkEvent networkEvent))
|
||||
switch (networkEvent.EventType)
|
||||
OnServerReadMessage(ref networkEvent);
|
||||
}
|
||||
|
||||
private static void OnServerReadMessage(ref NetworkEvent networkEvent)
|
||||
{
|
||||
using var _ = Utilities.ProfileScope("NetworkManager_OnServerReadMessage");
|
||||
|
||||
switch (networkEvent.EventType)
|
||||
{
|
||||
case NetworkEventType.Connected:
|
||||
{
|
||||
case NetworkEventType.Connected:
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) is trying to connect");
|
||||
|
||||
try
|
||||
{
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) is trying to connect");
|
||||
|
||||
try
|
||||
IsServer = true;
|
||||
if (GameModeManager.OnClientConnecting(networkEvent.Sender))
|
||||
{
|
||||
IsServer = true;
|
||||
if (GameModeManager.OnClientConnecting(networkEvent.Sender))
|
||||
{
|
||||
ConnectedClients.Add(networkEvent.Sender);
|
||||
Console.Print(
|
||||
$"Client({networkEvent.Sender.ConnectionId}) connected. Total clients: {ConnectedClients.Count}");
|
||||
ConnectedClients.Add(networkEvent.Sender);
|
||||
Console.Print(
|
||||
$"Client({networkEvent.Sender.ConnectionId}) connected. Total clients: {ConnectedClients.Count}");
|
||||
|
||||
GameModeManager.OnClientConnected(networkEvent.Sender);
|
||||
}
|
||||
else
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) connection refused");
|
||||
GameModeManager.OnClientConnected(networkEvent.Sender);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsServer = false;
|
||||
}
|
||||
|
||||
break;
|
||||
else
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) connection refused");
|
||||
}
|
||||
case NetworkEventType.Disconnected:
|
||||
case NetworkEventType.Timeout:
|
||||
finally
|
||||
{
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) disconnected!");
|
||||
|
||||
ConnectedClients.Remove(networkEvent.Sender);
|
||||
Console.Print("Connected clients: " + ConnectedClients.Count);
|
||||
break;
|
||||
IsServer = false;
|
||||
}
|
||||
case NetworkEventType.Message:
|
||||
{
|
||||
try
|
||||
{
|
||||
IsServer = true;
|
||||
OnNetworkMessage(ref networkEvent);
|
||||
|
||||
if (networkEvent.Message.Position > 0 &&
|
||||
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||
{
|
||||
string err =
|
||||
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.";
|
||||
|
||||
networkEvent.Message.Position = 0;
|
||||
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||
}
|
||||
|
||||
string messageBytesStr = string.Join(", ",
|
||||
messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||
|
||||
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsServer = false;
|
||||
server.RecycleMessage(networkEvent.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Disconnected:
|
||||
case NetworkEventType.Timeout:
|
||||
{
|
||||
Console.Print($"Client({networkEvent.Sender.ConnectionId}) disconnected!");
|
||||
|
||||
ConnectedClients.Remove(networkEvent.Sender);
|
||||
Console.Print("Connected clients: " + ConnectedClients.Count);
|
||||
break;
|
||||
}
|
||||
case NetworkEventType.Message:
|
||||
{
|
||||
try
|
||||
{
|
||||
IsServer = true;
|
||||
OnNetworkMessage(ref networkEvent);
|
||||
|
||||
if (networkEvent.Message.Position > 0 &&
|
||||
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||
{
|
||||
string err =
|
||||
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.";
|
||||
|
||||
networkEvent.Message.Position = 0;
|
||||
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||
}
|
||||
|
||||
string messageBytesStr = string.Join(", ",
|
||||
messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||
|
||||
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsServer = false;
|
||||
server.RecycleMessage(networkEvent.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnServerActorSpawned(Actor actor)
|
||||
|
||||
Reference in New Issue
Block a user