Add object/inventory stuff

This commit is contained in:
SilicaAndPina 2020-10-21 21:49:46 +13:00
parent 09a0fce73d
commit 2a241c35aa
21 changed files with 645 additions and 60 deletions

View file

@ -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":"<B>TAG!!</B> %USERNAME% is now it! (tagged by %TAGGER%) [%AMOUNT% buds]",
"for_others":"<B>TAG!!</B> %USERNAME% is now it! (tagged by %TAGGER%)"
@ -34,12 +36,19 @@
"area_format":" in %AREA%",
"location_format":" <I>You are%META% </I>",
"tile_format":"<B>%TILENAME%</B>",
"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^H<B>You are carrying the following %ITEMCOUNT% different items:</B> (%MAXITEMS% max)",
"long_full_line":"^L",
"inventory_format":"^ATYour Inventory^H<B>You are carrying the following %ITEMCOUNT% different items:</B> (%% 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":"<B>Players Nearby:</B>",
"east":"<B>East:</B>",
@ -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},

View file

@ -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 :(";

View file

@ -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;

View file

@ -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<ItemInstance> 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<ItemInstance> instances = new List<ItemInstance>();
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<DroppedItems.DroppedItem> itemList = new List<DroppedItems.DroppedItem>();
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))

View file

@ -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<DroppedItem> droppedItemsList = new List<DroppedItem>();
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<DroppedItem> items = new List<DroppedItem>();
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();
}
}
}

View file

@ -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;

View file

@ -79,7 +79,9 @@
<Compile Include="Database.cs" />
<Compile Include="Friends.cs" />
<Compile Include="Gamedata.cs" />
<Compile Include="Inventory.cs" />
<Compile Include="IInventory.cs" />
<Compile Include="DroppedItems.cs" />
<Compile Include="ItemInstance.cs" />
<Compile Include="Logger.cs" />
<Compile Include="ConfigReader.cs" />
<Compile Include="CrossDomainPolicy.cs" />
@ -89,6 +91,7 @@
<Compile Include="Item.cs" />
<Compile Include="Meta.cs" />
<Compile Include="PacketBuilder.cs" />
<Compile Include="PlayerInventory.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">

View file

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

View file

@ -44,5 +44,17 @@ namespace Horse_Isle_Server
}
public static List<ItemInformation> Items = new List<ItemInformation>();
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!");
}
}
}

View file

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

View file

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

View file

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

View file

@ -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 = "";

View file

@ -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)

View file

@ -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;

View file

@ -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<ItemInstance> instances = new List<ItemInstance>();
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);
}
}
}

View file

@ -18,6 +18,7 @@ namespace Horse_Isle_Server
Map.OpenMap();
Gamedata.ReadGamedata();
World.ReadWorldData();
DroppedItems.Init();
Server.StartServer();
}

View file

@ -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<Client> connectedClients = new List<Client>();
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()
{

View file

@ -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)

View file

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

View file

@ -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();