diff --git a/Torch.Mod/Messages/IncomingMessage.cs b/Torch.Mod/Messages/IncomingMessage.cs deleted file mode 100644 index 114a89d..0000000 --- a/Torch.Mod/Messages/IncomingMessage.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Torch.Mod.Messages -{ - /// - /// shim to store incoming message data - /// - internal class IncomingMessage : MessageBase - { - public IncomingMessage() - { - } - - public override void ProcessClient() - { - throw new Exception(); - } - - public override void ProcessServer() - { - throw new Exception(); - } - } -} diff --git a/Torch.Mod/Messages/JoinServerMessage.cs b/Torch.Mod/Messages/JoinServerMessage.cs index ffc8ab0..c13cc35 100644 --- a/Torch.Mod/Messages/JoinServerMessage.cs +++ b/Torch.Mod/Messages/JoinServerMessage.cs @@ -32,11 +32,6 @@ namespace Torch.Mod.Messages public override void ProcessClient() { - if (TorchModCore.Debug) - { - MyAPIGateway.Utilities.ShowMessage("Torch", $"Joining server {Address} with delay {Delay}"); - } - if (Delay <= 0) { MyAPIGateway.Multiplayer.JoinServer(Address); diff --git a/Torch.Mod/Messages/MessageBase.cs b/Torch.Mod/Messages/MessageBase.cs index 55bc140..212b113 100644 --- a/Torch.Mod/Messages/MessageBase.cs +++ b/Torch.Mod/Messages/MessageBase.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ProtoBuf; +using ProtoBuf; namespace Torch.Mod.Messages { @@ -17,36 +12,9 @@ namespace Torch.Mod.Messages [ProtoContract] public abstract class MessageBase { - [ProtoMember(101)] public ulong SenderId; public abstract void ProcessClient(); public abstract void ProcessServer(); - - //members below not serialized, they're just metadata about the intended target(s) of this message - internal MessageTarget TargetType; - internal ulong Target; - internal ulong[] Ignore; - internal byte[] CompressedData; - } - - public enum MessageTarget - { - /// - /// Send to Target - /// - Single, - /// - /// Send to Server - /// - Server, - /// - /// Send to all Clients (only valid from server) - /// - AllClients, - /// - /// Send to all except those steam ID listed in Ignore - /// - AllExcept, } } diff --git a/Torch.Mod/ModCommunication.cs b/Torch.Mod/ModCommunication.cs index 76be249..deb14db 100644 --- a/Torch.Mod/ModCommunication.cs +++ b/Torch.Mod/ModCommunication.cs @@ -1,161 +1,50 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; using Sandbox.ModAPI; using Torch.Mod.Messages; -using VRage; -using VRage.Collections; +using VRage.Game.Components; using VRage.Game.ModAPI; -using VRage.Network; -using VRage.Utils; -using Task = ParallelTasks.Task; +#if TORCH +using Torch.Utils; +using VRage.Library.Collections; +using System.Reflection; +#endif namespace Torch.Mod { - public static class ModCommunication + [MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)] + public class ModCommunication : MySessionComponentBase { - public const ushort NET_ID = 4352; - private static bool _closing = false; - private static BlockingCollection _processing; - private static MyConcurrentPool _messagePool; - private static List _playerCache; + public const ulong MOD_ID = 2915950488; + private const ushort CHANNEL = 7654; - public static void Register() + public override void BeforeStart() { - MyLog.Default.WriteLineAndConsole("TORCH MOD: Registering mod communication."); - _processing = new BlockingCollection(new ConcurrentQueue()); - _playerCache = new List(); - _messagePool = new MyConcurrentPool(8); - - MyAPIGateway.Multiplayer.RegisterMessageHandler(NET_ID, MessageHandler); - //background thread to handle de/compression and processing - _closing = false; - MyAPIGateway.Parallel.StartBackground(DoProcessing); - MyLog.Default.WriteLineAndConsole("TORCH MOD: Mod communication registered successfully."); + base.BeforeStart(); + MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(CHANNEL, MessageHandler); } - public static void Unregister() + private void MessageHandler(ushort channel, byte[] data, ulong sender, bool fromServer) { - MyLog.Default.WriteLineAndConsole("TORCH MOD: Unregistering mod communication."); - MyAPIGateway.Multiplayer?.UnregisterMessageHandler(NET_ID, MessageHandler); - _processing?.CompleteAdding(); - _closing = true; - //_task.Wait(); + if (!fromServer) + return; + + var message = MyAPIGateway.Utilities.SerializeFromBinary(data); + message.SenderId = sender; + + if (MyAPIGateway.Multiplayer.IsServer) message.ProcessServer(); + else message.ProcessClient(); } - private static void MessageHandler(byte[] bytes) - { - var m = _messagePool.Get(); - m.CompressedData = bytes; #if TORCH - m.SenderId = MyEventContext.Current.Sender.Value; -#endif + [ReflectedMethodInfo(typeof(MyAPIUtilities), "VRage.Game.ModAPI.IMyUtilities.SerializeToBinary")] + private static MethodInfo _serializeMethod = null!; - _processing.Add(m); - } + private static readonly CacheList Players = new(); - public static void DoProcessing() + private static byte[] Serialize(MessageBase message) { - while (!_closing) - { - try - { - MessageBase m; - try - { - m = _processing.Take(); - } - catch - { - continue; - } - - MyLog.Default.WriteLineAndConsole($"Processing message: {m.GetType().Name}"); - - if (m is IncomingMessage) //process incoming messages - { - MessageBase i; - try - { - var o = MyCompression.Decompress(m.CompressedData); - m.CompressedData = null; - _messagePool.Return((IncomingMessage)m); - i = MyAPIGateway.Utilities.SerializeFromBinary(o); - } - catch (Exception ex) - { - MyLog.Default.WriteLineAndConsole($"TORCH MOD: Failed to deserialize message! {ex}"); - continue; - } - - if (TorchModCore.Debug) - MyAPIGateway.Utilities.ShowMessage("Torch", $"Received message of type {i.GetType().Name}"); - - if (MyAPIGateway.Multiplayer.IsServer) - i.ProcessServer(); - else - i.ProcessClient(); - } - else //process outgoing messages - { - if (TorchModCore.Debug) - MyAPIGateway.Utilities.ShowMessage("Torch", $"Sending message of type {m.GetType().Name}"); - - var b = MyAPIGateway.Utilities.SerializeToBinary(m); - m.CompressedData = MyCompression.Compress(b); - - switch (m.TargetType) - { - case MessageTarget.Single: - MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, m.Target); - break; - case MessageTarget.Server: - MyAPIGateway.Multiplayer.SendMessageToServer(NET_ID, m.CompressedData); - break; - case MessageTarget.AllClients: - MyAPIGateway.Players.GetPlayers(_playerCache); - foreach (var p in _playerCache) - { - if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId) - continue; - MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, p.SteamUserId); - } - - break; - case MessageTarget.AllExcept: - MyAPIGateway.Players.GetPlayers(_playerCache); - foreach (var p in _playerCache) - { - if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId || m.Ignore.Contains(p.SteamUserId)) - continue; - MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, m.CompressedData, p.SteamUserId); - } - - break; - default: - throw new Exception(); - } - - _playerCache.Clear(); - } - } - catch (Exception ex) - { - MyLog.Default.WriteLineAndConsole($"TORCH MOD: Exception occurred in communication thread! {ex}"); - } - } - - MyLog.Default.WriteLineAndConsole("TORCH MOD: INFO: Communication thread shut down successfully! THIS IS NOT AN ERROR"); - //exit signal received. Clean everything and GTFO - _processing?.Dispose(); - _processing = null; - _messagePool?.Clean(); - _messagePool = null; - _playerCache = null; + return (byte[])_serializeMethod.MakeGenericMethod(message.GetType()) + .Invoke(MyAPIGateway.Utilities, new object[] { message }); } public static void SendMessageTo(MessageBase message, ulong target) @@ -163,12 +52,7 @@ namespace Torch.Mod if (!MyAPIGateway.Multiplayer.IsServer) throw new Exception("Only server can send targeted messages"); - if (_closing) - return; - - message.Target = target; - message.TargetType = MessageTarget.Single; - _processing.Add(message); + MyAPIGateway.Multiplayer.SendMessageTo(CHANNEL, Serialize(message), target); } public static void SendMessageToClients(MessageBase message) @@ -176,11 +60,7 @@ namespace Torch.Mod if (!MyAPIGateway.Multiplayer.IsServer) throw new Exception("Only server can send targeted messages"); - if (_closing) - return; - - message.TargetType = MessageTarget.AllClients; - _processing.Add(message); + MyAPIGateway.Multiplayer.SendMessageToOthers(CHANNEL, Serialize(message)); } public static void SendMessageExcept(MessageBase message, params ulong[] ignoredUsers) @@ -188,21 +68,20 @@ namespace Torch.Mod if (!MyAPIGateway.Multiplayer.IsServer) throw new Exception("Only server can send targeted messages"); - if (_closing) - return; + using var players = Players; + MyAPIGateway.Multiplayer.Players.GetPlayers(players, player => !ignoredUsers.Contains(player.SteamUserId)); - message.TargetType = MessageTarget.AllExcept; - message.Ignore = ignoredUsers; - _processing.Add(message); + var data = Serialize(message); + foreach (var player in players) + { + MyAPIGateway.Multiplayer.SendMessageTo(CHANNEL, data, player.SteamUserId); + } } public static void SendMessageToServer(MessageBase message) { - if (_closing) - return; - - message.TargetType = MessageTarget.Server; - _processing.Add(message); + throw new NotSupportedException(); } +#endif } } diff --git a/Torch.Mod/Torch.Mod.projitems b/Torch.Mod/Torch.Mod.projitems index 8ab2e95..1142029 100644 --- a/Torch.Mod/Torch.Mod.projitems +++ b/Torch.Mod/Torch.Mod.projitems @@ -9,13 +9,11 @@ Torch.Mod - - \ No newline at end of file diff --git a/Torch.Mod/TorchModCore.cs b/Torch.Mod/TorchModCore.cs deleted file mode 100644 index 7767b2e..0000000 --- a/Torch.Mod/TorchModCore.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Sandbox.ModAPI; -using VRage.Game.Components; - -namespace Torch.Mod -{ - [MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)] - public class TorchModCore : MySessionComponentBase - { - public const ulong MOD_ID = 2722000298; - private static bool _init; - public static bool Debug; - - public override void UpdateAfterSimulation() - { - if (_init) - return; - - _init = true; - ModCommunication.Register(); - MyAPIGateway.Utilities.MessageEntered += Utilities_MessageEntered; - } - - private void Utilities_MessageEntered(string messageText, ref bool sendToOthers) - { - if (messageText == "@!debug") - { - Debug = !Debug; - MyAPIGateway.Utilities.ShowMessage("Torch", $"Debug: {Debug}"); - sendToOthers = false; - } - } - - protected override void UnloadData() - { - try - { - MyAPIGateway.Utilities.MessageEntered -= Utilities_MessageEntered; - ModCommunication.Unregister(); - } - catch - { - //session unloading, don't care - } - } - } -} diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs index 0849374..25a8196 100644 --- a/Torch.Server/Managers/InstanceManager.cs +++ b/Torch.Server/Managers/InstanceManager.cs @@ -146,7 +146,7 @@ namespace Torch.Server.Managers { DedicatedConfig.Mods.Clear(); //remove the Torch mod to avoid running multiple copies of it - DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == TorchModCore.MOD_ID); + DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == ModCommunication.MOD_ID); foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods) DedicatedConfig.Mods.Add(new ModItemInfo(m)); Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync()); @@ -161,7 +161,7 @@ namespace Torch.Server.Managers { DedicatedConfig.Mods.Clear(); //remove the Torch mod to avoid running multiple copies of it - DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == TorchModCore.MOD_ID); + DedicatedConfig.SelectedWorld.WorldConfiguration.Mods.RemoveAll(m => m.PublishedFileId == ModCommunication.MOD_ID); foreach (var m in DedicatedConfig.SelectedWorld.WorldConfiguration.Mods) DedicatedConfig.Mods.Add(new ModItemInfo(m)); Task.Run(() => DedicatedConfig.UpdateAllModInfosAsync()); diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index 6342c56..df708eb 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -242,14 +242,12 @@ namespace Torch.Server case TorchSessionState.Unloading: _watchdog?.Dispose(); _watchdog = null; - ModCommunication.Unregister(); break; case TorchSessionState.Loaded: _multiplayerManagerDedicated = CurrentSession.Managers.GetManager(); _multiplayerManagerDedicated.PlayerJoined += MultiplayerManagerDedicatedOnPlayerJoined; _multiplayerManagerDedicated.PlayerLeft += MultiplayerManagerDedicatedOnPlayerLeft; CurrentSession.Managers.GetManager().RegisterCommandModule(typeof(WhitelistCommands)); - ModCommunication.Register(); break; case TorchSessionState.Loading: case TorchSessionState.Unloaded: diff --git a/Torch/Session/TorchSessionManager.cs b/Torch/Session/TorchSessionManager.cs index 3cfb711..09b4b96 100644 --- a/Torch/Session/TorchSessionManager.cs +++ b/Torch/Session/TorchSessionManager.cs @@ -50,7 +50,7 @@ namespace Torch.Session { _overrideMods = new Dictionary(); if (Torch.Config.UgcServiceType == UGCServiceType.Steam) - _overrideMods.Add(TorchModCore.MOD_ID, ModItemUtils.Create(TorchModCore.MOD_ID)); + _overrideMods.Add(ModCommunication.MOD_ID, ModItemUtils.Create(ModCommunication.MOD_ID)); } /// diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj index 6c2db3e..644196c 100644 --- a/Torch/Torch.csproj +++ b/Torch/Torch.csproj @@ -13,6 +13,7 @@ AnyCPU true true + TRACE;TORCH