diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index d9f9aae..435cf88 100644 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -8,9 +8,19 @@ "profile_save":"Your profile changes were saved.", "buddy_request":"Attempting to Add Buddy. The other player must click ADD BUDDY as well. (Many players reserve this for just a couple players so don't feel insulted if they do not).", "drawing_notice":"Drawing not sent to other players when you are not a subscriber.", - "grab_message":"You grabbed an object off the ground.", - "grab_all_message":"You grabbed all objects off the ground.", - "dropped_item_message":"You dropped an item on the ground.", + "dropped_items":{ + "grab_message":"You grabbed an object off the ground.", + "grab_all_message":"You grabbed all objects off the ground.", + "dropped_item_message":"You dropped an item on the ground.", + "grab_but_inv_full":"Your inventory is full! Cannot grab items." + }, + "shop":{ + "cant_afford_1":"You cannot afford that item!", + "cant_afford_5":"You cannot afford 5 of that item!", + "cant_afford_25":"You cannot afford 25 of that item!", + "brought_1_but_inv_full":"Your inventory is full! Cannot buy that item.", + "brought_1":"You bought a %ITEM% for $%PRICE%." + }, "tools":{ "binoculars":"You search high and low all around, but find nothing interesting.", "magnify":"You look all over at all the tiny details, but alas, nothing interesting.", @@ -48,7 +58,6 @@ "area_format":" in %AREA%", "location_format":" You are%META% ", "tile_format":"%TILENAME%", - "transport_format":"^LTransport via %METHOD% to %PLACE%^R1^I%ICON%^T4Trip Costs $%COST% one way. ^B1M%XY%^BY%ID%", "exit_this_place":"^X", "end_of_meta":"^Z", @@ -72,6 +81,9 @@ "npc_talk_button":"^BA%ID%" }, "inventory":{ + "full_inventory_grab":"Your inventory is full! Cannot grab items.", + "full_inventory_buy":"Your inventory is full! Cannot grab items.", + "header_format":"^ATYour Inventory^HYou are carrying the following %ITEMCOUNT% different items: (%MAXITEMS% max)", "item_entry":"^I%ICONID%^T4(%COUNT%) %TITLE%", "shop_entry":"^I%ICONID%^T4(%COUNT%) %TITLE% $%PRICE%", @@ -87,6 +99,7 @@ "buy_25_button":"^B4B2%ITEMID%", "sell_button":"^B4S%RANDOMID%", "sell_all_button":"^B4A%ITEMID%", + }, "dropped_items":{ "nothing_message":"^LYou see nothing on the ground of interest.^R1", diff --git a/Horse Isle Server/Horse Isle Server/Game/Messages.cs b/Horse Isle Server/Horse Isle Server/Game/Messages.cs index 14d6fac..043c7be 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Messages.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Messages.cs @@ -67,6 +67,7 @@ namespace HISP.Game public static string GrabAllItemsButton; public static string GrabAllItemsMessage; public static string GrabbedItemMessage; + public static string GrabbedItemButInventoryFull; public static string GrabbedAllObjectsMessage; public static string DroppedAnItemMessage; public static string ItemInformationFormat; @@ -97,6 +98,13 @@ namespace HISP.Game public static string ThingsIAmSelling; public static string ThingsYouSellMe; public static string InfinitySign; + public static string CantAfford1; + public static string CantAfford5; + public static string CantAfford25; + public static string Brought1Format; + public static string Brought1ButInventoryFull; + public static string Brought5; + public static string Brought25; // Npc public static string NpcStartChatFormat; @@ -139,7 +147,10 @@ namespace HISP.Game public static string BallonCutscene; - + public static string FormatBuyMessage(string itemName, int price) + { + return Brought1Format.Replace("%ITEM%", itemName).Replace("%PRICE%", price.ToString()); + } public static string FormatShopEntry(int iconid, string count, string name, int price) { return ShopEntryFormat.Replace("%ICONID%", iconid.ToString()).Replace("%COUNT%", count).Replace("%TITLE%", name).Replace("%PRICE%", price.ToString()); diff --git a/Horse Isle Server/Horse Isle Server/Game/Quest.cs b/Horse Isle Server/Horse Isle Server/Game/Quest.cs index 55d435f..7f2001e 100644 --- a/Horse Isle Server/Horse Isle Server/Game/Quest.cs +++ b/Horse Isle Server/Horse Isle Server/Game/Quest.cs @@ -135,7 +135,7 @@ namespace HISP.Game for (int i = 0; i < itemInfo.Quantity; i++) { ItemInstance itm = new ItemInstance(itemInfo.ItemId); - user.Inventory.Add(itm); + user.Inventory.AddIgnoringFull(itm); } } if (quest.WarpX != 0 && quest.WarpY != 0) diff --git a/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj b/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj index cc8fe85..9313cdd 100644 --- a/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj +++ b/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj @@ -72,6 +72,7 @@ + diff --git a/Horse Isle Server/Horse Isle Server/Player/PlayerInventory.cs b/Horse Isle Server/Horse Isle Server/Player/PlayerInventory.cs index 51ea7fd..24f47ad 100644 --- a/Horse Isle Server/Horse Isle Server/Player/PlayerInventory.cs +++ b/Horse Isle Server/Horse Isle Server/Player/PlayerInventory.cs @@ -5,8 +5,11 @@ using HISP.Server; namespace HISP.Player { + class PlayerInventory : IInventory { + + public User BaseUser; private List inventoryItems; public PlayerInventory(User forUser) @@ -143,8 +146,27 @@ namespace HISP.Player throw new KeyNotFoundException("random id: " + randomId + " not found in inventory"); } + public void AddIgnoringFull(ItemInstance item) + { + addItem(item, true); + } public void Add(ItemInstance item) { + // Check if has max allready + if(HasItemId(item.ItemId)) + { + InventoryItem items = GetItemByItemId(item.ItemId); + if (items.ItemInstances.Count >= ConfigReader.MAX_STACK) + { + throw new InventoryMaxStackException(); + } + else if (Count >= Messages.DefaultInventoryMax) + { + throw new InventoryFullException(); + } + } + + addItem(item, true); } } diff --git a/Horse Isle Server/Horse Isle Server/Server/ConfigReader.cs b/Horse Isle Server/Horse Isle Server/Server/ConfigReader.cs index f7fef64..b0e79ea 100644 --- a/Horse Isle Server/Horse Isle Server/Server/ConfigReader.cs +++ b/Horse Isle Server/Horse Isle Server/Server/ConfigReader.cs @@ -24,6 +24,8 @@ namespace HISP.Server public static bool BadWords; public static bool DoCorrections; + public const int MAX_STACK = 40; + private static string ConfigurationFileName = "server.properties"; public static void OpenConfig() { diff --git a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs index 87c135b..7f138c9 100644 --- a/Horse Isle Server/Horse Isle Server/Server/GameServer.cs +++ b/Horse Isle Server/Horse Isle Server/Server/GameServer.cs @@ -598,7 +598,18 @@ namespace HISP.Server try { DroppedItems.DroppedItem item = DroppedItems.GetDroppedItemById(randomId); - sender.LoggedinUser.Inventory.Add(item.instance); + try + { + sender.LoggedinUser.Inventory.Add(item.instance); + } + catch (InventoryException) + { + byte[] inventoryFullMessage = PacketBuilder.CreateChat(Messages.GrabbedItemButInventoryFull, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(inventoryFullMessage); + break; + } + + DroppedItems.RemoveDroppedItem(item); UpdateAreaForAll(sender.LoggedinUser.X, sender.LoggedinUser.Y); @@ -679,6 +690,67 @@ namespace HISP.Server sender.SendPacket(ChatPacket); } break; + case PacketBuilder.ITEM_BUY: // Handles buying an item. + packetStr = Encoding.UTF8.GetString(packet); + string itemIdStr = packetStr.Substring(2, packet.Length - 2); + int itemId = 0; + // Prevent crashing on non-int string. + try + { + itemId = Int32.Parse(itemIdStr); + } + catch (InvalidOperationException) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid object buy packet."); + return; + } + + Item.ItemInformation itemInfo = Item.GetItemById(itemId); + Shop shop = sender.LoggedinUser.LastShoppedAt; + if(shop != null) + { + int buyCost = shop.CalculateBuyCost(itemInfo); + if (sender.LoggedinUser.Money < buyCost) + { + byte[] cantAffordMessage = PacketBuilder.CreateChat(Messages.CantAfford1, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(cantAffordMessage); + break; + } + sender.LoggedinUser.Money -= buyCost; + if (shop.Inventory.HasItemId(itemId)) + { + ItemInstance itemInstance = shop.Inventory.GetItemByItemId(itemId).ItemInstances[0]; + + try + { + sender.LoggedinUser.Inventory.Add(itemInstance); + } + catch(InventoryException) + { + byte[] inventoryFullMessage = PacketBuilder.CreateChat(Messages.Brought1ButInventoryFull, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(inventoryFullMessage); + break; + } + + shop.Inventory.Remove(itemInstance); + UpdateAreaForAll(sender.LoggedinUser.X, sender.LoggedinUser.Y); + // Send chat message to client. + byte[] broughtItemMessage = PacketBuilder.CreateChat(Messages.FormatBuyMessage(itemInfo.Name,buyCost), PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(broughtItemMessage); + + } + else + { + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to buy a item that was not for sale."); + } + } + else + { + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to buy an item while not in a store."); + } + + break; + case PacketBuilder.INFORMATION: packetStr = Encoding.UTF8.GetString(packet); randomIdStr = packetStr.Substring(3, packet.Length - 3); @@ -696,7 +768,7 @@ namespace HISP.Server if (packet[2] == PacketBuilder.ITEM_INFORMATON) { - int itemId = -1; + itemId = -1; if (sender.LoggedinUser.Inventory.HasItem(randomId)) itemId = sender.LoggedinUser.Inventory.GetItemByRandomid(randomId).ItemId; else if (DroppedItems.IsDroppedItemExist(randomId)) diff --git a/Horse Isle Server/Horse Isle Server/Server/Gamedata.cs b/Horse Isle Server/Horse Isle Server/Server/Gamedata.cs index 06655f5..01ec2b6 100644 --- a/Horse Isle Server/Horse Isle Server/Server/Gamedata.cs +++ b/Horse Isle Server/Horse Isle Server/Server/Gamedata.cs @@ -418,8 +418,12 @@ namespace HISP.Server Messages.GrabItemFormat = gameData.messages.meta.dropped_items.item_format; Messages.ItemInformationFormat = gameData.messages.meta.dropped_items.item_information_format; Messages.GrabAllItemsButton = gameData.messages.meta.dropped_items.grab_all; - Messages.DroppedAnItemMessage = gameData.messages.dropped_item_message; - Messages.GrabbedAllObjectsMessage = gameData.messages.grab_all_message; + Messages.DroppedAnItemMessage = gameData.messages.dropped_items.dropped_item_message; + Messages.GrabbedAllObjectsMessage = gameData.messages.dropped_items.grab_all_message; + Messages.GrabbedItemMessage = gameData.messages.dropped_items.grab_message; + Messages.GrabAllItemsMessage = gameData.messages.dropped_items.grab_all_message; + + Messages.GrabbedItemButInventoryFull = gameData.messages.dropped_items.grab_but_inv_full; // Tools Messages.BinocularsNothing = gameData.messages.tools.binoculars; @@ -432,6 +436,13 @@ namespace HISP.Server Messages.ThingsYouSellMe = gameData.messages.meta.shop.sell_me; Messages.InfinitySign = gameData.messages.meta.shop.infinity; + Messages.CantAfford1 = gameData.messages.shop.cant_afford_1; + Messages.CantAfford5 = gameData.messages.shop.cant_afford_5; + Messages.CantAfford25 = gameData.messages.shop.cant_afford_25; + Messages.Brought1Format = gameData.messages.shop.brought_1; + + Messages.Brought1ButInventoryFull = gameData.messages.shop.brought_1_but_inv_full; + // Meta Format Messages.LocationFormat = gameData.messages.meta.location_format; @@ -446,8 +457,6 @@ namespace HISP.Server Messages.LongFullLine = gameData.messages.meta.long_full_line; Messages.MetaTerminator = gameData.messages.meta.end_of_meta; - Messages.GrabbedItemMessage = gameData.messages.grab_message; - Messages.GrabAllItemsMessage = gameData.messages.grab_all_message; Messages.NearbyPlayers = gameData.messages.meta.nearby.players_nearby; Messages.North = gameData.messages.meta.nearby.north; diff --git a/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs b/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs index 6e1440a..8442402 100644 --- a/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs +++ b/Horse Isle Server/Horse Isle Server/Server/PacketBuilder.cs @@ -67,6 +67,7 @@ namespace HISP.Server public const byte ITEM_DROP = 0x1E; public const byte ITEM_PICKUP = 0x14; + public const byte ITEM_BUY = 0x33; public const byte ITEM_BINOCULARS = 0x5C; public const byte ITEM_MAGNIFYING = 0x5D; public const byte ITEM_RAKE = 0x5B;