diff --git a/FFXIVClassic Map Server/CommandProcessor.cs b/FFXIVClassic Map Server/CommandProcessor.cs new file mode 100644 index 00000000..d815467a --- /dev/null +++ b/FFXIVClassic Map Server/CommandProcessor.cs @@ -0,0 +1,680 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; +using System.Threading; +using FFXIVClassic_Lobby_Server.common; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Lobby_Server.packets; +using System.IO; +using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server; +using FFXIVClassic_Map_Server.packets.send; +using FFXIVClassic_Map_Server.dataobjects.chara; +using FFXIVClassic_Map_Server.Actors; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.actors.chara.player; +using FFXIVClassic_Map_Server.Properties; + +namespace FFXIVClassic_Lobby_Server +{ + class CommandProcessor + { + private Dictionary mConnectedPlayerList; + private static WorldManager mWorldManager = Server.getWorldManager(); + private static Dictionary gamedataItems = Server.getItemGamedataList(); + + // For the moment, this is the only predefined item + // TODO: make a list/enum in the future so that items can be given by name, instead of by id + const UInt32 ITEM_GIL = 1000001; + + public CommandProcessor(Dictionary playerList) + { + mConnectedPlayerList = playerList; + } + + public void sendPacket(ConnectedPlayer client, string path) + { + BasePacket packet = new BasePacket(path); + + if (client != null) + { + packet.replaceActorID(client.actorID); + client.queuePacket(packet); + } + else + { + foreach (KeyValuePair entry in mConnectedPlayerList) + { + packet.replaceActorID(entry.Value.actorID); + entry.Value.queuePacket(packet); + } + } + } + + 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 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, string entranceId) + { + uint id; + + try + { + if (entranceId.ToLower().StartsWith("0x")) + id = Convert.ToUInt32(entranceId, 16); + else + id = Convert.ToUInt32(entranceId); + } + catch(FormatException e) + {return;} + + FFXIVClassic_Map_Server.WorldManager.ZoneEntrance ze = mWorldManager.getZoneEntrance(id); + + if (ze == null) + return; + + if (client != null) + mWorldManager.DoZoneChange(client.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f); + else + { + foreach (KeyValuePair entry in mConnectedPlayerList) + { + mWorldManager.DoZoneChange(entry.Value.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f); + } + } + } + + public void doWarp(ConnectedPlayer client, string zone, string privateArea, string sx, string sy, string sz) + { + uint zoneId; + float x,y,z; + + x = Single.Parse(sx); + y = Single.Parse(sy); + z = Single.Parse(sz); + + if (zone == null) + { + if (client != null) + mWorldManager.DoZoneChange(client.getActor(), 0, privateArea, 0x2, x, y, z, 0.0f); + } + else + { + if (zone.ToLower().StartsWith("0x")) + zoneId = Convert.ToUInt32(zone, 16); + else + zoneId = Convert.ToUInt32(zone); + + if (mWorldManager.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)); + Log.error("Zone does not exist or setting isn't valid."); + } + + if (client != null) + mWorldManager.DoZoneChange(client.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f); + else + { + foreach (KeyValuePair entry in mConnectedPlayerList) + { + mWorldManager.DoZoneChange(entry.Value.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f); + } + } + } + } + + 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(); + 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); + } + } + } + + /// + /// We only use the default options for SendMessagePacket. + /// May as well make it less unwieldly to view + /// + /// + /// + private void sendMessage(ConnectedPlayer client, String message) + { + if (client != null) + client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message)); + } + + internal bool doCommand(string input, ConnectedPlayer client) + { + input.Trim(); + if (input.StartsWith("!")) + input = input.Substring(1); + + String[] split = input.Split(' '); + split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands + split = split.Where(temp => temp != "").ToArray(); // strips extra whitespace from commands + + // 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); + */ + } + + return true; + } + #endregion + + #region !mypos + else if (split[0].Equals("mypos")) + { + try + { + printPos(client); + return true; + } + catch (Exception e) + { + Log.error("Could not load packet: " + e); + } + } + #endregion + + #region !reloadzones + else if (split[0].Equals("reloadzones")) + { + if (client != null) + { + 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)); + } + mWorldManager.reloadZone(client.getActor().zoneId); + return true; + } + #endregion + + #region !reloaditems + else if (split[0].Equals("reloaditems")) + { + Log.info(String.Format("Got request to reload item gamedata")); + sendMessage(client, "Reloading Item Gamedata..."); + gamedataItems.Clear(); + gamedataItems = Database.getItemGamedata(); + 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) + { + 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) + { + 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) + { + 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) + { + 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) + { + 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) + { + 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) + { + 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) + { + 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) + { + Log.error("Could not change music: " + e); + } + } + #endregion + + #region !warp + else if (split[0].Equals("warp")) + { + if (split.Length == 2) // Predefined list + doWarp(client, split[1]); + else if (split.Length == 4) // X/Y/Z + doWarp(client, null, null, split[1], split[2], split[3]); + else if (split.Length == 5) // Zone + X/Y/Z + doWarp(client, split[1], null, split[2], split[3], split[4]); + else if (split.Length == 6) // Zone + instance + X/Y/Z + doWarp(client, split[1], split[2], split[3], split[4], split[5]); + 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; + } + #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; + } + #endregion + } + return false; + } + } + +} diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 06a03b1e..3f114e1c 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -708,7 +708,7 @@ namespace FFXIVClassic_Lobby_Server player.getInventory(Inventory.NORMAL).initList(getInventory(player, 0, Inventory.NORMAL)); player.getInventory(Inventory.KEYITEMS).initList(getInventory(player, 0, Inventory.KEYITEMS)); - player.getInventory(Inventory.CURRANCY).initList(getInventory(player, 0, Inventory.CURRANCY)); + player.getInventory(Inventory.CURRENCY).initList(getInventory(player, 0, Inventory.CURRENCY)); player.getInventory(Inventory.BAZAAR).initList(getInventory(player, 0, Inventory.BAZAAR)); player.getInventory(Inventory.MELDREQUEST).initList(getInventory(player, 0, Inventory.MELDREQUEST)); player.getInventory(Inventory.LOOT).initList(getInventory(player, 0, Inventory.LOOT)); diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 80affaef..d11205d9 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -79,6 +79,7 @@ + @@ -250,6 +251,11 @@ + + True + True + Resources.resx + @@ -261,7 +267,12 @@ - + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + xcopy "$(SolutionDir)data" "$(SolutionDir)$(ProjectName)\$(OutDir)" /E /C /D diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 8d1cd62b..9f922c55 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -39,6 +39,7 @@ namespace FFXIVClassic_Lobby_Server class PacketProcessor { Server mServer; + CommandProcessor cp; Dictionary mPlayers; List mConnections; @@ -47,6 +48,7 @@ namespace FFXIVClassic_Lobby_Server mPlayers = playerList; mConnections = connectionList; mServer = server; + cp = new CommandProcessor(playerList); } public void processPacket(ClientConnection client, BasePacket packet) @@ -186,7 +188,7 @@ namespace FFXIVClassic_Lobby_Server subpacket.debugPrintSubPacket(); client.queuePacket(_0x2Packet.buildPacket(player.actorID), true, false); - Server.GetWorldManager().DoLogin(player.getActor()); + Server.getWorldManager().DoLogin(player.getActor()); break; @@ -198,7 +200,7 @@ namespace FFXIVClassic_Lobby_Server if (chatMessage.message.StartsWith("!")) { - if (mServer.doCommand(chatMessage.message, player)) + if (cp.doCommand(chatMessage.message, player)) continue; } @@ -265,7 +267,7 @@ namespace FFXIVClassic_Lobby_Server if (ownerActor == null) { //Is it a instance actor? - ownerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner); + ownerActor = Server.getWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner); if (ownerActor == null) { //Is it a Director? @@ -296,7 +298,7 @@ namespace FFXIVClassic_Lobby_Server Actor updateOwnerActor = Server.getStaticActors(player.getActor().eventCurrentOwner); if (updateOwnerActor == null) { - updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner); + updateOwnerActor = Server.getWorldManager().GetActorInWorld(player.getActor().eventCurrentOwner); if (player.getActor().currentDirector != null && player.getActor().eventCurrentOwner == player.getActor().currentDirector.actorId) updateOwnerActor = player.getActor().currentDirector; diff --git a/FFXIVClassic Map Server/Program.cs b/FFXIVClassic Map Server/Program.cs index 5c9cc061..4790bc0f 100644 --- a/FFXIVClassic Map Server/Program.cs +++ b/FFXIVClassic Map Server/Program.cs @@ -68,12 +68,13 @@ namespace FFXIVClassic_Lobby_Server if (startServer) { Server server = new Server(); + CommandProcessor cp = new CommandProcessor(server.getConnectedPlayerList()); server.startServer(); while (true) { String input = Console.ReadLine(); - server.doCommand(input, null); + cp.doCommand(input, null); } } diff --git a/FFXIVClassic Map Server/Properties/Resources.Designer.cs b/FFXIVClassic Map Server/Properties/Resources.Designer.cs new file mode 100644 index 00000000..cea7c949 --- /dev/null +++ b/FFXIVClassic Map Server/Properties/Resources.Designer.cs @@ -0,0 +1,256 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FFXIVClassic_Map_Server.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FFXIVClassic_Map_Server.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Adds the specified currency to the current player's inventory + /// + ///*Syntax: givecurrency <quantity> + /// givecurrency <quantity> <type> + ///<type> is the specific type of currency desired, defaults to gil if no type specified. + /// + public static string CPgivecurrency { + get { + return ResourceManager.GetString("CPgivecurrency", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adds the specified items to the current player's inventory + /// + ///*Syntax: giveitem <item id> + /// giveitem <item id> <quantity> + /// giveitem <item id> <quantity> <type> + ///<item id> is the item's specific id as defined in the server database + ///<type> is the type as defined in the server database (defaults to standard item if not specified). + /// + public static string CPgiveitem { + get { + return ResourceManager.GetString("CPgiveitem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Adds the specified key item to the current player's inventory + /// + ///*Syntax: givekeyitem <item id> + ///<item id> is the key item's specific id as defined in the server database. + /// + public static string CPgivekeyitem { + get { + return ResourceManager.GetString("CPgivekeyitem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use !help(command) for details + /// + ///Available commands: + ///Standard: mypos, music, warp + ///Server Administration: givecurrency, giveitem, givekeyitem, removecurrency, removekeyitem, reloaditems, reloadzones. + /// + public static string CPhelp { + get { + return ResourceManager.GetString("CPhelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changes the currently playing background music + /// + ///*Syntax: music <music id> + ///<music id> is the key item's specific id as defined in the server database. + /// + public static string CPmusic { + get { + return ResourceManager.GetString("CPmusic", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Prints out your current location + /// + ///*Note: The X/Y/Z coordinates do not correspond to the coordinates listed in the in-game map, they are based on the underlying game data. + /// + public static string CPmypos { + get { + return ResourceManager.GetString("CPmypos", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to *Syntax: property <value 1> <value 2> <value 3>. + /// + public static string CPproperty { + get { + return ResourceManager.GetString("CPproperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to *Syntax: property2 <value 1> <value 2> <value 3>. + /// + public static string CPproperty2 { + get { + return ResourceManager.GetString("CPproperty2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reloads the current item data from the database. + /// + public static string CPreloaditems { + get { + return ResourceManager.GetString("CPreloaditems", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reloads the current zone data from the database. + /// + public static string CPreloadzones { + get { + return ResourceManager.GetString("CPreloadzones", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removes the specified currency from the current player's inventory + /// + ///*Syntax: removecurrency <quantity> + /// removecurrency <quantity> <type> + ///<type> is the specific type of currency desired, defaults to gil if no type specified. + /// + public static string CPremovecurrency { + get { + return ResourceManager.GetString("CPremovecurrency", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removes the specified items to the current player's inventory + /// + ///*Syntax: removeitem <itemid> + /// removeitem <itemid> <quantity> + ///<item id> is the item's specific id as defined in the server database. + /// + public static string CPremoveitem { + get { + return ResourceManager.GetString("CPremoveitem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removes the specified key item to the current player's inventory + /// + ///*Syntax: removekeyitem <itemid> + ///<item id> is the key item's specific id as defined in the server database. + /// + public static string CPremovekeyitem { + get { + return ResourceManager.GetString("CPremovekeyitem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server sends a special packet to the client + /// + ///*Syntax: sendpacket <path to packet> + ///<Path to packet> is the path to the packet, starting in <map server install location>\packet. + /// + public static string CPsendpacket { + get { + return ResourceManager.GetString("CPsendpacket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Overrides the currently displayed character equipment in a specific slot + /// + ///*Note: Similar to Glamours in FFXIV:ARR, the overridden graphics are purely cosmetic, they do not affect the underlying stats of whatever is equipped on that slot + /// + ///*Syntax: sendpacket <slot> <wid> <eid> <vid> <cid> + ///<w/e/v/c id> are as defined in the client game data. + /// + public static string CPsetgraphic { + get { + return ResourceManager.GetString("CPsetgraphic", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Teleports the player to the specified location + /// + ///*Syntax: warp <location list> + /// warp <X coordinate> <Y coordinate> <Z coordinate> + /// warp <zone id> <X coordinate> <Y coordinate> <Z coordinate> + /// warp <zone id> <instance> <X coordinate> <Y coordinate> <Z coordinate> + ///<location list> is a pre-defined list of locations from the server database + ///<zone id> is the zone's id as defined in the server database + ///<instance> is an instanced copy of the desired zone that's only visible to the current player. + /// + public static string CPwarp { + get { + return ResourceManager.GetString("CPwarp", resourceCulture); + } + } + } +} diff --git a/FFXIVClassic Map Server/Properties/Resources.resx b/FFXIVClassic Map Server/Properties/Resources.resx new file mode 100644 index 00000000..71b54066 --- /dev/null +++ b/FFXIVClassic Map Server/Properties/Resources.resx @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Adds the specified currency to the current player's inventory + +*Syntax: givecurrency <quantity> + givecurrency <quantity> <type> +<type> is the specific type of currency desired, defaults to gil if no type specified + + + Adds the specified items to the current player's inventory + +*Syntax: giveitem <item id> + giveitem <item id> <quantity> + giveitem <item id> <quantity> <type> +<item id> is the item's specific id as defined in the server database +<type> is the type as defined in the server database (defaults to standard item if not specified) + + + Adds the specified key item to the current player's inventory + +*Syntax: givekeyitem <item id> +<item id> is the key item's specific id as defined in the server database + + + Use !help(command) for details + +Available commands: +Standard: mypos, music, warp +Server Administration: givecurrency, giveitem, givekeyitem, removecurrency, removekeyitem, reloaditems, reloadzones + + + Changes the currently playing background music + +*Syntax: music <music id> +<music id> is the key item's specific id as defined in the server database + + + Prints out your current location + +*Note: The X/Y/Z coordinates do not correspond to the coordinates listed in the in-game map, they are based on the underlying game data + + + *Syntax: property <value 1> <value 2> <value 3> + + + *Syntax: property2 <value 1> <value 2> <value 3> + + + Reloads the current item data from the database + + + Reloads the current zone data from the database + + + Removes the specified currency from the current player's inventory + +*Syntax: removecurrency <quantity> + removecurrency <quantity> <type> +<type> is the specific type of currency desired, defaults to gil if no type specified + + + Removes the specified items to the current player's inventory + +*Syntax: removeitem <itemid> + removeitem <itemid> <quantity> +<item id> is the item's specific id as defined in the server database + + + Removes the specified key item to the current player's inventory + +*Syntax: removekeyitem <itemid> +<item id> is the key item's specific id as defined in the server database + + + Server sends a special packet to the client + +*Syntax: sendpacket <path to packet> +<Path to packet> is the path to the packet, starting in <map server install location>\packet + + + Overrides the currently displayed character equipment in a specific slot + +*Note: Similar to Glamours in FFXIV:ARR, the overridden graphics are purely cosmetic, they do not affect the underlying stats of whatever is equipped on that slot + +*Syntax: sendpacket <slot> <wid> <eid> <vid> <cid> +<w/e/v/c id> are as defined in the client game data + + + Teleports the player to the specified location + +*Syntax: warp <location list> + warp <X coordinate> <Y coordinate> <Z coordinate> + warp <zone id> <X coordinate> <Y coordinate> <Z coordinate> + warp <zone id> <instance> <X coordinate> <Y coordinate> <Z coordinate> +<location list> is a pre-defined list of locations from the server database +<zone id> is the zone's id as defined in the server database +<instance> is an instanced copy of the desired zone that's only visible to the current player + + \ No newline at end of file diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index c87f47a1..206de92f 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -22,9 +22,9 @@ namespace FFXIVClassic_Lobby_Server { class Server { - public const int FFXIV_MAP_PORT = 54992; - public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF - public const int BACKLOG = 100; + public const int FFXIV_MAP_PORT = 54992; + public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF + public const int BACKLOG = 100; public const int HEALTH_THREAD_SLEEP_TIME = 5; public const string STATIC_ACTORS_PATH = "./staticactors.bin"; @@ -33,7 +33,7 @@ namespace FFXIVClassic_Lobby_Server private Socket mServerSocket; - private Dictionary mConnectedPlayerList = new Dictionary(); + private Dictionary mConnectedPlayerList = new Dictionary(); private List mConnectionList = new List(); private LuaEngine mLuaEngine = new LuaEngine(); @@ -83,10 +83,10 @@ namespace FFXIVClassic_Lobby_Server mConnectionHealthThread.Name = "MapThread:Health"; //mConnectionHealthThread.Start(); - mStaticActors = new StaticActors(STATIC_ACTORS_PATH); - + mStaticActors = new StaticActors(STATIC_ACTORS_PATH); + gamedataItems = Database.getItemGamedata(); - Log.info(String.Format("Loaded {0} items.",gamedataItems.Count)); + Log.info(String.Format("Loaded {0} items.", gamedataItems.Count)); mWorldManager = new WorldManager(this); mWorldManager.LoadZoneList(); @@ -95,8 +95,9 @@ namespace FFXIVClassic_Lobby_Server IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), FFXIV_MAP_PORT); - try{ - mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + try + { + mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } catch (Exception e) { @@ -145,8 +146,8 @@ namespace FFXIVClassic_Lobby_Server private void acceptCallback(IAsyncResult result) { ClientConnection conn = null; - Socket socket = (System.Net.Sockets.Socket)result.AsyncState; - + Socket socket = (System.Net.Sockets.Socket)result.AsyncState; + try { @@ -168,8 +169,8 @@ namespace FFXIVClassic_Lobby_Server catch (SocketException) { if (conn != null) - { - + { + lock (mConnectionList) { mConnectionList.Remove(conn); @@ -180,7 +181,7 @@ namespace FFXIVClassic_Lobby_Server catch (Exception) { if (conn != null) - { + { lock (mConnectionList) { mConnectionList.Remove(conn); @@ -224,7 +225,7 @@ namespace FFXIVClassic_Lobby_Server lock (mConnectionList) { mConnectionList.Remove(conn); - } + } if (conn.connType == BasePacket.TYPE_ZONE) Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); return; @@ -241,37 +242,37 @@ namespace FFXIVClassic_Lobby_Server int offset = 0; //Build packets until can no longer or out of data - while(true) - { - BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead); - - //If can't build packet, break, else process another - if (basePacket == null) - break; - else - mProcessor.processPacket(conn, basePacket); - } - - //Not all bytes consumed, transfer leftover to beginning + while (true) + { + BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead); + + //If can't build packet, break, else process another + if (basePacket == null) + break; + else + mProcessor.processPacket(conn, basePacket); + } + + //Not all bytes consumed, transfer leftover to beginning if (offset < bytesRead) Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset); conn.lastPartialSize = bytesRead - offset; //Build any queued subpackets into basepackets and send - conn.flushQueuedSendPackets(); - - if (offset < bytesRead) - //Need offset since not all bytes consumed + conn.flushQueuedSendPackets(); + + if (offset < bytesRead) + //Need offset since not all bytes consumed conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(receiveCallback), conn); - else - //All bytes consumed, full buffer available + else + //All bytes consumed, full buffer available conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn); } else { - Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); - + Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); + lock (mConnectionList) { mConnectionList.Remove(conn); @@ -279,15 +280,15 @@ namespace FFXIVClassic_Lobby_Server } } catch (SocketException) - { + { if (conn.socket != null) { - Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); - + Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); + lock (mConnectionList) { mConnectionList.Remove(conn); - } + } } } } @@ -325,532 +326,23 @@ namespace FFXIVClassic_Lobby_Server } return newPacket; - } - + } + #endregion - - public void sendPacket(ConnectedPlayer client, string path) - { - BasePacket packet = new BasePacket(path); - - if (client != null) - { - packet.replaceActorID(client.actorID); - client.queuePacket(packet); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - packet.replaceActorID(entry.Value.actorID); - entry.Value.queuePacket(packet); - } - } + + public static WorldManager getWorldManager() + { + return mWorldManager; } - 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 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); - } - } - } - - public void doWarp(ConnectedPlayer client, string entranceId) - { - uint id; - - try - { - if (entranceId.ToLower().StartsWith("0x")) - id = Convert.ToUInt32(entranceId, 16); - else - id = Convert.ToUInt32(entranceId); - } - catch(FormatException e) - {return;} - - FFXIVClassic_Map_Server.WorldManager.ZoneEntrance ze = mWorldManager.getZoneEntrance(id); - - if (ze == null) - return; - - if (client != null) - mWorldManager.DoZoneChange(client.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f); - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - mWorldManager.DoZoneChange(entry.Value.getActor(), ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, 0.0f); - } - } - } - - public void doWarp(ConnectedPlayer client, string zone, string privateArea, string sx, string sy, string sz) - { - uint zoneId; - float x,y,z; - - if (zone.ToLower().StartsWith("0x")) - zoneId = Convert.ToUInt32(zone, 16); - else - zoneId = Convert.ToUInt32(zone); - - if (mWorldManager.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)); - Log.error("Zone does not exist or setting isn't valid."); - } - - x = Single.Parse(sx); - y = Single.Parse(sy); - z = Single.Parse(sz); - - if (client != null) - mWorldManager.DoZoneChange(client.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f); - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - mWorldManager.DoZoneChange(entry.Value.getActor(), zoneId, privateArea, 0x2, x, y, z, 0.0f); - } - } - } - - public static WorldManager GetWorldManager() - { - return mWorldManager; - } - - 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("Position: {1}, {2}, {3}, {4}", p.customDisplayName, p.positionX, p.positionY, p.positionZ, p.rotation)), true, false)); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.getActor(); - Log.info(String.Format("{0} position: {1}, {2}, {3}, {4}", p.customDisplayName, 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 giveCurrancy(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.getActor(); - p.getInventory(Inventory.CURRANCY).addItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.getActor(); - p.getInventory(Inventory.CURRANCY).addItem(itemId, quantity); - } - } - } - - private void removeCurrancy(ConnectedPlayer client, uint itemId, int quantity) - { - if (client != null) - { - Player p = client.getActor(); - p.getInventory(Inventory.CURRANCY).removeItem(itemId, quantity); - } - else - { - foreach (KeyValuePair entry in mConnectedPlayerList) - { - Player p = entry.Value.getActor(); - p.getInventory(Inventory.CURRANCY).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); - } - } - } - - internal bool doCommand(string input, ConnectedPlayer client) - { - input.Trim(); - if (input.StartsWith("!")) - input = input.Substring(1); - - String[] split = input.Split(' '); - - if (split.Length >= 1) - { - if (split[0].Equals("mypos")) - { - try - { - printPos(client); - return true; - } - catch (Exception e) - { - Log.error("Could not load packet: " + e); - } - } - else if (split[0].Equals("resetzone")) - { - if (client != null) - { - 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("Resting zone {0}...", client.getActor().zoneId)), true, false)); - } - mWorldManager.reloadZone(client.getActor().zoneId); - return true; - } - else if (split[0].Equals("reloaditems")) - { - Log.info(String.Format("Got request to reload item gamedata")); - if (client != null) - client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", "Reloading Item Gamedata...")); - gamedataItems.Clear(); - gamedataItems = Database.getItemGamedata(); - Log.info(String.Format("Loaded {0} items.", gamedataItems.Count)); - if (client != null) - client.getActor().queuePacket(SendMessagePacket.buildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Loaded {0} items.", gamedataItems.Count))); - return true; - } - else if (split[0].Equals("sendpacket")) - { - if (split.Length < 2) - return false; - - try - { - sendPacket(client, "./packets/" + split[1]); - return true; - } - catch (Exception e) - { - Log.error("Could not load packet: " + e); - } - } - 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) - { - Log.error("Could not give item."); - } - } - 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) - { - Log.error("Could not give item."); - } - } - 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) - { - Log.error("Could not remove item."); - } - } - else if (split[0].Equals("givekeyitem")) - { - try - { - if (split.Length == 2) - giveKeyItem(client, UInt32.Parse(split[1])); - } - catch (Exception e) - { - Log.error("Could not give keyitem."); - } - } - 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) - { - Log.error("Could not remove keyitem."); - } - } - else if (split[0].Equals("givecurrancy")) - { - try - { - if (split.Length == 2) - giveCurrancy(client, UInt32.Parse(split[1]), 1); - else if (split.Length == 3) - giveCurrancy(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - } - catch (Exception e) - { - Log.error("Could not give currancy."); - } - } - else if (split[0].Equals("removecurrancy")) - { - if (split.Length < 2) - return false; - - try - { - if (split.Length == 2) - removeCurrancy(client, UInt32.Parse(split[1]), 1); - else if (split.Length == 3) - removeCurrancy(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); - return true; - } - catch (Exception e) - { - Log.error("Could not remove currancy."); - } - } - else if (split[0].Equals("music")) - { - if (split.Length < 2) - return false; - - try - { - doMusic(client, split[1]); - return true; - } - catch (Exception e) - { - Log.error("Could not change music: " + e); - } - } - else if (split[0].Equals("warp")) - { - if (split.Length == 2) - doWarp(client, split[1]); - else if (split.Length == 5) - doWarp(client, split[1], null, split[2], split[3], split[4]); - else if (split.Length == 6) - doWarp(client, split[1], split[2], split[3], split[4], split[5]); - 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; - } - 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; - } - } - return false; - } + public Dictionary getConnectedPlayerList() + { + return mConnectedPlayerList; + } + + public static Dictionary getItemGamedataList() + { + return gamedataItems; + } } - -} +} \ No newline at end of file diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index cbac035a..32e19250 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -372,26 +372,35 @@ namespace FFXIVClassic_Map_Server } //Add player to new zone and update - Area newArea; - - if (destinationPrivateArea == null) - newArea = GetZone(destinationZoneId); + Area newArea; + + if (destinationZoneId != 0) + { + if (destinationPrivateArea == null) + newArea = GetZone(destinationZoneId); + else + newArea = GetZone(destinationZoneId).getPrivateArea(destinationPrivateArea, 0); + } else - newArea = GetZone(destinationZoneId).getPrivateArea(destinationPrivateArea, 0); - + { + if (destinationPrivateArea == null) + newArea = GetZone(player.zoneId); + else + newArea = GetZone(player.zoneId).getPrivateArea(destinationPrivateArea, 0); + } //This server does not contain that zoneId if (newArea == null) return; - newArea.addActorToZone(player); - - //Update player actor's properties - player.zoneId = newArea.actorId; - player.zone = newArea; - player.positionX = spawnX; - player.positionY = spawnY; - player.positionZ = spawnZ; - player.rotation = spawnRotation; + newArea.addActorToZone(player); + + //Update player actor's properties + player.zoneId = newArea.actorId; + player.zone = newArea; + player.positionX = spawnX; + player.positionY = spawnY; + player.positionZ = spawnZ; + player.rotation = spawnRotation; //Send packets player.playerSession.queuePacket(DeleteAllActorsPacket.buildPacket(player.actorId), true, false); diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index 9e43c677..e78444cf 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -49,7 +49,7 @@ namespace FFXIVClassic_Map_Server.Actors { List lParams; - Player player = Server.GetWorldManager().GetPCInWorld(playerActorId); + Player player = Server.getWorldManager().GetPCInWorld(playerActorId); lParams = LuaEngine.doActorOnInstantiate(player, this); if (lParams == null) diff --git a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs index 07f1e336..52c90ef2 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs @@ -18,7 +18,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player public const ushort LOOT = 0x0004; //Max 0xA public const ushort MELDREQUEST = 0x0005; //Max 0x04 public const ushort BAZAAR = 0x0007; //Max 0x0A - public const ushort CURRANCY = 0x0063; //Max 0x140 + public const ushort CURRENCY = 0x0063; //Max 0x140 public const ushort KEYITEMS = 0x0064; //Max 0x500 public const ushort EQUIPMENT = 0x00FE; //Max 0x23 public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23 @@ -132,7 +132,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player { Database.setQuantity(owner, slot, inventoryCode, list[slot].quantity); - if (inventoryCode != CURRANCY && inventoryCode != KEYITEMS) + if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS) sendInventoryPackets(list[slot]); } @@ -144,13 +144,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player list.Add(addedItem); - if (inventoryCode != CURRANCY && inventoryCode != KEYITEMS) + if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS) sendInventoryPackets(addedItem); quantityCount -= gItem.maxStack; } - if (inventoryCode == CURRANCY || inventoryCode == KEYITEMS) + if (inventoryCode == CURRENCY || inventoryCode == KEYITEMS) sendFullInventory(); owner.queuePacket(InventorySetEndPacket.buildPacket(owner.actorId)); diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index a9d18ee5..27631503 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -43,7 +43,7 @@ namespace FFXIVClassic_Map_Server.lua Script script = new Script(); ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" }; script.Globals["getStaticActor"] = (Func)Server.getStaticActors; - script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor; + script.Globals["getWorldMaster"] = (Func)Server.getWorldManager().GetActor; script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata; script.DoFile(luaPath); DynValue result = script.Call(script.Globals["onInstantiate"], target); @@ -82,9 +82,9 @@ namespace FFXIVClassic_Map_Server.lua { Script script = new Script(); ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" }; - script.Globals["getWorldManager"] = (Func)Server.GetWorldManager; + script.Globals["getWorldManager"] = (Func)Server.getWorldManager; script.Globals["getStaticActor"] = (Func)Server.getStaticActors; - script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor; + script.Globals["getWorldMaster"] = (Func)Server.getWorldManager().GetActor; script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata; script.DoFile(luaPath); @@ -125,9 +125,9 @@ namespace FFXIVClassic_Map_Server.lua { Script script = new Script(); ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" }; - script.Globals["getWorldManager"] = (Func)Server.GetWorldManager; + script.Globals["getWorldManager"] = (Func)Server.getWorldManager; script.Globals["getStaticActor"] = (Func)Server.getStaticActors; - script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor; + script.Globals["getWorldMaster"] = (Func)Server.getWorldManager().GetActor; script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata; script.DoFile(luaPath); @@ -158,9 +158,9 @@ namespace FFXIVClassic_Map_Server.lua { Script script = new Script(); ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" }; - script.Globals["getWorldManager"] = (Func)Server.GetWorldManager; + script.Globals["getWorldManager"] = (Func)Server.getWorldManager; script.Globals["getStaticActor"] = (Func)Server.getStaticActors; - script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor; + script.Globals["getWorldMaster"] = (Func)Server.getWorldManager().GetActor; script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata; script.DoFile(luaPath); @@ -175,9 +175,9 @@ namespace FFXIVClassic_Map_Server.lua { Script script = new Script(); ((ScriptLoaderBase)script.Options.ScriptLoader).ModulePaths = new string[] { "./scripts/?", "./scripts/?.lua" }; - script.Globals["getWorldManager"] = (Func)Server.GetWorldManager; + script.Globals["getWorldManager"] = (Func)Server.getWorldManager; script.Globals["getStaticActor"] = (Func)Server.getStaticActors; - script.Globals["getWorldMaster"] = (Func)Server.GetWorldManager().GetActor; + script.Globals["getWorldMaster"] = (Func)Server.getWorldManager().GetActor; script.Globals["getItemGamedata"] = (Func)Server.getItemGamedata; script.DoFile(FILEPATH_PLAYER);