200 lines
6.4 KiB
C#
200 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using FlaxEditor;
|
|
using FlaxEngine;
|
|
using FlaxEngine.Assertions;
|
|
using FlaxEngine.Networking;
|
|
using Console = Game.Console;
|
|
|
|
namespace Game
|
|
{
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
public class NetworkPredictedAttribute : Attribute
|
|
{
|
|
}
|
|
|
|
// TODO: insert code to update variables with this attribute?
|
|
// rename to NetworkReplicatedAttribute?
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
public class NetworkedAttribute : Attribute
|
|
{
|
|
}
|
|
|
|
// NetworkMulticastAttribute: calls methods marked with this in all clients
|
|
|
|
public enum NetworkMessageType : byte
|
|
{
|
|
Handshake = 1,
|
|
Message
|
|
}
|
|
|
|
|
|
public static partial class NetworkManager
|
|
{
|
|
public delegate bool OnMessageDecl(ref NetworkEvent networkEvent);
|
|
|
|
private static bool initialized;
|
|
|
|
public static NetworkPeer server;
|
|
public static NetworkPeer client;
|
|
|
|
private static readonly ushort ServerPort = 59183;
|
|
private static string ServerAddress;
|
|
private static readonly ushort MTU = 1500;
|
|
private static readonly ushort MaximumClients = 32;
|
|
|
|
private static List<OnMessageDecl> OnClientMessageDelegates = new(3);
|
|
private static List<OnMessageDecl> OnServerMessageDelegates = new(3);
|
|
|
|
public static void RegisterClientMessageCallback(OnMessageDecl deleg)
|
|
{
|
|
Assert.IsTrue(!OnClientMessageDelegates.Contains(deleg));
|
|
OnClientMessageDelegates.Add(deleg);
|
|
}
|
|
public static void UnregisterClientMessageCallback(OnMessageDecl deleg)
|
|
{
|
|
Assert.IsTrue(OnClientMessageDelegates.Contains(deleg));
|
|
OnClientMessageDelegates.Remove(deleg);
|
|
}
|
|
|
|
public static void RegisterServerMessageCallback(OnMessageDecl deleg)
|
|
{
|
|
Assert.IsTrue(!OnServerMessageDelegates.Contains(deleg));
|
|
OnServerMessageDelegates.Add(deleg);
|
|
}
|
|
public static void UnregisterServerMessageCallback(OnMessageDecl deleg)
|
|
{
|
|
Assert.IsTrue(OnServerMessageDelegates.Contains(deleg));
|
|
OnServerMessageDelegates.Remove(deleg);
|
|
}
|
|
|
|
public static string DebugLastHandledMessage = "";
|
|
|
|
//public static bool IsServer = false;
|
|
//public static bool IsClient = false;
|
|
// static bool IsLocalClient = false; // Context dependant, true when message is handled by local client
|
|
|
|
public static void Init()
|
|
{
|
|
if (initialized)
|
|
return;
|
|
|
|
/*if (Engine.CommandLine.Contains("-server"))
|
|
{
|
|
StartServer();
|
|
ServerAddress = "localhost";
|
|
ConnectServer();
|
|
}
|
|
else if (Engine.CommandLine.Contains("-client"))
|
|
{
|
|
ServerAddress = "localhost";
|
|
ConnectServer();
|
|
}
|
|
//#if FLAX_EDITOR
|
|
else
|
|
{
|
|
StartServer();
|
|
ServerAddress = "localhost";
|
|
ConnectServer();
|
|
}*/
|
|
//#endif
|
|
|
|
initialized = true;
|
|
#if FLAX_EDITOR
|
|
Editor.Instance.PlayModeEnd += Cleanup;
|
|
#endif
|
|
|
|
//WorldStateManager.Init(); // FIXME
|
|
}
|
|
|
|
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)
|
|
{
|
|
NetworkPeer.ShutdownPeer(server);
|
|
server = null;
|
|
}
|
|
|
|
if (client != null)
|
|
{
|
|
NetworkPeer.ShutdownPeer(client);
|
|
client = null;
|
|
}
|
|
|
|
LocalPlayerClientId = 0;
|
|
|
|
#if FLAX_EDITOR
|
|
Editor.Instance.PlayModeEnd -= Cleanup;
|
|
//GameModeManager.Cleanup(); // FIXME
|
|
#endif
|
|
if (clientWorldStateManager != null)
|
|
{
|
|
clientWorldStateManager.Cleanup();
|
|
clientWorldStateManager = null;
|
|
}
|
|
|
|
StopRecording();
|
|
|
|
initialized = false;
|
|
}
|
|
|
|
private static void OnNetworkMessage(ref NetworkEvent networkEvent, Span<OnMessageDecl> funcs)
|
|
{
|
|
byte messageTypeByte = networkEvent.Message.ReadByte();
|
|
if (!Enum.IsDefined(typeof(NetworkMessageType), messageTypeByte))
|
|
{
|
|
Console.PrintError($"Unsupported message type received from client: {messageTypeByte}");
|
|
return;
|
|
}
|
|
|
|
NetworkMessageType messageType = (NetworkMessageType)messageTypeByte;
|
|
|
|
switch (messageType)
|
|
{
|
|
case NetworkMessageType.Handshake:
|
|
{
|
|
string message = networkEvent.Message.ReadString();
|
|
Console.Print($"Received handshake from {networkEvent.Sender.ConnectionId}, msg: " + message);
|
|
break;
|
|
}
|
|
case NetworkMessageType.Message:
|
|
{
|
|
var messageStartPosition = networkEvent.Message.Position;
|
|
foreach (var func in funcs)
|
|
{
|
|
networkEvent.Message.Position = messageStartPosition;
|
|
bool handled = func(ref networkEvent);
|
|
if (handled)
|
|
break;
|
|
}
|
|
|
|
//if (OnMessage != null)
|
|
/*{
|
|
// GetInvocationList() allocates, use allocation-free but unsafe way to iterate
|
|
//
|
|
//foreach (OnMessageDecl func in OnMessage.GetInvocationList()
|
|
// .Cast<OnMessageDecl>().ToArray())
|
|
foreach (OnMessageDecl func in OnMessageDelegates)
|
|
{
|
|
bool ret = func.Invoke(ref networkEvent);
|
|
if (ret)
|
|
break;
|
|
}
|
|
}*/
|
|
break;
|
|
}
|
|
default:
|
|
Console.PrintError($"Unsupported message type received from client: {messageTypeByte}");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} |