Esempio n. 1
0
        public PyDataType AcceptContract(PyInteger contractID, PyBool forCorp, CallInformation call)
        {
            if (forCorp == true)
            {
                throw new UserError("Cannot accept contracts for corporation yet");
            }

            using MySqlConnection connection = this.MarketDB.AcquireMarketLock();
            try
            {
                int callerCharacterID = call.Client.EnsureCharacterIsSelected();

                // TODO: SUPPORT forCorp
                ContractDB.Contract contract = this.DB.GetContract(connection, contractID);

                if (contract.Status != ContractStatus.Outstanding)
                {
                    throw new ConContractNotOutstanding();
                }
                if (contract.ExpireTime < DateTime.UtcNow.ToFileTimeUtc())
                {
                    throw new ConContractExpired();
                }

                Station station = this.ItemFactory.GetStaticStation(contract.StationID);

                // TODO: CHECK REWARD/PRICE
                switch (contract.Type)
                {
                case ContractTypes.ItemExchange:
                    this.AcceptItemExchangeContract(connection, call.Client, contract, station, callerCharacterID);
                    break;

                case ContractTypes.Auction:
                    throw new CustomError("Auctions cannot be accepted!");

                case ContractTypes.Courier:
                    throw new CustomError("Courier contracts not supported yet!");

                case ContractTypes.Loan:
                    throw new CustomError("Loan contracts not supported yet!");

                case ContractTypes.Freeform:
                    throw new CustomError("Freeform contracts not supported yet!");

                default:
                    throw new CustomError("Unknown contract type to accept!");
                }
            }
            finally
            {
                this.MarketDB.ReleaseMarketLock(connection);
            }

            return(null);
        }
Esempio 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));
            }
        }
Esempio n. 3
0
        public PyDataType PlaceBid(PyInteger contractID, PyInteger quantity, PyBool forCorp, PyObjectData locationData, CallInformation call)
        {
            using MySqlConnection connection = this.MarketDB.AcquireMarketLock();
            try
            {
                // TODO: SUPPORT PROPER CORP WALLET
                int bidderID = call.Client.EnsureCharacterIsSelected();

                if (forCorp == true)
                {
                    bidderID = call.Client.CorporationID;
                    throw new UserError("Corp bidding is not supported for now!");
                }

                ContractDB.Contract contract = this.DB.GetContract(connection, contractID);

                // ensure the contract is still in progress
                if (contract.Status != ContractStatus.Outstanding)
                {
                    throw new ConAuctionAlreadyClaimed();
                }

                this.DB.GetMaximumBid(connection, contractID, out int maximumBidderID, out int maximumBid);

                // calculate next bid slot
                int nextMinimumBid = maximumBid + (int)Math.Max(0.1 * (double)contract.Price, 1000);

                if (quantity < nextMinimumBid)
                {
                    throw new ConBidTooLow(quantity, nextMinimumBid);
                }

                // take the bid's money off the wallet
                using Wallet bidderWallet = this.WalletManager.AcquireWallet(bidderID, 1000);
                {
                    bidderWallet.EnsureEnoughBalance(quantity);
                    bidderWallet.CreateJournalRecord(
                        MarketReference.ContractAuctionBid, null, null, -quantity
                        );
                }

                // check who we'd outbid and notify them
                this.DB.GetOutbids(connection, contractID, quantity, out List <int> characterIDs, out List <int> corporationIDs);

                OnContractOutbid notification = new OnContractOutbid(contractID);

                foreach (int corporationID in corporationIDs)
                {
                    if (corporationID != bidderID)
                    {
                        this.NotificationManager.NotifyCorporation(corporationID, notification);
                    }
                }

                foreach (int characterID in characterIDs)
                {
                    if (characterID != bidderID)
                    {
                        this.NotificationManager.NotifyCharacter(characterID, notification);
                    }
                }

                // finally place the bid
                ulong bidID = this.DB.PlaceBid(connection, contractID, quantity, bidderID, forCorp);

                // return the money for the player that was the highest bidder
                using Wallet maximumBidderWallet = this.WalletManager.AcquireWallet(maximumBidderID, 1000);
                {
                    maximumBidderWallet.CreateJournalRecord(
                        MarketReference.ContractAuctionBidRefund, null, null, maximumBid, ""
                        );
                }
                return(bidID);
            }
            finally
            {
                this.MarketDB.ReleaseMarketLock(connection);
            }
        }