Files
GoakeFlax/Source/Game/GameMode/NetworkManager_Client.cs

164 lines
5.3 KiB
C#

using System;
using System.Linq;
using System.Runtime.InteropServices;
using FlaxEngine;
using FlaxEngine.Networking;
using Console = Game.Console;
using Object = FlaxEngine.Object;
namespace Game;
public static partial class NetworkManager
{
public static uint LocalPlayerClientId { get; /*private*/ set; }
public static INetworkDriver ClientNetworkDriver { get; set; }
//public static WorldStateManager clientWorldStateManager = null;
public static bool ConnectServer(string serverAddress = "localhost", bool listenServer = false)
{
if (!listenServer)
Cleanup();
ServerAddress = serverAddress;
//var driver = Object.New(typeof(ENetDriver));
//ClientNetworkDriver = null;
//INetworkDriver driver = Object.New<ENetDriver>();
INetworkDriver driver = Object.New<NetworkLagDriver>();
if (driver is NetworkLagDriver networkLagDriver)
networkLagDriver.Lag = 50.0f;
ClientNetworkDriver = driver;
client = NetworkPeer.CreatePeer(new NetworkConfig
{
NetworkDriver = (Object)driver,
ConnectionsLimit = MaximumClients,
MessagePoolSize = 2048,
MessageSize = MTU,
Address = ServerAddress == "localhost" ? "127.0.0.1" : ServerAddress,
Port = ServerPort
});
if (client == null)
{
Console.Print("Failed to create NetworkPeer.");
return false;
}
if (!client.Connect())
{
Console.Print("Failed to connect to the server.");
return false;
}
Debug.Log("Connected...");
/*if (!listenServer)
{
//WorldStateManager.Init();
clientWorldStateManager = new WorldStateManager(isClient: true);
}
else
{
clientWorldStateManager = new WorldStateManager(isLocalClient: true);
}*/
World.InitClient();
Scripting.Update += OnClientNetworkUpdate;
if (!listenServer)
{
Scripting.Exit += Cleanup;
//Level.ActorSpawned += OnClientActorSpawned;
}
string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}_v2.gdem");
RecordDemo(demoPath);
return true;
}
private static void OnClientNetworkUpdate()
{
using var _ = Utilities.ProfileScope("NetworkManager_OnClientNetworkUpdate");
while (client.PopEvent(out NetworkEvent networkEvent))
{
RecordMessage(ref networkEvent);
try
{
//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:
{
foreach (var func in OnClientConnectedDelegates)
func(networkEvent.Sender);
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, CollectionsMarshal.AsSpan(OnClientMessageDelegates));
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();
}
DebugLastHandledMessage = "";
}
private static void OnClientActorSpawned(Actor actor)
{
}
}