public PyDataType CharAddImplant(PyInteger itemID, CallInformation call) { if (this.Character.SkillQueue.Count > 0) { throw new FailedPlugInImplant(); } // get the item and plug it into our brain now! ItemEntity item = this.ItemFactory.LoadItem(itemID); // ensure the item is somewhere we can interact with it if (item.LocationID != call.Client.ShipID && item.LocationID != call.Client.StationID) { throw new CustomError("You do not have direct access to this implant"); } // check if the slot is free or not this.Character.EnsureFreeImplantSlot(item); // check ownership and skills required to plug in the implant item.EnsureOwnership(this.Character); item.CheckPrerequisites(this.Character); // separate the item if there's more than one if (item.Quantity > 1) { item.Quantity--; // notify the client of the stack change call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(item, item.Quantity + 1)); // save the item to the database item.Persist(); // create the new item with a default location and flag // this way the item location change notification is only needed once item = this.ItemFactory.CreateSimpleItem(item.Type, item.OwnerID, 0, Flags.None, 1, item.Contraband, item.Singleton); } int oldLocationID = item.LocationID; Flags oldFlag = item.Flag; item.LocationID = this.Character.ID; item.Flag = Flags.Implant; call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, oldFlag, oldLocationID)); // add the item to the inventory it belongs this.Character.AddItem(item); // persist item changes to database item.Persist(); return(null); }
public PyDataType MultiMerge(PyList merges, CallInformation call) { foreach (PyTuple merge in merges.GetEnumerable <PyTuple>()) { if (merge[0] is PyInteger == false || merge[1] is PyInteger == false || merge[2] is PyInteger == false) { continue; } PyInteger fromItemID = merge[0] as PyInteger; PyInteger toItemID = merge[1] as PyInteger; PyInteger quantity = merge[2] as PyInteger; if (this.mInventory.Items.TryGetValue(toItemID, out ItemEntity toItem) == false) { continue; } ItemEntity fromItem = this.ItemFactory.GetItem(fromItemID); // ignore singleton items if (fromItem.Singleton == true || toItem.Singleton == true) { continue; } // ignore items that are not the same type if (fromItem.Type.ID != toItem.Type.ID) { continue; } // if we're fully merging two stacks, just remove one item if (quantity == fromItem.Quantity) { int oldLocationID = fromItem.LocationID; // remove the item this.ItemFactory.DestroyItem(fromItem); // notify the client about the item too call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(fromItem, oldLocationID)); } else { // change the item's quantity fromItem.Quantity -= quantity; // notify the client about the change call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(fromItem, fromItem.Quantity + quantity)); fromItem.Persist(); } toItem.Quantity += quantity; call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(toItem, toItem.Quantity - quantity)); toItem.Persist(); } return(null); }
public PyDataType AssembleShip(PyInteger itemID, CallInformation call) { int callerCharacterID = call.Client.EnsureCharacterIsSelected(); int stationID = call.Client.EnsureCharacterIsInStation(); // ensure the item is loaded somewhere in this node // this will usually be taken care by the EVE Client if (this.ItemFactory.TryGetItem(itemID, out Ship ship) == false) { throw new CustomError("Ships not loaded for player and hangar!"); } Character character = this.ItemFactory.GetItem <Character>(callerCharacterID); if (ship.OwnerID != callerCharacterID) { throw new AssembleOwnShipsOnly(ship.OwnerID); } // do not do anything if item is already assembled if (ship.Singleton == true) { return(new ShipAlreadyAssembled(ship.Type)); } // first split the stack if (ship.Quantity > 1) { // subtract one off the stack ship.Quantity -= 1; ship.Persist(); // notify the quantity change call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(ship, ship.Quantity + 1)); // create the new item in the database Station station = this.ItemFactory.GetStaticStation(stationID); ship = this.ItemFactory.CreateShip(ship.Type, station, character); // notify the new item call.Client.NotifyMultiEvent(OnItemChange.BuildNewItemChange(ship)); } else { // stack of one, simple as changing the singleton flag ship.Singleton = true; call.Client.NotifyMultiEvent(OnItemChange.BuildSingletonChange(ship, false)); } // save the ship ship.Persist(); return(null); }
private void StackAll(Flags locationFlag, CallInformation call) { // TODO: ADD CONSTRAINTS CHECKS FOR THE LOCATIONFLAG foreach ((int firstItemID, ItemEntity firstItem) in this.mInventory.Items) { // singleton items are not even checked if (firstItem.Singleton == true || firstItem.Flag != locationFlag) { continue; } foreach ((int secondItemID, ItemEntity secondItem) in this.mInventory.Items) { // ignore the same itemID as they cannot really be merged if (firstItemID == secondItemID) { continue; } // ignore the item if it's singleton if (secondItem.Singleton == true || secondItem.Flag != locationFlag) { continue; } // ignore the item check if they're not the same type ID if (firstItem.Type.ID != secondItem.Type.ID) { continue; } int oldQuantity = secondItem.Quantity; // add the quantity of the first item to the second secondItem.Quantity += firstItem.Quantity; // also create the notification for the user call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(secondItem, oldQuantity)); this.ItemFactory.DestroyItem(firstItem); // notify the client about the item too call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(firstItem, firstItem.Flag, secondItem.LocationID)); // ensure the second item is saved to database too secondItem.Persist(); // finally break this loop as the merge was already done break; } } }
private void MoveItemHere(ItemEntity item, Flags newFlag) { // get the old location stored as it'll be used in the notifications int oldLocation = item.LocationID; Flags oldFlag = item.Flag; // rig slots cannot be moved if (item.IsInRigSlot() == true) { throw new CannotRemoveUpgradeManually(); } // special situation, if the old location is a module slot ensure the item is first offlined if (item.IsInModuleSlot() == true) { if (item is ShipModule module) { if (module.Attributes[Attributes.isOnline] == 1) { module.StopApplyingEffect("online", Client); } // disable passive effects too module.StopApplyingPassiveEffects(Client); } } // extra special situation, is the new flag an autofit one? if (newFlag == Flags.AutoFit) { // capsules cannot fit anything if (this.mInventory.Type.ID == (int)Types.Capsule) { throw new CantFitToCapsule(); } if (this.mInventory is Ship ship) { // determine where to put the item if (item is ShipModule module) { if (module.IsHighSlot() == true) { newFlag = this.GetFreeHighSlot(ship); } else if (module.IsMediumSlot() == true) { newFlag = this.GetFreeMediumSlot(ship); } else if (module.IsLowSlot() == true) { newFlag = this.GetFreeLowSlot(ship); } else if (module.IsRigSlot() == true) { newFlag = this.GetFreeRigSlot(ship); } else { // this item cannot be fitted, move it to cargo, maybe throw a exception about not being able to fit it? newFlag = Flags.Cargo; } } // TODO: HANDLE CHARGES! else { newFlag = Flags.Cargo; } } else { newFlag = Flags.Hangar; } } // special situation, if the new location is a module slot ensure the item is a singleton (TODO: HANDLE CHARGES TOO) if (newFlag.IsModule() == true) { ShipModule module = null; if (item is ShipModule shipModule) { module = shipModule; } if (item.Quantity == 1) { // remove item off the old inventory if required if (this.ItemFactory.TryGetItem(item.LocationID, out ItemInventory inventory) == true) { inventory.RemoveItem(item); } OnItemChange changes = new OnItemChange(item); if (item.Singleton == false) { changes.AddChange(ItemChange.Singleton, item.Singleton); } item.LocationID = this.mInventory.ID; item.Flag = newFlag; item.Singleton = true; changes .AddChange(ItemChange.LocationID, oldLocation) .AddChange(ItemChange.Flag, (int)oldFlag); // notify the character about the change Client.NotifyMultiEvent(changes); // update meta inventories too this.ItemFactory.MetaInventoryManager.OnItemMoved(item, oldLocation, this.mInventory.ID); // finally persist the item changes item.Persist(); } else { // item is not a singleton, create a new item, decrease quantity and send notifications ItemEntity newItem = this.ItemFactory.CreateSimpleItem(item.Type, item.OwnerID, this.mInventory.ID, newFlag, 1, false, true); item.Quantity -= 1; // notify the quantity change and the new item Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(item, item.Quantity + 1)); Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(newItem, Flags.None, 0)); item.Persist(); // replace reference so the following code handle things properly item = newItem; if (item is ShipModule shipModule2) { module = shipModule2; } } try { // apply all the passive effects (this also blocks the item fitting if the initialization fails) module?.ApplyPassiveEffects(Client); // extra check, ensure that the character has the required skills } catch (UserError) { // ensure that the passive effects that got applied already are removed from the item module?.StopApplyingPassiveEffects(Client); int newOldLocation = item.LocationID; Flags newOldFlag = item.Flag; // now undo the whole thing item.LocationID = oldLocation; item.Flag = oldFlag; Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, newOldFlag, newOldLocation)); throw; } // ensure the new inventory knows this.mInventory.AddItem(item); module?.Persist(); // put the module online after fitting it as long as it's a normal module if (module?.IsRigSlot() == false) { module?.ApplyEffect("online", Client); } } else { // remove item off the old inventory if required if (this.ItemFactory.TryGetItem(item.LocationID, out ItemInventory inventory) == true) { inventory.RemoveItem(item); } // set the new location for the item item.LocationID = this.mInventory.ID; item.Flag = newFlag; // notify the character about the change Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, oldFlag, oldLocation)); // update meta inventories too this.ItemFactory.MetaInventoryManager.OnItemMoved(item, oldLocation, this.mInventory.ID); // ensure the new inventory knows this.mInventory.AddItem(item); // finally persist the item changes item.Persist(); } }
public PyDataType InjectSkillIntoBrain(PyList itemIDs, CallInformation call) { foreach (PyInteger item in itemIDs.GetEnumerable <PyInteger>()) { try { // get the item by it's ID and change the location of it Skill skill = this.ItemFactory.GetItem <Skill>(item); // check if the character already has this skill injected if (this.Character.InjectedSkillsByTypeID.ContainsKey(skill.Type.ID) == true) { throw new CharacterAlreadyKnowsSkill(skill.Type); } // is this a stack of skills? if (skill.Quantity > 1) { // add one of the skill into the character's brain Skill newStack = this.ItemFactory.CreateSkill(skill.Type, this.Character, 0, SkillHistoryReason.None); // subtract one from the quantity skill.Quantity -= 1; // save to database skill.Persist(); // finally notify the client call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(skill, skill.Quantity + 1)); call.Client.NotifyMultiEvent(OnItemChange.BuildNewItemChange(newStack)); } else { // store old values for the notification int oldLocationID = skill.LocationID; Flags oldFlag = skill.Flag; // now set the new values skill.LocationID = this.Character.ID; skill.Flag = Flags.Skill; skill.Level = 0; skill.Singleton = true; // ensure the character has the skill in his/her brain this.Character.AddItem(skill); // ensure the changes are saved skill.Persist(); // notify the character of the change in the item call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(skill, oldFlag, oldLocationID)); call.Client.NotifyMultiEvent(OnItemChange.BuildSingletonChange(skill, false)); } } catch (CharacterAlreadyKnowsSkill) { throw; } catch (Exception) { Log.Error($"Cannot inject itemID {item} into {this.Character.ID}'s brain..."); throw; } } // send the skill injected notification to refresh windows if needed call.Client.NotifyMultiEvent(new OnSkillInjected()); return(null); }