Esempio n. 1
0
 public VolatileModuleState(VolatileModule self)
 {
     updateSequence             = self.updateSequence;
     volume                     = self.volume;
     energyProduction           = self.energyProductionTotal;
     self.energyProductionTotal = 0;
     energyTransferRate         = self.energyTransferRate;
     structuralIntegrity        = self.structuralIntegrity;
     structuralIntegrityMax     = self.structuralIntegrityMax;
     pressurisation             = self.pressurisation;
     pressurisationDesired      = self.pressurisationDesired;
     occupants                  = self.occupants;
     occupantsMax               = self.occupantsMax;
     // TODO IInventory SaveState()
     // if (self.pressurisation > 0) { self.pressurisationGasses.SaveState(); }
     // self.Inventory.SaveState();
     // self.CostOfOperation.SaveState();
     timestamp = DateTime.Now.Millisecond;
 }
Esempio n. 2
0
        // Methods
        /// <summary>
        /// Update is a thread safe method which locks and calls OverridableUpdate
        /// As well Update performs any general module logic, such as:
        /// Distributing Electricity
        /// Distributing Events
        /// Distributing Resources, given input and output hardpoints
        /// </summary>
        public void Update()
        {
            // RESET ----------------------------------------------------------------------------------
            // Reset all parameters that reset every update
            energyProductionTotal += energyProduction;
            energyProduction       = 0;

            // REQUESTS -------------------------------------------------------------------------------
            foreach (Hardpoint hardpoint in unityObject.hardpoints)
            {
                // Take all the requests from the hardpoint
                for (int i = 0; i < hardpoint.volatileHardpoint.RequestCount; i++)
                {
                    hardpoint.volatileHardpoint.Pop().Do(this);
                }
            }

            // Process all the requests
            for (int i = 0; i < RequestCount; i++)
            {
                Pop().Do(this);
            }

            // MODULE ---------------------------------------------------------------------------------
            OverridableUpdate();

            // SUBMODULES -----------------------------------------------------------------------------
            foreach (Submodule sub in unityObject.submodules)
            {
                sub.volatileSubmodule.Update();
            }

            // This establishes the number of hardpoints requiring power output.
            float hardpointsNeedingPower = 0;

            foreach (Hardpoint hardpoint in unityObject.hardpoints)
            {
                if (hardpoint.connection.module.volatileObject.energyProduction < energyProduction)
                {
                    hardpointsNeedingPower++;
                }
            }

            // HARDPOINTS -----------------------------------------------------------------------------
            // First calculate all output values for each hardpoint connection
            // Second send an update down every hardpoint with the necessary outputs
            foreach (Hardpoint hardpoint in unityObject.hardpoints)
            {
                if (hardpoint.connection != null)
                {
                    // Each hardpoint connection queues UpdateModuleRequests on the other modules hardpoint
                    UpdateModuleRequest newRequest = new UpdateModuleRequest();
                    newRequest.source          = this;
                    newRequest.sourceHardpoint = hardpoint.volatileHardpoint;

                    // Calculate the output through each hardpoint
                    // Electricity
                    // If the connected module has lower energy production than this one then send power
                    // Using the previously calculated hardpointsNeedingPower we can ensure that all the hardpoints in need get some
                    if ((float)hardpoint.connection.module.volatileObject.energyProduction < (float)energyProduction)
                    {
                        newRequest.energyIn = Mathf.Max(((float)energyProduction / hardpointsNeedingPower) * energyTransferRate, 0);
                    }

                    // Integrity
                    // TODO (Late) Implement technology that allows modules to repair each other via connections alone.
                    //if (hardpoint.connection.module.threaded.structuralIntegrity < hardpoint.connection.module.threaded.structuralIntegrityMax && structuralIntegrity >= structuralIntegrityMax)
                    //    newRequest.structuralIntegrityIn = Mathf.Max(SOME_VARIABLE_FOR_REPAIR_FIELD_STRENTH * structuralIntegrity, SOME_VARIABLE_FOR_MAXIMUM_REPAIR_STRENGTH);

                    // Pressurisation
                    // If this module has the resources necessary to increase the pressurisation of the connected module, it should send some, either from its pressurisationGasses inventory (first)
                    // Or from its inventory proper (second).
                    if ((float)hardpoint.connection.module.volatileObject.pressurisation < (float)hardpoint.connection.module.volatileObject.pressurisationDesired)
                    {
                        // If this module is more pressurised than it should be, take from the pressurisationGasses
                        if ((float)pressurisation > (float)pressurisationDesired)
                        {
                            // Calculate how much volume we can take based on the pressure from the pressurisationGasses inventory
                        }
                        // Take the rest if any more is necessary, from inventory, if it has any
                    }

                    // Distribution
                    // Need to take into account the number of output hardpoints that want to output the same resourcestacks, as they need to split the current amount between them, if between them they would take more than there is
                    if ((hardpoint.volatileHardpoint.direction & VolatileHardpoint.Direction.Output) != VolatileHardpoint.Direction.None)
                    {
                        // Get all the desired resources by filtering the module inventory through the hardpoint inventory, returning only those that both inventories have in common
                        ResourceStack[] desiredResources = hardpoint.volatileHardpoint.FilterInventory(Inventory);
                        // A temporary array of values indicating the total number of hardpoints desiring the resource in desiredResources at the same index
                        int[] desiredHardpoints = new int[desiredResources.Length];

                        // This will fill desiredHardpoints with the number of hardpoints desiring each resource in desiredResources, so as to evenly distribute between all hardpoints
                        // As is the case whenever the total amount desired by hardpoints exceeds the amount remaining in this module.
                        // Iterate across the hardpoints
                        foreach (Hardpoint other in unityObject.hardpoints)
                        {
                            if ((other.volatileHardpoint.direction & VolatileHardpoint.Direction.Output) != VolatileHardpoint.Direction.None)
                            {
                                // Iterate across the desiredResources
                                for (int i = 0; i < desiredResources.Length; i++)
                                {
                                    // If the hardpoint wants the desiredResource increment the index of desiredHardpoints matching the index of desiredResource
                                    if ((float)other.volatileHardpoint.Filter.GetResource(desiredResources[i].type).volume == 0)
                                    {
                                        desiredHardpoints[i]++;
                                    }
                                }
                            }
                        }

                        // The reason for this section of logic is to ensure that no one resource stack desired is taking more from this module than it has
                        // And than the module the resources are going to can take
                        Metre3 desiredVolume = 0;

                        foreach (ResourceStack stack in desiredResources)
                        {
                            desiredVolume += stack.volume;
                        }

                        // Iterate across the desiredResources
                        for (int i = 0; i < desiredResources.Length; i++)
                        {
                            // Get the ResourceStack in question from the Inventory
                            ResourceStack invResource = Inventory.GetResource(desiredResources[i].type);

                            // If the total amount desired is greater than the volume of the amount this module has
                            if (desiredResources[i].volume * desiredHardpoints[i] > invResource.volume)
                            {
                                desiredVolume -= desiredResources[i].volume;
                                // Set the amount desired to the total volume this module has divided by the number of hardpoints wanting it
                                desiredResources[i].volume = invResource.volume / desiredHardpoints[i];
                                desiredVolume += desiredResources[i].volume;
                            }

                            // Module Distribution based on the remaining space in the module this resource is being sent to
                            if (desiredVolume > hardpoint.connection.module.volatileObject.Volume)
                            {
                                // The logic here is that instead of attempting to send the desired amount of everything, we instead only send the percentage of that stuff as a total of all the stuff being sent
                                // And send only that percentage of the volume remaining in the module, that way whatever amounts we wanted to distribute, we maintain the percentage volume, but fill the module, instead of having whatever filled it first, fill it first.
                                // The only issue with this system, is that ultimately it doesn't take into account other pending, or will be pending by module update, requests, and they will therefore still have a first come first serve bases between several modules inputing on one module
                                desiredResources[i].volume = (desiredResources[i].volume / desiredVolume) * hardpoint.connection.module.volatileObject.Volume;
                            }
                            newRequest.resourcesIn.Add(desiredResources[i]);
                        }
                    }

                    // Queue hardpoint update, with the necessary inputs
                    hardpoint.connection.volatileHardpoint.Request(newRequest);

                    // If the connected hardpoints module has a lower update sequence than this one
                    // Queue an update of the module (this is the basis of the whole sequenced update system)
                    if (hardpoint.connection.module.volatileObject.updateSequence < updateSequence)
                    {
                        hardpoint.connection.module.volatileObject.updateSequence = updateSequence;
                        TaskHelper.TaskManager.QueueTask(new TaskNode(hardpoint.connection.module.volatileObject.Update, Literals.Tasks.UpdateModule), (float)TaskPriority.Medium);
                    }
                }
            }

            // LASTPASS ------------------------------------------------------------------------------
            // All the final updates to ensure that user data is correct
        }