/// <summary> /// Send _outgoing immediately. /// </summary> private void SendOutgoing() { const int maxSize = 4088; List <byte> bytes; ResourcePool.Get(out bytes); AddIdAndValue(bytes); int initCount = bytes.Count; if (initCount > maxSize) { alwaysLog("Cannot send message, value is too large. byte count: " + initCount + ", value: " + _outgoing.Value); _outgoing = null; return; } for (int entityIdIndex = _outgoing.EntityId.Count - 1; entityIdIndex >= 0; --entityIdIndex) { ByteConverter.AppendBytes(bytes, _outgoing.EntityId[entityIdIndex]); if (bytes.Count > maxSize) { traceLog("Over max size, splitting message"); SendOutgoing(bytes); AddIdAndValue(bytes); } } SendOutgoing(bytes); _outgoing = null; bytes.Clear(); ResourcePool.Return(bytes); }
/// <summary> /// Clear bytes, add SudMod, _id, and _outgoing.Value. /// </summary> /// <param name="bytes">Message being prepared.</param> private void AddIdAndValue(List <byte> bytes) { bytes.Clear(); ByteConverter.AppendBytes(bytes, MessageHandler.SubMod.Sync); ByteConverter.AppendBytes(bytes, _id); ByteConverter.AppendBytes(bytes, _outgoing.Value); }
/// <summary> /// Inform the server to send message to autopilot block. /// </summary> private static void ToServer(long sender, string recipientGrid, string recipientBlock, string message) { Static.bytes.Clear(); ByteConverter.AppendBytes(Static.bytes, MessageHandler.SubMod.Message); ByteConverter.AppendBytes(Static.bytes, sender); ByteConverter.AppendBytes(Static.bytes, recipientGrid); ByteConverter.AppendBytes(Static.bytes, recipientBlock); ByteConverter.AppendBytes(Static.bytes, message); if (MyAPIGateway.Multiplayer.TrySendMessageToServer(Static.bytes.ToArray())) { Logger.DebugLog("Sent message to server"); } else { Logger.AlwaysLog("Message too long", Logger.severity.WARNING); IMyEntity entity; if (MyAPIGateway.Entities.TryGetEntityById(sender, out entity)) { IMyTerminalBlock block = entity as IMyTerminalBlock; if (block != null) { block.AppendCustomInfo("Failed to send message:\nMessage too long (" + Static.bytes.Count + " > 4096 bytes)\n"); } } } }
private void Server_ReceiveMessage(byte[] message, int pos) { try { if (message == null) { Logger.DebugLog("Message is null"); return; } if (message.Length < 8) { Logger.DebugLog("Message is too short: " + message.Length); return; } ulong SteamUserId = ByteConverter.GetUlong(message, ref pos); Logger.DebugLog("Received request from: " + SteamUserId); List <byte> send = new List <byte>(); ByteConverter.AppendBytes(send, (byte)MessageHandler.SubMod.ServerSettings); ByteConverter.AppendBytes(send, m_serverVersion.Major); ByteConverter.AppendBytes(send, m_serverVersion.Minor); ByteConverter.AppendBytes(send, m_serverVersion.Build); ByteConverter.AppendBytes(send, m_serverVersion.Revision); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAirResistanceBeta)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAllowAutopilot)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAllowGuidedMissile)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAllowHacker)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAllowRadar)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bAllowWeaponControl)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bImmortalMiner)); ByteConverter.AppendBytes(send, GetSetting <bool>(SettingName.bUseRemoteControl)); ByteConverter.AppendBytes(send, GetSetting <float>(SettingName.fDefaultSpeed)); ByteConverter.AppendBytes(send, GetSetting <float>(SettingName.fMaxSpeed)); ByteConverter.AppendBytes(send, GetSetting <float>(SettingName.fMaxWeaponRange)); if (MyAPIGateway.Multiplayer.SendMessageTo(ModID, send.ToArray(), SteamUserId)) { Logger.DebugLog("Sent settings to " + SteamUserId, Rynchodon.Logger.severity.INFO); } else { Logger.AlwaysLog("Failed to send settings to " + SteamUserId, Rynchodon.Logger.severity.ERROR); } } catch (Exception ex) { Logger.AlwaysLog("Exception: " + ex, Rynchodon.Logger.severity.ERROR); } }
/// <summary> /// Server sends message to clients to let them know the weapon is being controlled by engager. /// </summary> private static void SendToClient_EngagerControl(long entityId, bool control) { if (MyAPIGateway.Multiplayer.IsServer) { return; } List <byte> message = new List <byte>(); ByteConverter.AppendBytes(message, (byte)MessageHandler.SubMod.FW_EngagerControl); ByteConverter.AppendBytes(message, entityId); ByteConverter.AppendBytes(message, control); if (!MyAPIGateway.Multiplayer.SendMessageToOthers(MessageHandler.ModId, message.ToArray())) { Logger.AlwaysLog("Failed to send message", Logger.severity.ERROR); } }
public static SyncBuilder GetBuilder() { if (_syncs == null) { throw new Exception("Not initialized"); } List <byte> bytes = new List <byte>(8192); foreach (KeyValuePair <Id, ASync> idSync in _syncs) { if (idSync.Value._save) { Logger.TraceLog("saving: " + idSync.Key); ByteConverter.AppendBytes(bytes, idSync.Key); idSync.Value.WriteToSave(bytes); } } return(new SyncBuilder(bytes.ToArray())); }
protected override sealed void WriteToSave(List <byte> bytes) { if (!MyAPIGateway.Multiplayer.IsServer) { alwaysLog("Cannot write values, this is not the server", Logger.severity.ERROR); return; } Dictionary <TValue, List <long> > values = new Dictionary <TValue, List <long> >(); foreach (KeyValuePair <long, TScript> pair in Registrar.IdScripts <TScript>()) { TValue v = _getter(pair.Value); if (IsDefault(v)) { continue; } List <long> ids; if (!values.TryGetValue(v, out ids)) { ids = new List <long>(); values.Add(v, ids); } ids.Add(pair.Key); } ByteConverter.AppendBytes(bytes, values.Count); foreach (KeyValuePair <TValue, List <long> > valueEntity in values) { ByteConverter.AppendBytes(bytes, valueEntity.Key); ByteConverter.AppendBytes(bytes, valueEntity.Value.Count); foreach (long entity in valueEntity.Value) { ByteConverter.AppendBytes(bytes, entity); } } }
private void RequestSettingsFromServer() { if (MyAPIGateway.Session.Player == null) { Logger.AlwaysLog("Could not get player, not requesting server settings.", Rynchodon.Logger.severity.WARNING); m_settingsLoaded = true; return; } List <byte> bytes = new List <byte>(); ByteConverter.AppendBytes(bytes, (byte)MessageHandler.SubMod.ServerSettings); ByteConverter.AppendBytes(bytes, MyAPIGateway.Session.Player.SteamUserId); if (MyAPIGateway.Multiplayer.SendMessageToServer(ModID, bytes.ToArray())) { Logger.DebugLog("Sent request to server", Rynchodon.Logger.severity.INFO); } else { Logger.AlwaysLog("Failed to send request to server", Rynchodon.Logger.severity.ERROR); } }
private static void SendStatus(RemoteTask task) { m_message.Clear(); ByteConverter.AppendBytes(m_message, MessageHandler.SubMod.LoadDistribution); ByteConverter.AppendBytes(m_message, task.TaskId); ByteConverter.AppendBytes(m_message, task.CurrentStatus); if (task.CurrentStatus == Status.Success) { Type taskType = task.GetType(); foreach (FieldInfo field in taskType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.HasAttribute <ResultAttribute>()) { ByteConverter.AppendBytes(m_message, field.GetValue(task)); } } foreach (PropertyInfo property in taskType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (property.HasAttribute <ResultAttribute>()) { ByteConverter.AppendBytes(m_message, property.GetValue(task)); } } } Logger.TraceLog("Sending status for " + task); if (MyAPIGateway.Multiplayer.IsServer) { HandleStatus(m_message.ToArray(), 1); } else { MyAPIGateway.Multiplayer.SendMessageToServer(m_message.ToArray()); } }
private static void RequestValues() { if (MyAPIGateway.Multiplayer.IsServer) { throw new Exception("Cannot request values, this is the server"); } List <byte> bytes; ResourcePool.Get(out bytes); bytes.Clear(); ByteConverter.AppendBytes(bytes, MessageHandler.SubMod.SyncRequest); ByteConverter.AppendBytes(bytes, MyAPIGateway.Multiplayer.MyId); Logger.DebugLog("requesting values from server"); if (!MyAPIGateway.Multiplayer.SendMessageToServer(MessageHandler.ModId, bytes.ToArray())) { Logger.AlwaysLog("Failed to send message, length: " + bytes.Count, Logger.severity.ERROR); } bytes.Clear(); ResourcePool.Return(bytes); }
/* * Start message format: Sub Mod ID, TaskId, Task Type ID[, param] * Status message format: Sub Mod ID, TaskId, Status * Success message format: Sub Mod ID, TaskId, Status.Success[, result] */ /// <summary> /// Start a task on a client if possible, otherwise it will run on the server. /// </summary> /// <typeparam name="T">The type of task to start.</typeparam> /// <param name="task">The task to start.</param> public static void StartTask <T>(T task, bool runOnServer = false) where T : RemoteTask, new() { if (!MyAPIGateway.Multiplayer.IsServer) { throw new Exception("Not server"); } if (m_outstandingTask.Count >= 100) { #if DEBUG foreach (KeyValuePair <int, RemoteTask> pair in m_outstandingTask) { Logger.DebugLog("Task ID: " + pair.Key + ", Task: " + pair.Value); } #endif throw new Exception("Too many outstanding tasks"); } Type taskType = task.GetType(); foreach (KeyValuePair <byte, Type> pair in m_taskTypes) { if (pair.Value == taskType) { task.SteamId = runOnServer ? GetServerClient() : GetIdlemostClient(); task.TaskId = m_nextOutstandingTaskId++; while (m_outstandingTask.ContainsKey(task.TaskId)) { task.TaskId = m_nextOutstandingTaskId++; } m_message.Clear(); ByteConverter.AppendBytes(m_message, MessageHandler.SubMod.LoadDistribution); ByteConverter.AppendBytes(m_message, task.TaskId); ByteConverter.AppendBytes(m_message, pair.Key); foreach (FieldInfo field in taskType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (field.HasAttribute <ArgumentAttribute>()) { ByteConverter.AppendBytes(m_message, field.GetValue(task)); } } foreach (PropertyInfo property in taskType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (property.HasAttribute <ArgumentAttribute>()) { ByteConverter.AppendBytes(m_message, property.GetValue(task)); } } Logger.TraceLog("Sending task request: " + typeof(T) + ", " + pair.Key + ", " + task.TaskId + ", task: " + task + ", m_outstandingTask.Count: " + m_outstandingTask.Count); m_outstandingTask.Add(task.TaskId, task); task.StartMonitorTask(); if (task.SteamId == ServerKey || task.SteamId == MyAPIGateway.Multiplayer.MyId) { HandleStartRequest(m_message.ToArray(), 1); } else { MyAPIGateway.Multiplayer.SendMessageTo(m_message.ToArray(), task.SteamId); } return; } } throw new Exception("No task found of type: " + typeof(T)); }
public static void Update100() { #if PROFILE Profiler.StartProfileBlock(); try { #endif if (Static.AllGuidedMissiles.Count == 0) { return; } if (MyAPIGateway.Multiplayer.IsServer) { if (Static.SerialPositions == null) { Static.SerialPositions = new List <byte>(); } else { Static.SerialPositions.Clear(); } ByteConverter.AppendBytes(Static.SerialPositions, MessageHandler.SubMod.GuidedMissile); } for (int index = Static.AllGuidedMissiles.Count - 1; index >= 0; index--) { GuidedMissile missile = Static.AllGuidedMissiles[index]; try { if (!missile.Stopped) { missile.ClearBlacklist(); if (missile.m_gravData != null) { missile.UpdateGravity(); } } if (!missile.Stopped) { missile.UpdateNetwork(); } if (MyAPIGateway.Multiplayer.IsServer && Static.SerialPositions.Count < 4000) // message fails at 4096 { ByteConverter.AppendBytes(Static.SerialPositions, missile.MyEntity.PositionComp.GetPosition()); ByteConverter.AppendBytes(Static.SerialPositions, missile.MyEntity.Physics.LinearVelocity); } } catch (Exception ex) { Logger.AlwaysLog("Exception with missile: " + missile.MyEntity + ":\n" + ex); Static.AllGuidedMissiles.Remove(missile); } } if (MyAPIGateway.Multiplayer.IsServer) { if (!MyAPIGateway.Multiplayer.SendMessageToOthers(MessageHandler.ModId, Static.SerialPositions.ToArray(), false)) { Logger.AlwaysLog("Missile sync failed, too many missiles in play: " + Static.AllGuidedMissiles.Count + ", byte count: " + Static.SerialPositions.Count); } } #if PROFILE } finally { Profiler.EndProfileBlock(); } #endif }