// An ItemTicket version to increase efficiency for the host
    void TicketValidityCheck(ItemTicket ticket, NetworkMessageInfo message)
    {
        // We know that DetermineTicketIndex will either return a correct index or an invalid index if it doesn't work
        int index = DetermineTicketIndex(ticket);

        // Using the validity of the index we can tell if the ticket is available and then check if it's still valid
        bool response = IsValidIndex(index) && m_requestTickets[index].IsValid();

        // Silly Unity workaround
        if (message.Equals(m_blankMessage))
        {
            RespondToTicketValidityCheck(response);
        }

        else
        {
            networkView.RPC("RespondToTicketValidityCheck", message.sender, response);
        }
    }
    void RequestItem(int itemID, int preferredIndex, NetworkMessageInfo message)
    {
        if (Network.isServer)
        {
            ItemTicket ticket = new ItemTicket();

            int index = DetermineDesiredIndex(itemID, preferredIndex, RequestCheck.Unrequested);

            if (IsValidIndex(index))
            {
                // Create the ticket
                ticket.uniqueID  = ticketNumber++;
                ticket.itemID    = itemID;
                ticket.itemIndex = index;

                // Ensure the item is successfully reserved
                ReserveItem(index, ticket);
            }

            // Else send back an invalid ticket
            //Debug.Log("Index: " + index + ", itemID: " + itemID + ", preferredIndex: " + preferredIndex + ".");

            // This is the only way I've found to check if the message is blank, an alternative method would be preferable
            if (message.Equals(m_blankMessage))
            {
                RespondToItemRequest(ticket);
            }

            else
            {
                networkView.RPC("RespondToItemRequest", message.sender, ticket.uniqueID, ticket.itemID, ticket.itemIndex);
            }
        }

        else
        {
            ResetResponse(true);
            Debug.LogError("A client attempted to call RequestItem in NetworkInventory.");
        }
    }
    void RequestAdd(int itemID, int index, bool adminMode, NetworkMessageInfo info)
    {
        if (Network.isServer)
        {
            // Create the default response
            ItemTicket ticket = new ItemTicket(-1, itemID, index);

            // We now need to check if the itemID is valid
            if (itemID >= 0)
            {
                bool isValidIndex = IsValidIndex(index);

                // An item can only be requested to be replaced if the item hasn't been requested or we're running in admin mode
                if (!isValidIndex || !m_isItemRequested[index] || adminMode)
                {
                    if (isValidIndex)
                    {
                        // Check to see if the item at the index is null, if so we know it is an add request.
                        if (!m_inventory[index])
                        {
                            if (!IsInventoryFull())
                            {
                                ticket.uniqueID = ticketNumber++;
                                ++addRequests;

                                ReserveItem(index, ticket);
                            }
                        }

                        // We know it is a replace request so it doesn't matter if the inventory is full, we also know that the item
                        // is either unrequested or we have access to overwrite it because of the intial conditions.
                        else
                        {
                            ticket.uniqueID = ticketNumber++;

                            ReserveItem(index, ticket);
                        }
                    }

                    // If the index is invalid it should be added on to the end which is an add request.
                    else if (!IsInventoryFull())
                    {
                        ticket.uniqueID = ticketNumber++;
                        ++addRequests;

                        ReserveItem(index, ticket);
                    }
                }
            }


            // Silly workaround for RPC sending limitation
            if (info.Equals(m_blankMessage))
            {
                RespondToAddRequest(ticket);
            }

            else
            {
                networkView.RPC("RespondToAddRequest", info.sender, ticket.uniqueID, ticket.itemID, ticket.itemIndex);
            }
        }

        // A client called the function
        else
        {
            ResetResponse(true);
            Debug.LogError("A client attempted to call RequestAdd in NetworkInventory");
        }
    }
Example #4
0
 internal void SendRequiredModList(string modList, NetworkMessageInfo info)
 {
     GadgetCore.CoreLogger.Log("Client has sent local mod list. Processing...");
     try
     {
         bool             isCompatible        = true;
         List <string>    incompatibleReasons = new List <string>();
         HashSet <string> handledGadgets      = new HashSet <string>();
         string[][]       splitModList        = string.IsNullOrEmpty(modList) ? new string[0][] : modList.Split(',').Select(x => x.Split(':')).ToArray();
         foreach (GadgetInfo mod in Gadgets.ListAllGadgetInfos().Where(x => x.Gadget.Enabled && x.Attribute.RequiredOnClients))
         {
             handledGadgets.Add(mod.Attribute.Name);
             string clientVersion = splitModList.SingleOrDefault(x => x[0] == mod.Attribute.Name)?[1];
             if (clientVersion == null)
             {
                 isCompatible = false;
                 incompatibleReasons.Add($"The Gadget '{mod.Attribute.Name}' (From the mod '{mod.ModName}') is not present on the client");
                 continue;
             }
             int[] clientVersionNums = clientVersion.Split('.').Select(x => int.Parse(x)).Take(4).ToArray();
             int[] hostVersionNums   = mod.Gadget.GetModVersionString().Split('.').Select(x => int.Parse(x)).ToArray();
             hostVersionNums   = hostVersionNums.Concat(Enumerable.Repeat(0, 4 - hostVersionNums.Length)).ToArray();
             clientVersionNums = clientVersionNums.Concat(Enumerable.Repeat(0, 4 - clientVersionNums.Length)).ToArray();
             if (!((mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MAJOR && clientVersionNums[0] == hostVersionNums[0] && (clientVersionNums[1] > hostVersionNums[1] || (clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))))) ||
                   (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MINOR && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))) ||
                   (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.NONBREAKING && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]) ||
                   (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.BUGFIX && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] == hostVersionNums[3])))
             {
                 isCompatible = false;
                 incompatibleReasons.Add($"The Gadget '{mod.Attribute.Name}' (From the mod '{mod.ModName}') is of incompatible versions: Host: {mod.Gadget.GetModVersionString()}, Client: {clientVersion}");
                 continue;
             }
         }
         if (handledGadgets.Count != splitModList.Length)
         {
             isCompatible = false;
             foreach (string[] modEntry in splitModList.Where(x => !handledGadgets.Contains(x[0])))
             {
                 incompatibleReasons.Add($"The Gadget '{modEntry[0]}' (From an unknown mod) is present on the client, but not on the host");
             }
         }
         if (isCompatible)
         {
             if (info.Equals(serverNMI))
             {
                 GadgetCore.CoreLogger.Log("Self-connection succesfully established and identified.");
                 ReceiveIDMatrixData(GadgetNetwork.GenerateIDMatrixData());
             }
             else
             {
                 GadgetCore.CoreLogger.Log("A client connected with compatible mods: " + info.sender.ipAddress);
                 string matrixData = GadgetNetwork.GenerateIDMatrixData();
                 if (matrixData.Length <= 4096)
                 {
                     GadgetCore.CoreLogger.Log("Sending ID Matrix data as a single block...");
                     view.RPC("ReceiveIDMatrixData", info.sender, matrixData);
                 }
                 else
                 {
                     string[] splitMatrixData = matrixData.SplitOnLength(MaxChunkSize).ToArray();
                     GadgetCore.CoreLogger.Log($"Sending ID Matrix data as {splitMatrixData.Length} chunks...");
                     for (int i = 0; i < splitMatrixData.Length; i++)
                     {
                         view.RPC("ReceiveIDMatrixDataChunk", info.sender, splitMatrixData[i], i, splitMatrixData.Length);
                     }
                 }
             }
         }
         else
         {
             GadgetCore.CoreLogger.LogWarning("A client tried to connect with incompatible mods: " + info.sender.ipAddress +
                                              Environment.NewLine + " - " + incompatibleReasons.Concat(Environment.NewLine + " - "));
             if (Network.isServer)
             {
                 DisconnectWithMessage(info.sender, "Your mods are incompatible with the server:" + Environment.NewLine + " - " + incompatibleReasons.Concat(Environment.NewLine + " - "));
             }
             else
             {
                 Network.Disconnect();
             }
         }
     }
     catch (Exception e)
     {
         GadgetCore.CoreLogger.LogWarning("The following error occured processing an incoming client's mod list: " + info.sender.ipAddress + Environment.NewLine + modList + Environment.NewLine + e.ToString());
         if (Network.isServer)
         {
             DisconnectWithMessage(info.sender, "An error occured processing your mod list:" + Environment.NewLine + modList + Environment.NewLine + e.ToString());
         }
         else
         {
             Network.Disconnect();
         }
     }
 }