// This function prepares the simulation by creating all the necessary data structures it will // need during the simulation. All required data is copied from the core game data structures // so that the simulation itself can be run in a background thread without having issues with // the core game changing the data while the simulation is running. public bool PrepareSimulation(List <Part> parts, double theGravity, double theAtmosphere = 0, double theMach = 0, bool dumpTree = false, bool vectoredThrust = false, bool fullThrust = false) { LogMsg log = null; if (SimManager.logOutput) { log = new LogMsg(); log.buf.AppendLine("PrepareSimulation started"); dumpTree = true; } this._timer.Start(); // Store the parameters in members for ease of access in other functions this.partList = parts; this.gravity = theGravity; this.atmosphere = theAtmosphere; this.mach = theMach; this.lastStage = Staging.lastStage; //MonoBehaviour.print("lastStage = " + lastStage); // Clear the lists for our simulation parts this.allParts.Clear(); this.allFuelLines.Clear(); this.drainingParts.Clear(); this.allEngines.Clear(); this.activeEngines.Clear(); this.drainingResources.Clear(); // A dictionary for fast lookup of Part->PartSim during the preparation phase partSimLookup.Clear(); if (this.partList.Count > 0 && this.partList[0].vessel != null) { this.vesselName = this.partList[0].vessel.vesselName; this.vesselType = this.partList[0].vessel.vesselType; } //MonoBehaviour.print("PrepareSimulation pool size = " + PartSim.pool.Count()); // First we create a PartSim for each Part (giving each a unique id) int partId = 1; for (int i = 0; i < this.partList.Count; i++) { Part part = this.partList[i]; // If the part is already in the lookup dictionary then log it and skip to the next part if (partSimLookup.ContainsKey(part)) { if (log != null) { log.buf.AppendLine("Part " + part.name + " appears in vessel list more than once"); } continue; } // Create the PartSim PartSim partSim = PartSim.New(part, partId, this.atmosphere, log); // Add it to the Part lookup dictionary and the necessary lists partSimLookup.Add(part, partSim); this.allParts.Add(partSim); if (partSim.isFuelLine) { this.allFuelLines.Add(partSim); } if (partSim.isEngine) { partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.mach, vectoredThrust, fullThrust, log); } partId++; } this.UpdateActiveEngines(); // Now that all the PartSims have been created we can do any set up that needs access to other parts // First we set up all the parent links for (int i = 0; i < this.allParts.Count; i++) { PartSim partSim = this.allParts[i]; partSim.SetupParent(partSimLookup, log); } // Then, in the VAB/SPH, we add the parent of each fuel line to the fuelTargets list of their targets if (HighLogic.LoadedSceneIsEditor) { for (int i = 0; i < this.allFuelLines.Count; i++) { PartSim partSim = this.allFuelLines[i]; CModuleFuelLine fuelLine = partSim.part.GetModule <CModuleFuelLine>(); if (fuelLine.target != null) { PartSim targetSim; if (partSimLookup.TryGetValue(fuelLine.target, out targetSim)) { if (log != null) { log.buf.AppendLine("Fuel line target is " + targetSim.name + ":" + targetSim.partId); } targetSim.fuelTargets.Add(partSim.parent); } else { if (log != null) { log.buf.AppendLine("No PartSim for fuel line target (" + partSim.part.partInfo.name + ")"); } } } else { if (log != null) { log.buf.AppendLine("Fuel line target is null"); } } } } //MonoBehaviour.print("SetupAttachNodes and count stages"); for (int i = 0; i < this.allParts.Count; i++) { PartSim partSim = this.allParts[i]; partSim.SetupAttachNodes(partSimLookup, log); if (partSim.decoupledInStage >= this.lastStage) { this.lastStage = partSim.decoupledInStage + 1; } } // And finally release the Part references from all the PartSims //MonoBehaviour.print("ReleaseParts"); for (int i = 0; i < this.allParts.Count; i++) { PartSim partSim = this.allParts[i]; partSim.ReleasePart(); } // And dereference the core's part list this.partList = null; this._timer.Stop(); if (log != null) { log.buf.AppendLine("PrepareSimulation: " + this._timer.ElapsedMilliseconds + "ms"); log.Flush(); } if (dumpTree) { this.Dump(); } return(true); }