From 2a241c35aa3a2da60e4fcd6538e215aeeec88051 Mon Sep 17 00:00:00 2001 From: SilicaAndPina Date: Wed, 21 Oct 2020 21:49:46 +1300 Subject: [PATCH] Add object/inventory stuff --- DataCollection/gamedata.json | 16 +- Horse Isle Server/Horse Isle Server/Chat.cs | 8 +- Horse Isle Server/Horse Isle Server/Client.cs | 3 + .../Horse Isle Server/Database.cs | 142 ++++++++++++- .../Horse Isle Server/DroppedItems.cs | 190 ++++++++++++++++++ .../Horse Isle Server/Gamedata.cs | 25 ++- .../Horse Isle Server.csproj | 5 +- .../Horse Isle Server/IInventory.cs | 24 +++ Horse Isle Server/Horse Isle Server/Item.cs | 12 ++ .../Horse Isle Server/ItemInstance.cs | 38 ++++ Horse Isle Server/Horse Isle Server/Logger.cs | 6 +- Horse Isle Server/Horse Isle Server/Map.cs | 4 +- .../Horse Isle Server/Messages.cs | 21 +- Horse Isle Server/Horse Isle Server/Meta.cs | 23 ++- .../Horse Isle Server/PacketBuilder.cs | 5 +- .../Horse Isle Server/PlayerInventory.cs | 45 +++++ .../Horse Isle Server/Program.cs | 1 + Horse Isle Server/Horse Isle Server/Server.cs | 125 ++++++++++-- .../Horse Isle Server/Transport.cs | 2 +- Horse Isle Server/Horse Isle Server/User.cs | 6 +- Horse Isle Server/Horse Isle Server/World.cs | 4 - 21 files changed, 645 insertions(+), 60 deletions(-) create mode 100644 Horse Isle Server/Horse Isle Server/DroppedItems.cs create mode 100644 Horse Isle Server/Horse Isle Server/IInventory.cs create mode 100644 Horse Isle Server/Horse Isle Server/ItemInstance.cs create mode 100644 Horse Isle Server/Horse Isle Server/PlayerInventory.cs diff --git a/DataCollection/gamedata.json b/DataCollection/gamedata.json index 09b39ed..72d72d4 100644 --- a/DataCollection/gamedata.json +++ b/DataCollection/gamedata.json @@ -7,6 +7,8 @@ "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.", "tag":{ "for_sender":"TAG!! %USERNAME% is now it! (tagged by %TAGGER%) [%AMOUNT% buds]", "for_others":"TAG!! %USERNAME% is now it! (tagged by %TAGGER%)" @@ -34,12 +36,19 @@ "area_format":" in %AREA%", "location_format":" You are%META% ", "tile_format":"%TILENAME%", - "nothing_message":"^LYou see nothing on the ground of interest.^R1", - "transport_format":"^LTransport via %METHOD% to %PLACE%^R1^I%ICON%^T4Trip Costs $%COST% one way. ^B1M%XY%^BY%ID%", + + "transport_format":"^R1^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", "back_to_map":"^M", - "inventory_format":"^ATYour Inventory^HYou are carrying the following %ITEMCOUNT% different items: (%MAXITEMS% max)", + "long_full_line":"^L", + "inventory_format":"^ATYour Inventory^HYou are carrying the following %ITEMCOUNT% different items: (%% max)", + "dropped_items":{ + "nothing_message":"^LYou see nothing on the ground of interest.^R1", + "items_message":"^LYou see the following on the ground:^R1", + "item_format":"^I%ICONID%^T3%ITEMNAME%^B4G%RANDOMID%^B4LE%RANDOMID%^R1", + "grab_all":"^T3^B4R^R1" + }, "nearby":{ "players_nearby":"Players Nearby:", "east":"East:", @@ -197,6 +206,7 @@ {"word":"shit","reason_type":"profanity","match_all":true}, {"word":"cunt","reason_type":"profanity","match_all":true}, {"word":"nigger","reason_type":"profanity","match_all":true}, + {"word":"stfu","reason_type":"profanity","match_all":false}, {"word":"nigga","reason_type":"profanity","match_all":true}, {"word":"homo","reason_type":"profanity","match_all":false}, {"word":"homosexual","reason_type":"profanity","match_all":true}, diff --git a/Horse Isle Server/Horse Isle Server/Chat.cs b/Horse Isle Server/Horse Isle Server/Chat.cs index 7808bdf..dbd5a80 100644 --- a/Horse Isle Server/Horse Isle Server/Chat.cs +++ b/Horse Isle Server/Horse Isle Server/Chat.cs @@ -331,12 +331,18 @@ namespace Horse_Isle_Server if (user.Moderator || user.Administrator) return Messages.FormatModChatMessage(user.Username, message); else - return user.Username+" is a hacker! (Sent in mod channel without being a mod) Maybe ban?"; + { + Logger.HackerPrint(user.Username + " Tried to send in mod chat without being a moderator. (Hack/Code Attempt)"); + return user.Username + " is a hacker! (Sent in mod channel without being a mod) Maybe ban?"; + } case ChatChannel.Admin: if (user.Administrator) return Messages.FormatAdminChatMessage(user.Username, message); else + { + Logger.HackerPrint(user.Username + " Tried to send in mod chat without being a moderator. (Hack/Code Attempt)"); return user.Username + " is a hacker! (Sent in admin channel without being a admin) Maybe ban?"; + } default: Logger.ErrorPrint(user.Username + " is trying to end a message in unknown channel " + channel.ToString("X")); return "not implemented yet :("; diff --git a/Horse Isle Server/Horse Isle Server/Client.cs b/Horse Isle Server/Horse Isle Server/Client.cs index 969e781..cb74fe2 100644 --- a/Horse Isle Server/Horse Isle Server/Client.cs +++ b/Horse Isle Server/Horse Isle Server/Client.cs @@ -161,6 +161,9 @@ namespace Horse_Isle_Server case PacketBuilder.PACKET_INVENTORY: Server.OnInventoryRequested(this, Packet); break; + case PacketBuilder.PACKET_ITEM_INTERACTION: + Server.OnItemInteraction(this,Packet); + break; default: Logger.ErrorPrint("Unimplemented Packet: " + BitConverter.ToString(Packet).Replace('-', ' ')); break; diff --git a/Horse Isle Server/Horse Isle Server/Database.cs b/Horse Isle Server/Horse Isle Server/Database.cs index adf3b7f..82a971d 100644 --- a/Horse Isle Server/Horse Isle Server/Database.cs +++ b/Horse Isle Server/Horse Isle Server/Database.cs @@ -19,7 +19,8 @@ namespace Horse_Isle_Server string MailTable = "CREATE TABLE Mailbox(IdTo INT, PlayerFrom TEXT(16),Subject TEXT(128), Message Text(1028), TimeSent INT)"; string BuddyTable = "CREATE TABLE BuddyList(Id INT, IdFriend INT, Pending BOOL)"; string WorldTable = "CREATE TABLE World(Time INT,Day INT, Year INT, Weather TEXT(64))"; - string DroppedTable = "CREATE TABLE DroppedItems(X INT, Y INT, ItemID INT)"; + string InventoryTable = "CREATE TABLE Inventory(PlayerID INT, RandomID INT, ItemID INT)"; + string DroppedItems = "CREATE TABLE DroppedItems(X INT, Y INT, RandomID INT, ItemID INT, DespawnTimer INT)"; try { @@ -72,11 +73,25 @@ namespace Horse_Isle_Server Logger.WarnPrint(e.Message); }; + try { MySqlCommand sqlCommand = db.CreateCommand(); - sqlCommand.CommandText = DroppedTable; + sqlCommand.CommandText = DroppedItems; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + catch (Exception e) + { + Logger.WarnPrint(e.Message); + }; + + try + { + + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = InventoryTable; sqlCommand.ExecuteNonQuery(); sqlCommand.Dispose(); } @@ -229,6 +244,129 @@ namespace Horse_Isle_Server } } + public static List GetPlayerInventory(int playerId) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + + sqlCommand.CommandText = "SELECT ItemId,RandomId FROM Inventory WHERE PlayerId=@playerId"; + sqlCommand.Parameters.AddWithValue("@playerId", playerId); + sqlCommand.Prepare(); + MySqlDataReader reader = sqlCommand.ExecuteReader(); + List instances = new List(); + + while(reader.Read()) + { + instances.Add(new ItemInstance(reader.GetInt32(0), reader.GetInt32(1))); + } + sqlCommand.Dispose(); + return instances; + } + } + public static void AddItemToInventory(int playerId, ItemInstance instance) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + + sqlCommand.CommandText = "INSERT INTO Inventory VALUES(@playerId,@randomId,@itemId)"; + sqlCommand.Parameters.AddWithValue("@playerId", playerId); + sqlCommand.Parameters.AddWithValue("@randomId", instance.RandomID); + sqlCommand.Parameters.AddWithValue("@itemId", instance.ItemID); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + + public static void RemoveItemFromInventory(int playerId, ItemInstance instance) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + + sqlCommand.CommandText = "DELETE FROM Inventory WHERE (PlayerId=@id AND RandomId=@randomId)"; + sqlCommand.Parameters.AddWithValue("@playerId", playerId); + sqlCommand.Parameters.AddWithValue("@randomId", instance.RandomID); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + + public static void RemoveDroppedItem(int randomId) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + + sqlCommand.CommandText = "DELETE FROM Inventory WHERE (RandomId=@randomId)"; + sqlCommand.Parameters.AddWithValue("@randomId", randomId); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + + public static DroppedItems.DroppedItem[] GetDroppedItems() + { + List itemList = new List(); + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.CommandText = "SELECT * FROM DroppedItems"; + sqlCommand.Prepare(); + MySqlDataReader reader = sqlCommand.ExecuteReader(); + while(reader.Read()) + { + DroppedItems.DroppedItem droppedItem = new DroppedItems.DroppedItem(); + droppedItem.X = reader.GetInt32(0); + droppedItem.Y = reader.GetInt32(1); + droppedItem.DespawnTimer = reader.GetInt32(4); + ItemInstance instance = new ItemInstance(reader.GetInt32(3),reader.GetInt32(4)); + droppedItem.instance = instance; + itemList.Add(droppedItem); + } + sqlCommand.Dispose(); + + } + return itemList.ToArray(); + } + public static void AddDroppedItems(DroppedItems.DroppedItem[] items) + { + using (MySqlConnection db = new MySqlConnection(ConnectionString)) + { + db.Open(); + MySqlTransaction transaction = db.BeginTransaction(); + + + foreach (DroppedItems.DroppedItem item in items) + { + + MySqlCommand sqlCommand = db.CreateCommand(); + sqlCommand.Transaction = transaction; + sqlCommand.CommandText = "INSERT INTO DroppedItems VALUES(@x, @y, @randomId, @itemId, @despawnTimer)"; + sqlCommand.Parameters.AddWithValue("@x", item.X); + sqlCommand.Parameters.AddWithValue("@y", item.Y); + sqlCommand.Parameters.AddWithValue("@randomId", item.instance.RandomID); + sqlCommand.Parameters.AddWithValue("@itemId", item.instance.ItemID); + sqlCommand.Parameters.AddWithValue("@despawnTimer", item.DespawnTimer); + sqlCommand.Prepare(); + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + + } + + transaction.Commit(); + } + + } public static void AddMail(int toId, string fromName, string subject, string message) { using (MySqlConnection db = new MySqlConnection(ConnectionString)) diff --git a/Horse Isle Server/Horse Isle Server/DroppedItems.cs b/Horse Isle Server/Horse Isle Server/DroppedItems.cs new file mode 100644 index 0000000..76423e9 --- /dev/null +++ b/Horse Isle Server/Horse Isle Server/DroppedItems.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Horse_Isle_Server +{ + class DroppedItems + { + public struct DroppedItem + { + public int X; + public int Y; + public int DespawnTimer; + public ItemInstance instance; + } + private static int epoch = 0; + private static List droppedItemsList = new List(); + public static int GetCountOfItem(Item.ItemInformation item) + { + + DroppedItem[] dropedItems = droppedItemsList.ToArray(); + int count = 0; + foreach(DroppedItem droppedItem in dropedItems) + { + if(droppedItem.instance.ItemID == item.Id) + { + count++; + } + } + return count; + } + + public static DroppedItem[] GetItemsAt(int x, int y) + { + + DroppedItem[] dropedItems = droppedItemsList.ToArray(); + List items = new List(); + foreach(DroppedItem droppedItem in dropedItems) + { + if(droppedItem.X == x && droppedItem.Y == y) + { + items.Add(droppedItem); + } + } + return items.ToArray(); + } + public static void ReadFromDatabase() + { + DroppedItem[] items = Database.GetDroppedItems(); + foreach (DroppedItem droppedItem in items) + droppedItemsList.Add(droppedItem); + } + public static void Update() + { + int epoch_new = (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + + DespawnItems(epoch, epoch_new); + epoch = epoch_new; + + GenerateItems(); + } + public static void RemoveDroppedItem(DroppedItem item) + { + Database.RemoveDroppedItem(item.instance.RandomID); + droppedItemsList.Remove(item); + } + public static DroppedItem GetDroppedItemById(int randomId) + { + + DroppedItem[] dropedItems = droppedItemsList.ToArray(); + + foreach (DroppedItem item in dropedItems) + { + if(item.instance.RandomID == randomId) + { + return item; + } + } + + throw new KeyNotFoundException("Random id: " + randomId.ToString() + " not found"); + + } + public static void DespawnItems(int old_epoch, int new_epoch) + { + DroppedItem[] items = droppedItemsList.ToArray(); + foreach (DroppedItem item in items) + { + if(old_epoch + item.DespawnTimer < new_epoch) + { + if(Server.GetUsersAt(item.X, item.Y,true,true).Length == 0) + { + RemoveDroppedItem(item); + } + } + } + } + public static void GenerateItems() + { + int newItems = 0; + foreach (Item.ItemInformation item in Item.Items) + { + int count = GetCountOfItem(item); + while (count < item.SpawnParamaters.SpawnCap) + { + + count++; + + int despawnTimer = Server.RandomNumberGenerator.Next(900, 1500); + + if (item.SpawnParamaters.SpawnInArea != null) + { + + } + else if (item.SpawnParamaters.SpawnOnSpecialTile != null) + { + + } + else if (item.SpawnParamaters.SpawnNearSpecialTile != null) + { + + } + else if (item.SpawnParamaters.SpawnOnTileType != null) + { + + while (true) + { + // Pick a random isle: + int isleId = Server.RandomNumberGenerator.Next(0, World.Isles.Count); + World.Isle isle = World.Isles[isleId]; + + // Pick a random location inside the isle + int tryX = Server.RandomNumberGenerator.Next(isle.StartX, isle.EndX); + int tryY = Server.RandomNumberGenerator.Next(isle.StartY, isle.EndY); + + + if (World.InTown(tryX, tryY) || World.InSpecialTile(tryX, tryY)) + continue; + + if (Map.CheckPassable(tryX, tryY)) // Can the player walk here? + { + int TileID = Map.GetTileId(tryX, tryY, false); + string TileType = Map.TerrainTiles[TileID - 1].Type; // Is it the right type? + + if (item.SpawnParamaters.SpawnOnTileType == TileType) + { + ItemInstance instance = new ItemInstance(item.Id); + DroppedItem droppedItem = new DroppedItem(); + droppedItem.X = tryX; + droppedItem.Y = tryY; + droppedItem.DespawnTimer = despawnTimer; + droppedItem.instance = instance; + droppedItemsList.Add(droppedItem); + Logger.DebugPrint("Created Item ID: " + instance.ItemID + " in " + isle.Name + " at: X: " + droppedItem.X + " Y: " + droppedItem.Y); + newItems++; + break; + + } + else + { + continue; + } + } + else + { + continue; + } + } + + } + + + + } + + } + if(newItems > 0) + Database.AddDroppedItems(droppedItemsList.ToArray()); + } + + public static void Init() + { + ReadFromDatabase(); + Logger.InfoPrint("Generating items, (this may take awhile on a fresh database!)"); + GenerateItems(); + } + + } +} diff --git a/Horse Isle Server/Horse Isle Server/Gamedata.cs b/Horse Isle Server/Horse Isle Server/Gamedata.cs index f86c829..eb8c67f 100644 --- a/Horse Isle Server/Horse Isle Server/Gamedata.cs +++ b/Horse Isle Server/Horse Isle Server/Gamedata.cs @@ -154,7 +154,7 @@ namespace Horse_Isle_Server Logger.DebugPrint("Registered Transport Location: "+ transportPlace.LocationTitle+" To Goto X: " + transportPlace.GotoX + " Y: " + transportPlace.GotoY); } - + // Register Items int totalItems = gameData.item.item_list.Count; for (int i = 0; i < totalItems; i++) { @@ -183,12 +183,12 @@ namespace Horse_Isle_Server item.Effects = effectsList; item.SpawnParamaters = new Item.SpawnRules(); item.SpawnParamaters.SpawnCap = gameData.item.item_list[i].spawn_parameters.spawn_cap; - item.SpawnParamaters.SpawnInArea = gameData.item.item_list[i].spawn_in_area; - item.SpawnParamaters.SpawnOnTileType = gameData.item.item_list[i].spawn_on_tile_type; - item.SpawnParamaters.SpawnOnSpecialTile = gameData.item.item_list[i].spawn_on_special_tile; - item.SpawnParamaters.SpawnNearSpecialTile = gameData.item.item_list[i].spawn_near_special_tile; + item.SpawnParamaters.SpawnInArea = gameData.item.item_list[i].spawn_parameters.spawn_in_area; + item.SpawnParamaters.SpawnOnTileType = gameData.item.item_list[i].spawn_parameters.spawn_on_tile_type; + item.SpawnParamaters.SpawnOnSpecialTile = gameData.item.item_list[i].spawn_parameters.spawn_on_special_tile; + item.SpawnParamaters.SpawnNearSpecialTile = gameData.item.item_list[i].spawn_parameters.spawn_near_special_tile; - Logger.DebugPrint("Registered Item ID: " + item.Id + " Name: " + item.Name); + Logger.DebugPrint("Registered Item ID: " + item.Id + " Name: " + item.Name + " spawns on: "+item.SpawnParamaters.SpawnOnTileType); Item.Items.Add(item); } @@ -247,11 +247,17 @@ namespace Horse_Isle_Server Messages.TileFormat = gameData.messages.meta.tile_format; Messages.TransportFormat = gameData.messages.meta.transport_format; Messages.InventoryFormat = gameData.messages.meta.inventory_format; - Messages.NothingMessage = gameData.messages.meta.nothing_message; Messages.ExitThisPlace = gameData.messages.meta.exit_this_place; Messages.BackToMap = gameData.messages.meta.back_to_map; + Messages.LongFullLine = gameData.messages.meta.long_full_line; Messages.MetaTerminator = gameData.messages.meta.end_of_meta; + Messages.NothingMessage = gameData.messages.meta.dropped_items.nothing_message; + Messages.ItemsOnGroundMessage = gameData.messages.meta.dropped_items.items_message; + Messages.GrabItemFormat = gameData.messages.meta.dropped_items.item_format; + 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; Messages.East = gameData.messages.meta.nearby.east; @@ -268,7 +274,8 @@ namespace Horse_Isle_Server { Map.TerrainTile tile = new Map.TerrainTile(); tile.Passable = gameData.tile_paramaters.terrain_tiles[i].passable; - tile.Type = gameData.tile_paramaters.terrain_tiles[i].passable; + tile.Type = gameData.tile_paramaters.terrain_tiles[i].tile_type; + Logger.DebugPrint("Registered Tile: " + i + " Passable: " + tile.Passable + " Type: " + tile.Type); terrainTiles.Add(tile); } Map.TerrainTiles = terrainTiles.ToArray(); @@ -286,7 +293,7 @@ namespace Horse_Isle_Server // Inventory - Inventory.DefaultInventoryMax = gameData.item.max_carryable; + Messages.DefaultInventoryMax = gameData.item.max_carryable; // Swf Messages.WagonCutscene = gameData.transport.wagon_cutscene; 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 480d351..9886002 100644 --- a/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj +++ b/Horse Isle Server/Horse Isle Server/Horse Isle Server.csproj @@ -79,7 +79,9 @@ - + + + @@ -89,6 +91,7 @@ + diff --git a/Horse Isle Server/Horse Isle Server/IInventory.cs b/Horse Isle Server/Horse Isle Server/IInventory.cs new file mode 100644 index 0000000..a607ef7 --- /dev/null +++ b/Horse Isle Server/Horse Isle Server/IInventory.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Horse_Isle_Server +{ + interface IInventory + { + + void Add(ItemInstance item); + void Remove(ItemInstance item); + + int Count + { + get; + } + + ItemInstance[] GetItemList(); + + + } +} diff --git a/Horse Isle Server/Horse Isle Server/Item.cs b/Horse Isle Server/Horse Isle Server/Item.cs index b93a1c9..c1084a4 100644 --- a/Horse Isle Server/Horse Isle Server/Item.cs +++ b/Horse Isle Server/Horse Isle Server/Item.cs @@ -44,5 +44,17 @@ namespace Horse_Isle_Server } public static List Items = new List(); + + public static ItemInformation GetItemById(int id) + { + foreach(ItemInformation item in Items) + { + if(item.Id == id) + { + return item; + } + } + throw new KeyNotFoundException("Item id " + id + " Not found!"); + } } } diff --git a/Horse Isle Server/Horse Isle Server/ItemInstance.cs b/Horse Isle Server/Horse Isle Server/ItemInstance.cs new file mode 100644 index 0000000..85d3ee4 --- /dev/null +++ b/Horse Isle Server/Horse Isle Server/ItemInstance.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Horse_Isle_Server +{ + class ItemInstance + { + public int RandomID; + public int ItemID; + private static int prevId = 0; + + + public Item.ItemInformation GetItemInfo() + { + return Item.GetItemById(ItemID); + + } + + public ItemInstance(int id,int randomId = -1) + { + prevId++; + if (randomId == -1) + RandomID = prevId; + else + RandomID = randomId; + + if (RandomID > prevId) + prevId = RandomID + 1; + + ItemID = id; + + } + + } +} diff --git a/Horse Isle Server/Horse Isle Server/Logger.cs b/Horse Isle Server/Horse Isle Server/Logger.cs index 531b867..7354450 100644 --- a/Horse Isle Server/Horse Isle Server/Logger.cs +++ b/Horse Isle Server/Horse Isle Server/Logger.cs @@ -8,6 +8,10 @@ namespace Horse_Isle_Server { class Logger { + public static void HackerPrint(string text) // When someone is obviously cheating. + { + Console.WriteLine("[HACK] " + text); + } public static void DebugPrint(string text) { if (ConfigReader.Debug) @@ -17,7 +21,7 @@ namespace Horse_Isle_Server { Console.WriteLine("[WARN] " + text); } - public static void ErrorPrint(string text) + public static void ErrorPrint(string text) { Console.WriteLine("[ERROR] " + text); } diff --git a/Horse Isle Server/Horse Isle Server/Map.cs b/Horse Isle Server/Horse Isle Server/Map.cs index a8c31a2..5a2045a 100644 --- a/Horse Isle Server/Horse Isle Server/Map.cs +++ b/Horse Isle Server/Horse Isle Server/Map.cs @@ -67,11 +67,11 @@ namespace Horse_Isle_Server bool tilePassable = false; if (terrainPassable || overlayPassable) tilePassable = true; - if (!overlayPassable && otileId != 0) + if (!overlayPassable && (tileId != 0 && otileId != 0)) tilePassable = false; - Logger.DebugPrint("Checking tile passibility for tileid: " + tileId + " and overlay tileid " + otileId + " at " + x + "," + y); + return tilePassable; } diff --git a/Horse Isle Server/Horse Isle Server/Messages.cs b/Horse Isle Server/Horse Isle Server/Messages.cs index 480e188..9a71612 100644 --- a/Horse Isle Server/Horse Isle Server/Messages.cs +++ b/Horse Isle Server/Horse Isle Server/Messages.cs @@ -8,6 +8,9 @@ namespace Horse_Isle_Server { class Messages { + public static int RequiredChatViolations; + public static int DefaultInventoryMax; + // Announcements public static string NewUserMessage; public static string WelcomeFormat; @@ -41,11 +44,19 @@ namespace Horse_Isle_Server public static string AdminChatFormatForSender; public static string ModChatFormatForSender; - public static int RequiredChatViolations; public static string ChatViolationMessageFormat; public static string PasswordNotice; public static string CapsNotice; + //Dropped Items + + public static string NothingMessage; + public static string ItemsOnGroundMessage; + public static string GrabItemFormat; + public static string GrabAllItemsMessage; + public static string GrabbedItemMessage; + public static string GrabbedAllObjectsMessage; + // Meta public static string IsleFormat; public static string TownFormat; @@ -60,12 +71,12 @@ namespace Horse_Isle_Server public static string West; public static string TileFormat; - public static string NothingMessage; public static string Seperator; public static string InventoryFormat; public static string ExitThisPlace; public static string BackToMap; + public static string LongFullLine; public static string MetaTerminator; // Disconnect Messages @@ -82,11 +93,15 @@ namespace Horse_Isle_Server return ChatViolationMessageFormat.Replace("%AMOUNT%", RequiredChatViolations.ToString()).Replace("%REASON%", violationReason.Message); } - public static string FormatInventoryMeta(int itemCount, int maxItems) + public static string FormatPlayerInventoryHeaderMeta(int itemCount, int maxItems) { return InventoryFormat.Replace("%ITEMCOUNT%", itemCount.ToString()).Replace("%MAXITEMS%", maxItems.ToString()); } // Meta + public static string FormatGrabItemMessage(string name, int randomid, int iconid) + { + return GrabItemFormat.Replace("%ICONID%",iconid.ToString()).Replace("%ITEMNAME%", name).Replace("%RANDOMID%", randomid.ToString()); + } public static string FormatTransportMessage(string method, string place, int cost, int id, int x, int y) { string xy = ""; diff --git a/Horse Isle Server/Horse Isle Server/Meta.cs b/Horse Isle Server/Horse Isle Server/Meta.cs index 85a20d2..30f26ed 100644 --- a/Horse Isle Server/Horse Isle Server/Meta.cs +++ b/Horse Isle Server/Horse Isle Server/Meta.cs @@ -81,12 +81,22 @@ namespace Horse_Isle_Server string message = ""; message += Messages.Seperator + buildNearbyString(x, y); + // Dropped Items - int[] itemIds = World.GetDroppedItems(x, y); - if (itemIds.Length == 0) + DroppedItems.DroppedItem[] Items = DroppedItems.GetItemsAt(x, y); + if (Items.Length == 0) message += Messages.NothingMessage; - - + else + { + message += Messages.ItemsOnGroundMessage; + foreach(DroppedItems.DroppedItem item in Items) + { + Item.ItemInformation itemInfo = item.instance.GetItemInfo(); + message += Messages.FormatGrabItemMessage(itemInfo.Name, item.instance.RandomID, itemInfo.IconId); + } + message += Messages.GrabAllItemsMessage; + } + Logger.DebugPrint(message); return message; } public static string BuildTransportInfo(Transport.TransportPoint transportPoint) @@ -126,11 +136,10 @@ namespace Horse_Isle_Server return message; } - public static string BuildInventoryInfo(Inventory inv) + public static string BuildInventoryInfo(IInventory inv) { string message = ""; - message += Messages.FormatInventoryMeta(inv.ItemList.Count, inv.MaxItems); - + message += Messages.FormatPlayerInventoryHeaderMeta(inv.Count, Messages.DefaultInventoryMax); return message; } public static string BuildMetaInfo(int x, int y) diff --git a/Horse Isle Server/Horse Isle Server/PacketBuilder.cs b/Horse Isle Server/Horse Isle Server/PacketBuilder.cs index 7714e74..f5f25d5 100644 --- a/Horse Isle Server/Horse Isle Server/PacketBuilder.cs +++ b/Horse Isle Server/Horse Isle Server/PacketBuilder.cs @@ -21,6 +21,7 @@ namespace Horse_Isle_Server public const byte PACKET_SWF_MODULE_GENTLE = 0x2A; public const byte PACKET_PLACE_INFO = 0x1E; public const byte PACKET_AREA_DEFS = 0x79; + public const byte PACKET_ITEM_INTERACTION = 0x1E; public const byte PACKET_ANNOUNCEMENT = 0x7E; public const byte PACKET_TILE_FLAGS = 0x75; public const byte PACKET_PLAYSOUND = 0x23; @@ -32,10 +33,12 @@ namespace Horse_Isle_Server public const byte PACKET_LEAVE = 0x7D; public const byte PACKET_PLAYERINFO = 0x16; + + public const byte PICKUP_OBJECT = 0x14; public const byte PLAYERINFO_LEAVE = 0x16; public const byte PLAYERINFO_UPDATE_OR_CREATE = 0x15; - + public const byte VIEW_PROFILE = 0x14; public const byte SAVE_PROFILE = 0x15; diff --git a/Horse Isle Server/Horse Isle Server/PlayerInventory.cs b/Horse Isle Server/Horse Isle Server/PlayerInventory.cs new file mode 100644 index 0000000..c59ec2d --- /dev/null +++ b/Horse Isle Server/Horse Isle Server/PlayerInventory.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Horse_Isle_Server +{ + class PlayerInventory : IInventory + { + private User baseUser; + private List instances = new List(); + + public PlayerInventory(User forUser) + { + baseUser = forUser; + instances = Database.GetPlayerInventory(baseUser.Id); + } + + public int Count + { + get + { + return instances.Count; + } + } + + public void Add(ItemInstance item) + { + instances.Add(item); + Database.AddItemToInventory(baseUser.Id, item); + } + + public ItemInstance[] GetItemList() + { + return instances.ToArray(); + } + + public void Remove(ItemInstance item) + { + instances.Remove(item); + Database.RemoveItemFromInventory(baseUser.Id, item); + } + } +} diff --git a/Horse Isle Server/Horse Isle Server/Program.cs b/Horse Isle Server/Horse Isle Server/Program.cs index 9cb0862..dd3953a 100644 --- a/Horse Isle Server/Horse Isle Server/Program.cs +++ b/Horse Isle Server/Horse Isle Server/Program.cs @@ -18,6 +18,7 @@ namespace Horse_Isle_Server Map.OpenMap(); Gamedata.ReadGamedata(); World.ReadWorldData(); + DroppedItems.Init(); Server.StartServer(); } diff --git a/Horse Isle Server/Horse Isle Server/Server.cs b/Horse Isle Server/Horse Isle Server/Server.cs index 24be539..5003e54 100644 --- a/Horse Isle Server/Horse Isle Server/Server.cs +++ b/Horse Isle Server/Horse Isle Server/Server.cs @@ -14,7 +14,7 @@ namespace Horse_Isle_Server { public static Socket ServerSocket; - + private static Timer serverTimer; public static Client[] ConnectedClients // Done to prevent Enumerator Changed errors. { @@ -26,12 +26,11 @@ namespace Horse_Isle_Server public static int IdleTimeout; public static int IdleWarning; - + public static Random RandomNumberGenerator = new Random(); // used for world time, private static int gameTickSpeed = 4320; // Changing this to ANYTHING else will cause desync with the client. - private static Timer serverTimer; - + private static List connectedClients = new List(); public static void OnCrossdomainPolicyRequest(Client sender) // When a cross-domain-policy request is received. { @@ -326,27 +325,43 @@ namespace Horse_Isle_Server Logger.ErrorPrint(sender.RemoteIp + " Tried to use a transport with id that is NaN."); return; } - - Transport.TransportLocation transportLocation = Transport.GetTransportLocation(transportid); - if (sender.LoggedinUser.Money >= transportLocation.Cost) + try { - - string swfToLoad = Messages.BoatCutscene; - if (transportLocation.Type == "WAGON") - swfToLoad = Messages.WagonCutscene; - - if (transportLocation.Type != "ROWBOAT") + Transport.TransportPoint transportPoint = Transport.GetTransportPoint(sender.LoggedinUser.X, sender.LoggedinUser.Y); + if (transportPoint.X != sender.LoggedinUser.X && transportPoint.Y != sender.LoggedinUser.Y) { - byte[] swfModulePacket = PacketBuilder.CreateSwfModulePacket(swfToLoad, PacketBuilder.PACKET_SWF_CUTSCENE); - sender.SendPacket(swfModulePacket); + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to use transport id: " + transportid.ToString() + " while not the correct transport point!"); + return; } - Teleport(sender, transportLocation.GotoX, transportLocation.GotoY); + Transport.TransportLocation transportLocation = Transport.GetTransportLocation(transportid); - sender.LoggedinUser.Money -= transportLocation.Cost; - + + if (sender.LoggedinUser.Money >= transportLocation.Cost) + { + + + string swfToLoad = Messages.BoatCutscene; + if (transportLocation.Type == "WAGON") + swfToLoad = Messages.WagonCutscene; + + if (transportLocation.Type != "ROWBOAT") + { + byte[] swfModulePacket = PacketBuilder.CreateSwfModulePacket(swfToLoad, PacketBuilder.PACKET_SWF_CUTSCENE); + sender.SendPacket(swfModulePacket); + } + + Teleport(sender, transportLocation.GotoX, transportLocation.GotoY); + + sender.LoggedinUser.Money -= transportLocation.Cost; + } } - + catch (KeyNotFoundException) + { + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to use transport id: " + transportid.ToString() + " while not on a transport point!"); + } + + } public static void OnChatPacket(Client sender, byte[] packet) { @@ -424,6 +439,59 @@ namespace Horse_Isle_Server sender.SendPacket(chatPacketSender); } + public static void OnItemInteraction(Client sender, byte[] packet) + { + if (!sender.LoggedIn) + { + Logger.ErrorPrint(sender.RemoteIp + " Sent object interaction packet when not logged in."); + return; + } + if (packet.Length < 3) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid object interaction packet."); + return; + } + + byte action = packet[1]; + switch(action) + { + case PacketBuilder.PICKUP_OBJECT: + string packetStr = Encoding.UTF8.GetString(packet); + string randomIdStr = packetStr.Substring(2, packet.Length - 2); + int randomId = 0; + + try + { + randomId = Int32.Parse(randomIdStr); + } + catch(InvalidOperationException) + { + Logger.ErrorPrint(sender.LoggedinUser.Username + " Sent an invalid object interaction packet."); + return; + } + + try + { + DroppedItems.DroppedItem item = DroppedItems.GetDroppedItemById(randomId); + sender.LoggedinUser.Inventory.Add(item.instance); + DroppedItems.RemoveDroppedItem(item); + + UpdateAreaForAll(item.X, item.Y); + + byte[] chatMessage = PacketBuilder.CreateChat(Messages.GrabbedItemMessage, PacketBuilder.CHAT_BOTTOM_RIGHT); + sender.SendPacket(chatMessage); + } + catch(KeyNotFoundException) + { + Logger.HackerPrint(sender.LoggedinUser.Username + " Tried to grab a non existing object."); + return; + } + + break; + } + + } + public static void OnInventoryRequested(Client sender, byte[] packet) { if (!sender.LoggedIn) @@ -434,11 +502,11 @@ namespace Horse_Isle_Server if (packet.Length < 2) { - Logger.ErrorPrint(sender.RemoteIp + " Sent an invalid chat packet."); + Logger.ErrorPrint(sender.RemoteIp + " Sent an invalid inventory request packet."); return; } - byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildInventoryInfo(sender.LoggedinUser.ItemInventory)); + byte[] metaPacket = PacketBuilder.CreateMetaPacket(Meta.BuildInventoryInfo(sender.LoggedinUser.Inventory)); sender.SendPacket(metaPacket); } public static void OnLoginRequest(Client sender, byte[] packet) @@ -678,7 +746,15 @@ namespace Horse_Isle_Server } - + public static void UpdateAreaForAll(int x, int y) + { + foreach(Client client in ConnectedClients) + { + if (client.LoggedIn) + if (client.LoggedinUser.X == x && client.LoggedinUser.Y == y) + UpdateArea(client, true); + } + } public static void UpdateArea(Client forClient, bool justArea = false) { if (!forClient.LoggedIn) @@ -756,6 +832,11 @@ namespace Horse_Isle_Server private static void onTick(object state) { World.TickWorldClock(); + + if(World.ServerTime.Minutes % 20 == 0) + { + DroppedItems.Update(); + } } public static void StartServer() { diff --git a/Horse Isle Server/Horse Isle Server/Transport.cs b/Horse Isle Server/Horse Isle Server/Transport.cs index e227ce0..c636ed4 100644 --- a/Horse Isle Server/Horse Isle Server/Transport.cs +++ b/Horse Isle Server/Horse Isle Server/Transport.cs @@ -38,7 +38,7 @@ namespace Horse_Isle_Server return transportPoint; } } - throw new KeyNotFoundException("Cannot find transport port at x:" + x + "y:" + y); + throw new KeyNotFoundException("Cannot find transport point at x:" + x + "y:" + y); } public static TransportLocation GetTransportLocation(int id) diff --git a/Horse Isle Server/Horse Isle Server/User.cs b/Horse Isle Server/Horse Isle Server/User.cs index b43b30f..316a0e5 100644 --- a/Horse Isle Server/Horse Isle Server/User.cs +++ b/Horse Isle Server/Horse Isle Server/User.cs @@ -29,7 +29,7 @@ namespace Horse_Isle_Server public Mailbox MailBox; public Friends Friends; public string Password; // For chat filter. - public Inventory ItemInventory; + public PlayerInventory Inventory; public int ChatViolations { get @@ -162,8 +162,6 @@ namespace Horse_Isle_Server NewPlayer = true; } - ItemInventory = new Inventory(); - Id = UserId; Username = Database.GetUsername(UserId); @@ -197,6 +195,8 @@ namespace Horse_Isle_Server Friends = new Friends(this); LoggedinClient = baseClient; + + Inventory = new PlayerInventory(this); } } } diff --git a/Horse Isle Server/Horse Isle Server/World.cs b/Horse Isle Server/Horse Isle Server/World.cs index 4ddc143..7fd8c7b 100644 --- a/Horse Isle Server/Horse Isle Server/World.cs +++ b/Horse Isle Server/Horse Isle Server/World.cs @@ -197,10 +197,6 @@ namespace Horse_Isle_Server throw new KeyNotFoundException("x,y not in a town!"); } - public static int[] GetDroppedItems(int x, int y) - { - return new int[] { }; // Not implemented yet. - } public static string GetWeather() { return Database.GetWorldWeather();