Latest tweaks from Sarbian
Latest tweaks from Sarbian

--- a/KerbalEngineer/Helpers/ForceAccumulator.cs
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -20,14 +20,13 @@
 using System;
 using System.Collections.Generic;
 using KerbalEngineer.VesselSimulator;
-using Smooth.Pools;
 
 namespace KerbalEngineer
 {
     // a (force, application point) tuple
     public class AppliedForce
     {
-        public static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset);
+        private static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset);
 
         public Vector3d vector;
         public Vector3d applicationPoint;
@@ -37,12 +36,22 @@
             return new AppliedForce();
         }
 
-        static  private void Reset(AppliedForce appliedForce) { }
+        static private void Reset(AppliedForce appliedForce) { }
 
-        public void Set(Vector3d vector, Vector3d applicationPoint) {
-            this.vector = vector;
-            this.applicationPoint = applicationPoint;
+        static public AppliedForce New(Vector3d vector, Vector3d applicationPoint)
+        {
+            AppliedForce force = pool.Borrow();
+            force.vector = vector;
+            force.applicationPoint = applicationPoint;
+            return force;
         }
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+
     }
 
 	// This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3

--- /dev/null
+++ b/KerbalEngineer/Helpers/Pool.cs
@@ -1,1 +1,54 @@
+using System.Collections.Generic;
 
+namespace KerbalEngineer
+{
+    /// <summary>
+    ///     Pool of object
+    /// </summary>
+    public class Pool<T> {
+        
+        private readonly Stack<T> values = new Stack<T>();
+
+        private readonly CreateDelegate<T> create;
+        private readonly ResetDelegate<T> reset;
+
+        public delegate R CreateDelegate<out R>();
+        public delegate void ResetDelegate<in T1>(T1 a);
+        
+        /// <summary>
+        ///     Creates an empty pool with the specified object creation and reset delegates.
+        /// </summary>
+        public Pool(CreateDelegate<T> create, ResetDelegate<T> reset) {
+            this.create = create;
+            this.reset = reset;
+        }
+
+        /// <summary>
+        ///     Borrows an object from the pool.
+        /// </summary>
+        public T Borrow() {
+            lock (values) {
+                return values.Count > 0 ? values.Pop() : create();
+            }
+        }
+        
+        /// <summary>
+        ///     Release an object, reset it and returns it to the pool.
+        /// </summary>
+        public void Release(T value) {
+            reset(value);
+            lock (values) {
+                values.Push(value);
+            }
+        }
+        
+        /// <summary>
+        ///     Current size of the pool.
+        /// </summary>
+        public int Count()
+        {
+            return values.Count;
+        }
+
+    }
+}

--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -21,7 +21,6 @@
 
 using System;
 using System.Text;
-using Smooth.Pools;
 
 #endregion
 
@@ -30,7 +29,7 @@
     internal class AttachNodeSim
     {
 
-        public static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset);
+        private static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset);
 
         public PartSim attachedPartSim;
         public String id;
@@ -41,14 +40,24 @@
             return new AttachNodeSim();
         }
 
-        public void Set(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+        public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
         {
-            this.attachedPartSim = partSim;
-            this.nodeType = newNodeType;
-            this.id = newId;
+            AttachNodeSim nodeSim = pool.Borrow();
+
+            nodeSim.attachedPartSim = partSim;
+            nodeSim.nodeType = newNodeType;
+            nodeSim.id = newId;
+
+            return nodeSim;
         }
 
         static private void Reset(AttachNodeSim attachNodeSim) { }
+
+
+        public void Release()
+        {
+            pool.Release(this);
+        }
 
         public void DumpToBuffer(StringBuilder buffer)
         {

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -23,7 +23,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-using Smooth.Pools;
 using UnityEngine;
 
 #endregion
@@ -32,7 +31,7 @@
 {
     public class EngineSim
     {
-        public static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
+        private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
 
         private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
 
@@ -60,13 +59,18 @@
             engineSim.isp = 0;
             for (int i = 0; i < engineSim.appliedForces.Count; i++)
             {
-                AppliedForce.pool.Release(engineSim.appliedForces[i]);
+                engineSim.appliedForces[i].Release();
             }
             engineSim.appliedForces.Clear();
             engineSim.thrust = 0;
         }
 
-        public void Set(PartSim theEngine,
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+        public static EngineSim New(PartSim theEngine,
                          double atmosphere,
                          double velocity,
                          float maxThrust,
@@ -83,6 +87,9 @@
                          bool correctThrust,
                          List<Transform> thrustTransforms)
         {
+            EngineSim engineSim = pool.Borrow();
+
+
             StringBuilder buffer = null;
             //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
             //MonoBehaviour.print("maxThrust = " + maxThrust);
@@ -91,29 +98,29 @@
             //MonoBehaviour.print("requestedThrust = " + requestedThrust);
             //MonoBehaviour.print("velocity = " + velocity);
 
-            this.partSim = theEngine;
-
-            this.isActive = active;
-            this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
+            engineSim.partSim = theEngine;
+
+            engineSim.isActive = active;
+            engineSim.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
             //MonoBehaviour.print("thrust = " + thrust);
 
-            this.thrustVec = vecThrust;
+            engineSim.thrustVec = vecThrust;
 
             double flowRate = 0d;
-            if (this.partSim.hasVessel)
+            if (engineSim.partSim.hasVessel)
             {
                 //MonoBehaviour.print("hasVessel is true");
-                this.actualThrust = isActive ? requestedThrust : 0.0;
+                engineSim.actualThrust = engineSim.isActive ? requestedThrust : 0.0;
                 if (velocityCurve != null)
                 {
-                    this.actualThrust *= velocityCurve.Evaluate((float)velocity);
+                    engineSim.actualThrust *= velocityCurve.Evaluate((float)velocity);
                     //MonoBehaviour.print("actualThrust at velocity = " + actualThrust);
                 }
 
-                this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm);
-                if (this.isp == 0d)
-                {
-                    MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
+                engineSim.isp = atmosphereCurve.Evaluate((float)engineSim.partSim.part.staticPressureAtm);
+                if (engineSim.isp == 0d)
+                {
+                    MonoBehaviour.print("Isp at " + engineSim.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
                 }
 
                 if (correctThrust && realIsp == 0)
@@ -121,7 +128,7 @@
                     float ispsl = atmosphereCurve.Evaluate(0);
                     if (ispsl != 0)
                     {
-                        this.thrust = this.thrust * this.isp / ispsl;
+                        engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl;
                     }
                     else
                     {
@@ -132,21 +139,21 @@
 
                 if (velocityCurve != null)
                 {
-                    this.thrust *= velocityCurve.Evaluate((float)velocity);
+                    engineSim.thrust *= velocityCurve.Evaluate((float)velocity);
                     //MonoBehaviour.print("thrust at velocity = " + thrust);
                 }
 
                 if (throttleLocked)
                 {
                     //MonoBehaviour.print("throttleLocked is true");
-                    flowRate = this.thrust / (this.isp * 9.82);
+                    flowRate = engineSim.thrust / (engineSim.isp * 9.82);
                 }
                 else
                 {
-                    if (this.partSim.isLanded)
+                    if (engineSim.partSim.isLanded)
                     {
                         //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
-                        flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82);
+                        flowRate = Math.Max(0.000001d, engineSim.thrust * FlightInputHandler.state.mainThrottle) / (engineSim.isp * 9.82);
                     }
                     else
                     {
@@ -159,12 +166,12 @@
                             }
 
                             //MonoBehaviour.print("requestedThrust > 0");
-                            flowRate = requestedThrust / (this.isp * 9.82);
+                            flowRate = requestedThrust / (engineSim.isp * 9.82);
                         }
                         else
                         {
                             //MonoBehaviour.print("requestedThrust <= 0");
-                            flowRate = this.thrust / (this.isp * 9.82);
+                            flowRate = engineSim.thrust / (engineSim.isp * 9.82);
                         }
                     }
                 }
@@ -172,8 +179,8 @@
             else
             {
                 //MonoBehaviour.print("hasVessel is false");
-                this.isp = atmosphereCurve.Evaluate((float)atmosphere);
-                if (this.isp == 0d)
+                engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
+                if (engineSim.isp == 0d)
                 {
                     MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
                 }
@@ -182,7 +189,7 @@
                     float ispsl = atmosphereCurve.Evaluate(0);
                     if (ispsl != 0)
                     {
-                        this.thrust = this.thrust * this.isp / ispsl;
+                        engineSim.thrust = engineSim.thrust * engineSim.isp / ispsl;
                     }
                     else
                     {
@@ -193,11 +200,11 @@
 
                 if (velocityCurve != null)
                 {
-                    this.thrust *= velocityCurve.Evaluate((float)velocity);
+                    engineSim.thrust *= velocityCurve.Evaluate((float)velocity);
                     //MonoBehaviour.print("thrust at velocity = " + thrust);
                 }
 
-                flowRate = this.thrust / (this.isp * 9.82);
+                flowRate = engineSim.thrust / (engineSim.isp * 9.82);
             }
 
             if (SimManager.logOutput)
@@ -236,7 +243,7 @@
                         theEngine.partId,
                         consumptionRate);
                 }
-                this.resourceConsumptions.Add(propellant.id, consumptionRate);
+                engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
             }
 
             if (SimManager.logOutput)
@@ -244,17 +251,17 @@
                 MonoBehaviour.print(buffer);
             }
 
-            double thrustPerThrustTransform = thrust / thrustTransforms.Count;
+            double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
             for (int i = 0; i < thrustTransforms.Count; i++)
             {
                 Transform thrustTransform = thrustTransforms[i];
                 Vector3d direction = thrustTransform.forward.normalized;
                 Vector3d position = thrustTransform.position;
 
-                AppliedForce appliedForce = AppliedForce.pool.Borrow();
-                appliedForce.Set(direction * thrustPerThrustTransform, position);
-                appliedForces.Add(appliedForce);
-            }
+                AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
+                engineSim.appliedForces.Add(appliedForce);
+            }
+            return engineSim;
         }
 
         public ResourceContainer ResourceConsumptions
@@ -333,11 +340,9 @@
                                 maxStage = stage;
                             }
 
-                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet) || sourcePartSet.Count == 0)
-                            {
-                                if (sourcePartSet == null)
-                                    sourcePartSet = new HashSet<PartSim>();
-
+                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
+                            {
+                                sourcePartSet = new HashSet<PartSim>();
                                 stagePartSets.Add(stage, sourcePartSet);
                             }
                             sourcePartSet.Add(aPartSim);

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -25,7 +25,6 @@
 using System.Text;
 
 using KerbalEngineer.Extensions;
-using Smooth.Pools;
 using UnityEngine;
 
 #endregion
@@ -36,7 +35,7 @@
 
     public class PartSim
     {
-        public static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset);
+        private static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset);
 
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
 
@@ -84,7 +83,7 @@
         {
             for (int i = 0; i < partSim.attachNodes.Count; i++)
             {
-                AttachNodeSim.pool.Release(partSim.attachNodes[i]);
+                partSim.attachNodes[i].Release();
             }
             partSim.attachNodes.Clear();
             partSim.fuelTargets.Clear();
@@ -95,49 +94,57 @@
             partSim.startMass = 0d;
         }
 
-        public void Set(Part thePart, int id, double atmosphere, LogMsg log)
-        {
-            this.part = thePart;
-            this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
-            this.partId = id;
-            this.name = this.part.partInfo.name;
+        public void Release()
+        {
+            pool.Release(this);
+        }
+
+        public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log)
+        {
+            PartSim partSim = pool.Borrow();
+
+
+            partSim.part = thePart;
+            partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
+            partSim.partId = id;
+            partSim.name = partSim.part.partInfo.name;
 
             if (log != null)
             {
-                log.buf.AppendLine("Create PartSim for " + this.name);
-            }
-
-            this.parent = null;
-            this.parentAttach = part.attachMode;
-            this.fuelCrossFeed = this.part.fuelCrossFeed;
-            this.noCrossFeedNodeKey = this.part.NoCrossFeedNodeKey;
-            this.decoupledInStage = this.DecoupledInStage(this.part);
-            this.isFuelLine = this.part.HasModule<CModuleFuelLine>();
-            this.isFuelTank = this.part is FuelTank;
-            this.isSepratron = this.IsSepratron();
-            this.inverseStage = this.part.inverseStage;
+                log.buf.AppendLine("Create PartSim for " + partSim.name);
+            }
+
+            partSim.parent = null;
+            partSim.parentAttach = partSim.part.attachMode;
+            partSim.fuelCrossFeed = partSim.part.fuelCrossFeed;
+            partSim.noCrossFeedNodeKey = partSim.part.NoCrossFeedNodeKey;
+            partSim.decoupledInStage = partSim.DecoupledInStage(partSim.part);
+            partSim.isFuelLine = partSim.part.HasModule<CModuleFuelLine>();
+            partSim.isFuelTank = partSim.part is FuelTank;
+            partSim.isSepratron = partSim.IsSepratron();
+            partSim.inverseStage = partSim.part.inverseStage;
             //MonoBehaviour.print("inverseStage = " + inverseStage);
 
-            this.cost = this.part.GetCostWet();
+            partSim.cost = partSim.part.GetCostWet();
 
             // Work out if the part should have no physical significance
-            this.isNoPhysics = this.part.HasModule<LaunchClamp>() ||
-                               this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
-                               this.part.PhysicsSignificance == 1;
-
-            if (!this.isNoPhysics)
-            {
-                this.baseMass = this.part.mass;
+            partSim.isNoPhysics = partSim.part.HasModule<LaunchClamp>() ||
+                               partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
+                               partSim.part.PhysicsSignificance == 1;
+
+            if (!partSim.isNoPhysics)
+            {
+                partSim.baseMass = partSim.part.mass;
             }
 
             if (SimManager.logOutput)
             {
-                MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
-            }
-
-            for (int i = 0; i < this.part.Resources.Count; i++)
-            {
-                PartResource resource = this.part.Resources[i];
+                MonoBehaviour.print((partSim.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + partSim.part.mass);
+            }
+
+            for (int i = 0; i < partSim.part.Resources.Count; i++)
+            {
+                PartResource resource = partSim.part.Resources[i];
 
                 // Make sure it isn't NaN as this messes up the part mass and hence most of the values
                 // This can happen if a resource capacity is 0 and tweakable
@@ -148,8 +155,8 @@
                         MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
                     }
 
-                    this.resources.Add(resource.info.id, resource.amount);
-                    this.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
+                    partSim.resources.Add(resource.info.id, resource.amount);
+                    partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
                 }
                 else
                 {
@@ -157,27 +164,28 @@
                 }
             }
 
-            this.startMass = this.GetMass();
-
-            this.hasVessel = (this.part.vessel != null);
-            this.isLanded = this.hasVessel && this.part.vessel.Landed;
-            if (this.hasVessel)
-            {
-                this.vesselName = this.part.vessel.vesselName;
-                this.vesselType = this.part.vesselType;
-            }
-            this.initialVesselName = this.part.initialVesselName;
-
-            this.hasMultiModeEngine = this.part.HasModule<MultiModeEngine>();
-            this.hasModuleEnginesFX = this.part.HasModule<ModuleEnginesFX>();
-            this.hasModuleEngines = this.part.HasModule<ModuleEngines>();
-
-            this.isEngine = this.hasMultiModeEngine || this.hasModuleEnginesFX || this.hasModuleEngines;
+            partSim.startMass = partSim.GetMass();
+
+            partSim.hasVessel = (partSim.part.vessel != null);
+            partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed;
+            if (partSim.hasVessel)
+            {
+                partSim.vesselName = partSim.part.vessel.vesselName;
+                partSim.vesselType = partSim.part.vesselType;
+            }
+            partSim.initialVesselName = partSim.part.initialVesselName;
+
+            partSim.hasMultiModeEngine = partSim.part.HasModule<MultiModeEngine>();
+            partSim.hasModuleEnginesFX = partSim.part.HasModule<ModuleEnginesFX>();
+            partSim.hasModuleEngines = partSim.part.HasModule<ModuleEngines>();
+
+            partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
 
             if (SimManager.logOutput)
             {
-                MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage);
-            }
+                MonoBehaviour.print("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+            }
+            return partSim;
         }
 
         public ResourceContainer Resources
@@ -224,8 +232,7 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
+                        EngineSim engineSim = EngineSim.New(
                             this,
                             atmosphere,
                             velocity,
@@ -261,8 +268,7 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
+                        EngineSim engineSim = EngineSim.New(
                             this,
                             atmosphere,
                             velocity,
@@ -296,8 +302,7 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.pool.Borrow();
-                        engineSim.Set(
+                        EngineSim engineSim = EngineSim.New(
                             this,
                             atmosphere,
                             velocity,
@@ -414,8 +419,7 @@
                             log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
                         }
 
-                        AttachNodeSim attachnode = AttachNodeSim.pool.Borrow();
-                        attachnode.Set(attachedSim, attachNode.id, attachNode.nodeType);
+                        AttachNodeSim attachnode = AttachNodeSim.New(attachedSim, attachNode.id, attachNode.nodeType);
                         this.attachNodes.Add(attachnode);
                     }
                     else

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -181,8 +181,7 @@
                 }
 
                 // Create the PartSim
-                PartSim partSim = PartSim.pool.Borrow();
-                partSim.Set(part, partId, this.atmosphere, log);
+                PartSim partSim = PartSim.New(part, partId, this.atmosphere, log);
 
                 // Add it to the Part lookup dictionary and the necessary lists
                 partSimLookup.Add(part, partSim);
@@ -641,14 +640,14 @@
             //MonoBehaviour.print("FreePooledObject pool size before = " + PartSim.pool.Count() + " for " + allParts.Count + " parts");
             foreach (PartSim part in allParts)
             {
-                PartSim.pool.Release(part);
+                part.Release();
             }
             //MonoBehaviour.print("FreePooledObject pool size after = " + PartSim.pool.Count());
 
             //MonoBehaviour.print("FreePooledObject pool size before = " + EngineSim.pool.Count() + " for " + allEngines.Count + " engines");
             foreach (EngineSim engine in allEngines)
             {
-                EngineSim.pool.Release(engine);
+                engine.Release();
             }
             //MonoBehaviour.print("FreePooledObject pool size after = " + EngineSim.pool.Count());
         }
@@ -900,7 +899,7 @@
             {
                 // Remove it from the all parts list
                 this.allParts.Remove(partSim);
-                PartSim.pool.Release(partSim);
+                partSim.Release();
                 if (partSim.isEngine)
                 {
                     // If it is an engine then loop through all the engine modules and remove all the ones from this engine part
@@ -910,7 +909,7 @@
                         if (engine.partSim == partSim)
                         {
                             this.allEngines.RemoveAt(i);
-                            EngineSim.pool.Release(engine);
+                            engine.Release();
                         }
                     }
                 }