/// <summary> /// Adds a single build to the buildTracker /// </summary> /// <param name="source">The InventoryPart to increment</param> /// <param name="typeToAdd">Says whether this is a new build, inventoried build, or combo build (TOTAL)</param> /// <returns>The corresponding InventoryPart that's actually stored</returns> private InventoryPart addBuild(InventoryPart source, TrackType typeToAdd) { InventoryPart found = _buildTracker.Keys.FirstOrDefault(ip => ip.IsSameAs(source, _strictness)); if (found != null) { _buildTracker[found].buildsTotal++; //increment it } else { found = source; _buildTracker[source] = new TrackObject(); _buildTracker[source].buildsTotal = 1; //add it } if (typeToAdd == TrackType.INVENTORIED || typeToAdd == TrackType.TOTAL) { _buildTracker[found].buildsInventoried++; } if (typeToAdd == TrackType.NEW || typeToAdd == TrackType.TOTAL) { _buildTracker[found].buildsNew++; } Logging.Log($"{found.Name} has been used in {_buildTracker[found].buildsTotal}/{_buildTracker[found].buildsNew}/{_buildTracker[found].buildsInventoried} (T/N/I) builds."); return(found); }
public int AddPart(InventoryPart part, int quantity = 1) { /*if (quantity > int.MinValue) * part.SetQuantity(quantity);*/ int previousAmount = 0; InventoryPart existingPart = FindPart(part); if (existingPart != null) { //Logging.DebugLog("ScrapYard", "Found existing part."); //existingPart.AddQuantity(part.Quantity); previousAmount = internalInventory[existingPart]; internalInventory[existingPart] += quantity; } else { //Logging.DebugLog("ScrapYard", "Didn't find existing part."); internalInventory.Add(part, quantity); existingPart = part; } int newAmount = internalInventory[existingPart]; if (!disableEvents) { //OnInventoryQuantityChanged(this, new InventoryChangedEventArgs(existingPart, previousAmount, newAmount)); Events.InventoryChangedEvent.Fire(existingPart, previousAmount, newAmount); } return(newAmount); }
/// <summary> /// Adds a single use to the useTracker. Automatically determines type /// </summary> /// <param name="source">The InventoryPart to increment</param> /// <returns>The corresponding InventoryPart that's actually stored</returns> private InventoryPart addUse(InventoryPart source) { InventoryPart found = _buildTracker.Keys.FirstOrDefault(ip => ip.IsSameAs(source, _strictness)); if (found != null) { _buildTracker[found].usesTotal++; //increment it } else { found = source; _buildTracker[source] = new TrackObject(); _buildTracker[source].usesTotal = 1; //add it } if (source.TrackerModule.Inventoried) { _buildTracker[found].usesInventoried++; } else { _buildTracker[found].usesNew++; } Logging.Log($"{found.Name} has been used {_buildTracker[found].usesTotal}/{_buildTracker[found].usesNew}/{_buildTracker[found].usesInventoried} (T/N/I) times."); return(found); }
//private void RecoveryDialogSpawn(MissionRecoveryDialog dialog) //{ // Debug.Log("ScrapYard: dialog spawn"); // Debug.Log($"fm:{dialog.FundsModifier} - rf:{dialog.recoveryFactor} - fe:{dialog.fundsEarned}"); // object value = dialog.GetType().GetField("partWidgets", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(dialog); // if (value == null) // Debug.Log("Value is null :/"); // List<PartWidget> partWidgets = value as List<PartWidget>; // if (partWidgets != null) // { // foreach (PartWidget widget in partWidgets) // { // //widget.partValue = widget.partValue * (dialog.recoveryFactor - 100) / 100.0; // widget.partValue = 0; // } // } // else // { // Debug.Log("Widgets were null :("); // } //} //public void VesselRecoverProcessingEvent(ProtoVessel recovered, MissionRecoveryDialog dialog, float someNum) //{ // Debug.Log("ScrapYard: Vessel Recovery Processing!"); // Debug.Log($"fm:{dialog.FundsModifier} - rf:{dialog.recoveryFactor} - fe:{dialog.fundsEarned}"); // LastRecoveryUI = dialog; // foreach (ProtoPartSnapshot pps in recovered.protoPartSnapshots) // { // InventoryPart recoveredPart = new InventoryPart(pps); // ScrapYard.Instance.TheInventory.AddPart(recoveredPart, 1); // Funding.Instance.AddFunds(-1*recoveredPart.DryCost, TransactionReasons.VesselRecovery); // //dialog.fundsEarned -= recoveredPart.DryCost; // } // //Debug.Log($"Type is {(dialog.GetType().GetMember("partWidgets", BindingFlags.NonPublic)?.GetValue(0) as MemberInfo)?.MemberType ?? default(MemberTypes) }"); // object value = dialog.GetType().GetField("partWidgets", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(dialog); // if (value == null) // Debug.Log("Value is null :/"); // List<PartWidget> partWidgets = value as List<PartWidget>; // if (partWidgets != null) // { // foreach (PartWidget widget in partWidgets) // { // //widget.partValue = widget.partValue * (dialog.recoveryFactor - 100) / 100.0; // widget.partValue = 0; // } // } // else // { // Debug.Log("Widgets were null :("); // } //} public void VesselRecovered(ProtoVessel vessel, bool someBool) { Debug.Log("ScrapYard: Recovered"); foreach (ProtoPartSnapshot pps in vessel.protoPartSnapshots) { InventoryPart recoveredPart = new InventoryPart(pps); ScrapYard.Instance.TheInventory.AddPart(recoveredPart, 1); if (ScrapYard.Instance.Settings.OverrideFunds) { Funding.Instance.AddFunds(-1 * recoveredPart.DryCost, TransactionReasons.VesselRecovery); } //dialog.fundsEarned -= recoveredPart.DryCost; } //MissionRecoveryDialog dialog = LastRecoveryUI; //Debug.Log("ScrapYard: Recovered"); //Debug.Log($"fm:{dialog.FundsModifier} - rf:{dialog.recoveryFactor} - fe:{dialog.fundsEarned}"); //object value = dialog.GetType().GetField("partWidgets", System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(dialog); //if (value == null) // Debug.Log("Value is null :/"); //List<PartWidget> partWidgets = value as List<PartWidget>; //if (partWidgets != null) //{ // foreach (PartWidget widget in partWidgets) // { // //widget.partValue = widget.partValue * (dialog.recoveryFactor - 100) / 100.0; // widget.partValue = 0; // } //} //else //{ // Debug.Log("Widgets were null :("); //} }
public void VesselRecovered(ProtoVessel vessel, bool someBool) { if (!ScrapYard.Instance.Settings.EnabledForSave) { return; } Logging.DebugLog("Recovered"); foreach (ProtoPartSnapshot pps in vessel.protoPartSnapshots) { try { InventoryPart recoveredPart = new InventoryPart(pps); recoveredPart.TrackerModule.TimesRecovered++; ScrapYard.Instance.TheInventory.AddPart(recoveredPart); if (HighLogic.CurrentGame.Parameters.CustomParams <SaveSpecificSettings>().OverrideFunds) { Funding.Instance?.AddFunds(-1 * recoveredPart.DryCost, TransactionReasons.VesselRecovery); } } catch (Exception ex) { Logging.LogException(ex); } } }
/// <summary> /// Gets the number of uses of a part /// </summary> /// <param name="part">The part to check</param> /// <param name="type">Which use counter to check</param> /// <returns>Number of uses</returns> public int GetUsesForPart(ConfigNode part, TrackType type = TrackType.TOTAL) { if (!TrackerEnabled) { return(0); } InventoryPart ip = new InventoryPart(part); return(getUses(ip, type)); }
/// <summary> /// Gets the number of builds for a part /// </summary> /// <param name="part">The part to check</param> /// /// <param name="type">Which build counter to check</param> /// <returns>Number of builds</returns> public int GetBuildsForPart(Part part, TrackType type = TrackType.TOTAL) { if (!TrackerEnabled) { return(0); } InventoryPart ip = new InventoryPart(part); return(getBuilds(ip, type)); }
//TODO: Move this stuff somewhere better private void handleButtonClick(bool enable) { if (enable) { if (EditorLogic.SelectedPart == null) { ScrapYard.Instance.InstanceSelectorUI.Show(); } else { List <Part> selectedParts = new List <Part>(EditorLogic.SelectedPart.children) { EditorLogic.SelectedPart }; List <InventoryPart> inventoriedParts = new List <InventoryPart>(); double cost = 0; uint count = 0; foreach (Part p in selectedParts) { InventoryPart iP = new InventoryPart(p); if (iP.TrackerModule.Inventoried) { cost += iP.DryCost * ScrapYard.Instance.Settings.CurrentSaveSettings.FundsSalePercent; count++; inventoriedParts.Add(iP); } } string descriptor = (ScrapYard.Instance.Settings.CurrentSaveSettings.OverrideFunds ? "Sell" : "Discard"); if (count > 0) { string message = $"Are you sure you'd like to sell the selected {count} parts for {cost} funds?"; if (!ScrapYard.Instance.Settings.CurrentSaveSettings.OverrideFunds) { message = $"Are you sure you'd like to discard the selected {count} parts?"; } MultiOptionDialog diag = new MultiOptionDialog("discardMsg", message, descriptor + "Parts", HighLogic.UISkin, new DialogGUIButton("Yes", () => InventoryManagement.SellParts(inventoriedParts)), new DialogGUIButton("No", () => { })); PopupDialog.SpawnPopupDialog(diag, false, HighLogic.UISkin); } else { //let them know they can sell parts here PopupDialog.SpawnPopupDialog(new Vector2(), new Vector2(), "dropPartsMsg", descriptor + " Parts Here", "You can " + descriptor.ToLower() + " parts by dropping parts from the inventory here.", "Ok", false, HighLogic.UISkin); } Button?.SetFalse(false); } } else { ScrapYard.Instance.InstanceSelectorUI.Close(); } }
/// <summary> /// Returns an IEnumerable with all parts in the Inventory /// </summary> /// <returns>All inventory parts in an IEnumerable</returns> public IEnumerable <InventoryPart> GetAllParts() { if (!InventoryEnabled) { return(null); } InventoryPart[] toReturn = new InventoryPart[internalInventory.Count]; internalInventory.CopyTo(toReturn); return(toReturn); }
public override bool Equals(object obj) { //return ReferenceEquals(this, obj); InventoryPart other = obj as InventoryPart; if (obj == null) { return(false); } return(GetHashCode() == other.GetHashCode() && IsSameAs(other, ComparisonStrength.STRICT)); }
public int GetPartQuantity(InventoryPart part) { if (part == null) { return(0); } InventoryPart internalPart = FindPart(part); if (internalPart != null) { return(internalInventory[internalPart]); } return(0); }
/// <summary> /// Adds a single part to the inventory, increments the recovery tracker if specified /// </summary> /// <param name="sourcePart">The source part to add</param> /// <param name="incrementRecovery">If true, increases the number of recoveries</param> /// <returns>True if added, false otherwise</returns> public bool AddPartToInventory_Node(ConfigNode sourcePart, bool incrementRecovery) { if (!ScrapYard.Instance.TheInventory.InventoryEnabled) { return(false); } InventoryPart iPart = new InventoryPart(sourcePart); if (incrementRecovery) { iPart.TrackerModule.TimesRecovered++; } return(ScrapYard.Instance.TheInventory.AddPart(iPart) != null); }
/// <summary> /// Adds a list of parts to the Inventory /// </summary> /// <param name="parts">The list of parts to add</param> /// <param name="incrementRecovery">If true, increments the number of recoveries in the tracker</param> public void AddPartsToInventory_Parts(IEnumerable <Part> parts, bool incrementRecovery) { if (!ScrapYard.Instance.TheInventory.InventoryEnabled) { return; } foreach (Part part in parts) { InventoryPart iPart = new InventoryPart(part); if (incrementRecovery) { iPart.TrackerModule.TimesRecovered++; } ScrapYard.Instance.TheInventory.AddPart(iPart); } }
/// <summary> /// Finds a part in the inventory for the given InventoryPart and a strictness of comparison /// </summary> /// <param name="part">The source part to find a match for</param> /// <param name="strength">The strictness of the comparison. Defaults to MODULES.</param> /// <returns>The InventoryPart or null if not found.</returns> public InventoryPart FindPart(InventoryPart part, ComparisonStrength strength = ComparisonStrength.MODULES) { if (!InventoryEnabled) { return(null); } if (strength == ComparisonStrength.STRICT) { InventoryPart found = internalInventory.FirstOrDefault(ip => ip == part); if (found != null) { return(found); } } return(internalInventory.FirstOrDefault(ip => ip.IsSameAs(part, strength))); }
/// <summary> /// Adds a part to the inventory using an InventoryPart /// </summary> /// <param name="part">The Inventory Part to add</param> public InventoryPart AddPart(InventoryPart part) { if (!InventoryEnabled || part.DoNotStore) //if not using the inventory, or the part shouldn't be stored, then do not add it { return(null); } part.TrackerModule.Inventoried = true; //run auto-refurbishment ScrapYard.Instance.Settings.AutomaticRefurbishment.ForEach(r => r.Refurbish(part)); internalInventory.Add(part); if (!disableEvents) { ScrapYardEvents.OnSYInventoryChanged.Fire(part, true); } return(part); }
/// <summary> /// Gets the number of uses for an InventoryPart /// </summary> /// <param name="part">Part to get uses for</param> /// <returns>Number of uses</returns> private int getUses(InventoryPart part, TrackType type) { InventoryPart found = _buildTracker.Keys.FirstOrDefault(ip => ip.IsSameAs(part, _strictness)); if (found != null) { switch (type) { case TrackType.TOTAL: return(_buildTracker[found].usesTotal); case TrackType.NEW: return(_buildTracker[found].usesNew); case TrackType.INVENTORIED: return(_buildTracker[found].usesInventoried); } } return(0); }
/// <summary> /// Removes a part from the inventory given an InventoryPart to compare and the strictness of comparison /// </summary> /// <param name="part">The source part to find a match for</param> /// <param name="strength">The strictness of the comparison. Defaults to MODULES</param> /// <returns>The removed InventoryPart, or null if none found</returns> public InventoryPart RemovePart(InventoryPart part, ComparisonStrength strength = ComparisonStrength.MODULES) { if (!InventoryEnabled) { return(null); } InventoryPart found = FindPart(part, strength); if (found != null && internalInventory.Remove(found)) { if (!disableEvents) { ScrapYardEvents.OnSYInventoryChanged.Fire(found, false); } return(found); } return(null); }
/// <summary> /// Removes a part with the given ID /// </summary> /// <param name="id">The ID of the part to remove</param> /// <returns>The removed InventoryPart, or null if none found</returns> public InventoryPart RemovePart(uint id) { if (!InventoryEnabled) { return(null); } InventoryPart found = FindPart(id); if (found != null && internalInventory.Remove(found)) { if (!disableEvents) { ScrapYardEvents.OnSYInventoryChanged.Fire(found, false); } return(found); } return(null); }
public InventoryPart Copy() { InventoryPart copy = new InventoryPart { _dryCost = _dryCost, _name = _name, savedModules = new List <ConfigNode>(savedModules), TrackerModule = new TrackerModuleWrapper(TrackerModule?.TrackerNode?.CreateCopy()) }; if (!copy.TrackerModule.HasModule && TrackerModule != null) { copy.TrackerModule = new TrackerModuleWrapper(TrackerModule.ID.Value, TrackerModule.TimesRecovered, TrackerModule.Inventoried); } //force the ID just to be sure copy.ID = ID; return(copy); }
public void VesselRolloutEvent(ShipConstruct vessel) { Debug.Log("ScrapYard: Vessel Rollout!"); //List<InventoryPart> UniqueParts = new List<InventoryPart>(), List <InventoryPart> UsedParts = new List <InventoryPart>(); foreach (Part part in vessel.parts) { InventoryPart inventoryPart = new InventoryPart(part); UsedParts.Add(inventoryPart); // if (UniqueParts.Find(p => p.IdenticalTo(inventoryPart)) == null) // UniqueParts.Add(inventoryPart); } //Increment the tracker //Logging.DebugLog("ScrapYard", "Incrementing the tracker."); /*foreach (InventoryPart part in UniqueParts) * { * ScrapYard.Instance.TheInventory.IncrementUsageCounter(part); * }*/ //Remove all possible inventory parts //Logging.DebugLog("ScrapYard", "Removing parts from inventory."); //Logging.DebugLog("ScrapYard", ScrapYard.instance.TheInventory.GetPartByIndex(0).Quantity); List <InventoryPart> inInventory, notInInventory; ScrapYard.Instance.TheInventory.SplitParts(UsedParts, out inInventory, out notInInventory); foreach (InventoryPart part in inInventory) { //Remove part //part.SetQuantity(-1); //Logging.DebugLog("ScrapYard", ScrapYard.instance.TheInventory.GetPartByIndex(0).Quantity); ScrapYard.Instance.TheInventory.AddPart(part, -1); //Refund its cost if (ScrapYard.Instance.Settings.OverrideFunds) { Funding.Instance.AddFunds(part.DryCost, TransactionReasons.VesselRollout); } } }
/// <summary> /// Takes a List of part ConfigNodes and returns the ConfigNodes that are present in the inventory. /// Assumes the default strictness. /// </summary> /// <param name="sourceParts">Source list of parts</param> /// <returns>List of part ConfigNodes that are in the inventory</returns> public IList <ConfigNode> GetPartsInInventory_ConfigNodes(IEnumerable <ConfigNode> sourceParts, string strictness) { if (!ScrapYard.Instance.TheInventory.InventoryEnabled) { return(new List <ConfigNode>()); } ComparisonStrength actualStrictness = parseStrictnessString(strictness); List <ConfigNode> inInventory = new List <ConfigNode>(); PartInventory InventoryCopy = ScrapYard.Instance.TheInventory.Copy(); foreach (ConfigNode part in sourceParts) { InventoryPart inputPart = new InventoryPart(part); if (InventoryCopy.RemovePart(inputPart, actualStrictness) != null) { inInventory.Add(part); } } return(inInventory); }
/*public InventoryPart GetPartByIndex(int index) * { * return InternalInventory * }*/ /*private int FindPartIndex(InventoryPart part) * { * InventoryPart target = FindPart(part); * if (target == null) * return -1; * return InternalInventory.IndexOf(target); * }*/ public void SetPartQuantity(InventoryPart part, int quantity) { //int index = FindPartIndex(part); InventoryPart internalPart = FindPart(part); if (internalPart != null) { int previousAmount = internalInventory[internalPart]; internalInventory[internalPart] = quantity; if (!disableEvents) { //OnInventoryQuantityChanged(this, new InventoryChangedEventArgs(internalPart, previousAmount, quantity)); Events.InventoryChangedEvent.Fire(internalPart, previousAmount, quantity); } } else { //part.SetQuantity(quantity); AddPart(part, quantity); } }
/// <summary> /// Refreshes a part node to be fresh and not from the inventory /// </summary> /// <param name="partNode">The part to refresh</param> /// <returns>Success</returns> public bool RefreshPart_Node(ConfigNode partNode) { if (!ScrapYard.Instance.TheInventory.InventoryEnabled) { return(false); } try { InventoryPart iPart = new InventoryPart(partNode); iPart.ID = 0; iPart.TrackerModule.Inventoried = false; iPart.TrackerModule.TimesRecovered = 0; return(true); } catch (Exception ex) { Logging.LogException(ex, "RefreshPart_Node"); } return(false); }
/// <summary> /// Checks to see if the passed InventoryPart is identical to this one, excluding Quantity and Used by default /// </summary> /// <param name="comparedPart"></param> /// <returns></returns> public bool IdenticalTo(InventoryPart comparedPart) { //Test to ensure the name, dry cost, and number of saved modules are identical if (Name == comparedPart.Name && DryCost == comparedPart.DryCost && savedModules.Count == comparedPart.savedModules.Count) { //If strict comparison, ensure the quantity and amount used are identical //if (strict && Quantity != comparedPart.Quantity) // return false; //Compare the saved modules to ensure they are identical for (int index = 0; index < savedModules.Count; ++index) { if (!savedModules[index].IsIdenticalTo(comparedPart.savedModules[index])) { return(false); } } //If everything has passed, they are considered equal return(true); } return(false); }
/// <summary> /// Finds all parts in the inventory for the given InventoryPart and the provided strictness /// </summary> /// <param name="part">The source part to find a match for</param> /// <param name="strength">The strictness of the comparison. Defaults to MODULES.</param> /// <returns>An IEnumerable of InventoryParts that match</returns> public IEnumerable <InventoryPart> FindParts(InventoryPart part, ComparisonStrength strength = ComparisonStrength.MODULES) { if (!InventoryEnabled) { return(null); } List <InventoryPart> foundParts = new List <InventoryPart>(); PartInventory copy = Copy(); InventoryPart found = null; do { found = copy.RemovePart(part, strength); if (found != null) { foundParts.Add(found); } } while (found != null); return(foundParts); }
/// <summary> /// Takes a list of parts and registers it as a build /// </summary> /// <param name="parts">The vessel as a list of parts</param> public void AddBuild(IEnumerable <Part> parts) { if (!TrackerEnabled || KRASHWrapper.simulationActive()) { return; } Logging.Log("Adding build (parts)"); Dictionary <InventoryPart, TrackType> uniqueParts = new Dictionary <InventoryPart, TrackType>(); foreach (Part part in parts) //add a use for each part and get the unique parts for the build tracker { InventoryPart converted = new InventoryPart(part); InventoryPart found = addUse(converted); InventoryPart found_bak = found; TrackType thisType = converted.TrackerModule.Inventoried ? TrackType.INVENTORIED : TrackType.NEW; if ((found = uniqueParts.Keys.FirstOrDefault(ip => ip.IsSameAs(converted, _strictness))) != null) { if (uniqueParts[found] != TrackType.TOTAL && uniqueParts[found] != thisType) { uniqueParts[found] = TrackType.TOTAL; } } else { //not previously in dictionary, so add found = found_bak; uniqueParts.Add(found, thisType); } } //Increment the build tracker foreach (var partPair in uniqueParts) { addBuild(partPair.Key, partPair.Value); } ScrapYardEvents.OnSYTrackerUpdated.Fire(uniqueParts.Keys); }
public void InventoryChangedEventListener(InventoryPart p, bool added) { //if removed then check if we should remove a corresponding part from the EditorLogic vessel if (!added) { if (EditorLogic.fetch?.ship?.Parts?.Count > 0) { //see if this part is on it, if so, overwrite it with a new one foreach (Part part in EditorLogic.fetch.ship.Parts) { InventoryPart shipPart = new InventoryPart(part); if (p.ID == shipPart.ID) { ModuleSYPartTracker module = part.Modules["ModuleSYPartTracker"] as ModuleSYPartTracker; module.MakeFresh(); break; //There can only be one part with this ID } } } } Logging.Log($"InventoryChangedEvent - part: '{p.Name}' added? {added}"); }
/// <summary> /// Checks to see if the passed InventoryPart is identical to this one, for a given strictness of "identical" /// </summary> /// <param name="comparedPart">The part to compare to</param> /// <param name="strictness">The strength of the comparison (just name? modules? everything?)</param> /// <returns>True if mathing, false otherwise</returns> public bool IsSameAs(InventoryPart comparedPart, ComparisonStrength strictness) { //Test that the name is the same if (Name != comparedPart.Name) { return(false); } if (strictness == ComparisonStrength.NAME) //If we're just comparing name then we're done { return(true); } //Verify the costs are within 1 funds if (Math.Abs(DryCost - comparedPart.DryCost) > 1.0) { return(false); } if (strictness == ComparisonStrength.COSTS) { return(true); } if (strictness == ComparisonStrength.STRICT) //Strict comparison, the ids must be the same { //Compare IDs now so we can avoid the full module comparison if they don't have the same ID if (comparedPart.ID != ID) { return(false); } } //Test to ensure the number of saved modules are identical if (savedModules.Count == comparedPart.savedModules.Count) { //Compare the saved modules to ensure they are identical for (int index = 0; index < savedModules.Count; ++index) { if (!savedModules[index].IsIdenticalTo(comparedPart.savedModules[index])) { return(false); } } //If everything has passed, they are considered equal } else { return(false); } if (strictness == ComparisonStrength.MODULES) { return(true); } //Tracker comparison, the times used must match if (TrackerModule.TimesRecovered != comparedPart.TrackerModule.TimesRecovered) { return(false); } if (TrackerModule.Inventoried != comparedPart.TrackerModule.Inventoried) { return(false); } if (strictness == ComparisonStrength.TRACKER) { return(true); } //Everything must match, they are the same return(true); }
private void InventoryChangedEventListener(InventoryPart p, int o, int n) { Debug.Log($"InventoryChangedEvent - part: {p.Name} - old: {o} - new: {n}"); }
/// <summary> /// Adds a part to the inventory using a ConfigNode of a Part /// </summary> /// <param name="partNode">The ConfigNode to add</param> public InventoryPart AddPart(ConfigNode partNode) { InventoryPart convertedPart = new InventoryPart(partNode); return(AddPart(convertedPart)); }