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); }
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)); } }
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); } }