diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index 923668a..c5bdd0b 100755 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -234,8 +234,8 @@ "you_offering":"You are offering %PLAYERNAME% the following: ", - "add_items":"^T6Add additional trade items:^D58|ADD^R1^H", - "other_offering":"%PLAYERNAME% is offering you the following:", + "add_items":"^T6Add additional trade items:^D58|ADD^R1", + "other_offering":"^H%PLAYERNAME% is offering you the following:", "when_done_click":"^T8When you are done offering things click ^D59|DONE^R1", "cancel_anytime":"^T6You may cancel trade at any time^B1J%PLAYERID%^R1", diff --git a/Horse Isle Server/HorseIsleServer/Game/Messages.cs b/Horse Isle Server/HorseIsleServer/Game/Messages.cs index 9001dfe..6d73a8d 100755 --- a/Horse Isle Server/HorseIsleServer/Game/Messages.cs +++ b/Horse Isle Server/HorseIsleServer/Game/Messages.cs @@ -45,9 +45,9 @@ namespace HISP.Game public static string TradeOfferItem; public static string TradeOfferItemFormat; - public static string TradeOfferObjectOtherPlayerInvFull; + public static string TradeOfferItemOtherPlayerInvFull; - // Trading : Money Offer Submenu + // Trading : Offer Submenu public static string TradeMoneyOfferSubmenuFormat; public static string TradeItemOfferSubmenuFormat; diff --git a/Horse Isle Server/HorseIsleServer/Game/Meta.cs b/Horse Isle Server/HorseIsleServer/Game/Meta.cs index f270b7d..e618468 100755 --- a/Horse Isle Server/HorseIsleServer/Game/Meta.cs +++ b/Horse Isle Server/HorseIsleServer/Game/Meta.cs @@ -41,6 +41,7 @@ namespace HISP.Game User[] playersAt = GameServer.GetUsersAt(x, y, true, true); if(playersAt.Length > 1) { + playersHere += Messages.Seperator; playersHere += Messages.PlayersHere; int count = 0; foreach(User playerAt in playersAt) @@ -406,11 +407,114 @@ namespace HISP.Game throw new Exception("A mathematically impossible error occured. please check wether the laws of physics still apply."); } + public static string BuildTradeAdd(Trade trade) + { + string message = Messages.FormatTradeWhatToOffer(trade.OtherTrade.Trader.Username); + message += Messages.TradeOfferMoney; + message += Messages.TradeOfferHorse; + foreach(HorseInstance horse in trade.Trader.HorseInventory.HorseList) + { + bool tacked = (horse.Equipment.Saddle != null || horse.Equipment.SaddlePad != null || horse.Equipment.Bridle != null || horse.Equipment.Companion != null); + message += Messages.FormatTradeOfferHorse(horse.Name, tacked, horse.RandomId); + } + + if(trade.Trader.Inventory.Count >= trade.Trader.MaxItems) + { + message += Messages.TradeOfferItemOtherPlayerInvFull; + } + else + { + message += Messages.TradeOfferItem; + foreach(InventoryItem item in trade.Trader.Inventory.GetItemList()) + { + Item.ItemInformation itemInfo = Item.GetItemById(item.ItemId); + message += Messages.FormatTradeOfferItem(itemInfo.IconId, itemInfo.Name, item.ItemInstances.Count, item.ItemId); + } + } + + message += Messages.BackToMap; + message += Messages.MetaTerminator; + return message; + + } + + public static string BuildTradeAddItem(int totalItems) + { + string message = ""; + message += Messages.FormatTradeOfferItemSubmenu(totalItems); + message += Messages.BackToMap; + message += Messages.MetaTerminator; + return message; + } + public static string BuildTradeAddMoney(int curMoney) + { + string message = ""; + message += Messages.FormatTradeOfferMoneySubmenu(curMoney); + message += Messages.BackToMap; + message += Messages.MetaTerminator; + return message; + } public static string BuildTrade(Trade trade) { - bool otherAccepted = (trade.OtherTrade.Stage == "ACCEPTED"); - bool youAccepted = trade.Stage == "ACCEPTED"; + string message = ""; + message += Messages.FormatTradeWithPlayer(trade.OtherTrade.Trader.Username); + + if (trade.Stage == "DONE" && trade.OtherTrade.Stage == "DONE") + message += Messages.TradeFinalReview; + else if (trade.Stage == "DONE") + message += Messages.TradeWaitingForOtherDone; + else if (trade.OtherTrade.Stage == "DONE") + message += Messages.TradeOtherPlayerIsDone; + + + message += Messages.FormatTradeYourOffering(trade.OtherTrade.Trader.Username); + if (trade.MoenyOffered == 0 && trade.ItemsOffered.Count == 0 && trade.HorsesOffered.Count == 0) + message += Messages.TradeOfferingNothing; + if (trade.MoenyOffered > 0) + message += Messages.FormatTradeMoneyOffer(trade.MoenyOffered); + if(trade.HorsesOffered.Count > 0) + foreach(HorseInstance horse in trade.HorsesOffered) + message += Messages.FormatTradeHorseOffer(horse.Name, horse.RandomId); + if(trade.ItemsOffered.Count > 0) + foreach(ItemInstance[] item in trade.ItemsOffered) + { + Item.ItemInformation itemInfo = item[0].GetItemInfo(); + string name = itemInfo.Name; + if (item.Length > 1) + name = itemInfo.PluralName; + + message += Messages.FormatTradeItemOffer(item.Length, name); + } + + if(trade.Stage == "OPEN") + message += Messages.TradeAddItems; + + message += Messages.FormatTradeOtherOffering(trade.OtherTrade.Trader.Username); + if (trade.OtherTrade.MoenyOffered == 0 && trade.OtherTrade.ItemsOffered.Count == 0 && trade.OtherTrade.HorsesOffered.Count == 0) + message += Messages.TradeOfferingNothing; + if (trade.OtherTrade.MoenyOffered > 0) + message += Messages.FormatTradeMoneyOffer(trade.OtherTrade.MoenyOffered); + if (trade.OtherTrade.HorsesOffered.Count > 0) + foreach (HorseInstance horse in trade.OtherTrade.HorsesOffered) + message += Messages.FormatTradeHorseOffer(horse.Name, horse.RandomId); + if (trade.OtherTrade.ItemsOffered.Count > 0) + foreach (ItemInstance[] item in trade.OtherTrade.ItemsOffered) + { + Item.ItemInformation itemInfo = item[0].GetItemInfo(); + string name = itemInfo.Name; + if (item.Length > 1) + name = itemInfo.PluralName; + + message += Messages.FormatTradeItemOffer(item.Length, name); + } + + if (trade.Stage == "OPEN") + message += Messages.TradeWhenDoneClick; + if (((trade.Stage == "DONE" || trade.Stage == "ACCEPTED") && (trade.OtherTrade.Stage == "DONE" || trade.Stage == "ACCEPTED")) ) + message += Messages.TradeAcceptTrade; + + message += Messages.TradeCancelAnytime; return message; } diff --git a/Horse Isle Server/HorseIsleServer/Player/Trade.cs b/Horse Isle Server/HorseIsleServer/Player/Trade.cs index e8ae1fc..cfc4f77 100644 --- a/Horse Isle Server/HorseIsleServer/Player/Trade.cs +++ b/Horse Isle Server/HorseIsleServer/Player/Trade.cs @@ -1,6 +1,8 @@ -using HISP.Game.Horse; +using HISP.Game; +using HISP.Game.Horse; using HISP.Game.Items; using HISP.Security; +using HISP.Server; using System; using System.Collections.Generic; using System.Linq; @@ -25,7 +27,38 @@ namespace HISP.Player public int MoenyOffered = 0; public List HorsesOffered = new List(); - public List ItemsOffered = new List(); + public List ItemsOffered = new List(); + + private void endTrade() + { + Trader.PendingTradeTo = 0; + Trader.TradingWith = null; + + OtherTrade.Trader.PendingTradeTo = 0; + OtherTrade.Trader.TradingWith = null; + + GameServer.UpdateArea(Trader.LoggedinClient); + GameServer.UpdateArea(OtherTrade.Trader.LoggedinClient); + } + + public void CancelTrade() + { + byte[] tradeCanceled = PacketBuilder.CreateChat(Messages.TradeCanceledByYouMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); + Trader.LoggedinClient.SendPacket(tradeCanceled); + + byte[] tradeCanceledOther = PacketBuilder.CreateChat(Messages.FormatTradeCanceledByPlayer(Trader.Username), PacketBuilder.CHAT_BOTTOM_RIGHT); + OtherTrade.Trader.LoggedinClient.SendPacket(tradeCanceledOther); + + endTrade(); + } + public void CancelTradeMoved() + { + byte[] playerMoved = PacketBuilder.CreateChat(Messages.TradeCanceledBecuasePlayerMovedMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); + Trader.LoggedinClient.SendPacket(playerMoved); + OtherTrade.Trader.LoggedinClient.SendPacket(playerMoved); + + endTrade(); + } } } diff --git a/Horse Isle Server/HorseIsleServer/Player/User.cs b/Horse Isle Server/HorseIsleServer/Player/User.cs index 40b5230..aea7ef4 100755 --- a/Horse Isle Server/HorseIsleServer/Player/User.cs +++ b/Horse Isle Server/HorseIsleServer/Player/User.cs @@ -78,6 +78,7 @@ namespace HISP.Player public string PawneerOrderColor = ""; public string PawneerOrderGender = ""; + public int PendingTradeTo; public Mailbox MailBox; public Friends Friends; public string Password; // For chat filter. diff --git a/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs b/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs index 2cd6acc..c3176ee 100755 --- a/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs +++ b/Horse Isle Server/HorseIsleServer/Server/GameDataJson.cs @@ -838,7 +838,7 @@ namespace HISP.Server Messages.TradeWhenDoneClick = gameData.messages.meta.player_interaction.trade.when_done_click; Messages.TradeCancelAnytime = gameData.messages.meta.player_interaction.trade.cancel_anytime; - Messages.TradeAcceptedMessage = gameData.messages.meta.player_interaction.trade.accept_trade; + Messages.TradeAcceptTrade = gameData.messages.meta.player_interaction.trade.accept_trade; Messages.TradeOfferingNothing = gameData.messages.meta.player_interaction.trade.offering_nothing; Messages.TradeOfferingMoneyFormat = gameData.messages.meta.player_interaction.trade.offering_money; @@ -856,7 +856,7 @@ namespace HISP.Server Messages.TradeOfferItem = gameData.messages.meta.player_interaction.trade.offer_object; Messages.TradeOfferItemFormat = gameData.messages.meta.player_interaction.trade.offer_object_format; - Messages.TradeOfferObjectOtherPlayerInvFull = gameData.messages.meta.player_interaction.trade.offer_object_inv_full; + Messages.TradeOfferItemOtherPlayerInvFull = gameData.messages.meta.player_interaction.trade.offer_object_inv_full; // Trading : Offer Submenu @@ -879,6 +879,7 @@ namespace HISP.Server Messages.TradeAcceptedMessage = gameData.messages.meta.player_interaction.trade.trade_accepted; Messages.TradeCanceledByYouMessage = gameData.messages.meta.player_interaction.trade.you_canceled; Messages.TradeCanceledByOtherPlayerFormat = gameData.messages.meta.player_interaction.trade.other_canceled; + Messages.TradeCanceledBecuasePlayerMovedMessage = gameData.messages.meta.player_interaction.trade.trade_canceled_moved; Messages.TradeCanceledInterupted = gameData.messages.meta.player_interaction.trade.trade_interupted; Messages.TradeYouCantHandleMoreHorses = gameData.messages.meta.player_interaction.trade.cant_handle_more_horses; diff --git a/Horse Isle Server/HorseIsleServer/Server/GameServer.cs b/Horse Isle Server/HorseIsleServer/Server/GameServer.cs index a24ea1c..a10edaa 100755 --- a/Horse Isle Server/HorseIsleServer/Server/GameServer.cs +++ b/Horse Isle Server/HorseIsleServer/Server/GameServer.cs @@ -200,6 +200,124 @@ namespace HISP.Server Logger.ErrorPrint(sender.RemoteIp + " Requested Bird Map when not logged in."); return; } + byte method = packet[1]; + switch(method) + { + case PacketBuilder.PLAYER_INTERACTION_TRADE_REJECT: + if (sender.LoggedinUser.TradingWith != null) + sender.LoggedinUser.TradingWith.CancelTrade(); + break; + case PacketBuilder.PLAYER_INTERACTION_ADD_ITEM: + if (sender.LoggedinUser.TradingWith == null) + break; + if (packet.Length < 5) + break; + + string packetStr = Encoding.UTF8.GetString(packet); + string idStr = packetStr.Substring(2, packetStr.Length - 4); + char firstChar = idStr[0]; + switch(firstChar) + { + case '3': // Money + + if (sender.LoggedinUser.Bids.Count > 0) + { + byte[] cantBuyWhileAuctioning = PacketBuilder.CreateChat(Messages.AuctionNoOtherTransactionAllowed, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(cantBuyWhileAuctioning); + break; + } + + + byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildTradeAddMoney(sender.LoggedinUser.Money)); + sender.SendPacket(metaPacket); + + break; + case '2': // Horse + string horseRandomIdStr = idStr.Substring(1); + int horseRandomId = -1; + try + { + horseRandomId = int.Parse(horseRandomIdStr); + } + catch (FormatException) + { + break; + } + + if (!sender.LoggedinUser.HorseInventory.HorseIdExist(horseRandomId)) + break; + + HorseInstance horse = sender.LoggedinUser.HorseInventory.GetHorseById(horseRandomId); + sender.LoggedinUser.TradingWith.HorsesOffered.Add(horse); + + UpdateArea(sender); + UpdateArea(sender.LoggedinUser.TradingWith.Trader.LoggedinClient); + + break; + case '1': // Item + string itemIdStr = idStr.Substring(1); + int itemId = -1; + try + { + itemId = int.Parse(itemIdStr); + } + catch(FormatException) + { + break; + } + + if (!sender.LoggedinUser.Inventory.HasItemId(itemId)) + break; + + InventoryItem item = sender.LoggedinUser.Inventory.GetItemByItemId(itemId); + byte[] addItemPacket = PacketBuilder.CreateMetaPacket(Meta.BuildTradeAddItem(item.ItemInstances.Count)); + sender.SendPacket(addItemPacket); + break; + + } + break; + case PacketBuilder.PLAYER_INTERACTION_TRADE: + packetStr = Encoding.UTF8.GetString(packet); + string playerIdStr = packetStr.Substring(2, packetStr.Length - 4); + int playerId = -1; + try + { + playerId = int.Parse(playerIdStr); + } + catch(FormatException) + { + Logger.InfoPrint(sender.LoggedinUser.Username + " tried to trade with User ID NaN."); + } + if(IsUserOnline(playerId)) + { + User user = GetUserById(playerId); + byte[] tradeMsg = PacketBuilder.CreateChat(Messages.TradeRequiresBothPlayersMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(tradeMsg); + + sender.LoggedinUser.PendingTradeTo = user.Id; + + if (user.PendingTradeTo == sender.LoggedinUser.Id) + { + // Start Trade + Trade tradeWithYou = new Trade(sender.LoggedinUser); + Trade tradeWithOther = new Trade(user); + tradeWithYou.OtherTrade = tradeWithOther; + tradeWithOther.OtherTrade = tradeWithYou; + + sender.LoggedinUser.TradingWith = tradeWithYou; + user.TradingWith = tradeWithOther; + + UpdateArea(sender); + UpdateArea(user.LoggedinClient); + } + + } + break; + default: + Logger.DebugPrint("Unknown Player interaction Method: 0x" + method.ToString("X") + " Packet: "+BitConverter.ToString(packet).Replace("-", " ")); + break; + } + return; } public static void OnBirdMapRequested(GameClient sender, byte[] packet) { @@ -2288,6 +2406,25 @@ namespace HISP.Server metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildMiscStats(sender.LoggedinUser)); sender.SendPacket(metaPacket); break; + case "58": // Add new item to trade + if(sender.LoggedinUser.TradingWith != null) + { + sender.LoggedinUser.MetaPriority = true; + metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildTradeAdd(sender.LoggedinUser.TradingWith)); + sender.SendPacket(metaPacket); + } + break; + case "59": // Done + if (sender.LoggedinUser.TradingWith != null) + { + sender.LoggedinUser.TradingWith.Stage = "DONE"; + + if (sender.LoggedinUser.TradingWith.OtherTrade.Trader.MetaPriority == false) + UpdateArea(sender.LoggedinUser.TradingWith.OtherTrade.Trader.LoggedinClient); + UpdateArea(sender); + + } + break; case "60": // Ranch Sell sender.LoggedinUser.MetaPriority = true; metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildRanchSellConfirmation()); @@ -3874,6 +4011,9 @@ namespace HISP.Server } } + if (loggedInUser.TradingWith != null) + loggedInUser.TradingWith.CancelTradeMoved(); + byte[] moveResponse = PacketBuilder.CreateMovementPacket(loggedInUser.X, loggedInUser.Y, loggedInUser.CharacterId, loggedInUser.Facing, direction, true); sender.SendPacket(moveResponse); } @@ -6193,6 +6333,13 @@ namespace HISP.Server return; } + if(forClient.LoggedinUser.TradingWith != null) + { + forClient.LoggedinUser.MetaPriority = true; + byte[] tradeMeta = PacketBuilder.CreateMetaPacket(Meta.BuildTrade(forClient.LoggedinUser.TradingWith)); + forClient.SendPacket(tradeMeta); + return; + } forClient.LoggedinUser.MetaPriority = false; diff --git a/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs b/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs index 81f2ff8..3757570 100755 --- a/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs +++ b/Horse Isle Server/HorseIsleServer/Server/PacketBuilder.cs @@ -52,7 +52,9 @@ namespace HISP.Server public const byte PACKET_AUCTION = 0x24; public const byte PACKET_PLAYER_INTERACTION = 0x2A; - public const byte PLAYER_INTERACTION_TRADE = 0x31; + public const byte PLAYER_INTERACTION_TRADE = 0x28; + public const byte PLAYER_INTERACTION_ADD_ITEM = 0x29; + public const byte PLAYER_INTERACTION_TRADE_REJECT = 0x2B; public const byte AUCTION_BID_100 = 0x29; public const byte AUCTION_BID_1K = 0x2A;