From 1ad2b5d7d0856aabe88bfb5e4cb7074bf08640a5 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Fri, 17 Jun 2016 05:05:31 +0100 Subject: [PATCH] more work on commands - moved script object to wrapper class to catch and log exceptions - added loggers for basepacket/subpacket (todo: colour and use them in NLog.config) - finished up most commands (todo: !property and !property2) - todo: create and use mysql wrapper class to log exceptions --- .../FFXIVClassic Common Class Lib.csproj | 10 + FFXIVClassic Common Class Lib/Sql.cs | 80 ++ FFXIVClassic Common Class Lib/app.config | 9 + FFXIVClassic Common Class Lib/packages.config | 3 +- FFXIVClassic Lobby Server/Program.cs | 11 +- .../packets/BasePacket.cs | 13 +- .../packets/SubPacket.cs | 8 +- FFXIVClassic Map Server/CommandProcessor.cs | 789 ++---------------- .../FFXIVClassic Map Server.csproj | 1 + FFXIVClassic Map Server/NLog.config | 5 +- FFXIVClassic Map Server/actors/Actor.cs | 10 + FFXIVClassic Map Server/actors/area/Area.cs | 23 +- .../actors/chara/npc/Npc.cs | 2 +- .../actors/chara/player/Inventory.cs | 11 +- .../actors/chara/player/Player.cs | 20 + FFXIVClassic Map Server/lua/LuaEngine.cs | 201 +---- FFXIVClassic Map Server/lua/LuaScript.cs | 240 ++++++ ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 FFXIVClassic Map Server/packets/BasePacket.cs | 7 +- FFXIVClassic Map Server/packets/SubPacket.cs | 8 +- data/scripts/commands/gm/delcurrency.lua | 37 + data/scripts/commands/gm/delitem.lua | 37 + data/scripts/commands/gm/delkeyitem.lua | 37 + data/scripts/commands/gm/givecurrency.lua | 37 + data/scripts/commands/gm/giveitem.lua | 26 +- data/scripts/commands/gm/givekeyitem.lua | 37 + data/scripts/commands/gm/graphic.lua | 3 +- .../{command - Copy (7).lua => property.lua} | 0 data/scripts/commands/gm/reloadzone.lua | 15 +- data/scripts/commands/gm/test.lua | 9 - data/scripts/commands/gm/warp.lua | 13 +- data/scripts/commands/gm/weather.lua | 30 + data/scripts/global.lua | 6 +- 35 files changed, 780 insertions(+), 958 deletions(-) create mode 100644 FFXIVClassic Common Class Lib/Sql.cs create mode 100644 FFXIVClassic Common Class Lib/app.config create mode 100644 FFXIVClassic Map Server/lua/LuaScript.cs delete mode 100644 FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs delete mode 100644 FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs delete mode 100644 FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs create mode 100644 data/scripts/commands/gm/delcurrency.lua create mode 100644 data/scripts/commands/gm/delitem.lua create mode 100644 data/scripts/commands/gm/delkeyitem.lua create mode 100644 data/scripts/commands/gm/givecurrency.lua create mode 100644 data/scripts/commands/gm/givekeyitem.lua rename data/scripts/commands/gm/{command - Copy (7).lua => property.lua} (100%) delete mode 100644 data/scripts/commands/gm/test.lua create mode 100644 data/scripts/commands/gm/weather.lua diff --git a/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj b/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj index 1adbda3e..a3fe065d 100644 --- a/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj +++ b/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj @@ -35,6 +35,14 @@ false + + ..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll + True + + + ..\packages\NLog.4.3.5\lib\net45\NLog.dll + True + @@ -49,10 +57,12 @@ + + diff --git a/FFXIVClassic Common Class Lib/Sql.cs b/FFXIVClassic Common Class Lib/Sql.cs new file mode 100644 index 00000000..fcad7791 --- /dev/null +++ b/FFXIVClassic Common Class Lib/Sql.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MySql.Data.MySqlClient; +using NLog; + +namespace FFXIVClassic.Common +{ + /* + class SqlCommand + { + public static Logger Log = LogManager.GetCurrentClassLogger(); + + public SqlCommand() + { + + } + + public SqlCommand(string cmdText) + { + try + { + MySqlCommand.MySqlCommand(""); + } + } + public SqlCommand(string cmdText, MySqlConnection connection); + public SqlCommand(string cmdText, MySqlConnection connection, MySqlTransaction transaction); + + ~SqlCommand() + { + + } + + public int CacheAge { get; set; } + + public string CommandText { get; set; } + public int CommandTimeout { get; set; } + + public CommandType CommandType { get; set; } + + public MySqlConnection Connection { get; set; } + + public bool DesignTimeVisible { get; set; } + public bool EnableCaching { get; set; } + + public bool IsPrepared { get; } + + public long LastInsertedId { get; } + + public MySqlParameterCollection Parameters { get; } + + public MySqlTransaction Transaction { get; set; } + public UpdateRowSource UpdatedRowSource { get; set; } + protected DbConnection DbConnection { get; set; } + protected DbParameterCollection DbParameterCollection { get; } + protected DbTransaction DbTransaction { get; set; } + + public IAsyncResult BeginExecuteNonQuery(); + public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback, object stateObject); + public IAsyncResult BeginExecuteReader(); + public IAsyncResult BeginExecuteReader(CommandBehavior behavior); + public void Cancel(); + public SqlCommand Clone(); + public MySqlParameter CreateParameter(); + public void Dispose(); + public int EndExecuteNonQuery(IAsyncResult asyncResult); + public MySqlDataReader EndExecuteReader(IAsyncResult result); + public int ExecuteNonQuery(); + public MySqlDataReader ExecuteReader(); + public MySqlDataReader ExecuteReader(CommandBehavior behavior); + public object ExecuteScalar(); + public void Prepare(); + protected DbParameter CreateDbParameter(); + protected void Dispose(bool disposing); + protected DbDataReader ExecuteDbDataReader(CommandBehavior behavior); + } + */ +} diff --git a/FFXIVClassic Common Class Lib/app.config b/FFXIVClassic Common Class Lib/app.config new file mode 100644 index 00000000..143834c2 --- /dev/null +++ b/FFXIVClassic Common Class Lib/app.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/FFXIVClassic Common Class Lib/packages.config b/FFXIVClassic Common Class Lib/packages.config index c171747f..d0ca21c2 100644 --- a/FFXIVClassic Common Class Lib/packages.config +++ b/FFXIVClassic Common Class Lib/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/FFXIVClassic Lobby Server/Program.cs b/FFXIVClassic Lobby Server/Program.cs index c5967a87..ee40fced 100644 --- a/FFXIVClassic Lobby Server/Program.cs +++ b/FFXIVClassic Lobby Server/Program.cs @@ -12,13 +12,13 @@ namespace FFXIVClassic_Lobby_Server public static Logger Log; static void Main(string[] args) - { - - // set up logging + { + + // set up logging Log = LogManager.GetCurrentClassLogger(); #if DEBUG TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out); - Debug.Listeners.Add(myWriter); + Debug.Listeners.Add(myWriter); #endif Program.Log.Info("--------FFXIV 1.0 Lobby Server--------"); @@ -55,6 +55,9 @@ namespace FFXIVClassic_Lobby_Server { Server server = new Server(); server.StartServer(); + + while (true) + Thread.Sleep(1000); } Program.Log.Info("Press any key to continue..."); diff --git a/FFXIVClassic Lobby Server/packets/BasePacket.cs b/FFXIVClassic Lobby Server/packets/BasePacket.cs index f37d6721..332e7d6f 100644 --- a/FFXIVClassic Lobby Server/packets/BasePacket.cs +++ b/FFXIVClassic Lobby Server/packets/BasePacket.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using System.Diagnostics; using FFXIVClassic.Common; using System.IO; +using NLog; namespace FFXIVClassic_Lobby_Server.packets { @@ -21,7 +22,7 @@ namespace FFXIVClassic_Lobby_Server.packets public class BasePacket { - + public static Logger Log = LogManager.GetCurrentClassLogger(); public const int TYPE_ZONE = 1; public const int TYPE_CHAT = 2; public const int BASEPACKET_SIZE = 0x10; @@ -332,12 +333,12 @@ namespace FFXIVClassic_Lobby_Server.packets #endregion public void DebugPrintPacket() - { + { #if DEBUG - // todo: create new target for colourful packet logging - //Console.BackgroundColor = ConsoleColor.DarkYellow; - - Program.Log.Debug("IsAuth: {0} Size: 0x{1:X}, NumSubpackets: {2}{3}{4}", header.isAuthenticated, header.packetSize, header.numSubpackets, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); + // todo: create new target for colourful packet logging + //Console.BackgroundColor = ConsoleColor.DarkYellow; + + Log.Debug("IsAuth: {0} Size: 0x{1:X}, NumSubpackets: {2}{3}{4}", header.isAuthenticated, header.packetSize, header.numSubpackets, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); foreach (SubPacket sub in GetSubpackets()) { diff --git a/FFXIVClassic Lobby Server/packets/SubPacket.cs b/FFXIVClassic Lobby Server/packets/SubPacket.cs index 1711dc65..0dcb526b 100644 --- a/FFXIVClassic Lobby Server/packets/SubPacket.cs +++ b/FFXIVClassic Lobby Server/packets/SubPacket.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using FFXIVClassic.Common; +using NLog; namespace FFXIVClassic_Lobby_Server.packets { @@ -26,6 +27,7 @@ namespace FFXIVClassic_Lobby_Server.packets public class SubPacket { + public static Logger Log = LogManager.GetCurrentClassLogger(); public const int SUBPACKET_SIZE = 0x10; public const int GAMEMESSAGE_SIZE = 0x10; @@ -141,14 +143,14 @@ namespace FFXIVClassic_Lobby_Server.packets { #if DEBUG // todo: create new target for colourful packet logging - Program.Log.Debug("Size: 0x{0:X}{1}{2}", header.subpacketSize, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); + Log.Debug("Size: 0x{0:X}{1}{2}", header.subpacketSize, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); if (header.type == 0x03) { - Program.Log.Debug("Opcode: 0x{0:X}{1}{2}", gameMessage.opcode, Environment.NewLine, Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE)); + Log.Debug("Opcode: 0x{0:X}{1}{2}", gameMessage.opcode, Environment.NewLine, Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE)); } - Program.Log.Debug("Data: {0}{1}", Environment.NewLine, Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE)); + Log.Debug("Data: {0}{1}", Environment.NewLine, Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE)); #endif } diff --git a/FFXIVClassic Map Server/CommandProcessor.cs b/FFXIVClassic Map Server/CommandProcessor.cs index 849b682f..456f2b7a 100644 --- a/FFXIVClassic Map Server/CommandProcessor.cs +++ b/FFXIVClassic Map Server/CommandProcessor.cs @@ -73,418 +73,6 @@ namespace FFXIVClassic_Map_Server } } - public void DoMusic(ConnectedPlayer client, string music) - { - ushort musicId; - - if (music.ToLower().StartsWith("0x")) - musicId = Convert.ToUInt16(music, 16); - else - musicId = Convert.ToUInt16(music); - - if (client != null) - client.QueuePacket(BasePacket.CreatePacket(SetMusicPacket.BuildPacket(client.actorID, musicId, 1), true, false)); - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - BasePacket musicPacket = BasePacket.CreatePacket(SetMusicPacket.BuildPacket(entry.Value.actorID, musicId, 1), true, false); - entry.Value.QueuePacket(musicPacket); - } - } - } - - /// - /// Teleports player to a location on a predefined list - /// - /// The current player - /// Predefined list: <ffxiv_database>\server_zones_spawnlocations - public void DoWarp(ConnectedPlayer client, uint id) - { - WorldManager worldManager = Server.GetWorldManager(); - FFXIVClassic_Map_Server.WorldManager.ZoneEntrance ze = worldManager.GetZoneEntrance(id); - - if (ze == null) - return; - - if (client != null) - worldManager.DoZoneChange(client.GetActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation); - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - worldManager.DoZoneChange(entry.Value.GetActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation); - } - } - } - - public void DoWarp(ConnectedPlayer client, uint zoneId, string privateArea, byte spawnType, float x, float y, float z, float r) - { - WorldManager worldManager = Server.GetWorldManager(); - if (worldManager.GetZone(zoneId) == null) - { - if (client != null) - client.QueuePacket(BasePacket.CreatePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", "Zone does not exist or setting isn't valid."), true, false)); - Program.Log.Error("Zone does not exist or setting isn't valid."); - } - - if (client != null) - worldManager.DoZoneChange(client.GetActor(), zoneId, privateArea, spawnType, x, y, z, r); - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - worldManager.DoZoneChange(entry.Value.GetActor(), zoneId, privateArea, spawnType, x, y, z, r); - } - } - } - - public void PrintPos(ConnectedPlayer client) - { - if (client != null) - { - Player p = client.GetActor(); - client.QueuePacket(BasePacket.CreatePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("{0}\'s position: ZoneID: {1}, X: {2}, Y: {3}, Z: {4}, Rotation: {5}", p.customDisplayName, p.zoneId, p.positionX, p.positionY, p.positionZ, p.rotation)), true, false)); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - Program.Log.Info(String.Format("{0}\'s position: ZoneID: {1}, X: {2}, Y: {3}, Z: {4}, Rotation: {5}", p.customDisplayName, p.zoneId, p.positionX, p.positionY, p.positionZ, p.rotation)); - } - } - } - - private void SetGraphic(ConnectedPlayer client, uint slot, uint wId, uint eId, uint vId, uint cId) - { - if (client != null) - { - Player p = client.GetActor(); - p.GraphicChange(slot, wId, eId, vId, cId); - p.SendAppearance(); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GraphicChange(slot, wId, eId, vId, cId); - p.SendAppearance(); - } - } - } - - private void GiveItem(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.NORMAL).AddItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.NORMAL).AddItem(itemId, quantity); - } - } - } - - private void GiveItem(ConnectedPlayer client, uint itemId, int quantity, ushort type) - { - if (client != null) - { - Player p = client.GetActor(); - - if (p.GetInventory(type) != null) - p.GetInventory(type).AddItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - - if (p.GetInventory(type) != null) - p.GetInventory(type).AddItem(itemId, quantity); - } - } - } - - private void RemoveItem(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.NORMAL).RemoveItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.NORMAL).RemoveItem(itemId, quantity); - } - } - } - - private void RemoveItem(ConnectedPlayer client, uint itemId, int quantity, ushort type) - { - if (client != null) - { - Player p = client.GetActor(); - - if (p.GetInventory(type) != null) - p.GetInventory(type).RemoveItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - - if (p.GetInventory(type) != null) - p.GetInventory(type).RemoveItem(itemId, quantity); - } - } - } - - private void GiveCurrency(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.CURRENCY).AddItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.CURRENCY).AddItem(itemId, quantity); - } - } - } - - // TODO: make RemoveCurrency() Remove all quantity of a currency if quantity_to_Remove > quantity_in_inventory instead of silently failing - private void RemoveCurrency(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.CURRENCY).RemoveItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.CURRENCY).RemoveItem(itemId, quantity); - } - } - } - - private void GiveKeyItem(ConnectedPlayer client, uint itemId) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.KEYITEMS).AddItem(itemId, 1); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.KEYITEMS).AddItem(itemId, 1); - } - } - } - - private void RemoveKeyItem(ConnectedPlayer client, uint itemId) - { - if (client != null) - { - Player p = client.GetActor(); - p.GetInventory(Inventory.KEYITEMS).RemoveItem(itemId, 1); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.GetActor(); - p.GetInventory(Inventory.KEYITEMS).RemoveItem(itemId, 1); - } - } - } - - private void ParseWarp(ConnectedPlayer client, string[] split) - { - float x = 0, y = 0, z = 0, r = 0.0f; - uint zoneId = 0; - string privatearea = null; - - if (split.Length == 2) // Predefined list - { - // TODO: Handle !warp Playername - #region !warp (predefined list) - try - { - if (split[1].ToLower().StartsWith("0x")) - zoneId = Convert.ToUInt32(split[1], 16); - else - zoneId = Convert.ToUInt32(split[1]); - } - catch{return;} - #endregion - - DoWarp(client, zoneId); - } - else if (split.Length == 4) - { - #region !warp X Y Z - if (split[1].StartsWith("@")) - { - split[1] = split[1].Replace("@", string.Empty); - - if (String.IsNullOrEmpty(split[1])) - split[1] = "0"; - - try { x = Single.Parse(split[1]) + client.GetActor().positionX; } - catch{return;} - - split[1] = x.ToString(); - } - if (split[2].StartsWith("@")) - { - split[2] = split[2].Replace("@", string.Empty); - - if (String.IsNullOrEmpty(split[2])) - split[2] = "0"; - - try { y = Single.Parse(split[2]) + client.GetActor().positionY; } - catch{return;} - - split[2] = y.ToString(); - } - if (split[3].StartsWith("@")) - { - split[3] = split[3].Replace("@", string.Empty); - - if (String.IsNullOrEmpty(split[3])) - split[3] = "0"; - - try { z = Single.Parse(split[3]) + client.GetActor().positionZ; } - catch{return;} - - split[3] = z.ToString(); - } - - try - { - x = Single.Parse(split[1]); - y = Single.Parse(split[2]); - z = Single.Parse(split[3]); - } - catch{return;} - - zoneId = client.GetActor().zoneId; - r = client.GetActor().rotation; - #endregion - - SendMessage(client, String.Format("Warping to: ZoneID: {0} X: {1}, Y: {2}, Z: {3}", zoneId, x, y, z)); - DoWarp(client, zoneId, privatearea, 0x00, x, y, z, r); - } - else if (split.Length == 5) - { - #region !warp Zone X Y Z - try - { - x = Single.Parse(split[2]); - y = Single.Parse(split[3]); - z = Single.Parse(split[4]); - } - catch{return;} - - if (split[1].ToLower().StartsWith("0x")) - { - try { zoneId = Convert.ToUInt32(split[1], 16); } - catch{return;} - } - else - { - try { zoneId = Convert.ToUInt32(split[1]); } - catch{return;} - } - #endregion - - SendMessage(client, String.Format("Warping to: ZoneID: {0} X: {1}, Y: {2}, Z: {3}", zoneId, x, y, z)); - DoWarp(client, zoneId, privatearea, 0x2, x, y, z, r); - } - else if (split.Length == 6) - { - #region !warp Zone Instance X Y Z - try - { - x = Single.Parse(split[3]); - y = Single.Parse(split[4]); - z = Single.Parse(split[5]); - } - catch{return;} - - if (split[1].ToLower().StartsWith("0x")) - { - try { zoneId = Convert.ToUInt32(split[1], 16); } - catch{return;} - } - else - { - try { zoneId = Convert.ToUInt32(split[1]); } - catch{return;} - } - - privatearea = split[2]; - #endregion - - SendMessage(client, String.Format("Warping to: ZoneID: {0} X: {1}, Y: {2}, Z: {3}", zoneId, x, y, z)); - DoWarp(client, zoneId, privatearea, 0x2, x, y, z, r); - } - else - return; // catch any invalid warps here - } - - private void DoWeather(ConnectedPlayer client, string weatherID, string value) - { - ushort weather = Convert.ToUInt16(weatherID); - - if (client != null) - { - client.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(client.actorID, weather, Convert.ToUInt16(value)), true, false)); - } - - /* - * WIP: Change weather serverside, currently only clientside - * - uint currentZoneID; - if (client != null) - { - currentZoneID = client.GetActor().zoneId; - - foreach (KeyValuePair entry in mConnectedPlayerList) - { - // Change the weather for everyone in the same zone - if (currentZoneID == entry.Value.GetActor().zoneId) - { - BasePacket weatherPacket = BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(entry.Value.actorID, weather), true, false); - entry.Value.QueuePacket(weatherPacket); - } - } - } - */ - } - /// /// We only use the default options for SendMessagePacket. /// May as well make it less unwieldly to view @@ -512,8 +100,8 @@ namespace FFXIVClassic_Map_Server ) .SelectMany(str => str).ToArray(); - split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands - + split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands + var cmd = split?.ElementAt(0); if (cmd.Any()) @@ -543,334 +131,63 @@ namespace FFXIVClassic_Map_Server LuaEngine.RunGMCommand(player, cmd.ToString(), split.ToArray()); return true; - } - // Debug - //SendMessage(client, string.Join(",", split)); - - if (split.Length >= 1) - { - #region !help - if (split[0].Equals("help")) - { - if (split.Length == 1) - { - SendMessage(client, Resources.CPhelp); - } - if (split.Length == 2) - { - if (split[1].Equals("mypos")) - SendMessage(client, Resources.CPmypos); - else if (split[1].Equals("music")) - SendMessage(client, Resources.CPmusic); - else if (split[1].Equals("warp")) - SendMessage(client, Resources.CPwarp); - else if (split[1].Equals("givecurrency")) - SendMessage(client, Resources.CPgivecurrency); - else if (split[1].Equals("giveitem")) - SendMessage(client, Resources.CPgiveitem); - else if (split[1].Equals("givekeyitem")) - SendMessage(client, Resources.CPgivekeyitem); - else if (split[1].Equals("Removecurrency")) - SendMessage(client, Resources.CPRemovecurrency); - else if (split[1].Equals("Removeitem")) - SendMessage(client, Resources.CPRemoveitem); - else if (split[1].Equals("Removekeyitem")) - SendMessage(client, Resources.CPRemovekeyitem); - else if (split[1].Equals("reloaditems")) - SendMessage(client, Resources.CPreloaditems); - else if (split[1].Equals("reloadzones")) - SendMessage(client, Resources.CPreloadzones); - /* - else if (split[1].Equals("property")) - SendMessage(client, Resources.CPproperty); - else if (split[1].Equals("property2")) - SendMessage(client, Resources.CPproperty2); - else if (split[1].Equals("sendpacket")) - SendMessage(client, Resources.CPsendpacket); - else if (split[1].Equals("setgraphic")) - SendMessage(client, Resources.CPsetgraphic); - */ - } - if (split.Length == 3) - { - if(split[1].Equals("test")) - { - if (split[2].Equals("weather")) - SendMessage(client, Resources.CPtestweather); - } - } - - return true; - } + } + // Debug + //SendMessage(client, string.Join(",", split)); + + if (split.Length >= 1) + { + + #region !reloaditems + if (split[0].Equals("reloaditems")) + { + Program.Log.Info(String.Format("Got request to reload item gamedata")); + SendMessage(client, "Reloading Item Gamedata..."); + gamedataItems.Clear(); + gamedataItems = Database.GetItemGamedata(); + Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count)); + SendMessage(client, String.Format("Loaded {0} items.", gamedataItems.Count)); + return true; + } #endregion - - #region !test - else if (split[0].Equals("test")) - { - if (split.Length == 1) - { - // catch invalid commands - SendMessage(client, Resources.CPhelp); - } - else if (split.Length >= 2) - { - #region !test weather - if (split[1].Equals("weather")) - { - try - { - DoWeather(client, split[2], split[3]); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not change weather: " + e); - } - } - #endregion - } - - } - #endregion - - #region !mypos - else if (split[0].Equals("mypos")) - { - try - { - PrintPos(client); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not load packet: " + e); - } - } - #endregion - - #region !reloadzones - else if (split[0].Equals("reloadzones")) - { - if (client != null) - { - Program.Log.Info(String.Format("Got request to reset zone: {0}", client.GetActor().zoneId)); - client.GetActor().zone.Clear(); - client.GetActor().zone.AddActorToZone(client.GetActor()); - client.GetActor().SendInstanceUpdate(); - client.QueuePacket(BasePacket.CreatePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Reseting zone {0}...", client.GetActor().zoneId)), true, false)); - } - Server.GetWorldManager().ReloadZone(client.GetActor().zoneId); - return true; - } - #endregion - - #region !reloaditems - else if (split[0].Equals("reloaditems")) - { - Program.Log.Info(String.Format("Got request to reload item gamedata")); - SendMessage(client, "Reloading Item Gamedata..."); - gamedataItems.Clear(); - gamedataItems = Database.GetItemGamedata(); - Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count)); - SendMessage(client, String.Format("Loaded {0} items.", gamedataItems.Count)); - return true; - } - #endregion - + #region !sendpacket - else if (split[0].Equals("sendpacket")) - { - if (split.Length < 2) - return false; - - try - { - SendPacket(client, "./packets/" + split[1]); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not load packet: " + e); - } - } + else if (split[0].Equals("sendpacket")) + { + if (split.Length < 2) + return false; + + try + { + SendPacket(client, "./packets/" + split[1]); + return true; + } + catch (Exception e) + { + Program.Log.Error("Could not load packet: " + e); + } + } #endregion - - #region !graphic - else if (split[0].Equals("graphic")) - { - try - { - if (split.Length == 6) - SetGraphic(client, UInt32.Parse(split[1]), UInt32.Parse(split[2]), UInt32.Parse(split[3]), UInt32.Parse(split[4]), UInt32.Parse(split[5])); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not give item."); - } - } - #endregion - - #region !giveitem - else if (split[0].Equals("giveitem")) - { - try - { - if (split.Length == 2) - GiveItem(client, UInt32.Parse(split[1]), 1); - else if (split.Length == 3) - GiveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - else if (split.Length == 4) - GiveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3])); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not give item."); - } - } - #endregion - - #region !Removeitem - else if (split[0].Equals("Removeitem")) - { - if (split.Length < 2) - return false; - - try - { - if (split.Length == 2) - RemoveItem(client, UInt32.Parse(split[1]), 1); - else if (split.Length == 3) - RemoveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - else if (split.Length == 4) - RemoveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3])); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not Remove item."); - } - } - #endregion - - #region !givekeyitem - else if (split[0].Equals("givekeyitem")) - { - try - { - if (split.Length == 2) - GiveKeyItem(client, UInt32.Parse(split[1])); - } - catch (Exception e) - { - Program.Log.Error("Could not give keyitem."); - } - } - #endregion - - #region !Removekeyitem - else if (split[0].Equals("Removekeyitem")) - { - if (split.Length < 2) - return false; - - try - { - if (split.Length == 2) - RemoveKeyItem(client, UInt32.Parse(split[1])); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not Remove keyitem."); - } - } - #endregion - - #region !givecurrency - else if (split[0].Equals("givecurrency")) - { - try - { - if (split.Length == 2) - GiveCurrency(client, ITEM_GIL, Int32.Parse(split[1])); - else if (split.Length == 3) - GiveCurrency(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - } - catch (Exception e) - { - Program.Log.Error("Could not give currency."); - } - } - #endregion - - #region !Removecurrency - else if (split[0].Equals("Removecurrency")) - { - if (split.Length < 2) - return false; - - try - { - if (split.Length == 2) - RemoveCurrency(client, ITEM_GIL, Int32.Parse(split[1])); - else if (split.Length == 3) - RemoveCurrency(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not Remove currency."); - } - } - #endregion - - #region !music - else if (split[0].Equals("music")) - { - if (split.Length < 2) - return false; - - try - { - DoMusic(client, split[1]); - return true; - } - catch (Exception e) - { - Program.Log.Error("Could not change music: " + e); - } - } - #endregion - - #region !warp - else if (split[0].Equals("warp")) - { - ParseWarp(client, split); - return true; - } - #endregion - + #region !property - else if (split[0].Equals("property")) - { - if (split.Length == 4) - { - ChangeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]); - } - return true; - } + else if (split[0].Equals("property")) + { + if (split.Length == 4) + { + ChangeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]); + } + return true; + } #endregion - + #region !property2 - else if (split[0].Equals("property2")) - { - if (split.Length == 4) - { - ChangeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]); - } - return true; + else if (split[0].Equals("property2")) + { + if (split.Length == 4) + { + ChangeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]); + } + return true; } #endregion } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index f01958b6..f178f04e 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -119,6 +119,7 @@ + diff --git a/FFXIVClassic Map Server/NLog.config b/FFXIVClassic Map Server/NLog.config index 1d8fb2f4..839421a0 100644 --- a/FFXIVClassic Map Server/NLog.config +++ b/FFXIVClassic Map Server/NLog.config @@ -29,8 +29,11 @@ --> - + + + + diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index 30397547..b94246be 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -377,6 +377,16 @@ namespace FFXIVClassic_Map_Server.Actors // todo: handle zone? zone.BroadcastPacketAroundActor(this, MoveActorToPositionPacket.BuildPacket(this.actorId, this.actorId, x, y, z, rot, moveState)); } + + public Area GetZone() + { + return zone; + } + + public uint GetZoneID() + { + return zoneId; + } } } diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index c9767c1d..73a2b5ac 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -13,7 +13,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; - +using FFXIVClassic_Map_Server.packets.send; + namespace FFXIVClassic_Map_Server.Actors { class Area : Actor @@ -352,5 +353,25 @@ namespace FFXIVClassic_Map_Server.Actors AddActorToZone(npc); } + public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false) + { + weatherNormal = weather; + + if (player != null && !zoneWide) + { + player.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime), true, false)); + } + if (zoneWide) + { + foreach (var actor in mActorList) + { + if (actor.Value is Player) + { + player = ((Player)actor.Value); + player.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime), true, false)); + } + } + } + } } } diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index eb4aea77..35ba4583 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -3,7 +3,7 @@ using FFXIVClassic_Map_Server.actors; using FFXIVClassic_Map_Server.Actors.Chara; using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.lua; -using FFXIVClassic_Map_Server.packets; +using FFXIVClassic_Map_Server.packets; using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.utils; diff --git a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs index 38ec5ffe..19538ae4 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs @@ -87,15 +87,21 @@ namespace FFXIVClassic_Map_Server.actors.chara.player AddItem(itemId, quantity, 1); } - public void AddItem(uint itemId, int quantity, byte quality) + public bool AddItem(uint itemId, int quantity, byte quality) { if (!IsSpaceForAdd(itemId, quantity)) - return; + return false; Item gItem = Server.GetItemGamedata(itemId); List slotsToUpdate = new List(); List addItemPackets = new List(); + if (gItem == null) + { + Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); + return false; + } + //Check if item id exists int quantityCount = quantity; for (int i = 0; i < list.Count; i++) @@ -152,6 +158,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + return true; } public void AddItem(uint[] itemId) diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 82f801de..42ecf917 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -749,6 +749,26 @@ namespace FFXIVClassic_Map_Server.Actors //zone.BroadcastPacketAroundActor(this, worldMasterMessage); } + public void ChangeProperty(uint id, uint value, string target) + { + SetActorPropetyPacket ChangeProperty = new SetActorPropetyPacket(target); + + ChangeProperty.SetTarget(target); + ChangeProperty.AddInt(id, value); + ChangeProperty.AddTarget(); + + /*foreach (KeyValuePair entry in mConnectedPlayerList) + { + SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.actorID), (entry.Value.actorID)); + + BasePacket packet = BasePacket.CreatePacket(ChangePropertyPacket, true, false); + packet.DebugPrintPacket(); + + entry.Value.QueuePacket(packet); + } + */ + } + public void GraphicChange(uint slot, uint graphicId) { appearanceIds[slot] = graphicId; diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index 67249ba1..01683358 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Diagnostics; +using FFXIVClassic_Map_Server.lua; namespace FFXIVClassic_Map_Server.lua { @@ -37,12 +38,12 @@ namespace FFXIVClassic_Map_Server.lua luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return null; - DynValue result = RunScript(script, script.Globals["init"], target); + DynValue result = script.Call(script.Globals["init"], target); List lparams = LuaUtils.CreateLuaParamList(result); return lparams; } @@ -79,7 +80,7 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; @@ -95,7 +96,7 @@ namespace FFXIVClassic_Map_Server.lua //Run Script if (!script.Globals.Get("onEventStarted").IsNil()) - RunScript(script, script.Globals["onEventStarted"], objects.ToArray()); + script.Call(script.Globals["onEventStarted"], objects.ToArray()); } else { @@ -110,14 +111,14 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; //Run Script if (!script.Globals.Get("onSpawn").IsNil()) - RunScript(script, script.Globals["onSpawn"], player, target); + script.Call(script.Globals["onSpawn"], player, target); } else { @@ -145,7 +146,7 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; @@ -159,7 +160,7 @@ namespace FFXIVClassic_Map_Server.lua //Run Script if (!script.Globals.Get("onEventUpdate").IsNil()) - RunScript(script, script.Globals["onEventUpdate"], objects.ToArray()); + script.Call(script.Globals["onEventUpdate"], objects.ToArray()); } else { @@ -173,14 +174,14 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; //Run Script if (!script.Globals.Get("onZoneIn").IsNil()) - RunScript(script, script.Globals["onZoneIn"], player); + script.Call(script.Globals["onZoneIn"], player); } } @@ -188,14 +189,14 @@ namespace FFXIVClassic_Map_Server.lua { if (File.Exists(FILEPATH_PLAYER)) { - Script script = LoadScript(FILEPATH_PLAYER); + LuaScript script = LoadScript(FILEPATH_PLAYER); if (script == null) return; //Run Script if (!script.Globals.Get("onBeginLogin").IsNil()) - RunScript(script, script.Globals["onBeginLogin"], player); + script.Call(script.Globals["onBeginLogin"], player); } } @@ -203,14 +204,14 @@ namespace FFXIVClassic_Map_Server.lua { if (File.Exists(FILEPATH_PLAYER)) { - Script script = LoadScript(FILEPATH_PLAYER); + LuaScript script = LoadScript(FILEPATH_PLAYER); if (script == null) return; //Run Script if (!script.Globals.Get("onLogin").IsNil()) - RunScript(script, script.Globals["onLogin"], player); + script.Call(script.Globals["onLogin"], player); } } @@ -224,7 +225,7 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(path)) { // load global functions - Script script = LoadGlobals(); + LuaScript script = LoadGlobals(); // see if this script has any syntax errors try @@ -275,7 +276,7 @@ namespace FFXIVClassic_Map_Server.lua } } } - catch (Exception e) { Program.Log.Error("LuaEngine.RunGMCommand: " + e.Message); return; } + catch (Exception e) { LuaScript.Log.Error("LuaEngine.RunGMCommand: " + e.Message); return; } } // if this isnt a console command, make sure player exists @@ -295,7 +296,7 @@ namespace FFXIVClassic_Map_Server.lua } else if (help) { - Program.Log.Info("[Commands] [{0}]: {1}", cmd, description); + LuaScript.Log.Info("[Commands] [{0}]: {1}", cmd, description); return; } @@ -323,7 +324,7 @@ namespace FFXIVClassic_Map_Server.lua LuaParam.Add(param[i + 1]); continue; default: - Program.Log.Info("LuaEngine.RunGMCommand: {0} unknown parameter {1}.", path, parameters[i]); + LuaScript.Log.Info("LuaEngine.RunGMCommand: {0} unknown parameter {1}.", path, parameters[i]); LuaParam.Add(param[i + 1]); continue; } @@ -341,18 +342,18 @@ namespace FFXIVClassic_Map_Server.lua LuaParam.Insert(1, i); // run the script - RunScript(script, script.Globals["onTrigger"], LuaParam.ToArray()); + script.Call(script.Globals["onTrigger"], LuaParam.ToArray()); return; } } - Program.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path); + LuaScript.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path); return; } #endregion - public static Script LoadScript(string filename) + public static LuaScript LoadScript(string filename) { - Script script = LoadGlobals(); + LuaScript script = LoadGlobals(); try { @@ -366,9 +367,9 @@ namespace FFXIVClassic_Map_Server.lua return script; } - public static Script LoadGlobals(Script script = null) + public static LuaScript LoadGlobals(LuaScript script = null) { - script = script ?? new Script(); + script = script ?? new LuaScript(); // register and load all global functions here ((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua"); @@ -396,14 +397,14 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; //Run Script if (!script.Globals.Get("onTalked").IsNil()) - RunScript(script, script.Globals["onTalked"], player, npc); + script.Call(script.Globals["onTalked"], player, npc); } else { @@ -417,161 +418,19 @@ namespace FFXIVClassic_Map_Server.lua if (File.Exists(luaPath)) { - Script script = LoadScript(luaPath); + LuaScript script = LoadScript(luaPath); if (script == null) return; //Run Script if (!script.Globals.Get("onCommand").IsNil()) - RunScript(script, script.Globals["onCommand"], player, command); + script.Call(script.Globals["onCommand"], player, command); } else { SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); } - } - - - #region RunScript - // - // Summary: - // Calls the specified function. - // - // Parameters: - // function: - // The Lua/MoonSharp function to be called - // - // Returns: - // The return value(s) of the function call. - // - // Exceptions: - // T:System.ArgumentException: - // Thrown if function is not of DataType.Function - public static DynValue RunScript(Script script, DynValue function) - { - DynValue res = null; - try - { - res = script.Call(function); - } - catch (InterpreterException e) - { - Program.Log.Error(e.DecoratedMessage); - } - return res; - } - // - // Summary: - // Calls the specified function. - // - // Parameters: - // function: - // The Lua/MoonSharp function to be called - // - // Exceptions: - // T:System.ArgumentException: - // Thrown if function is not of DataType.Function - public static DynValue RunScript(Script script, object function) - { - DynValue res = null; - try - { - res = script.Call(function); - } - catch (InterpreterException e) - { - Program.Log.Error(e.DecoratedMessage); - } - return res; - } - // - // Summary: - // Calls the specified function. - // - // Parameters: - // function: - // The Lua/MoonSharp function to be called - // - // args: - // The arguments to pass to the function. - // - // Exceptions: - // T:System.ArgumentException: - // Thrown if function is not of DataType.Function - public static DynValue RunScript(Script script, object function, params object[] args) - { - DynValue res = null; - try - { - res = script.Call(function, args); - } - catch (InterpreterException e) - { - Program.Log.Error(e.DecoratedMessage); - } - return res; - } - // - // Summary: - // Calls the specified function. - // - // Parameters: - // function: - // The Lua/MoonSharp function to be called - // - // args: - // The arguments to pass to the function. - // - // Returns: - // The return value(s) of the function call. - // - // Exceptions: - // T:System.ArgumentException: - // Thrown if function is not of DataType.Function - public static DynValue RunScript(Script script, DynValue function, params DynValue[] args) - { - DynValue res = null; - try - { - res = script.Call(function, args); - } - catch (InterpreterException e) - { - Program.Log.Error(e.DecoratedMessage); - } - return res; - } - // - // Summary: - // Calls the specified function. - // - // Parameters: - // function: - // The Lua/MoonSharp function to be called - // - // args: - // The arguments to pass to the function. - // - // Returns: - // The return value(s) of the function call. - // - // Exceptions: - // T:System.ArgumentException: - // Thrown if function is not of DataType.Function - public static DynValue RunScript(Script script, DynValue function, params object[] args) - { - DynValue res = null; - try - { - res = script.Call(function, args); - } - catch (InterpreterException e) - { - Program.Log.Error(e.DecoratedMessage); - } - return res; - } - #endregion + } } } diff --git a/FFXIVClassic Map Server/lua/LuaScript.cs b/FFXIVClassic Map Server/lua/LuaScript.cs new file mode 100644 index 00000000..6442ceca --- /dev/null +++ b/FFXIVClassic Map Server/lua/LuaScript.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MoonSharp; +using MoonSharp.Interpreter; +using NLog; +using MoonSharp.Interpreter.Debugging; +using System.IO; + +namespace FFXIVClassic_Map_Server.lua +{ + class LuaScript : Script + { + public static Logger Log = LogManager.GetCurrentClassLogger(); + + public LuaScript() + { + this.Options.DebugPrint = s => { Log.Debug(s); }; + } + public new static DynValue RunFile(string filename) + { + try + { + return Script.RunFile(filename); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new void AttachDebugger(IDebugger debugger) + { + try + { + ((Script)this).AttachDebugger(debugger); + } + catch (Exception e) + { + Log.Debug(e.Message); + } + } + + public new DynValue Call(DynValue function) + { + try + { + return ((Script)this).Call(function); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue Call(object function) + { + try + { + return ((Script)this).Call(function); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue Call(object function, params object[] args) + { + try + { + return ((Script)this).Call(function, args); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue Call(DynValue function, params DynValue[] args) + { + try + { + return ((Script)this).Call(function, args); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue Call(DynValue function, params object[] args) + { + try + { + return ((Script)this).Call(function, args); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue CreateCoroutine(DynValue function) + { + try + { + return ((Script)this).CreateCoroutine(function); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue CreateCoroutine(object function) + { + try + { + return ((Script)this).CreateCoroutine(function); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue DoString(string code, Table globalContext = null) + { + try + { + return ((Script)this).DoString(code, globalContext); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new DynValue DoFile(string filename, Table globalContext = null) + { + try + { + return ((Script)this).DoFile(filename, globalContext); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new void Dump(DynValue function, Stream stream) + { + try + { + ((Script)this).Dump(function, stream); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + } + } + + public new DynValue RequireModule(string modname, Table globalContext = null) + { + try + { + return ((Script)this).RequireModule(modname, globalContext); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + return null; + } + } + + public new void SetTypeMetatable(DataType type, Table metatable) + { + try + { + ((Script)this).SetTypeMetatable(type, metatable); + } + catch (Exception e) + { + if (e is InterpreterException) + Log.Debug(((InterpreterException)e).DecoratedMessage); + else + Log.Debug(e.Message); + } + } + } +} diff --git a/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs deleted file mode 100644 index e69de29b..00000000 diff --git a/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs deleted file mode 100644 index e69de29b..00000000 diff --git a/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/FFXIVClassic Map Server/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs deleted file mode 100644 index e69de29b..00000000 diff --git a/FFXIVClassic Map Server/packets/BasePacket.cs b/FFXIVClassic Map Server/packets/BasePacket.cs index ae9b5700..ef2597e0 100644 --- a/FFXIVClassic Map Server/packets/BasePacket.cs +++ b/FFXIVClassic Map Server/packets/BasePacket.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using System.Diagnostics; using System.IO; using FFXIVClassic.Common; +using NLog; namespace FFXIVClassic_Map_Server.packets { @@ -19,7 +20,9 @@ namespace FFXIVClassic_Map_Server.packets public ulong timestamp; //Miliseconds } - public class BasePacket{ + public class BasePacket + { + public static Logger Log = LogManager.GetCurrentClassLogger(); public const int TYPE_ZONE = 1; public const int TYPE_CHAT = 2; @@ -335,7 +338,7 @@ namespace FFXIVClassic_Map_Server.packets // todo: create new target for colourful packet logging //Console.BackgroundColor = ConsoleColor.DarkYellow; - Program.Log.Debug("IsAuth: {0} IsEncrypted: {1}, Size: 0x{2:X}, NumSubpackets: {3}{4}{5}", header.isAuthenticated, header.isCompressed, header.packetSize, header.numSubpackets, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); + Log.Debug("IsAuth: {0} IsEncrypted: {1}, Size: 0x{2:X}, NumSubpackets: {3}{4}{5}", header.isAuthenticated, header.isCompressed, header.packetSize, header.numSubpackets, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); foreach (SubPacket sub in GetSubpackets()) { diff --git a/FFXIVClassic Map Server/packets/SubPacket.cs b/FFXIVClassic Map Server/packets/SubPacket.cs index e4b28170..bd432915 100644 --- a/FFXIVClassic Map Server/packets/SubPacket.cs +++ b/FFXIVClassic Map Server/packets/SubPacket.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using FFXIVClassic.Common; +using NLog; namespace FFXIVClassic_Map_Server.packets { @@ -26,6 +27,7 @@ namespace FFXIVClassic_Map_Server.packets public class SubPacket { + public static Logger Log = LogManager.GetCurrentClassLogger(); public const int SUBPACKET_SIZE = 0x10; public const int GAMEMESSAGE_SIZE = 0x10; @@ -143,15 +145,15 @@ namespace FFXIVClassic_Map_Server.packets // todo: create new target for colourful packet logging //Console.BackgroundColor = ConsoleColor.DarkRed; - Program.Log.Debug("Size: 0x{0:X}{1}{2}", header.subpacketSize, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); + Log.Debug("Size: 0x{0:X}{1}{2}", header.subpacketSize, Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())); if (header.type == 0x03) { - Program.Log.Debug("Opcode: 0x{0:X}{1}{2}", gameMessage.opcode, Environment.NewLine, Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE)); + Log.Debug("Opcode: 0x{0:X}{1}{2}", gameMessage.opcode, Environment.NewLine, Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE)); //Console.BackgroundColor = ConsoleColor.DarkMagenta; - Program.Log.Debug("Data: {0}{1}", Environment.NewLine, Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE)); + Log.Debug("Data: {0}{1}", Environment.NewLine, Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE)); } //Console.BackgroundColor = ConsoleColor.Black; diff --git a/data/scripts/commands/gm/delcurrency.lua b/data/scripts/commands/gm/delcurrency.lua new file mode 100644 index 00000000..4eaaf4fe --- /dev/null +++ b/data/scripts/commands/gm/delcurrency.lua @@ -0,0 +1,37 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sssss", + description = "removes from , currency is removed from user if is nil", +} + +function onTrigger(player, argc, currency, qty, location, name, lastName) + local sender = "[delcurrency] "; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + + if player then + currency = tonumber(currency) or nil; + qty = 1; + location = INVENTORY_CURRENCY; + + local removed = player:GetInventory(location):removecurrency(currency, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to remove currency"; + + if currency and removed then + message = string.format("removed currency %u from %s", currency, player:GetName()); + end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to remove currency, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/delitem.lua b/data/scripts/commands/gm/delitem.lua new file mode 100644 index 00000000..90c89082 --- /dev/null +++ b/data/scripts/commands/gm/delitem.lua @@ -0,0 +1,37 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sssss", + description = "removes from for . and are optional, item is removed from user if is nil", +} + +function onTrigger(player, argc, item, qty, location, name, lastName) + local sender = "[delitem] "; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + + if player then + item = tonumber(item) or nil; + qty = tonumber(qty) or 1; + location = tonumber(itemtype) or INVENTORY_NORMAL; + + local removed = player:GetInventory(location):removeItem(item, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to remove item"; + + if item and removed then + message = string.format("removed item %u from %s", item, player:GetName()); + end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to remove item, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/delkeyitem.lua b/data/scripts/commands/gm/delkeyitem.lua new file mode 100644 index 00000000..66ad8549 --- /dev/null +++ b/data/scripts/commands/gm/delkeyitem.lua @@ -0,0 +1,37 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "ssss", + description = "removes from , keyitem is removed from user if is nil", +} + +function onTrigger(player, argc, keyitem, qty, name, lastName) + local sender = "[delkeyitem] "; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + + if player then + keyitem = tonumber(keyitem) or nil; + qty = 1; + location = INVENTORY_KEYITEMS; + + local removed = player:GetInventory(location):removeItem(item, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to remove keyitem"; + + if keyitem and removed then + message = string.format("removed keyitem %u from %s", keyitem, player:GetName()); + end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to remove keyitem, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/givecurrency.lua b/data/scripts/commands/gm/givecurrency.lua new file mode 100644 index 00000000..fea8f5fd --- /dev/null +++ b/data/scripts/commands/gm/givecurrency.lua @@ -0,0 +1,37 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sss", + description = "adds to self or .", +} + +function onTrigger(player, argc, currency, name, lastName) + local sender = "[givecurrency] "; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + + if player then + currency = tonumber(currency) or nil; + qty = 1; + location = INVENTORY_CURRENCY; + + local added = player:GetInventory(location):AddItem(currency, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to add currency"; + + if currency and added then + message = string.format("added currency %u to %s", currency, player:GetName()); + end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to add currency, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/giveitem.lua b/data/scripts/commands/gm/giveitem.lua index 84ae4f8f..47c94a57 100644 --- a/data/scripts/commands/gm/giveitem.lua +++ b/data/scripts/commands/gm/giveitem.lua @@ -2,21 +2,35 @@ require("global"); properties = { permissions = 0, - parameters = "ssss", + parameters = "sssss", description = "adds to for . and are optional, item is added to user if is nil", } -function onTrigger(player, argc, item, qty, location, target) +function onTrigger(player, argc, item, qty, location, name, lastName) local sender = "[giveitem] "; - player = GetWorldManager():GetPCInWorld(target) or player; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + if player then item = tonumber(item) or nil; qty = tonumber(qty) or 1; location = tonumber(itemtype) or INVENTORY_NORMAL; + local added = player:GetInventory(location):AddItem(item, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to add item"; - if item then - player:GetInventory(location):AddItem(item, qty); - player:SendMessage(MSG_TYPE_SYSTEM_ERROR, "[giveitem] ", string.format("Added item %u to %s", item, player:GetName()); + if item and added then + message = string.format("added item %u to %s", item, player:GetName()); end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to add item, ensure player name is valid."); end; end; \ No newline at end of file diff --git a/data/scripts/commands/gm/givekeyitem.lua b/data/scripts/commands/gm/givekeyitem.lua new file mode 100644 index 00000000..af8aca70 --- /dev/null +++ b/data/scripts/commands/gm/givekeyitem.lua @@ -0,0 +1,37 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sss", + description = "adds to self or .", +} + +function onTrigger(player, argc, keyitem, name, lastName) + local sender = "[givekeyitem] "; + + if name then + if lastName then + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; + else + player = GetWorldManager():GetPCInWorld(name) or nil; + end; + end; + + if player then + keyitem = tonumber(keyitem) or nil; + qty = 1; + location = INVENTORY_KEYITEMS; + + local added = player:GetInventory(location):AddItem(keyitem, qty); + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local message = "unable to add keyitem"; + + if keyitem and added then + message = string.format("added keyitem %u to %s", keyitem, player:GetName()); + end + player:SendMessage(messageID, sender, message); + print(message); + else + print(sender.."unable to add keyitem, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/graphic.lua b/data/scripts/commands/gm/graphic.lua index 19a28c5d..c577f305 100644 --- a/data/scripts/commands/gm/graphic.lua +++ b/data/scripts/commands/gm/graphic.lua @@ -1,8 +1,7 @@ properties = { permissions = 0, parameters = "sssss", - description = [[changes appearance for equipment in . Parameters: , - idk what any of those mean either]], + description = "changes appearance for equipment in . Parameters: , (idk what any of those mean either)", } function onTrigger(player, argc, slot, wId, eId, vId, cId) diff --git a/data/scripts/commands/gm/command - Copy (7).lua b/data/scripts/commands/gm/property.lua similarity index 100% rename from data/scripts/commands/gm/command - Copy (7).lua rename to data/scripts/commands/gm/property.lua diff --git a/data/scripts/commands/gm/reloadzone.lua b/data/scripts/commands/gm/reloadzone.lua index 35db5d1e..1db18069 100644 --- a/data/scripts/commands/gm/reloadzone.lua +++ b/data/scripts/commands/gm/reloadzone.lua @@ -7,17 +7,26 @@ properties = { } function onTrigger(player, argc, zone) - if not zone or tonumber(zone) == 0 then - printf("%s is not a valid zone!", zone); + if not player and not zone or tonumber(zone) == 0 then + printf("No valid zone specified!"); return; end; + local sender = "[reloadzones] "; + zone = tonumber(zone); if player then - local messageID = MSG_TYPE_SYSTEM_ERROR; + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + zone = zone or player:GetZoneID(); player:SendMessage(messageID, "[reloadzones] ", string.format("Reloading zone: %u", zone)); + --[[ todo: get this working legit + player:GetZone():Clear(); + player:GetZone():AddActorToZone(player); + player:SendInstanceUpdate(); + ]] end; GetWorldManager():ReloadZone(zone); + printf("%s reloaded zone %u", sender, zone); end; \ No newline at end of file diff --git a/data/scripts/commands/gm/test.lua b/data/scripts/commands/gm/test.lua deleted file mode 100644 index 6b0221b7..00000000 --- a/data/scripts/commands/gm/test.lua +++ /dev/null @@ -1,9 +0,0 @@ -properties = { - permissions = 0, - parameters = "sss", - description = "", -} - -function onTrigger(player, argc) - -- todo: change weather -end; \ No newline at end of file diff --git a/data/scripts/commands/gm/warp.lua b/data/scripts/commands/gm/warp.lua index 01b689fb..4fa2c2b9 100644 --- a/data/scripts/commands/gm/warp.lua +++ b/data/scripts/commands/gm/warp.lua @@ -3,20 +3,21 @@ require("global"); properties = { permissions = 0, parameters = "sssssss", - description = [[ + description = +[[ | | . ]], } -function onTrigger(player, argc, p1, p2, p3, p4, privateArea, firstName, lastName) +function onTrigger(player, argc, p1, p2, p3, p4, privateArea, name, lastName) - if firstName then + if name then if lastName then - player = GetWorldManager():GetPCInWorld(firstName.." "..lastName) or nil; + player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil; else - player = GetWorldManager():GetPCInWorld(firstName) or nil; + player = GetWorldManager():GetPCInWorld(name) or nil; end; end; @@ -60,7 +61,7 @@ function onTrigger(player, argc, p1, p2, p3, p4, privateArea, firstName, lastNam local z = tonumber(applyPositionOffset(p4, player_z)) or player_z; if privateArea == "" then privateArea = nil end; player:SendMessage(messageID, sender, string.format("setting coordinates X:%d Y:%d Z:%d to new zone (%d) private area:%s", x, y, z, zone, privateArea or "unspecified")); - worldManager:DoZoneChange(player, zone, privateArea, 0x0F, x, y, z, 0.00); + worldManager:DoZoneChange(player, zone, privateArea, 0x02, x, y, z, 0.00); end else diff --git a/data/scripts/commands/gm/weather.lua b/data/scripts/commands/gm/weather.lua new file mode 100644 index 00000000..e1fd6703 --- /dev/null +++ b/data/scripts/commands/gm/weather.lua @@ -0,0 +1,30 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "ssss", + description = "usage: .", +} + +function onTrigger(player, argc, weather, updateTime, zonewide) + -- todo: change weather + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local sender = "[weather] "; + local message = "unable to change weather"; + + if player then + weather = tonumber(weather) or 0; + updateTime = tonumber(updateTime) or 0; + zonewide = tonumber(zonewide) or 0; + message = "changed weather to %u "; + if zonewide ~= 0 then + message = string.format(message.."for zone %u", player:GetZoneID()); + else + message = string.format(message.."%s", player:GetName()); + end; + -- weatherid, updateTime + player:GetZone():ChangeWeather(weather, updateTime, player, zonewide ~= 0); + player:SendMessage(messageID, sender, message); + end; + print(sender..message); +end; \ No newline at end of file diff --git a/data/scripts/global.lua b/data/scripts/global.lua index d79ae0d8..15de27dd 100644 --- a/data/scripts/global.lua +++ b/data/scripts/global.lua @@ -57,5 +57,9 @@ INVENTORY_EQUIPMENT_OTHERPLAYER = 0x00F9; --Max 0x23 function printf(s, ...) - print(s:format(...)); + if ... then + print(s:format(...)); + else + print(s); + end; end; \ No newline at end of file