Ejemplo n.º 1
0
        private void PrepareItemsForCourierOrAuctionContract(MySqlConnection connection, ulong contractID,
                                                             ClusterConnection clusterConnection, PyList <PyList> itemList, Station station, int ownerID, int shipID)
        {
            // create the container in the system to ensure it's not visible to the player
            Container container = this.ItemFactory.CreateSimpleItem(this.TypeManager[Types.PlasticWrap],
                                                                    this.ItemFactory.LocationSystem.ID, station.ID, Flags.None) as Container;

            Dictionary <int, ContractDB.ItemQuantityEntry> items =
                this.DB.PrepareItemsForContract(connection, contractID, itemList, station, ownerID, container.ID, shipID);

            double volume = 0;

            // build notification for item changes
            OnItemChange changes            = new OnItemChange();
            long         stationNode        = this.SystemManager.GetNodeStationBelongsTo(station.ID);
            bool         stationBelongsToUs = this.SystemManager.StationBelongsToUs(station.ID);

            // notify the changes in the items to the nodes
            foreach ((int _, ContractDB.ItemQuantityEntry item) in items)
            {
                if (stationNode == 0 || stationBelongsToUs == true)
                {
                    ItemEntity entity = this.ItemFactory.LoadItem(item.ItemID);

                    entity.LocationID = container.ID;
                    entity.Persist();

                    // notify the character
                    this.NotificationManager.NotifyCharacter(ownerID, Notifications.Client.Inventory.OnItemChange.BuildLocationChange(entity, station.ID));
                }
                else
                {
                    // queue the notification
                    changes.AddChange(item.ItemID, "locationID", station.ID, container.ID);
                }

                // ensure the volume is taken into account
                volume += item.Volume;
            }

            // notify the proper node if needed
            if (changes.Updates.Count > 0)
            {
                this.NotificationManager.NotifyNode(stationNode, changes);
            }

            // update the contract with the crate and the new volume
            this.DB.UpdateContractCrateAndVolume(ref connection, contractID, container.ID, volume);
        }
Ejemplo n.º 2
0
        private void AcceptItemExchangeContract(MySqlConnection connection, Client client, ContractDB.Contract contract, Station station, int ownerID, Flags flag = Flags.Hangar)
        {
            List <ContractDB.ItemQuantityEntry> offeredItems = this.DB.GetOfferedItems(connection, contract.ID);
            Dictionary <int, int> itemsToCheck = this.DB.GetRequiredItemTypeIDs(connection, contract.ID);
            List <ContractDB.ItemQuantityEntry> changedItems = this.DB.CheckRequiredItemsAtStation(connection, station, ownerID, contract.IssuerID, flag, itemsToCheck);

            // extract the crate
            this.DB.ExtractCrate(connection, contract.CrateID, station.ID, ownerID);

            long stationNode = this.SystemManager.GetNodeStationBelongsTo(station.ID);

            if (stationNode == 0 || this.SystemManager.StationBelongsToUs(station.ID) == true)
            {
                foreach (ContractDB.ItemQuantityEntry change in changedItems)
                {
                    ItemEntity item = this.ItemFactory.LoadItem(change.ItemID);

                    if (change.Quantity == 0)
                    {
                        // remove item from the meta inventories
                        this.ItemFactory.MetaInventoryManager.OnItemDestroyed(item);
                        // temporarily move the item to the recycler, let the current owner know
                        item.LocationID = this.ItemFactory.LocationRecycler.ID;
                        client.NotifyMultiEvent(Notifications.Client.Inventory.OnItemChange.BuildLocationChange(item, station.ID));
                        // now set the item to the correct owner and place and notify it's new owner
                        // TODO: TAKE forCorp INTO ACCOUNT
                        item.LocationID = station.ID;
                        item.OwnerID    = contract.IssuerID;
                        this.NotificationManager.NotifyCharacter(contract.IssuerID, Notifications.Client.Inventory.OnItemChange.BuildNewItemChange(item));
                        // add the item back to meta inventories if required
                        this.ItemFactory.MetaInventoryManager.OnItemLoaded(item);
                    }
                    else
                    {
                        int oldQuantity = item.Quantity;
                        item.Quantity = change.Quantity;
                        client.NotifyMultiEvent(Notifications.Client.Inventory.OnItemChange.BuildQuantityChange(item, oldQuantity));

                        item.Persist();

                        // unload the item if required
                        this.ItemFactory.UnloadItem(item);
                    }
                }

                // move the offered items
                foreach (ContractDB.ItemQuantityEntry entry in offeredItems)
                {
                    ItemEntity item = this.ItemFactory.LoadItem(entry.ItemID);

                    item.LocationID = station.ID;
                    item.OwnerID    = ownerID;

                    client.NotifyMultiEvent(Notifications.Client.Inventory.OnItemChange.BuildLocationChange(item, contract.CrateID));

                    item.Persist();

                    // unload the item if possible
                    this.ItemFactory.UnloadItem(item);
                }
            }
            else
            {
                OnItemChange changes = new OnItemChange();

                foreach (ContractDB.ItemQuantityEntry change in changedItems)
                {
                    if (change.Quantity == 0)
                    {
                        changes
                        .AddChange(change.ItemID, "locationID", contract.CrateID, station.ID)
                        .AddChange(change.ItemID, "ownerID", contract.IssuerID, ownerID);
                    }
                    else
                    {
                        // change the item quantity
                        changes.AddChange(change.ItemID, "quantity", change.OldQuantity, change.Quantity);
                        // create a new item and notify the new node about it
                        // TODO: HANDLE BLUEPRINTS TOO! RIGHT NOW NO DATA IS COPIED FOR THEM
                        ItemEntity item = this.ItemFactory.CreateSimpleItem(
                            this.TypeManager[change.TypeID], contract.IssuerID, station.ID, Flags.Hangar, change.OldQuantity - change.Quantity, false, false
                            );
                        // unload the created item
                        this.ItemFactory.UnloadItem(item);
                        changes.AddChange(item.ID, "location", 0, station.ID);
                    }
                }

                // move the offered items
                foreach (ContractDB.ItemQuantityEntry entry in offeredItems)
                {
                    // TODO: TAKE INTO ACCOUNT forCorp
                    changes
                    .AddChange(entry.ItemID, "locationID", contract.CrateID, station.ID)
                    .AddChange(entry.ItemID, "ownerID", contract.IssuerID, station.ID);
                }
            }

            // the contract was properly accepted, update it's status
            this.DB.UpdateContractStatus(ref connection, contract.ID, ContractStatus.Finished);
            this.DB.UpdateAcceptorID(ref connection, contract.ID, ownerID);
            this.DB.UpdateAcceptedDate(ref connection, contract.ID);
            this.DB.UpdateCompletedDate(ref connection, contract.ID);
            // notify the contract as being accepted
            if (contract.ForCorp == false)
            {
                this.NotificationManager.NotifyCharacter(contract.IssuerID, new OnContractAccepted(contract.ID));
            }
            else
            {
                this.NotificationManager.NotifyCorporation(contract.IssuerCorpID, new OnContractAccepted(contract.ID));
            }
        }
Ejemplo n.º 3
0
        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();
                }
            }
        }
Ejemplo n.º 4
0
        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();
            }
        }
Ejemplo n.º 5
0
        private void PlaceSellOrderCharUpdateItems(MySqlConnection connection, Client client, int stationID, int typeID, int quantity)
        {
            Dictionary <int, MarketDB.ItemQuantityEntry> items = null;

            // depending on where the character that is placing the order, the way to detect the items should be different
            if (stationID == client.StationID)
            {
                items = this.DB.PrepareItemForOrder(connection, typeID, stationID, client.ShipID ?? -1, quantity, (int)client.CharacterID);
            }
            else
            {
                items = this.DB.PrepareItemForOrder(connection, typeID, stationID, -1, quantity, (int)client.CharacterID);
            }

            if (items is null)
            {
                throw new NotEnoughQuantity(this.TypeManager[typeID]);
            }

            long stationNode = this.SystemManager.GetNodeStationBelongsTo(stationID);

            if (this.SystemManager.StationBelongsToUs(stationID) == true || stationNode == 0)
            {
                // load the items here and send proper notifications
                foreach ((int _, MarketDB.ItemQuantityEntry entry) in items)
                {
                    ItemEntity item = this.ItemFactory.LoadItem(entry.ItemID);

                    if (entry.Quantity == 0)
                    {
                        // item has to be destroyed
                        this.ItemFactory.DestroyItem(item);
                        // notify item destroyal
                        client.NotifyMultiEvent(Notifications.Client.Inventory.OnItemChange.BuildLocationChange(item, stationID));
                    }
                    else
                    {
                        // just a quantity change
                        item.Quantity = entry.Quantity;
                        // notify the client
                        client.NotifyMultiEvent(Notifications.Client.Inventory.OnItemChange.BuildQuantityChange(item, entry.OriginalQuantity));
                        // unload the item if it's not needed
                        this.ItemFactory.UnloadItem(item);
                    }
                }
            }
            else
            {
                // the item changes should be handled by a different node
                OnItemChange changes = new OnItemChange();

                foreach ((int _, MarketDB.ItemQuantityEntry entry) in items)
                {
                    if (entry.Quantity == 0)
                    {
                        changes.AddChange(entry.ItemID, "locationID", stationID, this.ItemFactory.LocationMarket.ID);
                    }
                    else
                    {
                        changes.AddChange(entry.ItemID, "quantity", entry.OriginalQuantity, entry.Quantity);
                    }
                }
            }
        }