using System; using System.Linq; 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 bool ConnectServer(string serverAddress = "localhost", bool listenServer = false) { if (!listenServer) { Cleanup(); GameModeManager.Init(); } ServerAddress = serverAddress; //var driver = Object.New(typeof(ENetDriver)); //ClientNetworkDriver = null; NetworkLagDriver driver = Object.New(); driver.Lag = 0f; ClientNetworkDriver = driver; client = NetworkPeer.CreatePeer(new NetworkConfig { NetworkDriver = 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; } Scripting.FixedUpdate += OnClientUpdate; if (!listenServer) { Scripting.Exit += Cleanup; Level.ActorSpawned += OnClientActorSpawned; } return true; } private static void OnClientUpdate() { using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnClientUpdate"); while (client.PopEvent(out NetworkEvent networkEvent)) 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: { 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(); } } private static void OnClientActorSpawned(Actor actor) { } } }