private void HandleOnItemUpdate(Notifications.Nodes.Inventory.OnItemChange change) { foreach ((PyInteger itemID, PyDictionary _changes) in change.Updates) { PyDictionary <PyString, PyTuple> changes = _changes.GetEnumerable <PyString, PyTuple>(); ItemEntity item = this.ItemFactory.LoadItem(itemID, out bool loadRequired); // if the item was just loaded there's extra things to take into account // as the item might not even need a notification to the character it belongs to if (loadRequired == true) { // trust that the notification got to the correct node // load the item and check the owner, if it's logged in and the locationID is loaded by us // that means the item should be kept here if (this.ItemFactory.TryGetItem(item.LocationID, out ItemEntity location) == false || this.CharacterManager.IsCharacterConnected(item.OwnerID) == false) { // this item should not be loaded, so unload and return this.ItemFactory.UnloadItem(item); return; } bool locationBelongsToUs = true; switch (location) { case Station _: locationBelongsToUs = this.SystemManager.StationBelongsToUs(location.ID); break; case SolarSystem _: locationBelongsToUs = this.SystemManager.SolarSystemBelongsToUs(location.ID); break; } if (locationBelongsToUs == false) { this.ItemFactory.UnloadItem(item); return; } } OnItemChange itemChange = new OnItemChange(item); // update item and build change notification if (changes.TryGetValue("locationID", out PyTuple locationChange) == true) { PyInteger oldValue = locationChange[0] as PyInteger; PyInteger newValue = locationChange[1] as PyInteger; itemChange.AddChange(ItemChange.LocationID, oldValue); item.LocationID = newValue; } if (changes.TryGetValue("quantity", out PyTuple quantityChange) == true) { PyInteger oldValue = quantityChange[0] as PyInteger; PyInteger newValue = quantityChange[1] as PyInteger; itemChange.AddChange(ItemChange.Quantity, oldValue); item.Quantity = newValue; } if (changes.TryGetValue("ownerID", out PyTuple ownerChange) == true) { PyInteger oldValue = ownerChange[0] as PyInteger; PyInteger newValue = ownerChange[1] as PyInteger; itemChange.AddChange(ItemChange.OwnerID, oldValue); item.OwnerID = newValue; } if (changes.TryGetValue("singleton", out PyTuple singletonChange) == true) { PyBool oldValue = singletonChange[0] as PyBool; PyBool newValue = singletonChange[1] as PyBool; itemChange.AddChange(ItemChange.Singleton, oldValue); item.Singleton = newValue; } // TODO: IDEALLY THIS WOULD BE ENQUEUED SO ALL OF THEM ARE SENT AT THE SAME TIME // TODO: BUT FOR NOW THIS SHOULD SUFFICE // send the notification this.NotificationManager.NotifyCharacter(item.OwnerID, "OnMultiEvent", new PyTuple(1) { [0] = new PyList(1) { [0] = itemChange } }); if (item.LocationID == this.ItemFactory.LocationRecycler.ID) { // the item is removed off the database if the new location is the recycler item.Destroy(); } else if (item.LocationID == this.ItemFactory.LocationMarket.ID) { // items that are moved to the market can be unloaded this.ItemFactory.UnloadItem(item); } else { // save the item if the new location is not removal item.Persist(); } } }
public PyDataType UnasembleItems(PyDictionary validIDsByStationID, PyList skipChecks, CallInformation call) { int characterID = call.Client.EnsureCharacterIsSelected(); List <RepairDB.ItemRepackageEntry> entries = new List <RepairDB.ItemRepackageEntry>(); bool ignoreContractVoiding = false; bool ignoreRepackageWithUpgrades = false; foreach (PyString check in skipChecks.GetEnumerable <PyString>()) { if (check == "RepairUnassembleVoidsContract") { ignoreContractVoiding = true; } if (check == "ConfirmRepackageSomethingWithUpgrades") { ignoreRepackageWithUpgrades = true; } } foreach ((PyInteger stationID, PyList itemIDs) in validIDsByStationID.GetEnumerable <PyInteger, PyList>()) { foreach (PyInteger itemID in itemIDs.GetEnumerable <PyInteger>()) { RepairDB.ItemRepackageEntry entry = this.RepairDB.GetItemToRepackage(itemID, characterID, stationID); if (entry.HasContract == true && ignoreContractVoiding == false) { throw new RepairUnassembleVoidsContract(itemID); } if (entry.HasUpgrades == true && ignoreRepackageWithUpgrades == false) { throw new ConfirmRepackageSomethingWithUpgrades(); } if (entry.Damage != 0.0) { throw new CantRepackageDamagedItem(); } entries.Add(entry); } } foreach (RepairDB.ItemRepackageEntry entry in entries) { if (entry.Singleton == false) { continue; } // extra situation, the repair is happening on a item in our node, the client must know immediately if (entry.NodeID == this.Container.NodeID || this.SystemManager.StationBelongsToUs(entry.LocationID) == true) { ItemEntity item = this.ItemFactory.LoadItem(entry.ItemID, out bool loadRequired); // the item is an inventory, take everything out! if (item is ItemInventory inventory) { foreach ((int _, ItemEntity itemInInventory) in inventory.Items) { // if the item is in a rig slot, destroy it if (itemInInventory.IsInRigSlot() == true) { Flags oldFlag = itemInInventory.Flag; this.ItemFactory.DestroyItem(itemInInventory); // notify the client about the change call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(itemInInventory, oldFlag, entry.ItemID)); } else { Flags oldFlag = itemInInventory.Flag; // update item's location itemInInventory.LocationID = entry.LocationID; itemInInventory.Flag = Flags.Hangar; // notify the client about the change call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(itemInInventory, oldFlag, entry.ItemID)); // save the item itemInInventory.Persist(); } } } // update the singleton flag too item.Singleton = false; call.Client.NotifyMultiEvent(OnItemChange.BuildSingletonChange(item, true)); // load was required, the item is not needed anymore if (loadRequired == true) { this.ItemFactory.UnloadItem(item); } } else { long nodeID = this.SystemManager.GetNodeStationBelongsTo(entry.LocationID); if (nodeID > 0) { Notifications.Nodes.Inventory.OnItemChange change = new Notifications.Nodes.Inventory.OnItemChange(); change.AddChange(entry.ItemID, "singleton", true, false); this.NotificationManager.NotifyNode(nodeID, change); } } // finally repackage the item this.RepairDB.RepackageItem(entry.ItemID, entry.LocationID); // remove any insurance contract for the ship this.InsuranceDB.UnInsureShip(entry.ItemID); } return(null); }