mirror of
				https://bitbucket.org/Ioncannon/project-meteor-server.git
				synced 2025-05-20 08:26:59 -04:00 
			
		
		
		
	Merge branch 'proxy_server' into develop
# Conflicts: # FFXIVClassic Common Class Lib/packages.config
This commit is contained in:
		| @@ -1,40 +1,25 @@ | ||||
| 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.Common; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_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; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server | ||||
| { | ||||
|     class CommandProcessor | ||||
|     { | ||||
|         private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList; | ||||
|         private static Dictionary<uint, Item> gamedataItems = Server.GetGamedataItems(); | ||||
|  | ||||
|         // 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<uint, ConnectedPlayer> playerList) | ||||
|         { | ||||
|             mConnectedPlayerList = playerList; | ||||
|         } | ||||
|  | ||||
|        | ||||
|         public void ChangeProperty(uint id, uint value, string target) | ||||
|         { | ||||
|             SetActorPropetyPacket ChangeProperty = new SetActorPropetyPacket(target); | ||||
| @@ -43,9 +28,11 @@ namespace FFXIVClassic_Map_Server | ||||
|             ChangeProperty.AddInt(id, value); | ||||
|             ChangeProperty.AddTarget(); | ||||
|  | ||||
|             foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList) | ||||
|             Dictionary<uint, Session> sessionList = Server.GetServer().GetSessionList(); | ||||
|  | ||||
|             foreach (KeyValuePair<uint, Session> entry in sessionList) | ||||
|             { | ||||
|                 SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.actorID), (entry.Value.actorID)); | ||||
|                 SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.id), (entry.Value.id)); | ||||
|  | ||||
|                 BasePacket packet = BasePacket.CreatePacket(ChangePropertyPacket, true, false); | ||||
|                 packet.DebugPrintPacket(); | ||||
| @@ -60,13 +47,13 @@ namespace FFXIVClassic_Map_Server | ||||
|         /// </summary> | ||||
|         /// <param name="client"></param> | ||||
|         /// <param name="message"></param> | ||||
|         private void SendMessage(ConnectedPlayer client, String message) | ||||
|         private void SendMessage(Session session, String message) | ||||
|         { | ||||
|             if (client != null) | ||||
|                client.GetActor().QueuePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message)); | ||||
|             if (session != null) | ||||
|                 session.GetActor().QueuePacket(SendMessagePacket.BuildPacket(session.id, session.id, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message)); | ||||
|         } | ||||
|  | ||||
|         internal bool DoCommand(string input, ConnectedPlayer client) | ||||
|         internal bool DoCommand(string input, Session session) | ||||
|         { | ||||
|             if (!input.Any() || input.Equals("")) | ||||
|                 return false; | ||||
| @@ -88,7 +75,9 @@ namespace FFXIVClassic_Map_Server | ||||
|             if (cmd.Any()) | ||||
|             { | ||||
|                 // if client isnt null, take player to be the player actor | ||||
|                 var player = client?.GetActor(); | ||||
|                 Player player = null; | ||||
|                 if (session != null) | ||||
|                     player = session.GetActor(); | ||||
|  | ||||
|                 if (cmd.Equals("help")) | ||||
|                 { | ||||
| @@ -125,11 +114,11 @@ namespace FFXIVClassic_Map_Server | ||||
|             if (split[0].Equals("reloaditems")) | ||||
|                 { | ||||
|                     Program.Log.Info(String.Format("Got request to reload item gamedata")); | ||||
|                     SendMessage(client, "Reloading Item Gamedata..."); | ||||
|                     SendMessage(session, "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)); | ||||
|                     SendMessage(session, String.Format("Loaded {0} items.", gamedataItems.Count)); | ||||
|                     return true; | ||||
|                 } | ||||
|                 #endregion | ||||
|   | ||||
| @@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server | ||||
|             INIFile configIni = new INIFile("./map_config.ini"); | ||||
|  | ||||
|             ConfigConstants.OPTIONS_BINDIP =        configIni.GetValue("General", "server_ip", "127.0.0.1"); | ||||
|             ConfigConstants.OPTIONS_PORT =          configIni.GetValue("General", "server_port", "54992"); | ||||
|             ConfigConstants.OPTIONS_PORT =          configIni.GetValue("General", "server_port", "1989"); | ||||
|             ConfigConstants.OPTIONS_TIMESTAMP =     configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true"); | ||||
|  | ||||
|             ConfigConstants.DATABASE_WORLDID =      UInt32.Parse(configIni.GetValue("Database", "worldid", "0")); | ||||
|   | ||||
| @@ -5,7 +5,7 @@ using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.utils; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.packets.send.player; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| @@ -258,6 +258,8 @@ namespace FFXIVClassic_Map_Server | ||||
|                     positionY = @y, | ||||
|                     positionZ = @z, | ||||
|                     rotation = @rot, | ||||
|                     destinationZoneId = @destZone, | ||||
|                     destinationSpawnType = @destSpawn, | ||||
|                     currentZoneId = @zoneId | ||||
|                     WHERE id = @charaId | ||||
|                     "; | ||||
| @@ -269,6 +271,8 @@ namespace FFXIVClassic_Map_Server | ||||
|                     cmd.Parameters.AddWithValue("@z", player.positionZ); | ||||
|                     cmd.Parameters.AddWithValue("@rot", player.rotation); | ||||
|                     cmd.Parameters.AddWithValue("@zoneId", player.zoneId); | ||||
|                     cmd.Parameters.AddWithValue("@destZone", player.destinationZone); | ||||
|                     cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType); | ||||
|  | ||||
|                     cmd.ExecuteNonQuery(); | ||||
|                 } | ||||
| @@ -402,7 +406,9 @@ namespace FFXIVClassic_Map_Server | ||||
|                     tribe, | ||||
|                     restBonus, | ||||
|                     achievementPoints, | ||||
|                     playTime | ||||
|                     playTime, | ||||
|                     destinationZoneId, | ||||
|                     destinationSpawnType | ||||
|                     FROM characters WHERE id = @charId";                     | ||||
|  | ||||
|                     cmd = new MySqlCommand(query, conn); | ||||
| @@ -419,8 +425,7 @@ namespace FFXIVClassic_Map_Server | ||||
|                             player.oldRotation = player.rotation = reader.GetFloat(4); | ||||
|                             player.currentMainState = reader.GetUInt16(5); | ||||
|                             player.zoneId = reader.GetUInt32(6); | ||||
|                             player.isZoning = true; | ||||
|                             player.zone = Server.GetWorldManager().GetZone(player.zoneId); | ||||
|                             player.isZoning = true;                             | ||||
|                             player.gcCurrent = reader.GetByte(7); | ||||
|                             player.gcRankLimsa = reader.GetByte(8); | ||||
|                             player.gcRankGridania = reader.GetByte(9); | ||||
| @@ -434,6 +439,13 @@ namespace FFXIVClassic_Map_Server | ||||
|                             player.playerWork.restBonusExpRate = reader.GetInt32(17); | ||||
|                             player.achievementPoints = reader.GetUInt32(18); | ||||
|                             player.playTime = reader.GetUInt32(19); | ||||
|                             player.destinationZone = reader.GetUInt32("destinationZoneId"); | ||||
|                             player.destinationSpawnType = reader.GetByte("destinationSpawnType"); | ||||
|  | ||||
|                             if (player.destinationZone != 0) | ||||
|                                 player.zoneId = player.destinationZone; | ||||
|  | ||||
|                             player.zone = Server.GetWorldManager().GetZone(player.zoneId); | ||||
|                         } | ||||
|                     } | ||||
|                    | ||||
|   | ||||
| @@ -93,7 +93,7 @@ | ||||
|     <Compile Include="actors\quest\Quest.cs" /> | ||||
|     <Compile Include="actors\StaticActors.cs" /> | ||||
|     <Compile Include="actors\world\WorldMaster.cs" /> | ||||
|     <Compile Include="ClientConnection.cs" /> | ||||
|     <Compile Include="dataobjects\ZoneConnection.cs" /> | ||||
|     <Compile Include="CommandProcessor.cs" /> | ||||
|     <Compile Include="ConfigConstants.cs" /> | ||||
|     <Compile Include="Database.cs" /> | ||||
| @@ -112,7 +112,7 @@ | ||||
|     <Compile Include="actors\chara\player\PlayerWork.cs" /> | ||||
|     <Compile Include="dataobjects\DBWorld.cs" /> | ||||
|     <Compile Include="dataobjects\InventoryItem.cs" /> | ||||
|     <Compile Include="dataobjects\ConnectedPlayer.cs" /> | ||||
|     <Compile Include="dataobjects\Session.cs" /> | ||||
|     <Compile Include="dataobjects\Item.cs" /> | ||||
|     <Compile Include="dataobjects\RecruitmentDetails.cs" /> | ||||
|     <Compile Include="dataobjects\SeamlessBoundry.cs" /> | ||||
| @@ -124,7 +124,6 @@ | ||||
|     <Compile Include="lua\LuaPlayer.cs" /> | ||||
|     <Compile Include="lua\LuaScript.cs" /> | ||||
|     <Compile Include="PacketProcessor.cs" /> | ||||
|     <Compile Include="packets\BasePacket.cs" /> | ||||
|     <Compile Include="packets\receive\ChatMessagePacket.cs" /> | ||||
|     <Compile Include="packets\receive\events\EventUpdatePacket.cs" /> | ||||
|     <Compile Include="packets\receive\events\EventStartPacket.cs" /> | ||||
| @@ -258,9 +257,13 @@ | ||||
|     <Compile Include="packets\send\_0x02Packet.cs" /> | ||||
|     <Compile Include="packets\send\_0x10Packet.cs" /> | ||||
|     <Compile Include="packets\send\_0xE2Packet.cs" /> | ||||
|     <Compile Include="packets\SubPacket.cs" /> | ||||
|     <Compile Include="packets\receive\PingPacket.cs" /> | ||||
|     <Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" /> | ||||
|     <Compile Include="packets\WorldPackets\Receive\ErrorPacket.cs" /> | ||||
|     <Compile Include="packets\WorldPackets\Receive\SessionEndPacket.cs" /> | ||||
|     <Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" /> | ||||
|     <Compile Include="packets\WorldPackets\Send\SessionBeginConfirmPacket.cs" /> | ||||
|     <Compile Include="packets\WorldPackets\Send\SessionEndConfirmPacket.cs" /> | ||||
|     <Compile Include="Program.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="lua\LuaUtils.cs" /> | ||||
| @@ -286,6 +289,7 @@ | ||||
|       <SubType>Designer</SubType> | ||||
|     </None> | ||||
|     <None Include="packages.config" /> | ||||
|     <Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <EmbeddedResource Include="Properties\Resources.resx"> | ||||
|   | ||||
| @@ -38,13 +38,13 @@ | ||||
|     <target xsi:type="ColoredConsole" name="packets" | ||||
|             layout="${message}"> | ||||
|       <highlight-row | ||||
|         condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.BasePacket') and equals('${event-context:item=color}', '6')" | ||||
|         condition="equals('${logger}', 'FFXIVClassic.Common.BasePacket') and equals('${event-context:item=color}', '6')" | ||||
|         backgroundColor="DarkYellow" foregroundColor="NoChange" /> | ||||
|       <highlight-row | ||||
|         condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '4')" | ||||
|         condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '4')" | ||||
|         backgroundColor="DarkRed" foregroundColor="NoChange" /> | ||||
|       <highlight-row | ||||
|         condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '5')" | ||||
|         condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '5')" | ||||
|         backgroundColor="DarkMagenta" foregroundColor="NoChange" /> | ||||
|     </target> | ||||
|   </targets> | ||||
| @@ -55,6 +55,7 @@ | ||||
|     <logger name='FFXIVClassic_Map_Server.Program' minlevel='Trace' writeTo='console' /> | ||||
|     <logger name='FFXIVClassic_Map_Server.lua.*' minlevel='Trace' writeTo='console' /> | ||||
|     <logger name='FFXIVClassic_Map_Server.packets.*' minlevel='Debug' writeTo='packets' /> | ||||
|     <logger name='FFXIVClassic.Common.*' minlevel='Debug' writeTo='packets' /> | ||||
|     <!-- | ||||
|     Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f" | ||||
|     <logger name="*" minlevel="Debug" writeTo="f" /> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| @@ -17,402 +17,319 @@ using FFXIVClassic_Map_Server.packets.receive.recruitment; | ||||
| using FFXIVClassic_Map_Server.packets.send.recruitment; | ||||
| using FFXIVClassic_Map_Server.packets.receive.events; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.packets.WorldPackets.Send; | ||||
| using FFXIVClassic_Map_Server.packets.WorldPackets.Receive; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server | ||||
| { | ||||
|     class PacketProcessor | ||||
|     { | ||||
|         Server mServer; | ||||
|         CommandProcessor cp; | ||||
|         Dictionary<uint, ConnectedPlayer> mPlayers; | ||||
|         List<ClientConnection> mConnections; | ||||
|  | ||||
|         public PacketProcessor(Server server, Dictionary<uint, ConnectedPlayer> playerList, List<ClientConnection> connectionList) | ||||
|         public PacketProcessor(Server server) | ||||
|         { | ||||
|             mPlayers = playerList; | ||||
|             mConnections = connectionList; | ||||
|             mServer = server; | ||||
|             cp = new CommandProcessor(playerList); | ||||
|         }      | ||||
|  | ||||
|         public void ProcessPacket(ClientConnection client, BasePacket packet) | ||||
|         {                       | ||||
|             if (packet.header.isCompressed == 0x01)                        | ||||
|                 BasePacket.DecryptPacket(client.blowfish, ref packet); | ||||
|         public void ProcessPacket(ZoneConnection client, SubPacket subpacket) | ||||
|         {                           | ||||
|                 Session session = mServer.GetSession(subpacket.header.targetId); | ||||
|  | ||||
|                 if (session == null && subpacket.gameMessage.opcode != 0x1000) | ||||
|                     return; | ||||
|  | ||||
|             List<SubPacket> subPackets = packet.GetSubpackets(); | ||||
|             foreach (SubPacket subpacket in subPackets) | ||||
|             { | ||||
|                 if (subpacket.header.type == 0x01) | ||||
|                 {                  | ||||
|                     packet.DebugPrintPacket(); | ||||
|                     byte[] reply1Data = { | ||||
|                                             0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
|                                             0x18, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFD, 0xFF, 0xFF, | ||||
|                                             0xE5, 0x6E, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x0 | ||||
|                                         }; | ||||
|  | ||||
|                     byte[] reply2Data = { | ||||
|                                             0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
|                                             0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2B, 0x5F, 0x26, | ||||
|                                             0x66, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xAF, 0x2B, 0x38, 0x2B, 0x5F, 0x26, 0xB8, 0x8D, 0xF0, 0x2B, | ||||
|                                             0xC8, 0xFD, 0x85, 0xFE, 0xA8, 0x7C, 0x5B, 0x09, 0x38, 0x2B, 0x5F, 0x26, 0xC8, 0xD6, 0xAF, 0x2B, | ||||
|                                             0xB8, 0x8D, 0xF0, 0x2B, 0x88, 0xAF, 0x5E, 0x26 | ||||
|                                         }; | ||||
|  | ||||
|                     BasePacket reply1 = new BasePacket(reply1Data); | ||||
|                     BasePacket reply2 = new BasePacket(reply2Data); | ||||
|  | ||||
|                     //Write Timestamp into Reply1 | ||||
|                     using (MemoryStream mem = new MemoryStream(reply1.data)) | ||||
|                     { | ||||
|                         using (BinaryWriter binReader = new BinaryWriter(mem)) | ||||
|                         { | ||||
|                             binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); | ||||
|                             binReader.Write((UInt32)Utils.UnixTimeStampUTC()); | ||||
|                         } | ||||
|                     }                    | ||||
|  | ||||
|                     //Read in Actor Id that owns this connection | ||||
|                     uint actorID = 0; | ||||
|                     using (MemoryStream mem = new MemoryStream(packet.data)) | ||||
|                     { | ||||
|                         using (BinaryReader binReader = new BinaryReader(mem)) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 byte[] readIn = new byte[12]; | ||||
|                                 binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); | ||||
|                                 binReader.Read(readIn, 0, 12); | ||||
|                                 actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn)); | ||||
|                             } | ||||
|                             catch (Exception) | ||||
|                             { } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     //Should never happen.... unless actor id IS 0! | ||||
|                     if (actorID == 0) | ||||
|                 //Normal Game Opcode | ||||
|                 switch (subpacket.gameMessage.opcode) | ||||
|                 { | ||||
|                     //World Server - Error | ||||
|                     case 0x100A: | ||||
|                         ErrorPacket worldError = new ErrorPacket(subpacket.data); | ||||
|                         switch (worldError.errorCode) | ||||
|                         { | ||||
|                             case 0x01: | ||||
|                                 session.GetActor().SendGameMessage(Server.GetWorldManager().GetActor(), 60005, 0x20); | ||||
|                                 break; | ||||
|                         } | ||||
|                         break; | ||||
|                     //World Server - Session Begin | ||||
|                     case 0x1000: | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         session = mServer.AddSession(subpacket.header.targetId); | ||||
|  | ||||
|                         if (session.GetActor().destinationZone != 0) | ||||
|                             Server.GetWorldManager().DoZoneIn(session.GetActor(), false, session.GetActor().destinationSpawnType); | ||||
|  | ||||
|                         Program.Log.Info("{0} has been added to the session list.", session.GetActor().customDisplayName); | ||||
|  | ||||
|                         client.FlushQueuedSendPackets(); | ||||
|                         break; | ||||
|                     //World Server - Session End | ||||
|                     case 0x1001: | ||||
|                         SessionEndPacket endSessionPacket = new SessionEndPacket(subpacket.data); | ||||
|  | ||||
|                         if (endSessionPacket.destinationZoneId == 0) | ||||
|                             session.GetActor().CleanupAndSave(); | ||||
|                         else                         | ||||
|                             session.GetActor().CleanupAndSave(endSessionPacket.destinationZoneId, endSessionPacket.destinationSpawnType, endSessionPacket.destinationX, endSessionPacket.destinationY, endSessionPacket.destinationZ, endSessionPacket.destinationRot); | ||||
|  | ||||
|                         Server.GetServer().RemoveSession(session.id); | ||||
|                         Program.Log.Info("{0} has been removed from the session list.", session.GetActor().customDisplayName); | ||||
|  | ||||
|                         client.QueuePacket(SessionEndConfirmPacket.BuildPacket(session, endSessionPacket.destinationZoneId), true, false); | ||||
|                         client.FlushQueuedSendPackets(); | ||||
|                         break;                              | ||||
|                     //Ping | ||||
|                     case 0x0001: | ||||
|                         //subpacket.DebugPrintSubPacket(); | ||||
|                         PingPacket pingPacket = new PingPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(session.id, pingPacket.time), true, false)); | ||||
|                         session.Ping(); | ||||
|                         break; | ||||
|                     //Unknown | ||||
|                     case 0x0002: | ||||
|  | ||||
|                     client.owner = actorID; | ||||
|                    | ||||
|                     //Write Actor ID into reply2 | ||||
|                     using (MemoryStream mem = new MemoryStream(reply2.data)) | ||||
|                     { | ||||
|                         using (BinaryWriter binReader = new BinaryWriter(mem)) | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         session = mServer.AddSession(subpacket.header.targetId); | ||||
|                         client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false); | ||||
|  | ||||
|                         LuaEngine.OnBeginLogin(session.GetActor()); | ||||
|                         Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1); | ||||
|                         LuaEngine.OnLogin(session.GetActor()); | ||||
|  | ||||
|                         client.FlushQueuedSendPackets(); | ||||
|  | ||||
|                         break; | ||||
|                     //Chat Received | ||||
|                     case 0x0003: | ||||
|                         ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data); | ||||
|                         Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType); | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|  | ||||
|                         if (chatMessage.message.StartsWith("!")) | ||||
|                         { | ||||
|                             binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); | ||||
|                             binReader.Write(actorID); | ||||
|                         } | ||||
|                     } | ||||
|                             if (Server.GetCommandProcessor().DoCommand(chatMessage.message, session)) | ||||
|                                 return; ; | ||||
|                         } | ||||
|  | ||||
|                         session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false); | ||||
|  | ||||
|                     ConnectedPlayer player = null; | ||||
|  | ||||
|                     if (packet.header.connectionType == BasePacket.TYPE_ZONE) | ||||
|                     { | ||||
|                         while (mPlayers != null && !mPlayers.ContainsKey(client.owner)) | ||||
|                         { } | ||||
|                         player = mPlayers[client.owner]; | ||||
|                     } | ||||
|  | ||||
|                     //Create connected player if not Created | ||||
|                     if (player == null) | ||||
|                     {  | ||||
|                         player = new ConnectedPlayer(actorID); | ||||
|                         mPlayers[actorID] = player; | ||||
|                     } | ||||
|                      | ||||
|                     player.SetConnection(packet.header.connectionType, client); | ||||
|  | ||||
|                     if (packet.header.connectionType == BasePacket.TYPE_ZONE) | ||||
|                         Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.GetAddress()); | ||||
|                     else if (packet.header.connectionType == BasePacket.TYPE_CHAT) | ||||
|                         Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.GetAddress()); | ||||
|  | ||||
|                     //Create player actor | ||||
|                     reply1.DebugPrintPacket(); | ||||
|                     client.QueuePacket(reply1); | ||||
|                     client.QueuePacket(reply2); | ||||
|                     break; | ||||
|                 } | ||||
|                 else if (subpacket.header.type == 0x07) | ||||
|                 { | ||||
|                     BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x08); | ||||
|                     //client.QueuePacket(init); | ||||
|                 } | ||||
|                 else if (subpacket.header.type == 0x08) | ||||
|                 { | ||||
|                     //Response, client's current [actorID][time] | ||||
|                     //BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x07); | ||||
|                     //client.QueuePacket(init); | ||||
|                     packet.DebugPrintPacket(); | ||||
|                 } | ||||
|                 else if (subpacket.header.type == 0x03) | ||||
|                 { | ||||
|                     ConnectedPlayer player = null; | ||||
|  | ||||
|                     if(mPlayers.ContainsKey(client.owner)) | ||||
|                         player = mPlayers[client.owner]; | ||||
|  | ||||
|                     if (player == null || !player.IsClientConnectionsReady()) | ||||
|                         return; | ||||
|  | ||||
|                     //Normal Game Opcode | ||||
|                     switch (subpacket.gameMessage.opcode) | ||||
|                     { | ||||
|                         //Ping | ||||
|                         case 0x0001: | ||||
|                             //subpacket.DebugPrintSubPacket(); | ||||
|                             PingPacket pingPacket = new PingPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false)); | ||||
|                             player.Ping(); | ||||
|                             break; | ||||
|                         //Unknown | ||||
|                         case 0x0002: | ||||
|  | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|                             client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false); | ||||
|  | ||||
|                             Server.GetWorldManager().DoLogin(player.GetActor()); | ||||
|  | ||||
|  | ||||
|                             break; | ||||
|                         //Chat Received | ||||
|                         case 0x0003: | ||||
|                             ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data); | ||||
|                             Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType); | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|  | ||||
|                             if (chatMessage.message.StartsWith("!")) | ||||
|                             { | ||||
|                                 if (cp.DoCommand(chatMessage.message, player)) | ||||
|                                     continue; | ||||
|                             }                            | ||||
|  | ||||
|                             player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false); | ||||
|  | ||||
|                             break; | ||||
|                         //Langauge Code | ||||
|                         case 0x0006: | ||||
|                             LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data); | ||||
|                             player.languageCode = langCode.languageCode; | ||||
|                             break; | ||||
|                         //Unknown - Happens a lot at login, then once every time player zones | ||||
|                         case 0x0007: | ||||
|                             //subpacket.DebugPrintSubPacket(); | ||||
|                             _0x07Packet unknown07 = new _0x07Packet(subpacket.data); | ||||
|                             break; | ||||
|                         break; | ||||
|                     //Langauge Code | ||||
|                     case 0x0006: | ||||
|                         LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data); | ||||
|                         session.languageCode = langCode.languageCode; | ||||
|                         break; | ||||
|                     //Unknown - Happens a lot at login, then once every time player zones | ||||
|                     case 0x0007: | ||||
|                         //subpacket.DebugPrintSubPacket(); | ||||
|                         _0x07Packet unknown07 = new _0x07Packet(subpacket.data); | ||||
|                         break; | ||||
|                     //Update Position | ||||
|                     case 0x00CA: | ||||
|                         //Update Position | ||||
|                         case 0x00CA: | ||||
|                             //Update Position | ||||
|                             //subpacket.DebugPrintSubPacket(); | ||||
|                             UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); | ||||
|                             player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); | ||||
|                             player.GetActor().SendInstanceUpdate(); | ||||
|                         UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); | ||||
|                         session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); | ||||
|                         session.GetActor().SendInstanceUpdate(); | ||||
|  | ||||
|                         if (session.GetActor().IsInZoneChange()) | ||||
|                             session.GetActor().SetZoneChanging(false); | ||||
|  | ||||
|                         break; | ||||
|                     //Set Target  | ||||
|                     case 0x00CD: | ||||
|                         //subpacket.DebugPrintSubPacket(); | ||||
|  | ||||
|                         SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); | ||||
|                         session.GetActor().currentTarget = setTarget.actorID; | ||||
|                         session.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(session.id, session.id, setTarget.actorID), true); | ||||
|                         break; | ||||
|                     //Lock Target | ||||
|                     case 0x00CC: | ||||
|                         LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); | ||||
|                         session.GetActor().currentLockedTarget = lockTarget.actorID; | ||||
|                         break; | ||||
|                     //Start Event | ||||
|                     case 0x012D: | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         EventStartPacket eventStart = new EventStartPacket(subpacket.data); | ||||
|  | ||||
|                         /* | ||||
|                         if (eventStart.error != null) | ||||
|                         { | ||||
|                             player.errorMessage += eventStart.error; | ||||
|  | ||||
|                             if (eventStart.errorIndex == eventStart.errorNum - 1) | ||||
|                                 Program.Log.Error("\n"+player.errorMessage); | ||||
|  | ||||
|                             if (player.GetActor().IsInZoneChange()) | ||||
|                                 player.GetActor().SetZoneChanging(false); | ||||
|  | ||||
|                             break; | ||||
|                         //Set Target  | ||||
|                         case 0x00CD: | ||||
|                             //subpacket.DebugPrintSubPacket(); | ||||
|                         } | ||||
|                         */ | ||||
|  | ||||
|                             SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); | ||||
|                             player.GetActor().currentTarget = setTarget.actorID; | ||||
|                             player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true); | ||||
|                             break; | ||||
|                         //Lock Target | ||||
|                         case 0x00CC: | ||||
|                             LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); | ||||
|                             player.GetActor().currentLockedTarget = lockTarget.actorID; | ||||
|                             break; | ||||
|                         //Start Event | ||||
|                         case 0x012D: | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|                             EventStartPacket eventStart = new EventStartPacket(subpacket.data); | ||||
|  | ||||
|                             /* | ||||
|                             if (eventStart.error != null) | ||||
|                             { | ||||
|                                 player.errorMessage += eventStart.error; | ||||
|  | ||||
|                                 if (eventStart.errorIndex == eventStart.errorNum - 1) | ||||
|                                     Program.Log.Error("\n"+player.errorMessage); | ||||
|  | ||||
|  | ||||
|                                 break; | ||||
|                             } | ||||
|                             */ | ||||
|  | ||||
|                             Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID); | ||||
|                         Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID); | ||||
|                              | ||||
|                       | ||||
|                             player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID; | ||||
|                             player.GetActor().currentEventName = eventStart.triggerName; | ||||
|                         session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID; | ||||
|                         session.GetActor().currentEventName = eventStart.triggerName; | ||||
|                      | ||||
|  | ||||
|                         if (ownerActor == null) | ||||
|                         { | ||||
|                             //Is it a instance actor? | ||||
|                             ownerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner); | ||||
|                             if (ownerActor == null) | ||||
|                             { | ||||
|                                 //Is it a instance actor? | ||||
|                                 ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner); | ||||
|                                 if (ownerActor == null) | ||||
|                                 //Is it a Director? | ||||
|                                 if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId) | ||||
|                                     ownerActor = session.GetActor().currentDirector; | ||||
|                                 else | ||||
|                                 { | ||||
|                                     //Is it a Director? | ||||
|                                     if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId) | ||||
|                                         ownerActor = player.GetActor().currentDirector; | ||||
|                                     else | ||||
|                                     { | ||||
|                                         Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams)); | ||||
|                                         break; | ||||
|                                     } | ||||
|                                 }                                     | ||||
|                             } | ||||
|  | ||||
|                             player.GetActor().StartEvent(ownerActor, eventStart); | ||||
|  | ||||
|                             Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams)); | ||||
|                             break; | ||||
|                         //Unknown, happens at npc spawn and cutscene play???? | ||||
|                         case 0x00CE: | ||||
|                             break; | ||||
|                         //Event Result | ||||
|                         case 0x012E: | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|                             EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data); | ||||
|                             Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams)); | ||||
|                             /* | ||||
|                             //Is it a static actor? If not look in the player's instance | ||||
|                             Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner); | ||||
|                             if (updateOwnerActor == null) | ||||
|                             { | ||||
|                                 updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner); | ||||
|  | ||||
|                                 if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId) | ||||
|                                     updateOwnerActor = player.GetActor().currentDirector; | ||||
|  | ||||
|                                 if (updateOwnerActor == null) | ||||
|                                     Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams)); | ||||
|                                     break; | ||||
|                             } | ||||
|                             */ | ||||
|                             player.GetActor().UpdateEvent(eventUpdate); | ||||
|                                 } | ||||
|                             }                                     | ||||
|                         } | ||||
|  | ||||
|                             //LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate); | ||||
|                         session.GetActor().StartEvent(ownerActor, eventStart); | ||||
|  | ||||
|                         Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams)); | ||||
|                         break; | ||||
|                     //Unknown, happens at npc spawn and cutscene play???? | ||||
|                     case 0x00CE: | ||||
|                         break; | ||||
|                     //Event Result | ||||
|                     case 0x012E: | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data); | ||||
|                         Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams)); | ||||
|                         /* | ||||
|                         //Is it a static actor? If not look in the player's instance | ||||
|                         Actor updateOwnerActor = Server.GetStaticActors(session.GetActor().currentEventOwner); | ||||
|                         if (updateOwnerActor == null) | ||||
|                         { | ||||
|                             updateOwnerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner); | ||||
|  | ||||
|                             if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId) | ||||
|                                 updateOwnerActor = session.GetActor().currentDirector; | ||||
|  | ||||
|                             if (updateOwnerActor == null) | ||||
|                                 break; | ||||
|                         } | ||||
|                         */ | ||||
|                         session.GetActor().UpdateEvent(eventUpdate); | ||||
|  | ||||
|                         //LuaEngine.DoActorOnEventUpdated(session.GetActor(), updateOwnerActor, eventUpdate); | ||||
|                              | ||||
|                             break; | ||||
|                         case 0x012F: | ||||
|                             //subpacket.DebugPrintSubPacket(); | ||||
|                             ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data); | ||||
|                             if (paramRequest.paramName.Equals("charaWork/exp")) | ||||
|                                 player.GetActor().SendCharaExpInfo(); | ||||
|                             break; | ||||
|                         /* RECRUITMENT */ | ||||
|                         //Start Recruiting | ||||
|                         case 0x01C3: | ||||
|                             StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false)); | ||||
|                             break; | ||||
|                         //End Recruiting | ||||
|                         case 0x01C4: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false)); | ||||
|                             break; | ||||
|                         //Party Window Opened, Request State | ||||
|                         case 0x01C5: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false)); | ||||
|                             break; | ||||
|                         //Search Recruiting | ||||
|                         case 0x01C7: | ||||
|                             RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data); | ||||
|                             break; | ||||
|                         //Get Recruitment Details | ||||
|                         case 0x01C8: | ||||
|                             RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data); | ||||
|                             RecruitmentDetails details = new RecruitmentDetails(); | ||||
|                             details.recruiterName = "Localhost Character"; | ||||
|                             details.purposeId = 2; | ||||
|                             details.locationId = 1; | ||||
|                             details.subTaskId = 1; | ||||
|                             details.comment = "This is a test details packet sent by the server. No implementation has been Created yet..."; | ||||
|                             details.num[0] = 1; | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false)); | ||||
|                             break; | ||||
|                         //Accepted Recruiting | ||||
|                         case 0x01C6: | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|                             break; | ||||
|                         /* SOCIAL STUFF */ | ||||
|                         case 0x01C9: | ||||
|                             AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(player.actorID, true, addBlackList.name), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CA: | ||||
|                             AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CB: | ||||
|                             int offset1 = 0; | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CC: | ||||
|                             AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CD: | ||||
|                             AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CE: | ||||
|                             int offset2 = 0; | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(player.actorID, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2), true, false)); | ||||
|                             break; | ||||
|                         case 0x01CF: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false)); | ||||
|                             break; | ||||
|                         /* SUPPORT DESK STUFF */ | ||||
|                         //Request for FAQ/Info List | ||||
|                         case 0x01D0: | ||||
|                             FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false)); | ||||
|                             break; | ||||
|                         //Request for body of a faq/info selection | ||||
|                         case 0x01D1: | ||||
|                             FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, "HERE IS A GIANT BODY. Nothing else to say!"), true, false)); | ||||
|                             break; | ||||
|                         //Request issue list | ||||
|                         case 0x01D2: | ||||
|                             GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false)); | ||||
|                             break; | ||||
|                         //Request if GM ticket exists | ||||
|                         case 0x01D3: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, false), true, false)); | ||||
|                             break; | ||||
|                         //Request for GM response message | ||||
|                         case 0x01D4: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false)); | ||||
|                             break; | ||||
|                         //GM Ticket Sent | ||||
|                         case 0x01D5: | ||||
|                             GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); | ||||
|                             Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false)); | ||||
|                             break; | ||||
|                         //Request to end ticket | ||||
|                         case 0x01D6: | ||||
|                             client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false)); | ||||
|                             break; | ||||
|                         default: | ||||
|                             Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode); | ||||
|                             subpacket.DebugPrintSubPacket(); | ||||
|                             break; | ||||
|                     } | ||||
|                         break; | ||||
|                     case 0x012F: | ||||
|                         //subpacket.DebugPrintSubPacket(); | ||||
|                         ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data); | ||||
|                         if (paramRequest.paramName.Equals("charaWork/exp")) | ||||
|                             session.GetActor().SendCharaExpInfo(); | ||||
|                         break; | ||||
|                     /* RECRUITMENT */ | ||||
|                     //Start Recruiting | ||||
|                     case 0x01C3: | ||||
|                         StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(session.id, true), true, false)); | ||||
|                         break; | ||||
|                     //End Recruiting | ||||
|                     case 0x01C4: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(session.id), true, false)); | ||||
|                         break; | ||||
|                     //Party Window Opened, Request State | ||||
|                     case 0x01C5: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(session.id, true, true, 1), true, false)); | ||||
|                         break; | ||||
|                     //Search Recruiting | ||||
|                     case 0x01C7: | ||||
|                         RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data); | ||||
|                         break; | ||||
|                     //Get Recruitment Details | ||||
|                     case 0x01C8: | ||||
|                         RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data); | ||||
|                         RecruitmentDetails details = new RecruitmentDetails(); | ||||
|                         details.recruiterName = "Localhost Character"; | ||||
|                         details.purposeId = 2; | ||||
|                         details.locationId = 1; | ||||
|                         details.subTaskId = 1; | ||||
|                         details.comment = "This is a test details packet sent by the server. No implementation has been Created yet..."; | ||||
|                         details.num[0] = 1; | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(session.id, details), true, false)); | ||||
|                         break; | ||||
|                     //Accepted Recruiting | ||||
|                     case 0x01C6: | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         break; | ||||
|                     /* SOCIAL STUFF */ | ||||
|                     case 0x01C9: | ||||
|                         AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(session.id, true, addBlackList.name), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CA: | ||||
|                         AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(session.id, true, RemoveBlackList.name), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CB: | ||||
|                         int offset1 = 0; | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(session.id, new String[] { "Test" }, ref offset1), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CC: | ||||
|                         AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(session.id, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CD: | ||||
|                         AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(session.id, true, RemoveFriendList.name), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CE: | ||||
|                         int offset2 = 0; | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(session.id, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2), true, false)); | ||||
|                         break; | ||||
|                     case 0x01CF: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(session.id, null), true, false)); | ||||
|                         break; | ||||
|                     /* SUPPORT DESK STUFF */ | ||||
|                     //Request for FAQ/Info List | ||||
|                     case 0x01D0: | ||||
|                         FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(session.id, new string[] { "Testing FAQ1", "Coded style!" }), true, false)); | ||||
|                         break; | ||||
|                     //Request for body of a faq/info selection | ||||
|                     case 0x01D1: | ||||
|                         FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(session.id, "HERE IS A GIANT BODY. Nothing else to say!"), true, false)); | ||||
|                         break; | ||||
|                     //Request issue list | ||||
|                     case 0x01D2: | ||||
|                         GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(session.id, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false)); | ||||
|                         break; | ||||
|                     //Request if GM ticket exists | ||||
|                     case 0x01D3: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(session.id, false), true, false)); | ||||
|                         break; | ||||
|                     //Request for GM response message | ||||
|                     case 0x01D4: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(session.id, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false)); | ||||
|                         break; | ||||
|                     //GM Ticket Sent | ||||
|                     case 0x01D5: | ||||
|                         GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); | ||||
|                         Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(session.id, true), true, false)); | ||||
|                         break; | ||||
|                     //Request to end ticket | ||||
|                     case 0x01D6: | ||||
|                         client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(session.id), true, false)); | ||||
|                         break; | ||||
|                     default: | ||||
|                         Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode); | ||||
|                         subpacket.DebugPrintSubPacket(); | ||||
|                         break; | ||||
|                 } | ||||
|                 else | ||||
|                     packet.DebugPrintPacket(); | ||||
|             } | ||||
|              | ||||
|         }         | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -63,14 +63,14 @@ namespace FFXIVClassic_Map_Server | ||||
|             if (startServer) | ||||
|             { | ||||
|                 Server server = new Server(); | ||||
|                 CommandProcessor cp = new CommandProcessor(server.GetConnectedPlayerList()); | ||||
|                  | ||||
|                 server.StartServer(); | ||||
|  | ||||
|                 while (startServer) | ||||
|                 { | ||||
|                     String input = Console.ReadLine(); | ||||
|                     Log.Info("[Console Input] " + input); | ||||
|                     cp.DoCommand(input, null); | ||||
|                     Server.GetCommandProcessor().DoCommand(input, null); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -2,11 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using System.Threading; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using NLog; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
|  | ||||
| @@ -17,7 +15,6 @@ namespace FFXIVClassic_Map_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 HEALTH_THREAD_SLEEP_TIME = 5; | ||||
|  | ||||
|         public const string STATIC_ACTORS_PATH = "./staticactors.bin"; | ||||
|  | ||||
| @@ -25,60 +22,28 @@ namespace FFXIVClassic_Map_Server | ||||
|  | ||||
|         private Socket mServerSocket; | ||||
|  | ||||
|         private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>(); | ||||
|         private List<ClientConnection> mConnectionList = new List<ClientConnection>(); | ||||
|         private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();         | ||||
|         private LuaEngine mLuaEngine = new LuaEngine(); | ||||
|  | ||||
|         private static CommandProcessor mCommandProcessor = new CommandProcessor(); | ||||
|         private static ZoneConnection mWorldConnection = new ZoneConnection(); | ||||
|         private static WorldManager mWorldManager; | ||||
|         private static Dictionary<uint, Item> gamedataItems; | ||||
|         private static Dictionary<uint, Item> mGamedataItems; | ||||
|         private static StaticActors mStaticActors; | ||||
|  | ||||
|         private PacketProcessor mProcessor; | ||||
|  | ||||
|         private Thread mConnectionHealthThread; | ||||
|         private bool killHealthThread = false; | ||||
|  | ||||
|         private void ConnectionHealth() | ||||
|         { | ||||
|             Program.Log.Info("Connection Health thread started; it will run every {0} seconds.", HEALTH_THREAD_SLEEP_TIME); | ||||
|             while (!killHealthThread) | ||||
|             { | ||||
|                 lock (mConnectedPlayerList) | ||||
|                 { | ||||
|                     List<ConnectedPlayer> dcedPlayers = new List<ConnectedPlayer>(); | ||||
|                     foreach (ConnectedPlayer cp in mConnectedPlayerList.Values) | ||||
|                     { | ||||
|                         if (cp.CheckIfDCing()) | ||||
|                             dcedPlayers.Add(cp); | ||||
|                     } | ||||
|  | ||||
|                     foreach (ConnectedPlayer cp in dcedPlayers) | ||||
|                         cp.GetActor().CleanupAndSave(); | ||||
|                 } | ||||
|                 Thread.Sleep(HEALTH_THREAD_SLEEP_TIME * 1000); | ||||
|             } | ||||
|         } | ||||
|         private PacketProcessor mProcessor;         | ||||
|  | ||||
|         public Server() | ||||
|         { | ||||
|             mSelf = this; | ||||
|         } | ||||
|  | ||||
|         public static Server GetServer() | ||||
|         { | ||||
|             return mSelf; | ||||
|         } | ||||
|  | ||||
|          | ||||
|         public bool StartServer() | ||||
|         { | ||||
|             mConnectionHealthThread = new Thread(new ThreadStart(ConnectionHealth)); | ||||
|             mConnectionHealthThread.Name = "MapThread:Health"; | ||||
|             //mConnectionHealthThread.Start(); | ||||
|  | ||||
|         {            | ||||
|             mStaticActors = new StaticActors(STATIC_ACTORS_PATH); | ||||
|  | ||||
|             gamedataItems = Database.GetItemGamedata(); | ||||
|             Program.Log.Info("Loaded {0} items.", gamedataItems.Count); | ||||
|             mGamedataItems = Database.GetItemGamedata(); | ||||
|             Program.Log.Info("Loaded {0} items.", mGamedataItems.Count); | ||||
|  | ||||
|             mWorldManager = new WorldManager(this); | ||||
|             mWorldManager.LoadZoneList(); | ||||
| @@ -88,11 +53,11 @@ namespace FFXIVClassic_Map_Server | ||||
|             mWorldManager.LoadSpawnLocations(); | ||||
|             mWorldManager.SpawnAllActors(); | ||||
|  | ||||
|             IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT)); | ||||
|             IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT)); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|                 mServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
| @@ -120,40 +85,73 @@ namespace FFXIVClassic_Map_Server | ||||
|             Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port); | ||||
|             Console.ForegroundColor = ConsoleColor.Gray; | ||||
|  | ||||
|             mProcessor = new PacketProcessor(this, mConnectedPlayerList, mConnectionList); | ||||
|             mProcessor = new PacketProcessor(this); | ||||
|  | ||||
|             //mGameThread = new Thread(new ThreadStart(mProcessor.update)); | ||||
|             //mGameThread.Start(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         public void RemovePlayer(Player player) | ||||
|         #region Session Handling | ||||
|  | ||||
|         public Session AddSession(uint id) | ||||
|         { | ||||
|             lock (mConnectedPlayerList) | ||||
|             if (mSessionList.ContainsKey(id)) | ||||
|                 return mSessionList[id]; | ||||
|  | ||||
|             Session session = new Session(id); | ||||
|             mSessionList.Add(id, session); | ||||
|             return session; | ||||
|         } | ||||
|  | ||||
|         public void RemoveSession(uint id) | ||||
|         { | ||||
|             if (mSessionList.ContainsKey(id)) | ||||
|             { | ||||
|                 if (mConnectedPlayerList.ContainsKey(player.actorId)) | ||||
|                     mConnectedPlayerList.Remove(player.actorId); | ||||
|                 mSessionList.Remove(id);                 | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public Session GetSession(uint id) | ||||
|         { | ||||
|             if (mSessionList.ContainsKey(id)) | ||||
|                 return mSessionList[id]; | ||||
|             else | ||||
|                 return null; | ||||
|         } | ||||
|  | ||||
|         public Session GetSession(string name) | ||||
|         { | ||||
|             foreach (Session s in mSessionList.Values) | ||||
|             { | ||||
|                 if (s.GetActor().customDisplayName.ToLower().Equals(name.ToLower())) | ||||
|                     return s; | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public Dictionary<uint, Session> GetSessionList() | ||||
|         { | ||||
|             return mSessionList; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region Socket Handling | ||||
|         private void AcceptCallback(IAsyncResult result) | ||||
|         { | ||||
|             ClientConnection conn = null; | ||||
|             ZoneConnection conn = null; | ||||
|             Socket socket = (System.Net.Sockets.Socket)result.AsyncState; | ||||
|  | ||||
|             try | ||||
|             { | ||||
|  | ||||
|                 conn = new ClientConnection(); | ||||
|                 conn = new ZoneConnection(); | ||||
|                 conn.socket = socket.EndAccept(result); | ||||
|                 conn.buffer = new byte[BUFFER_SIZE]; | ||||
|  | ||||
|                 lock (mConnectionList) | ||||
|                 { | ||||
|                     mConnectionList.Add(conn); | ||||
|                 } | ||||
|  | ||||
|                 mWorldConnection = conn; | ||||
|                  | ||||
|                 Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port); | ||||
|                 //Queue recieving of data from the connection | ||||
|                 conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn); | ||||
| @@ -164,11 +162,7 @@ namespace FFXIVClassic_Map_Server | ||||
|             { | ||||
|                 if (conn != null) | ||||
|                 { | ||||
|  | ||||
|                     lock (mConnectionList) | ||||
|                     { | ||||
|                         mConnectionList.Remove(conn); | ||||
|                     } | ||||
|                     mWorldConnection = null; | ||||
|                 } | ||||
|                 mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket); | ||||
|             } | ||||
| @@ -176,53 +170,25 @@ namespace FFXIVClassic_Map_Server | ||||
|             { | ||||
|                 if (conn != null) | ||||
|                 { | ||||
|                     lock (mConnectionList) | ||||
|                     { | ||||
|                         mConnectionList.Remove(conn); | ||||
|                     } | ||||
|                     mWorldConnection = null; | ||||
|                 } | ||||
|                 mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static Actor GetStaticActors(uint id) | ||||
|         { | ||||
|             return mStaticActors.GetActor(id); | ||||
|         } | ||||
|  | ||||
|         public static Actor GetStaticActors(string name) | ||||
|         { | ||||
|             return mStaticActors.FindStaticActor(name); | ||||
|         } | ||||
|  | ||||
|         public static Item GetItemGamedata(uint id) | ||||
|         { | ||||
|             if (gamedataItems.ContainsKey(id)) | ||||
|                 return gamedataItems[id]; | ||||
|             else | ||||
|                 return null; | ||||
|         } | ||||
|  | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend. | ||||
|         /// </summary> | ||||
|         /// <param name="result"></param> | ||||
|         private void ReceiveCallback(IAsyncResult result) | ||||
|         { | ||||
|             ClientConnection conn = (ClientConnection)result.AsyncState; | ||||
|             ZoneConnection conn = (ZoneConnection)result.AsyncState; | ||||
|  | ||||
|             //Check if disconnected | ||||
|             if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0)) | ||||
|             { | ||||
|                 if (mConnectedPlayerList.ContainsKey(conn.owner)) | ||||
|                     mConnectedPlayerList.Remove(conn.owner); | ||||
|                 lock (mConnectionList) | ||||
|                 { | ||||
|                     mConnectionList.Remove(conn); | ||||
|                 } | ||||
|                 if (conn.connType == BasePacket.TYPE_ZONE) | ||||
|                     Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner); | ||||
|                 return; | ||||
|                 mWorldConnection = null; | ||||
|                 Program.Log.Info("Disconnected from world server!"); | ||||
|             } | ||||
|  | ||||
|             try | ||||
| @@ -238,13 +204,13 @@ namespace FFXIVClassic_Map_Server | ||||
|                     //Build packets until can no longer or out of data | ||||
|                     while (true) | ||||
|                     { | ||||
|                         BasePacket basePacket = BuildPacket(ref offset, conn.buffer, bytesRead); | ||||
|                         SubPacket subPacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead); | ||||
|  | ||||
|                         //If can't build packet, break, else process another | ||||
|                         if (basePacket == null) | ||||
|                         if (subPacket == null) | ||||
|                             break; | ||||
|                         else | ||||
|                             mProcessor.ProcessPacket(conn, basePacket); | ||||
|                             mProcessor.ProcessPacket(conn, subPacket); | ||||
|                     } | ||||
|  | ||||
|                     //Not all bytes consumed, transfer leftover to beginning | ||||
| @@ -265,79 +231,63 @@ namespace FFXIVClassic_Map_Server | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner); | ||||
|  | ||||
|                     lock (mConnectionList) | ||||
|                     { | ||||
|                         mConnectionList.Remove(conn); | ||||
|                     } | ||||
|                     mWorldConnection = null; | ||||
|                     Program.Log.Info("Disconnected from world server!"); | ||||
|                 } | ||||
|             } | ||||
|             catch (SocketException) | ||||
|             { | ||||
|                 if (conn.socket != null) | ||||
|                 { | ||||
|                     Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner); | ||||
|  | ||||
|                     lock (mConnectionList) | ||||
|                     { | ||||
|                         mConnectionList.Remove(conn); | ||||
|                     } | ||||
|                     mWorldConnection = null; | ||||
|                     Program.Log.Info("Disconnected from world server!"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null. | ||||
|         /// </summary> | ||||
|         /// <param name="offset">Current offset in buffer.</param> | ||||
|         /// <param name="buffer">Incoming buffer.</param> | ||||
|         /// <returns>Returns either a BasePacket or null if not enough data.</returns> | ||||
|         public BasePacket BuildPacket(ref int offset, byte[] buffer, int bytesRead) | ||||
|         { | ||||
|             BasePacket newPacket = null; | ||||
|  | ||||
|             //Too small to even get length | ||||
|             if (bytesRead <= offset) | ||||
|                 return null; | ||||
|  | ||||
|             ushort packetSize = BitConverter.ToUInt16(buffer, offset); | ||||
|  | ||||
|             //Too small to whole packet | ||||
|             if (bytesRead < offset + packetSize) | ||||
|                 return null; | ||||
|  | ||||
|             if (buffer.Length < offset + packetSize) | ||||
|                 return null; | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 newPacket = new BasePacket(buffer, ref offset); | ||||
|             } | ||||
|             catch (OverflowException) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             return newPacket; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         public static ZoneConnection GetWorldConnection() | ||||
|         { | ||||
|             return mWorldConnection; | ||||
|         } | ||||
|  | ||||
|         public static Server GetServer() | ||||
|         { | ||||
|             return mSelf; | ||||
|         } | ||||
|  | ||||
|         public static CommandProcessor GetCommandProcessor() | ||||
|         { | ||||
|             return mCommandProcessor; | ||||
|         }         | ||||
|  | ||||
|         public static WorldManager GetWorldManager() | ||||
|         { | ||||
|             return mWorldManager; | ||||
|         } | ||||
|  | ||||
|         public Dictionary<uint, ConnectedPlayer> GetConnectedPlayerList() | ||||
|         { | ||||
|             return mConnectedPlayerList; | ||||
|         } | ||||
|  | ||||
|          | ||||
|         public static Dictionary<uint, Item> GetGamedataItems() | ||||
|         { | ||||
|             return gamedataItems; | ||||
|             return mGamedataItems; | ||||
|         } | ||||
|  | ||||
|         public static Actor GetStaticActors(uint id) | ||||
|         { | ||||
|             return mStaticActors.GetActor(id); | ||||
|         } | ||||
|  | ||||
|         public static Actor GetStaticActors(string name) | ||||
|         { | ||||
|             return mStaticActors.FindStaticActor(name); | ||||
|         } | ||||
|  | ||||
|         public static Item GetItemGamedata(uint id) | ||||
|         { | ||||
|             if (mGamedataItems.ContainsKey(id)) | ||||
|                 return mGamedataItems[id]; | ||||
|             else | ||||
|                 return null; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -61,11 +61,14 @@ namespace FFXIVClassic_Map_Server | ||||
|                                     canRideChocobo, | ||||
|                                     canStealth, | ||||
|                                     isInstanceRaid | ||||
|                                     FROM server_zones  | ||||
|                                     WHERE zoneName IS NOT NULL"; | ||||
|                                     FROM server_zones | ||||
|                                     WHERE zoneName IS NOT NULL and serverIp = @ip and serverPort = @port"; | ||||
|  | ||||
|                     MySqlCommand cmd = new MySqlCommand(query, conn); | ||||
|  | ||||
|                     cmd.Parameters.AddWithValue("@ip", ConfigConstants.OPTIONS_BINDIP); | ||||
|                     cmd.Parameters.AddWithValue("@port", ConfigConstants.OPTIONS_PORT); | ||||
|  | ||||
|                     using (MySqlDataReader reader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         while (reader.Read()) | ||||
| @@ -333,14 +336,21 @@ namespace FFXIVClassic_Map_Server | ||||
|                     using (MySqlDataReader reader = cmd.ExecuteReader()) | ||||
|                     { | ||||
|                         while (reader.Read()) | ||||
|                         { | ||||
|                         {                             | ||||
|                             uint zoneId = reader.GetUInt32("zoneId"); | ||||
|                             uint classId = reader.GetUInt32("actorClassId"); | ||||
|                             if (!actorClasses.ContainsKey(classId)) | ||||
|                                 continue; | ||||
|                             if (!zoneList.ContainsKey(zoneId)) | ||||
|                                 continue; | ||||
|                             Zone zone = zoneList[zoneId]; | ||||
|                             if (zone == null) | ||||
|                                 continue; | ||||
|  | ||||
|                             string customName = null; | ||||
|                             if (!reader.IsDBNull(11)) | ||||
|                                 customName = reader.GetString("customDisplayName"); | ||||
|  | ||||
|                             uint classId = reader.GetUInt32("actorClassId"); | ||||
|                             string uniqueId = reader.GetString("uniqueId"); | ||||
|                             uint zoneId = reader.GetUInt32("zoneId"); | ||||
|                             string uniqueId = reader.GetString("uniqueId");                           | ||||
|                             string privAreaName = reader.GetString("privateAreaName"); | ||||
|                             uint privAreaLevel = reader.GetUInt32("privateAreaLevel"); | ||||
|                             float x = reader.GetFloat("positionX"); | ||||
| @@ -349,16 +359,7 @@ namespace FFXIVClassic_Map_Server | ||||
|                             float rot = reader.GetFloat("rotation"); | ||||
|                             ushort state = reader.GetUInt16("actorState"); | ||||
|                             uint animId = reader.GetUInt32("animationId"); | ||||
|  | ||||
|                             if (!actorClasses.ContainsKey(classId))                                 | ||||
|                                 continue; | ||||
|                             if (!zoneList.ContainsKey(zoneId)) | ||||
|                                 continue; | ||||
|  | ||||
|                             Zone zone = zoneList[zoneId]; | ||||
|                             if (zone == null) | ||||
|                                 continue; | ||||
|  | ||||
|                              | ||||
|                             SpawnLocation spawn = new SpawnLocation(classId, uniqueId, zoneId, privAreaName, privAreaLevel, x, y, z, rot, state, animId); | ||||
|  | ||||
|                             zone.AddSpawnLocation(spawn); | ||||
| @@ -523,14 +524,7 @@ namespace FFXIVClassic_Map_Server | ||||
|  | ||||
|         //Moves actor to new zone, and sends packets to spawn at the given coords. | ||||
|         public void DoZoneChange(Player player, uint destinationZoneId, string destinationPrivateArea, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation) | ||||
|         { | ||||
|             Area oldZone = player.zone; | ||||
|             //Remove player from currentZone if transfer else it's login | ||||
|             if (player.zone != null) | ||||
|             { | ||||
|                 oldZone.RemoveActorFromZone(player); | ||||
|             } | ||||
|  | ||||
|         {        | ||||
|             //Add player to new zone and update | ||||
|             Area newArea; | ||||
|  | ||||
| @@ -542,17 +536,18 @@ namespace FFXIVClassic_Map_Server | ||||
|             //This server does not contain that zoneId | ||||
|             if (newArea == null) | ||||
|             { | ||||
|                 if (oldZone != null) | ||||
|                 { | ||||
|                     oldZone.AddActorToZone(player); | ||||
|                 } | ||||
|  | ||||
|                 var message = "WorldManager.DoZoneChange: unable to change areas, new area is not valid."; | ||||
|                 player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM, "[Debug]", message); | ||||
|                 Program.Log.Debug(message); | ||||
|                 Program.Log.Debug("Request to change to zone not on this server by: {0}.", player.customDisplayName); | ||||
|                 RequestWorldServerZoneChange(player, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             Area oldZone = player.zone; | ||||
|             //Remove player from currentZone if transfer else it's login | ||||
|             if (player.zone != null) | ||||
|             { | ||||
|                 oldZone.RemoveActorFromZone(player); | ||||
|             } | ||||
|  | ||||
|             newArea.AddActorToZone(player); | ||||
|  | ||||
|             //Update player actor's properties | ||||
| @@ -613,8 +608,8 @@ namespace FFXIVClassic_Map_Server | ||||
|             }             | ||||
|         } | ||||
|  | ||||
|         //Login Zone In | ||||
|         public void DoLogin(Player player) | ||||
|         //Session started, zone into world | ||||
|         public void DoZoneIn(Player player, bool isLogin, ushort spawnType) | ||||
|         { | ||||
|             //Add player to new zone and update | ||||
|             Zone zone = GetZone(player.zoneId); | ||||
| @@ -625,15 +620,25 @@ namespace FFXIVClassic_Map_Server | ||||
|  | ||||
|             //Set the current zone and add player | ||||
|             player.zone = zone; | ||||
|  | ||||
|             LuaEngine.OnBeginLogin(player); | ||||
|              | ||||
|             zone.AddActorToZone(player); | ||||
|              | ||||
|             //Send packets             | ||||
|             player.SendZoneInPackets(this, 0x1); | ||||
|             if (!isLogin) | ||||
|             { | ||||
|                 player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId), true, false); | ||||
|                 player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x2), true, false); | ||||
|                 player.SendZoneInPackets(this, spawnType); | ||||
|             } | ||||
|  | ||||
|             player.SendZoneInPackets(this, spawnType); | ||||
|  | ||||
|             player.destinationZone = 0; | ||||
|             player.destinationSpawnType = 0; | ||||
|             Database.SavePlayerPosition(player); | ||||
|  | ||||
|             player.playerSession.LockUpdates(false); | ||||
|  | ||||
|             LuaEngine.OnLogin(player); | ||||
|             LuaEngine.OnZoneIn(player); | ||||
|         } | ||||
|  | ||||
| @@ -648,6 +653,12 @@ namespace FFXIVClassic_Map_Server | ||||
|  | ||||
|         } | ||||
|  | ||||
|         private void RequestWorldServerZoneChange(Player player, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation) | ||||
|         { | ||||
|             ZoneConnection zc = Server.GetWorldConnection(); | ||||
|             zc.RequestZoneChange(player.playerSession.id, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation); | ||||
|         } | ||||
|  | ||||
|         public Player GetPCInWorld(string name) | ||||
|         {             | ||||
|             foreach (Zone zone in zoneList.Values) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| @@ -71,7 +71,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             return SetActorSpeedPacket.BuildPacket(actorId, playerActorId); | ||||
|         } | ||||
|  | ||||
|         public SubPacket CreateSpawnPositonPacket(uint playerActorId, uint spawnType) | ||||
|         public SubPacket CreateSpawnPositonPacket(uint playerActorId, ushort spawnType) | ||||
|         { | ||||
|             SubPacket spawnPacket; | ||||
|             if (!spawnedFirstTime && playerActorId == actorId) | ||||
| @@ -92,7 +92,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             return spawnPacket; | ||||
|         } | ||||
|  | ||||
|         public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType) | ||||
|         public SubPacket CreateSpawnTeleportPacket(uint playerActorId, ushort spawnType) | ||||
|         { | ||||
|             SubPacket spawnPacket; | ||||
|  | ||||
| @@ -224,7 +224,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             return GetSpawnPackets(playerActorId, 0x1); | ||||
|         } | ||||
|  | ||||
|         public virtual BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) | ||||
|         public virtual BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType) | ||||
|         { | ||||
|             List<SubPacket> subpackets = new List<SubPacket>(); | ||||
|             subpackets.Add(CreateAddActorPacket(playerActorId, 8)); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| using FFXIVClassic_Map_Server; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.area; | ||||
| using FFXIVClassic_Map_Server.actors.chara.npc; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| using FFXIVClassic_Map_Server; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.chara.npc; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors.Chara; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|  | ||||
| @@ -35,6 +36,8 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         public const int L_INDEXFINGER = 26; | ||||
|         public const int UNKNOWN = 27; | ||||
|  | ||||
|         public bool isStatic = false; | ||||
|  | ||||
|         public uint modelId; | ||||
|         public uint[] appearanceIds = new uint[28]; | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ using FFXIVClassic_Map_Server.actors.chara.npc; | ||||
| 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.receive.events; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using FFXIVClassic_Map_Server.utils; | ||||
| @@ -86,13 +86,17 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             List<LuaParam> lParams; | ||||
|  | ||||
|             Player player = Server.GetWorldManager().GetPCInWorld(playerActorId); | ||||
|             lParams = DoActorInit(player);             | ||||
|             lParams = DoActorInit(player); | ||||
|  | ||||
|             if (lParams != null && lParams.Count >= 3 && lParams[2].typeID == 0 && (int)lParams[2].value == 0) | ||||
|                 isStatic = true; | ||||
|  | ||||
|             if (lParams == null) | ||||
|             { | ||||
|                 string classPathFake = "/Chara/Npc/Populace/PopulaceStandard"; | ||||
|                 string classNameFake = "PopulaceStandard"; | ||||
|                 lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0); | ||||
|                 isStatic = true; | ||||
|                 //ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket(); | ||||
|                 return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams); | ||||
|             } | ||||
| @@ -111,7 +115,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); | ||||
|         } | ||||
|  | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType) | ||||
|         { | ||||
|             List<SubPacket> subpackets = new List<SubPacket>(); | ||||
|             subpackets.Add(CreateAddActorPacket(playerActorId)); | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor.inventory; | ||||
| using FFXIVClassic_Map_Server.packets.send.Actor.inventory; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.actors.chara.player | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor.inventory; | ||||
| using FFXIVClassic_Map_Server.packets.send.Actor.inventory; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.chara.player; | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| @@ -7,8 +7,6 @@ using FFXIVClassic_Map_Server.dataobjects.chara; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor.events; | ||||
| using FFXIVClassic_Map_Server.packets.send.Actor.inventory; | ||||
| using FFXIVClassic_Map_Server.packets.send.events; | ||||
| using FFXIVClassic_Map_Server.packets.send.list; | ||||
| using FFXIVClassic_Map_Server.packets.send.player; | ||||
| @@ -17,7 +15,8 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using MoonSharp.Interpreter; | ||||
| using FFXIVClassic_Map_Server.packets.receive.events; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.packets.send.actor.inventory; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.Actors | ||||
| { | ||||
|     class Player : Character | ||||
| @@ -84,7 +83,9 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|  | ||||
|         public Coroutine currentEventRunning; | ||||
|  | ||||
|         //Player Info | ||||
|         //Player Info | ||||
|         public uint destinationZone; | ||||
|         public ushort destinationSpawnType; | ||||
|         public uint[] timers = new uint[20]; | ||||
|         public ushort currentJob; | ||||
|         public uint currentTitle; | ||||
| @@ -124,9 +125,9 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|  | ||||
|         public PlayerWork playerWork = new PlayerWork(); | ||||
|  | ||||
|         public ConnectedPlayer playerSession; | ||||
|         public Session playerSession; | ||||
|  | ||||
|         public Player(ConnectedPlayer cp, uint actorID) : base(actorID) | ||||
|         public Player(Session cp, uint actorID) : base(actorID) | ||||
|         { | ||||
|             playerSession = cp; | ||||
|             actorName = String.Format("_pc{0:00000000}", actorID); | ||||
| @@ -258,9 +259,9 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             else | ||||
|                 lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true); | ||||
|             return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); | ||||
|         }         | ||||
|  | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) | ||||
|         } | ||||
|  | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType) | ||||
|         { | ||||
|             List<SubPacket> subpackets = new List<SubPacket>(); | ||||
|             subpackets.Add(CreateAddActorPacket(playerActorId, 8)); | ||||
| @@ -481,7 +482,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); | ||||
|  | ||||
|             QueuePacket(GetSpawnPackets(actorId, spawnType));             | ||||
|             GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); | ||||
|             //GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); | ||||
|  | ||||
|             #region grouptest | ||||
|             //Retainers | ||||
| @@ -653,16 +654,39 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         } | ||||
|  | ||||
|         public void CleanupAndSave() | ||||
|         {                         | ||||
|         { | ||||
|             playerSession.LockUpdates(true); | ||||
|  | ||||
|             //Remove actor from zone and main server list | ||||
|             zone.RemoveActorFromZone(this); | ||||
|             Server.GetServer().RemovePlayer(this); | ||||
|  | ||||
|             //Set Destination to 0 | ||||
|             this.destinationZone = 0; | ||||
|             this.destinationSpawnType = 0; | ||||
|  | ||||
|             //Save Player | ||||
|             Database.SavePlayerPlayTime(this); | ||||
|             Database.SavePlayerPosition(this); | ||||
|  | ||||
|             Program.Log.Info("{0} has been logged out and saved.", this.customDisplayName); | ||||
|         } | ||||
|  | ||||
|         public void CleanupAndSave(uint destinationZone, ushort spawnType, float destinationX, float destinationY, float destinationZ, float destinationRot) | ||||
|         { | ||||
|             playerSession.LockUpdates(true); | ||||
|  | ||||
|             //Remove actor from zone and main server list | ||||
|             zone.RemoveActorFromZone(this); | ||||
|  | ||||
|             //Set destination | ||||
|             this.destinationZone = destinationZone; | ||||
|             this.destinationSpawnType = spawnType; | ||||
|             this.positionX = destinationX; | ||||
|             this.positionY = destinationY; | ||||
|             this.positionZ = destinationZ; | ||||
|             this.rotation = destinationRot; | ||||
|  | ||||
|             //Save Player | ||||
|             Database.SavePlayerPlayTime(this); | ||||
|             Database.SavePlayerPosition(this);             | ||||
|         } | ||||
|  | ||||
|         public Area GetZone() | ||||
| @@ -730,8 +754,8 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         } | ||||
|  | ||||
|         public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams) | ||||
|         { | ||||
|             if (msgParams.Length == 0) | ||||
|         { | ||||
|             if (msgParams == null || msgParams.Length == 0) | ||||
|             { | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log)); | ||||
|             } | ||||
| @@ -740,24 +764,24 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         } | ||||
|  | ||||
|         public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams) | ||||
|         { | ||||
|             if (msgParams.Length == 0) | ||||
|         { | ||||
|             if (msgParams == null || msgParams.Length == 0) | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log)); | ||||
|             else | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); | ||||
|         } | ||||
|  | ||||
|         public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams) | ||||
|         { | ||||
|             if (msgParams.Length == 0) | ||||
|         { | ||||
|             if (msgParams == null || msgParams.Length == 0) | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log)); | ||||
|             else | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams))); | ||||
|         } | ||||
|  | ||||
|         public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams) | ||||
|         { | ||||
|             if (msgParams.Length == 0) | ||||
|         { | ||||
|             if (msgParams == null || msgParams.Length == 0) | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log)); | ||||
|             else | ||||
|                 QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams))); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using System.Collections.Generic; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using System.Collections.Generic; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| using FFXIVClassic_Map_Server; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
| 
 | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| @@ -12,66 +12,33 @@ using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace FFXIVClassic_Map_Server.dataobjects | ||||
| { | ||||
|     class ConnectedPlayer | ||||
|     class Session | ||||
|     { | ||||
|         public uint actorID = 0; | ||||
|         public uint id = 0; | ||||
|         Player playerActor; | ||||
|         public List<Actor> actorInstanceList = new List<Actor>(); | ||||
| 
 | ||||
|         public uint languageCode = 1; | ||||
| 
 | ||||
|         private ClientConnection zoneConnection; | ||||
|         private ClientConnection chatConnection; | ||||
| 
 | ||||
|         public uint languageCode = 1;         | ||||
|         private uint lastPingPacket = Utils.UnixTimeStampUTC(); | ||||
| 
 | ||||
|         public bool isUpdatesLocked = true; | ||||
| 
 | ||||
|         public string errorMessage = ""; | ||||
| 
 | ||||
|         public ConnectedPlayer(uint actorId) | ||||
|         public Session(uint sessionId) | ||||
|         { | ||||
|             this.actorID = actorId; | ||||
|             playerActor = new Player(this, actorId); | ||||
|             this.id = sessionId; | ||||
|             playerActor = new Player(this, sessionId); | ||||
|             actorInstanceList.Add(playerActor); | ||||
|         } | ||||
| 
 | ||||
|         public void SetConnection(int type, ClientConnection conn) | ||||
|         { | ||||
|             conn.connType = type; | ||||
|             switch (type) | ||||
|             { | ||||
|                 case BasePacket.TYPE_ZONE: | ||||
|                     zoneConnection = conn; | ||||
|                     break; | ||||
|                 case BasePacket.TYPE_CHAT: | ||||
|                     chatConnection = conn; | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool IsClientConnectionsReady() | ||||
|         { | ||||
|             return (zoneConnection != null && chatConnection != null); | ||||
|         } | ||||
| 
 | ||||
|         public void Disconnect() | ||||
|         { | ||||
|             zoneConnection.Disconnect(); | ||||
|             chatConnection.Disconnect(); | ||||
|         } | ||||
| 
 | ||||
|         public bool IsDisconnected() | ||||
|         { | ||||
|             return (!zoneConnection.IsConnected() && !chatConnection.IsConnected()); | ||||
|         } | ||||
| 
 | ||||
|         public void QueuePacket(BasePacket basePacket) | ||||
|         { | ||||
|             zoneConnection.QueuePacket(basePacket); | ||||
|             Server.GetWorldConnection().QueuePacket(basePacket); | ||||
|         } | ||||
| 
 | ||||
|         public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted) | ||||
|         { | ||||
|             zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted); | ||||
|         { | ||||
|             Server.GetWorldConnection().QueuePacket(subPacket, isAuthed, isEncrypted); | ||||
|         } | ||||
| 
 | ||||
|         public Player GetActor() | ||||
| @@ -98,6 +65,9 @@ namespace FFXIVClassic_Map_Server.dataobjects | ||||
| 
 | ||||
|         public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState) | ||||
|         { | ||||
|             if (isUpdatesLocked) | ||||
|                 return; | ||||
| 
 | ||||
|             playerActor.oldPositionX = playerActor.positionX; | ||||
|             playerActor.oldPositionY = playerActor.positionY; | ||||
|             playerActor.oldPositionZ = playerActor.positionZ; | ||||
| @@ -115,6 +85,9 @@ namespace FFXIVClassic_Map_Server.dataobjects | ||||
| 
 | ||||
|         public void UpdateInstance(List<Actor> list) | ||||
|         { | ||||
|             if (isUpdatesLocked) | ||||
|                 return; | ||||
| 
 | ||||
|             List<BasePacket> basePackets = new List<BasePacket>(); | ||||
|             List<SubPacket> RemoveActorSubpackets = new List<SubPacket>(); | ||||
|             List<SubPacket> posUpdateSubpackets = new List<SubPacket>(); | ||||
| @@ -139,6 +112,10 @@ namespace FFXIVClassic_Map_Server.dataobjects | ||||
| 
 | ||||
|                 if (actorInstanceList.Contains(actor)) | ||||
|                 { | ||||
|                     //Don't send for static characters (npcs) | ||||
|                     if (actor is Character && ((Character)actor).isStatic) | ||||
|                         continue; | ||||
| 
 | ||||
|                     GetActor().QueuePacket(actor.CreatePositionUpdatePacket(playerActor.actorId)); | ||||
|                 } | ||||
|                 else | ||||
| @@ -163,5 +140,10 @@ namespace FFXIVClassic_Map_Server.dataobjects | ||||
|             actorInstanceList.Clear(); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         public void LockUpdates(bool f) | ||||
|         { | ||||
|             isUpdatesLocked = f; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,33 +1,32 @@ | ||||
| using System; | ||||
| using System.Net.Sockets; | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
| 
 | ||||
| using FFXIVClassic.Common; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Net; | ||||
| using System.Collections.Generic; | ||||
| using FFXIVClassic_Map_Server.packets.WorldPackets.Send; | ||||
| 
 | ||||
| namespace FFXIVClassic_Map_Server | ||||
| namespace FFXIVClassic_Map_Server.dataobjects | ||||
| { | ||||
|     class ClientConnection | ||||
|     class ZoneConnection | ||||
|     { | ||||
|         //Connection stuff | ||||
|         public Blowfish blowfish; | ||||
|         public Socket socket; | ||||
|         public byte[] buffer; | ||||
|         private BlockingCollection<BasePacket> SendPacketQueue = new BlockingCollection<BasePacket>(1000); | ||||
|         private BlockingCollection<SubPacket> SendPacketQueue = new BlockingCollection<SubPacket>(1000); | ||||
|         public int lastPartialSize = 0; | ||||
| 
 | ||||
|         //Instance Stuff | ||||
|         public uint owner = 0; | ||||
|         public int connType = 0; | ||||
| 
 | ||||
|         public void QueuePacket(BasePacket packet) | ||||
|         { | ||||
|             SendPacketQueue.Add(packet); | ||||
|             List<SubPacket> subPackets = packet.GetSubpackets(); | ||||
|             foreach (SubPacket s in subPackets) | ||||
|                 SendPacketQueue.Add(s); | ||||
|         } | ||||
| 
 | ||||
|         public void QueuePacket(SubPacket subpacket, bool isAuthed, bool isEncrypted) | ||||
|         { | ||||
|             SendPacketQueue.Add(BasePacket.CreatePacket(subpacket, isAuthed, isEncrypted)); | ||||
|             SendPacketQueue.Add(subpacket); | ||||
|         } | ||||
| 
 | ||||
|         public void FlushQueuedSendPackets() | ||||
| @@ -37,9 +36,9 @@ namespace FFXIVClassic_Map_Server | ||||
| 
 | ||||
|             while (SendPacketQueue.Count > 0) | ||||
|             { | ||||
|                 BasePacket packet = SendPacketQueue.Take();                 | ||||
|                 SubPacket packet = SendPacketQueue.Take(); | ||||
| 
 | ||||
|                 byte[] packetBytes = packet.GetPacketBytes(); | ||||
|                 byte[] packetBytes = packet.GetBytes(); | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
| @@ -65,5 +64,11 @@ namespace FFXIVClassic_Map_Server | ||||
|             if (socket.Connected) | ||||
|                 socket.Disconnect(false); | ||||
|         } | ||||
| 
 | ||||
|         public void RequestZoneChange(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation) | ||||
|         { | ||||
|             WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation).DebugPrintSubPacket(); | ||||
|             QueuePacket(WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation), true, false); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,207 +1,208 @@ | ||||
| using FFXIVClassic_Map_Server.packets; | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets.receive.events; | ||||
| using FFXIVClassic_Map_Server.packets.send; | ||||
| using FFXIVClassic_Map_Server.packets.send.events; | ||||
| using MoonSharp.Interpreter; | ||||
| using MoonSharp.Interpreter.Interop; | ||||
| using MoonSharp.Interpreter.Loaders; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Diagnostics; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.lua | ||||
| { | ||||
|     class LuaEngine | ||||
|     { | ||||
|         const string FILEPATH_PLAYER = "./scripts/player.lua"; | ||||
|         const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua"; | ||||
|         const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua"; | ||||
|         const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua"; | ||||
|         const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua"; | ||||
|  | ||||
|         public LuaEngine() | ||||
|         { | ||||
|             UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic; | ||||
|         } | ||||
|  | ||||
|         public static List<LuaParam> DoActorInstantiate(Player player, Actor target) | ||||
|         { | ||||
|             string luaPath; | ||||
|  | ||||
|             if (target is Npc) | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|                 if (File.Exists(luaPath)) | ||||
|                 { | ||||
|                     LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                     if (script == null) | ||||
|                         return null; | ||||
|  | ||||
|                     DynValue result = script.Call(script.Globals["init"], target); | ||||
|                     List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result); | ||||
|                     return lparams; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets.receive.events; | ||||
| using FFXIVClassic_Map_Server.packets.send; | ||||
| using FFXIVClassic_Map_Server.packets.send.events; | ||||
| using MoonSharp.Interpreter; | ||||
| using MoonSharp.Interpreter.Interop; | ||||
| using MoonSharp.Interpreter.Loaders; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Diagnostics; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.lua | ||||
| { | ||||
|     class LuaEngine | ||||
|     { | ||||
|         const string FILEPATH_PLAYER = "./scripts/player.lua"; | ||||
|         const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua"; | ||||
|         const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua"; | ||||
|         const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua"; | ||||
|         const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua"; | ||||
|  | ||||
|         public LuaEngine() | ||||
|         { | ||||
|             UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic; | ||||
|         } | ||||
|  | ||||
|         public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart) | ||||
|         {            | ||||
|             string luaPath; | ||||
|  | ||||
|             if (target is Command) | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); | ||||
|             } | ||||
|             else if (target is Director) | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); | ||||
|             } | ||||
|             else | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return null; | ||||
|  | ||||
|                 if (!script.Globals.Get("onEventStarted").IsNil()) | ||||
|                     return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine; | ||||
|                 else | ||||
|                     return null; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|                 return null; | ||||
|         public static List<LuaParam> DoActorInstantiate(Player player, Actor target) | ||||
|         { | ||||
|             string luaPath; | ||||
|  | ||||
|             if (target is Npc) | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|                 if (File.Exists(luaPath)) | ||||
|                 { | ||||
|                     LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                     if (script == null) | ||||
|                         return null; | ||||
|  | ||||
|                     DynValue result = script.Call(script.Globals["init"], target); | ||||
|                     List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result); | ||||
|                     return lparams; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public static void DoActorOnSpawn(Player player, Npc target) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onSpawn").IsNil()) | ||||
|                     script.Call(script.Globals["onSpawn"], player, target); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate) | ||||
|         { | ||||
|             if (target is Npc) | ||||
|             { | ||||
|                 ((Npc)target).DoEventUpdate(player, eventUpdate); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart) | ||||
|         {            | ||||
|             string luaPath; | ||||
|  | ||||
|             if (target is Command) | ||||
|                 luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); | ||||
|             else if (target is Director) | ||||
|                 luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); | ||||
|             else | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Have to Do this to combine LuaParams | ||||
|                 List<Object> objects = new List<Object>(); | ||||
|                 objects.Add(player); | ||||
|                 objects.Add(target); | ||||
|                 objects.Add(eventUpdate.val2); | ||||
|                 objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams)); | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onEventUpdate").IsNil()) | ||||
|                     script.Call(script.Globals["onEventUpdate"], objects.ToArray()); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static void OnZoneIn(Player player) | ||||
|         { | ||||
|             else if (target is Director) | ||||
|             { | ||||
|                 luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); | ||||
|             } | ||||
|             else | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return null; | ||||
|  | ||||
|                 if (!script.Globals.Get("onEventStarted").IsNil()) | ||||
|                     return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine; | ||||
|                 else | ||||
|                     return null; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public static void DoActorOnSpawn(Player player, Npc target) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onSpawn").IsNil()) | ||||
|                     script.Call(script.Globals["onSpawn"], player, target); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate) | ||||
|         { | ||||
|             if (target is Npc) | ||||
|             { | ||||
|                 ((Npc)target).DoEventUpdate(player, eventUpdate); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             string luaPath; | ||||
|  | ||||
|             if (target is Command) | ||||
|                 luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); | ||||
|             else if (target is Director) | ||||
|                 luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); | ||||
|             else | ||||
|                 luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Have to Do this to combine LuaParams | ||||
|                 List<Object> objects = new List<Object>(); | ||||
|                 objects.Add(player); | ||||
|                 objects.Add(target); | ||||
|                 objects.Add(eventUpdate.val2); | ||||
|                 objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams)); | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onEventUpdate").IsNil()) | ||||
|                     script.Call(script.Globals["onEventUpdate"], objects.ToArray()); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static void OnZoneIn(Player player) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onZoneIn").IsNil()) | ||||
|                     script.Call(script.Globals["onZoneIn"], player); | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onZoneIn").IsNil()) | ||||
|                     script.Call(script.Globals["onZoneIn"], player); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static void OnBeginLogin(Player player) | ||||
|         { | ||||
|             if (File.Exists(FILEPATH_PLAYER)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(FILEPATH_PLAYER); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onBeginLogin").IsNil()) | ||||
|                     script.Call(script.Globals["onBeginLogin"], player); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static void OnLogin(Player player) | ||||
|         { | ||||
|             if (File.Exists(FILEPATH_PLAYER)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(FILEPATH_PLAYER); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onLogin").IsNil()) | ||||
|                     script.Call(script.Globals["onLogin"], player); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public static void OnBeginLogin(Player player) | ||||
|         { | ||||
|             if (File.Exists(FILEPATH_PLAYER)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(FILEPATH_PLAYER); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onBeginLogin").IsNil()) | ||||
|                     script.Call(script.Globals["onBeginLogin"], player); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static void OnLogin(Player player) | ||||
|         { | ||||
|             if (File.Exists(FILEPATH_PLAYER)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(FILEPATH_PLAYER); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onLogin").IsNil()) | ||||
|                     script.Call(script.Globals["onLogin"], player); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #region RunGMCommand | ||||
|         public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false) | ||||
|         { | ||||
| @@ -336,22 +337,22 @@ namespace FFXIVClassic_Map_Server.lua | ||||
|             LuaScript.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path); | ||||
|             return; | ||||
|         } | ||||
|         #endregion | ||||
|  | ||||
|         public static LuaScript LoadScript(string filename) | ||||
|         { | ||||
|             LuaScript script = LoadGlobals(); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 script.DoFile(filename); | ||||
|             } | ||||
|             catch (SyntaxErrorException e) | ||||
|             { | ||||
|                 Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage); | ||||
|                 return null; | ||||
|             } | ||||
|             return script; | ||||
|         #endregion | ||||
|  | ||||
|         public static LuaScript LoadScript(string filename) | ||||
|         { | ||||
|             LuaScript script = LoadGlobals(); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 script.DoFile(filename); | ||||
|             } | ||||
|             catch (SyntaxErrorException e) | ||||
|             { | ||||
|                 Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage); | ||||
|                 return null; | ||||
|             } | ||||
|             return script; | ||||
|         } | ||||
|  | ||||
|         public static LuaScript LoadGlobals(LuaScript script = null) | ||||
| @@ -367,57 +368,57 @@ namespace FFXIVClassic_Map_Server.lua | ||||
|  | ||||
|             script.Options.DebugPrint = s => { Program.Log.Debug(s); }; | ||||
|             return script; | ||||
|         } | ||||
|  | ||||
|         public static void SendError(Player player, string message) | ||||
|         { | ||||
|             List<SubPacket> SendError = new List<SubPacket>(); | ||||
|             SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName)); | ||||
|             player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message); | ||||
|             player.playerSession.QueuePacket(BasePacket.CreatePacket(SendError, true, false)); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         internal static void DoDirectorOnTalked(Director director, Player player, Npc npc) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onTalked").IsNil()) | ||||
|                     script.Call(script.Globals["onTalked"], player, npc); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         internal static void DoDirectorOnCommand(Director director, Player player, Command command) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onCommand").IsNil()) | ||||
|                     script.Call(script.Globals["onCommand"], player, command); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|         } | ||||
|  | ||||
|         public static void SendError(Player player, string message) | ||||
|         { | ||||
|             List<SubPacket> SendError = new List<SubPacket>(); | ||||
|             SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName)); | ||||
|             player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message); | ||||
|             player.playerSession.QueuePacket(BasePacket.CreatePacket(SendError, true, false)); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         internal static void DoDirectorOnTalked(Director director, Player player, Npc npc) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onTalked").IsNil()) | ||||
|                     script.Call(script.Globals["onTalked"], player, npc); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         internal static void DoDirectorOnCommand(Director director, Player player, Command command) | ||||
|         { | ||||
|             string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); | ||||
|  | ||||
|             if (File.Exists(luaPath)) | ||||
|             { | ||||
|                 LuaScript script = LoadScript(luaPath); | ||||
|  | ||||
|                 if (script == null) | ||||
|                     return; | ||||
|  | ||||
|                 //Run Script | ||||
|                 if (!script.Globals.Get("onCommand").IsNil()) | ||||
|                     script.Call(script.Globals["onCommand"], player, command); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,362 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.IO; | ||||
| using System.Runtime.InteropServices; | ||||
| using FFXIVClassic.Common; | ||||
| using NLog; | ||||
| using NLog.Targets; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets | ||||
| { | ||||
|     [StructLayout(LayoutKind.Sequential)] | ||||
|     public struct BasePacketHeader | ||||
|     { | ||||
|         public byte isAuthenticated; | ||||
|         public byte isCompressed; | ||||
|         public ushort connectionType; | ||||
|         public ushort packetSize; | ||||
|         public ushort numSubpackets; | ||||
|         public ulong timestamp; //Miliseconds | ||||
|     } | ||||
|  | ||||
|     public class BasePacket | ||||
|     { | ||||
|         public const int TYPE_ZONE = 1; | ||||
|         public const int TYPE_CHAT = 2; | ||||
|         public const int BASEPACKET_SIZE = 0x10; | ||||
|         private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | ||||
|         public byte[] data; | ||||
|  | ||||
|         public BasePacketHeader header; | ||||
|  | ||||
|         //Loads a sniffed packet from a file | ||||
|         public unsafe BasePacket(string path) | ||||
|         { | ||||
|             var bytes = File.ReadAllBytes(path); | ||||
|  | ||||
|             if (bytes.Length < BASEPACKET_SIZE) | ||||
|                 throw new OverflowException("Packet Error: Packet was too small"); | ||||
|  | ||||
|             fixed (byte* pdata = &bytes[0]) | ||||
|             { | ||||
|                 header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader)); | ||||
|             } | ||||
|  | ||||
|             if (bytes.Length < header.packetSize) | ||||
|                 throw new OverflowException("Packet Error: Packet size didn't equal given size"); | ||||
|  | ||||
|             int packetSize = header.packetSize; | ||||
|  | ||||
|             if (packetSize - BASEPACKET_SIZE != 0) | ||||
|             { | ||||
|                 data = new byte[packetSize - BASEPACKET_SIZE]; | ||||
|                 Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE); | ||||
|             } | ||||
|             else | ||||
|                 data = new byte[0]; | ||||
|         } | ||||
|  | ||||
|         //Loads a sniffed packet from a byte array | ||||
|         public unsafe BasePacket(byte[] bytes) | ||||
|         { | ||||
|             if (bytes.Length < BASEPACKET_SIZE) | ||||
|                 throw new OverflowException("Packet Error: Packet was too small"); | ||||
|  | ||||
|             fixed (byte* pdata = &bytes[0]) | ||||
|             { | ||||
|                 header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader)); | ||||
|             } | ||||
|  | ||||
|             if (bytes.Length < header.packetSize) | ||||
|                 throw new OverflowException("Packet Error: Packet size didn't equal given size"); | ||||
|  | ||||
|             int packetSize = header.packetSize; | ||||
|  | ||||
|             data = new byte[packetSize - BASEPACKET_SIZE]; | ||||
|             Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE); | ||||
|         } | ||||
|  | ||||
|         public unsafe BasePacket(byte[] bytes, ref int offset) | ||||
|         { | ||||
|             if (bytes.Length < offset + BASEPACKET_SIZE) | ||||
|                 throw new OverflowException("Packet Error: Packet was too small"); | ||||
|  | ||||
|             fixed (byte* pdata = &bytes[offset]) | ||||
|             { | ||||
|                 header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader)); | ||||
|             } | ||||
|  | ||||
|             int packetSize = header.packetSize; | ||||
|  | ||||
|             if (bytes.Length < offset + header.packetSize) | ||||
|                 throw new OverflowException("Packet Error: Packet size didn't equal given size"); | ||||
|  | ||||
|             data = new byte[packetSize - BASEPACKET_SIZE]; | ||||
|             Array.Copy(bytes, offset + BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE); | ||||
|  | ||||
|             offset += packetSize; | ||||
|         } | ||||
|  | ||||
|         public BasePacket(BasePacketHeader header, byte[] data) | ||||
|         { | ||||
|             this.header = header; | ||||
|             this.data = data; | ||||
|         } | ||||
|  | ||||
|         public List<SubPacket> GetSubpackets() | ||||
|         { | ||||
|             var subpackets = new List<SubPacket>(header.numSubpackets); | ||||
|  | ||||
|             var offset = 0; | ||||
|  | ||||
|             while (offset < data.Length) | ||||
|                 subpackets.Add(new SubPacket(data, ref offset)); | ||||
|  | ||||
|             return subpackets; | ||||
|         } | ||||
|  | ||||
|         public static unsafe BasePacketHeader GetHeader(byte[] bytes) | ||||
|         { | ||||
|             BasePacketHeader header; | ||||
|             if (bytes.Length < BASEPACKET_SIZE) | ||||
|                 throw new OverflowException("Packet Error: Packet was too small"); | ||||
|  | ||||
|             fixed (byte* pdata = &bytes[0]) | ||||
|             { | ||||
|                 header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader)); | ||||
|             } | ||||
|  | ||||
|             return header; | ||||
|         } | ||||
|  | ||||
|         public byte[] GetHeaderBytes() | ||||
|         { | ||||
|             var size = Marshal.SizeOf(header); | ||||
|             var arr = new byte[size]; | ||||
|  | ||||
|             var ptr = Marshal.AllocHGlobal(size); | ||||
|             Marshal.StructureToPtr(header, ptr, true); | ||||
|             Marshal.Copy(ptr, arr, 0, size); | ||||
|             Marshal.FreeHGlobal(ptr); | ||||
|             return arr; | ||||
|         } | ||||
|  | ||||
|         public byte[] GetPacketBytes() | ||||
|         { | ||||
|             var outBytes = new byte[header.packetSize]; | ||||
|             Array.Copy(GetHeaderBytes(), 0, outBytes, 0, BASEPACKET_SIZE); | ||||
|             Array.Copy(data, 0, outBytes, BASEPACKET_SIZE, data.Length); | ||||
|             return outBytes; | ||||
|         } | ||||
|  | ||||
|         //Replaces all instances of the sniffed actorID with the given one | ||||
|         public void ReplaceActorID(uint actorID) | ||||
|         { | ||||
|             using (var mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (var binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     using (var binreader = new BinaryReader(mem)) | ||||
|                     { | ||||
|                         while (binreader.BaseStream.Position + 4 < data.Length) | ||||
|                         { | ||||
|                             var read = binreader.ReadUInt32(); | ||||
|                             if (read == 0x029B2941 || read == 0x02977DC7 || read == 0x0297D2C8 || read == 0x0230d573 || | ||||
|                                 read == 0x23317df || read == 0x23344a3 || read == 0x1730bdb || read == 0x6c) | ||||
|                                 //Original ID | ||||
|                             { | ||||
|                                 binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin); | ||||
|                                 binWriter.Write(actorID); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //Replaces all instances of the sniffed actorID with the given one | ||||
|         public void ReplaceActorID(uint fromActorID, uint actorID) | ||||
|         { | ||||
|             using (var mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (var binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     using (var binreader = new BinaryReader(mem)) | ||||
|                     { | ||||
|                         while (binreader.BaseStream.Position + 4 < data.Length) | ||||
|                         { | ||||
|                             var read = binreader.ReadUInt32(); | ||||
|                             if (read == fromActorID) //Original ID | ||||
|                             { | ||||
|                                 binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin); | ||||
|                                 binWriter.Write(actorID); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void DebugPrintPacket() | ||||
|         { | ||||
| #if DEBUG | ||||
|             logger.ColorDebug( | ||||
|                 string.Format("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())), ConsoleOutputColor.DarkYellow); | ||||
|  | ||||
|             foreach (var sub in GetSubpackets()) | ||||
|             { | ||||
|                 sub.DebugPrintSubPacket(); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|  | ||||
|         #region Utility Functions | ||||
|  | ||||
|         public static BasePacket CreatePacket(List<SubPacket> subpackets, bool isAuthed, bool isCompressed) | ||||
|         { | ||||
|             //Create Header | ||||
|             var header = new BasePacketHeader(); | ||||
|             byte[] data = null; | ||||
|  | ||||
|             header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0; | ||||
|             header.isCompressed = isCompressed ? (byte) 1 : (byte) 0; | ||||
|             header.numSubpackets = (ushort) subpackets.Count; | ||||
|             header.packetSize = BASEPACKET_SIZE; | ||||
|             header.timestamp = Utils.MilisUnixTimeStampUTC(); | ||||
|  | ||||
|             //Get packet size | ||||
|             foreach (var subpacket in subpackets) | ||||
|                 header.packetSize += subpacket.header.subpacketSize; | ||||
|  | ||||
|             data = new byte[header.packetSize - 0x10]; | ||||
|  | ||||
|             //Add Subpackets | ||||
|             var offset = 0; | ||||
|             foreach (var subpacket in subpackets) | ||||
|             { | ||||
|                 var subpacketData = subpacket.GetBytes(); | ||||
|                 Array.Copy(subpacketData, 0, data, offset, subpacketData.Length); | ||||
|                 offset += (ushort) subpacketData.Length; | ||||
|             } | ||||
|  | ||||
|             Debug.Assert(data != null && offset == data.Length && header.packetSize == 0x10 + offset); | ||||
|  | ||||
|             var packet = new BasePacket(header, data); | ||||
|             return packet; | ||||
|         } | ||||
|  | ||||
|         public static BasePacket CreatePacket(SubPacket subpacket, bool isAuthed, bool isCompressed) | ||||
|         { | ||||
|             //Create Header | ||||
|             var header = new BasePacketHeader(); | ||||
|             byte[] data = null; | ||||
|  | ||||
|             header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0; | ||||
|             header.isCompressed = isCompressed ? (byte) 1 : (byte) 0; | ||||
|             header.numSubpackets = 1; | ||||
|             header.packetSize = BASEPACKET_SIZE; | ||||
|             header.timestamp = Utils.MilisUnixTimeStampUTC(); | ||||
|  | ||||
|             //Get packet size | ||||
|             header.packetSize += subpacket.header.subpacketSize; | ||||
|  | ||||
|             data = new byte[header.packetSize - 0x10]; | ||||
|  | ||||
|             //Add Subpackets | ||||
|             var subpacketData = subpacket.GetBytes(); | ||||
|             Array.Copy(subpacketData, 0, data, 0, subpacketData.Length); | ||||
|  | ||||
|             Debug.Assert(data != null); | ||||
|  | ||||
|             var packet = new BasePacket(header, data); | ||||
|             return packet; | ||||
|         } | ||||
|  | ||||
|         public static BasePacket CreatePacket(byte[] data, bool isAuthed, bool isCompressed) | ||||
|         { | ||||
|             Debug.Assert(data != null); | ||||
|  | ||||
|             //Create Header | ||||
|             var header = new BasePacketHeader(); | ||||
|  | ||||
|             header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0; | ||||
|             header.isCompressed = isCompressed ? (byte) 1 : (byte) 0; | ||||
|             header.numSubpackets = 1; | ||||
|             header.packetSize = BASEPACKET_SIZE; | ||||
|             header.timestamp = Utils.MilisUnixTimeStampUTC(); | ||||
|  | ||||
|             //Get packet size | ||||
|             header.packetSize += (ushort) data.Length; | ||||
|  | ||||
|             var packet = new BasePacket(header, data); | ||||
|             return packet; | ||||
|         } | ||||
|  | ||||
|         public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet) | ||||
|         { | ||||
|             var data = packet.data; | ||||
|             int size = packet.header.packetSize; | ||||
|  | ||||
|             var offset = 0; | ||||
|             while (offset < data.Length) | ||||
|             { | ||||
|                 if (data.Length < offset + SubPacket.SUBPACKET_SIZE) | ||||
|                     throw new OverflowException("Packet Error: Subpacket was too small"); | ||||
|  | ||||
|                 SubPacketHeader header; | ||||
|                 fixed (byte* pdata = &data[offset]) | ||||
|                 { | ||||
|                     header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader)); | ||||
|                 } | ||||
|  | ||||
|                 if (data.Length < offset + header.subpacketSize) | ||||
|                     throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data"); | ||||
|  | ||||
|                 blowfish.Encipher(data, offset + 0x10, header.subpacketSize - 0x10); | ||||
|  | ||||
|                 offset += header.subpacketSize; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static unsafe void DecryptPacket(Blowfish blowfish, ref BasePacket packet) | ||||
|         { | ||||
|             var data = packet.data; | ||||
|             int size = packet.header.packetSize; | ||||
|  | ||||
|             var offset = 0; | ||||
|             while (offset < data.Length) | ||||
|             { | ||||
|                 if (data.Length < offset + SubPacket.SUBPACKET_SIZE) | ||||
|                     throw new OverflowException("Packet Error: Subpacket was too small"); | ||||
|  | ||||
|                 SubPacketHeader header; | ||||
|                 fixed (byte* pdata = &data[offset]) | ||||
|                 { | ||||
|                     header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader)); | ||||
|                 } | ||||
|  | ||||
|                 if (data.Length < offset + header.subpacketSize) | ||||
|                     throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data"); | ||||
|  | ||||
|                 blowfish.Decipher(data, offset + 0x10, header.subpacketSize - 0x10); | ||||
|  | ||||
|                 offset += header.subpacketSize; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|     } | ||||
|  | ||||
|     public static class LoggerExtensions | ||||
|     { | ||||
|         public static void ColorDebug(this Logger logger, string message, ConsoleOutputColor color) | ||||
|         { | ||||
|             var logEvent = new LogEventInfo(LogLevel.Debug, logger.Name, message); | ||||
|             logEvent.Properties["color"] = (int) color; | ||||
|             logger.Log(logEvent); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,163 +0,0 @@ | ||||
| using System; | ||||
| using System.Runtime.InteropServices; | ||||
| using FFXIVClassic.Common; | ||||
| using NLog; | ||||
| using NLog.Targets; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets | ||||
| { | ||||
|     [StructLayout(LayoutKind.Sequential)] | ||||
|     public struct SubPacketHeader | ||||
|     { | ||||
|         public ushort subpacketSize; | ||||
|         public ushort type; | ||||
|         public uint sourceId; | ||||
|         public uint targetId; | ||||
|         public uint unknown1; | ||||
|     } | ||||
|  | ||||
|     [StructLayout(LayoutKind.Sequential)] | ||||
|     public struct GameMessageHeader | ||||
|     { | ||||
|         public ushort unknown4; //Always 0x14 | ||||
|         public ushort opcode; | ||||
|         public uint unknown5; | ||||
|         public uint timestamp; | ||||
|         public uint unknown6; | ||||
|     } | ||||
|  | ||||
|     public class SubPacket | ||||
|     { | ||||
|         public const int SUBPACKET_SIZE = 0x10; | ||||
|         public const int GAMEMESSAGE_SIZE = 0x10; | ||||
|         private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | ||||
|         public byte[] data; | ||||
|         public GameMessageHeader gameMessage; | ||||
|  | ||||
|         public SubPacketHeader header; | ||||
|  | ||||
|         public unsafe SubPacket(byte[] bytes, ref int offset) | ||||
|         { | ||||
|             if (bytes.Length < offset + SUBPACKET_SIZE) | ||||
|                 throw new OverflowException("Packet Error: Subpacket was too small"); | ||||
|  | ||||
|             fixed (byte* pdata = &bytes[offset]) | ||||
|             { | ||||
|                 header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader)); | ||||
|             } | ||||
|  | ||||
|             if (header.type == 0x3) | ||||
|             { | ||||
|                 fixed (byte* pdata = &bytes[offset + SUBPACKET_SIZE]) | ||||
|                 { | ||||
|                     gameMessage = | ||||
|                         (GameMessageHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(GameMessageHeader)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (bytes.Length < offset + header.subpacketSize) | ||||
|                 throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data"); | ||||
|  | ||||
|             if (header.type == 0x3) | ||||
|             { | ||||
|                 data = new byte[header.subpacketSize - SUBPACKET_SIZE - GAMEMESSAGE_SIZE]; | ||||
|                 Array.Copy(bytes, offset + SUBPACKET_SIZE + GAMEMESSAGE_SIZE, data, 0, data.Length); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 data = new byte[header.subpacketSize - SUBPACKET_SIZE]; | ||||
|                 Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length); | ||||
|             } | ||||
|  | ||||
|             offset += header.subpacketSize; | ||||
|         } | ||||
|  | ||||
|         public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) | ||||
|         { | ||||
|             header = new SubPacketHeader(); | ||||
|             gameMessage = new GameMessageHeader(); | ||||
|  | ||||
|             gameMessage.opcode = opcode; | ||||
|             header.sourceId = sourceId; | ||||
|             header.targetId = targetId; | ||||
|  | ||||
|             gameMessage.timestamp = Utils.UnixTimeStampUTC(); | ||||
|  | ||||
|             header.type = 0x03; | ||||
|             header.unknown1 = 0x00; | ||||
|             gameMessage.unknown4 = 0x14; | ||||
|             gameMessage.unknown5 = 0x00; | ||||
|             gameMessage.unknown6 = 0x00; | ||||
|  | ||||
|             this.data = data; | ||||
|  | ||||
|             header.subpacketSize = (ushort) (SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length); | ||||
|         } | ||||
|  | ||||
|         public SubPacket(SubPacket original, uint newTargetId) | ||||
|         { | ||||
|             header = new SubPacketHeader(); | ||||
|             gameMessage = original.gameMessage; | ||||
|             header.subpacketSize = original.header.subpacketSize; | ||||
|             header.type = original.header.type; | ||||
|             header.sourceId = original.header.sourceId; | ||||
|             header.targetId = newTargetId; | ||||
|             data = original.data; | ||||
|         } | ||||
|  | ||||
|         public byte[] GetHeaderBytes() | ||||
|         { | ||||
|             var size = Marshal.SizeOf(header); | ||||
|             var arr = new byte[size]; | ||||
|  | ||||
|             var ptr = Marshal.AllocHGlobal(size); | ||||
|             Marshal.StructureToPtr(header, ptr, true); | ||||
|             Marshal.Copy(ptr, arr, 0, size); | ||||
|             Marshal.FreeHGlobal(ptr); | ||||
|             return arr; | ||||
|         } | ||||
|  | ||||
|         public byte[] GetGameMessageBytes() | ||||
|         { | ||||
|             var size = Marshal.SizeOf(gameMessage); | ||||
|             var arr = new byte[size]; | ||||
|  | ||||
|             var ptr = Marshal.AllocHGlobal(size); | ||||
|             Marshal.StructureToPtr(gameMessage, ptr, true); | ||||
|             Marshal.Copy(ptr, arr, 0, size); | ||||
|             Marshal.FreeHGlobal(ptr); | ||||
|             return arr; | ||||
|         } | ||||
|  | ||||
|         public byte[] GetBytes() | ||||
|         { | ||||
|             var outBytes = new byte[header.subpacketSize]; | ||||
|             Array.Copy(GetHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE); | ||||
|  | ||||
|             if (header.type == 0x3) | ||||
|                 Array.Copy(GetGameMessageBytes(), 0, outBytes, SUBPACKET_SIZE, GAMEMESSAGE_SIZE); | ||||
|  | ||||
|             Array.Copy(data, 0, outBytes, SUBPACKET_SIZE + (header.type == 0x3 ? GAMEMESSAGE_SIZE : 0), data.Length); | ||||
|             return outBytes; | ||||
|         } | ||||
|  | ||||
|         public void DebugPrintSubPacket() | ||||
|         { | ||||
| #if DEBUG | ||||
|             logger.ColorDebug( | ||||
|                 string.Format("Size:0x{0:X} Opcode:0x{1:X}{2}{3}", header.subpacketSize, gameMessage.opcode, | ||||
|                     Environment.NewLine, | ||||
|                     Utils.ByteArrayToHex(GetHeaderBytes())), ConsoleOutputColor.DarkRed); | ||||
|  | ||||
|             if (header.type == 0x03) | ||||
|             { | ||||
|                 logger.ColorDebug(Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE), | ||||
|                     ConsoleOutputColor.DarkRed); | ||||
|  | ||||
|                 logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE), | ||||
|                     ConsoleOutputColor.DarkMagenta); | ||||
|             } | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,35 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive | ||||
| { | ||||
|     class ErrorPacket | ||||
|     { | ||||
|         public uint errorCode; | ||||
|         | ||||
|         public bool invalidPacket = false; | ||||
|  | ||||
|         public ErrorPacket(byte[] data) | ||||
|         { | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryReader binReader = new BinaryReader(mem)) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         errorCode = binReader.ReadUInt32();                         | ||||
|                     } | ||||
|                     catch (Exception) | ||||
|                     { | ||||
|                         invalidPacket = true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive | ||||
| { | ||||
|     class SessionBeginPacket | ||||
|     { | ||||
|         public bool invalidPacket = false; | ||||
|  | ||||
|         public SessionBeginPacket(byte[] data) | ||||
|         { | ||||
|             | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive | ||||
| { | ||||
|     class SessionEndPacket | ||||
|     { | ||||
|         public uint destinationZoneId; | ||||
|         public ushort destinationSpawnType; | ||||
|         public float destinationX; | ||||
|         public float destinationY; | ||||
|         public float destinationZ; | ||||
|         public float destinationRot; | ||||
|  | ||||
|         public bool invalidPacket = false; | ||||
|  | ||||
|         public SessionEndPacket(byte[] data) | ||||
|         { | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryReader binReader = new BinaryReader(mem)) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         destinationZoneId = binReader.ReadUInt32(); | ||||
|                         destinationSpawnType = binReader.ReadUInt16(); | ||||
|                         destinationX = binReader.ReadSingle(); | ||||
|                         destinationY = binReader.ReadSingle(); | ||||
|                         destinationZ = binReader.ReadSingle(); | ||||
|                         destinationRot = binReader.ReadSingle(); | ||||
|                     } | ||||
|                     catch (Exception) | ||||
|                     { | ||||
|                         invalidPacket = true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,27 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.WorldPackets.Send | ||||
| { | ||||
|     class SessionBeginConfirmPacket | ||||
|     { | ||||
|         public const ushort OPCODE = 0x1000; | ||||
|         public const uint PACKET_SIZE = 0x28; | ||||
|  | ||||
|         public static SubPacket BuildPacket(Session session, ushort errorCode = 0) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     binWriter.Write((UInt32)session.id); | ||||
|                     binWriter.Write((UInt16)errorCode); | ||||
|                 } | ||||
|             } | ||||
|             return new SubPacket(true, OPCODE, 0, session.id, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send | ||||
| { | ||||
|     class SessionEndConfirmPacket | ||||
|     { | ||||
|         public const ushort OPCODE = 0x1001; | ||||
|         public const uint PACKET_SIZE = 0x30; | ||||
|  | ||||
|         public static SubPacket BuildPacket(Session session, uint destinationZone, ushort errorCode = 0) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     binWriter.Write((UInt32)session.id); | ||||
|                     binWriter.Write((UInt16)errorCode); | ||||
|                     binWriter.Write((UInt32)destinationZone); | ||||
|                 } | ||||
|             } | ||||
|             return new SubPacket(true, OPCODE, 0, session.id, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send | ||||
| { | ||||
|     class WorldRequestZoneChangePacket | ||||
|     { | ||||
|         public const ushort OPCODE = 0x1002; | ||||
|         public const uint PACKET_SIZE = 0x048; | ||||
|  | ||||
|         public static SubPacket BuildPacket(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     binWriter.Write((UInt32)sessionId); | ||||
|                     binWriter.Write((UInt32)destinationZoneId); | ||||
|                     binWriter.Write((UInt16)spawnType); | ||||
|                     binWriter.Write((Single)spawnX); | ||||
|                     binWriter.Write((Single)spawnY); | ||||
|                     binWriter.Write((Single)spawnZ); | ||||
|                     binWriter.Write((Single)spawnRotation); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SubPacket(OPCODE, sessionId, sessionId, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class ActorDoEmotePacket | ||||
|     { | ||||
|   | ||||
| @@ -4,7 +4,9 @@ using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class ActorInstantiatePacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorQuestGraphicPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class AddActorPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| using System.IO; | ||||
| using FFXIVClassic.Common; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class BattleAction1Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,8 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class DeleteAllActorsPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class MoveActorToPositionPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class RemoveActorPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorAppearancePacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorIconPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorIdleAnimationPacket | ||||
|     {         | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorIsZoningPacket | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorNamePacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorPositionPacket | ||||
|     { | ||||
| @@ -22,7 +24,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
|         public const float INNPOS_Z     = 165.050003f; | ||||
|         public const float INNPOS_ROT   =  -1.530000f; | ||||
|  | ||||
|         public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, uint spawnType, bool isZoningPlayer) | ||||
|         public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, ushort spawnType, bool isZoningPlayer) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE-0x20]; | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,9 @@ using System.Linq; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorPropetyPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorSpeedPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorStatePacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorStatusAllPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorStatusPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| using System; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class SetActorTargetAnimatedPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class _0x132Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor | ||||
| { | ||||
|     class _0xFPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| { | ||||
|     class BattleAction | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| { | ||||
|     class BattleActionX00Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| { | ||||
|     class BattleActionX01Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| { | ||||
|     class BattleActionX10Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.battle | ||||
| { | ||||
|     class BattleActionX18Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
| using FFXIVClassic_Map_Server.actors; | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.actors; | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetEmoteEventCondition | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetEventStatus | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetNoticeEventCondition | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetPushEventConditionWithCircle | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetPushEventConditionWithFan | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetPushEventConditionWithTriggerBox | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.events | ||||
| { | ||||
|     class SetTalkEventCondition | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class EquipmentListX01Packet | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class EquipmentListX08Packet | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class EquipmentListX16Packet | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class EquipmentListX32Packet | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class EquipmentListX64Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryBeginChangePacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryEndChangePacket | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryItemEndPacket | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryItemPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryListX01Packet | ||||
|     { | ||||
|   | ||||
| @@ -3,7 +3,9 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryListX08Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryListX16Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryListX32Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryListX64Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryRemoveX01Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,8 +1,11 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryRemoveX08Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryRemoveX16Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryRemoveX32Packet | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventoryRemoveX64Packet | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventorySetBeginPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace  FFXIVClassic_Map_Server.packets.send.actor.inventory | ||||
| { | ||||
|     class InventorySetEndPacket | ||||
|     { | ||||
|   | ||||
| @@ -4,6 +4,8 @@ using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class GameMessagePacket | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class LogoutPacket | ||||
|     { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.receive | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class QuitPacket | ||||
|     { | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class SendMessagePacket | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| using System.IO; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class SetMapPacket | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| using System; | ||||
|  | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send | ||||
| { | ||||
|     class SetMusicPacket | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user