Пример #1
0
        /// <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);
        }
Пример #2
0
 /// <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);
 }
Пример #3
0
        /// <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");
                    }
                }
            }
        }
Пример #4
0
        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); }
        }
Пример #5
0
        /// <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);
            }
        }
Пример #6
0
        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()));
        }
Пример #7
0
        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);
                }
            }
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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());
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        /*
         * 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));
        }
Пример #12
0
        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
        }