예제 #1
0
        /// <summary>
        /// Calculates how many bytes can be stored in the given message.
        /// </summary>
        /// <param name="message">The message in which the bytes will be stored.</param>
        /// <returns>The number of bytes that can be stored until the message is too big to be sent.</returns>
        public static int GetFreeByteElementCount(MessageIncomingMessageParts message)
        {
            message.Content = new byte[1];
            var xmlText = MyAPIGateway.Utilities.SerializeToXML <MessageContainer>(new MessageContainer()
            {
                Content = message
            });
            var oneEntry = System.Text.Encoding.UTF8.GetBytes(xmlText).Length;

            message.Content = new byte[4];
            xmlText         = MyAPIGateway.Utilities.SerializeToXML <MessageContainer>(new MessageContainer()
            {
                Content = message
            });
            var twoEntries = System.Text.Encoding.UTF8.GetBytes(xmlText).Length;

            // we calculate the difference between one and two entries in the array to get the count of bytes that describe one entry
            // we divide by 3 because 3 entries are stored in one block of the array
            var difference = (double)(twoEntries - oneEntry) / 3d;

            // get the size of the message without any entries
            var freeBytes = MAX_MESSAGE_SIZE - oneEntry - Math.Ceiling(difference);

            int count = (int)Math.Floor((double)freeBytes / difference);

            // finally we test if the calculation was right
            message.Content = new byte[count];
            xmlText         = MyAPIGateway.Utilities.SerializeToXML <MessageContainer>(new MessageContainer()
            {
                Content = message
            });
            var finalLength = System.Text.Encoding.UTF8.GetBytes(xmlText).Length;

            LSELogger.Instance.LogDebug(string.Format("FinalLength: {0}", finalLength));
            if (MAX_MESSAGE_SIZE >= finalLength)
            {
                return(count);
            }
            else
            {
                throw new Exception(string.Format("Calculation failed. OneEntry: {0}, TwoEntries: {1}, Difference: {2}, FreeBytes: {3}, Count: {4}, FinalLength: {5}", oneEntry, twoEntries, difference, freeBytes, count, finalLength));
            }
        }
예제 #2
0
        private static void SendMessageParts(byte[] byteData, MessageSide side, ulong receiver = 0)
        {
            LSELogger.Instance.LogDebug(string.Format("SendMessageParts {0} {1} {2}", byteData.Length, side, receiver));

            var byteList = byteData.ToList();

            while (byteList.Count > 0)
            {
                // we create an empty message part
                var messagePart = new MessageIncomingMessageParts()
                {
                    Side          = side,
                    SenderSteamId = side == MessageSide.ServerSide ? MyAPIGateway.Session.Player.SteamUserId : 0,
                    LastPart      = false,
                };

                try
                {
                    // let's check how much we could store in the message
                    int freeBytes = GetFreeByteElementCount(messagePart);

                    int count = freeBytes;

                    // we check if that might be the last message
                    if (freeBytes > byteList.Count)
                    {
                        messagePart.LastPart = true;

                        // since we changed LastPart, we should make sure that we are still able to send all the stuff
                        if (GetFreeByteElementCount(messagePart) > byteList.Count)
                        {
                            count = byteList.Count;
                        }
                        else
                        {
                            throw new Exception("Failed to send message parts. The leftover could not be sent!");
                        }
                    }

                    // fill the message with content
                    messagePart.Content = byteList.GetRange(0, count).ToArray();
                    var xmlPart = MyAPIGateway.Utilities.SerializeToXML <MessageContainer>(new MessageContainer()
                    {
                        Content = messagePart
                    });
                    var bytes = System.Text.Encoding.UTF8.GetBytes(xmlPart);

                    // and finally send the message
                    switch (side)
                    {
                    case MessageSide.ClientSide:
                        if (MyAPIGateway.Multiplayer.SendMessageTo(MessageId, bytes, receiver))
                        {
                            byteList.RemoveRange(0, count);
                        }
                        else
                        {
                            throw new Exception("Failed to send message parts to client.");
                        }
                        break;

                    case MessageSide.ServerSide:
                        if (MyAPIGateway.Multiplayer.SendMessageToServer(MessageId, bytes))
                        {
                            byteList.RemoveRange(0, count);
                        }
                        else
                        {
                            throw new Exception("Failed to send message parts to server.");
                        }
                        break;
                    }
                }
                catch (Exception ex)
                {
                    LSELogger.Instance.LogException(ex);
                    return;
                }
            }
        }