/// <summary> /// Sends a command packet to the client(s) /// </summary> /// <param name="cmd">The object to be sent to the client</param> /// <param name="steamId">The players steam id</param> /// <param name="isReliable">Make sure the data arrives</param> internal override void SendCommand(Command cmd, ulong steamId = ulong.MinValue, bool isReliable = true) { if (cmd.Data != null && cmd.Data.Length > CompressionThreshold) { cmd.Data = MyCompression.Compress(cmd.Data); cmd.IsCompressed = true; } if (!string.IsNullOrWhiteSpace(cmd.Message) && MyAPIGateway.Multiplayer.IsServer && MyAPIGateway.Session != null) { MyAPIGateway.Utilities.ShowMessage(ModName, cmd.Message); } byte[] packet = MyAPIGateway.Utilities.SerializeToBinary(cmd); if (LogNetworkTraffic) { MyLog.Default.Info($"[NetworkAPI] TRANSMITTING Bytes: {packet.Length} Command: {cmd.CommandString} User: {steamId}"); } if (steamId == ulong.MinValue) { MyAPIGateway.Multiplayer.SendMessageToOthers(ComId, packet, isReliable); } else { MyAPIGateway.Multiplayer.SendMessageTo(ComId, packet, steamId, isReliable); } }
private static bool Prefix() { if (!Game.IsDedicated || MyGameService.GameServer == null) { return(true); } byte[] array; using (var memoryStream = new MemoryStream()) { var settings = (MyObjectBuilder_SessionSettings)_memberwiseClone(MySession.Static.Settings); settings.BlockTypeLimits = new SerializableDictionary <string, short>(); var myServerData = new MyCachedServerItem.MyServerData { Settings = settings, ExperimentalMode = MySession.Static.IsSettingsExperimental(), // to determinate "it's not a vanilla" Mods = new List <WorkshopId> { new WorkshopId(1406994352, "Steam") }, Description = MySandboxGame.ConfigDedicated?.ServerDescription }; Serializer.Serialize(memoryStream, myServerData); array = MyCompression.Compress(memoryStream.ToArray()); } MyGameService.GameServer.SetKeyValue("sc", array.Length.ToString()); for (var i = 0; i < Math.Ceiling(array.Length / 93.0); i++) { byte[] part; var partLength = array.Length - 93 * i; if (partLength >= 93) { part = new byte[93]; Array.Copy(array, i * 93, part, 0, 93); } else { part = new byte[partLength]; Array.Copy(array, i * 93, part, 0, partLength); } MyGameService.GameServer.SetKeyValue($"sc{i}", Convert.ToBase64String(part)); } return(false); }
/// <summary> /// Sends a command packet to the server /// </summary> /// <param name="cmd">The object to be sent to the client</param> /// <param name="steamId">The users steam ID</param> /// <param name="isReliable">Makes sure the message is recieved by the server</param> internal override void SendCommand(Command cmd, ulong steamId = ulong.MinValue, bool isReliable = true) { if (cmd.Data != null && cmd.Data.Length > CompressionThreshold) { cmd.Data = MyCompression.Compress(cmd.Data); cmd.IsCompressed = true; } cmd.Timestamp = DateTime.UtcNow.Ticks; byte[] packet = MyAPIGateway.Utilities.SerializeToBinary(cmd); if (LogNetworkTraffic) { MyLog.Default.Info($"[NetworkAPI] TRANSMITTING Bytes: {packet.Length} Command: {cmd.CommandString} User: {steamId}"); } MyAPIGateway.Multiplayer.SendMessageToServer(ComId, packet, isReliable); }
/// <summary> /// Sends a command packet to the client(s) /// </summary> /// <param name="cmd">The object to be sent to the client</param> /// <param name="point">the center of the sync location</param> /// <param name="radius">the distance the message reaches (defaults to sync distance)</param> /// <param name="steamId">The players steam id</param> /// <param name="isReliable">Make sure the data arrives</param> internal override void SendCommand(Command cmd, Vector3D point, double radius = 0, ulong steamId = ulong.MinValue, bool isReliable = true) { if (cmd.Data != null && cmd.Data.Length > CompressionThreshold) { cmd.Data = MyCompression.Compress(cmd.Data); cmd.IsCompressed = true; } if (radius == 0) { radius = MyAPIGateway.Session.SessionSettings.SyncDistance; } List <IMyPlayer> players = new List <IMyPlayer>(); if (steamId == ulong.MinValue) { MyAPIGateway.Players.GetPlayers(players, (p) => (p.GetPosition() - point).LengthSquared() < (radius * radius) && p.SteamUserId != cmd.SteamId); } else { MyAPIGateway.Players.GetPlayers(players, p => p.SteamUserId == steamId); } if (!string.IsNullOrWhiteSpace(cmd.Message) && MyAPIGateway.Multiplayer.IsServer && MyAPIGateway.Session != null) { MyAPIGateway.Utilities.ShowMessage(ModName, cmd.Message); } cmd.Timestamp = DateTime.UtcNow.Ticks; byte[] packet = MyAPIGateway.Utilities.SerializeToBinary(cmd); if (LogNetworkTraffic) { MyLog.Default.Info($"[NetworkAPI] _TRANSMITTING_ Bytes: {packet.Length} Command: {cmd.CommandString} To: {players.Count} Users within {radius}m"); } foreach (IMyPlayer player in players) { MyAPIGateway.Multiplayer.SendMessageTo(ComId, packet, player.SteamUserId, isReliable); } }
public byte[] GetCompressedData() { MemoryStream ms; byte[] copy; using (ms = MemoryStream.CreateEmptyStream(0x4000)) { ms.Write(STORAGE_TYPE_NAME_OCTREE); ms.Write7BitEncodedInt(STORAGE_TYPE_VERSION_OCTREE); SaveInternal(ms); copy = new byte[ms.WriteHead]; Array.Copy(ms.Backing, 0, copy, 0, ms.WriteHead); } var lenPData = MyCompression.Compress(copy); // Compress adds an int for some reason. var output = new byte[lenPData.Length - 4]; Array.Copy(lenPData, 4, output, 0, lenPData.Length - 4); return(output); }
public static void DoProcessing() { while (!_closing) { try { byte[] incoming; while (_incoming.TryDequeue(out incoming)) { MessageBase m; try { var o = MyCompression.Decompress(incoming); m = MyAPIGateway.Utilities.SerializeFromBinary <MessageBase>(o); } catch (Exception ex) { MyLog.Default.WriteLineAndConsole($"TORCH MOD: Failed to deserialize message! {ex}"); continue; } if (MyAPIGateway.Multiplayer.IsServer) { m.ProcessServer(); } else { m.ProcessClient(); } } if (!_outgoing.IsEmpty) { List <MessageBase> tosend = new List <MessageBase>(_outgoing.Count); MessageBase outMessage; while (_outgoing.TryDequeue(out outMessage)) { var b = MyAPIGateway.Utilities.SerializeToBinary(outMessage); outMessage.CompressedData = MyCompression.Compress(b); tosend.Add(outMessage); } MyAPIGateway.Utilities.InvokeOnGameThread(() => { MyAPIGateway.Players.GetPlayers(_playerCache); foreach (var outgoing in tosend) { switch (outgoing.TargetType) { case MessageTarget.Single: MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, outgoing.Target); break; case MessageTarget.Server: MyAPIGateway.Multiplayer.SendMessageToServer(NET_ID, outgoing.CompressedData); break; case MessageTarget.AllClients: foreach (var p in _playerCache) { if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId) { continue; } MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, p.SteamUserId); } break; case MessageTarget.AllExcept: foreach (var p in _playerCache) { if (p.SteamUserId == MyAPIGateway.Multiplayer.MyId || outgoing.Ignore.Contains(p.SteamUserId)) { continue; } MyAPIGateway.Multiplayer.SendMessageTo(NET_ID, outgoing.CompressedData, p.SteamUserId); } break; default: throw new Exception(); } } _playerCache.Clear(); }); } AcquireLock(); } catch (Exception ex) { MyLog.Default.WriteLineAndConsole($"TORCH MOD: Exception occurred in communication thread! {ex}"); } } MyLog.Default.WriteLineAndConsole("TORCH MOD: COMMUNICATION THREAD: EXIT SIGNAL RECIEVED!"); //exit signal received. Clean everything and GTFO _outgoing = null; _incoming = null; _playerCache = null; _lock = null; }
public static byte[] Compress(this byte[] data) { return(MyCompression.Compress(data)); }
public static void DoProcessing() { 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 <MessageBase>(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; }
public static void DoProcessing() { while (!_closing) { try { var m = _processing.Take(); MyLog.Default.WriteLineAndConsole($"Processing message: {m.GetType().Name}"); if (m is IncomingMessage) { MessageBase i; try { var o = MyCompression.Decompress(m.CompressedData); m.CompressedData = null; _messagePool.Return((IncomingMessage)m); i = MyAPIGateway.Utilities.SerializeFromBinary <MessageBase>(o); } catch (Exception ex) { MyLog.Default.WriteLineAndConsole($"TORCH MOD: Failed to deserialize message! {ex}"); continue; } if (MyAPIGateway.Multiplayer.IsServer) { i.ProcessServer(); } else { i.ProcessClient(); } } else { var b = MyAPIGateway.Utilities.SerializeToBinary(m); m.CompressedData = MyCompression.Compress(b); MyAPIGateway.Utilities.InvokeOnGameThread(() => { 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: COMMUNICATION THREAD: EXIT SIGNAL RECEIVED!"); //exit signal received. Clean everything and GTFO _processing?.Dispose(); _processing = null; _messagePool?.Clean(); _messagePool = null; _playerCache = null; }