mirror of
				https://bitbucket.org/Ioncannon/project-meteor-server.git
				synced 2025-05-20 08:26:59 -04:00 
			
		
		
		
	Merge branch 'fix_connection' into multiplayer
This commit is contained in:
		| @@ -20,22 +20,12 @@ namespace FFXIVClassic_Lobby_Server | ||||
|         public Blowfish blowfish; | ||||
|         public Socket socket; | ||||
|         public byte[] buffer = new byte[0xffff]; | ||||
|         public CircularBuffer<byte> incomingStream = new CircularBuffer<byte>(1024); | ||||
|         private BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(100); | ||||
|         private BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(1000); | ||||
|  | ||||
|         //Instance Stuff | ||||
|         public uint owner = 0; | ||||
|         public uint connType = 0; | ||||
|  | ||||
|  | ||||
|         public void processIncoming(int bytesIn) | ||||
|         { | ||||
|             if (bytesIn == 0) | ||||
|                 return; | ||||
|  | ||||
|             incomingStream.Put(buffer, 0, bytesIn); | ||||
|         } | ||||
|  | ||||
|         public void queuePacket(BasePacket packet) | ||||
|         { | ||||
|             sendPacketQueue.Add(packet); | ||||
|   | ||||
| @@ -25,7 +25,6 @@ namespace FFXIVClassic_Lobby_Server | ||||
|     { | ||||
|         Dictionary<uint, Player> mPlayers; | ||||
|         List<ClientConnection> mConnections; | ||||
|         Boolean isAlive = true; | ||||
|  | ||||
|         Zone inn = new Zone(); | ||||
|  | ||||
| @@ -33,54 +32,9 @@ namespace FFXIVClassic_Lobby_Server | ||||
|         { | ||||
|             mPlayers = playerList; | ||||
|             mConnections = connectionList; | ||||
|         } | ||||
|         }      | ||||
|  | ||||
|         public void update() | ||||
|         { | ||||
|             Console.WriteLine("Packet processing thread has started"); | ||||
|             while (isAlive) | ||||
|             { | ||||
|                 lock (mConnections) | ||||
|                 { | ||||
|                     foreach (ClientConnection conn in mConnections) | ||||
|                     { | ||||
|                         //Receive conn1 packets | ||||
|                         while (true) | ||||
|                         { | ||||
|                             if (conn == null || conn.incomingStream.Size < BasePacket.BASEPACKET_SIZE) | ||||
|                                 break; | ||||
|  | ||||
|                             try { | ||||
|                                 if (conn.incomingStream.Size < BasePacket.BASEPACKET_SIZE) | ||||
|                                     break; | ||||
|                                 BasePacketHeader header = BasePacket.getHeader(conn.incomingStream.Peek(BasePacket.BASEPACKET_SIZE)); | ||||
|  | ||||
|                                 if (conn.incomingStream.Size < header.packetSize) | ||||
|                                     break; | ||||
|  | ||||
|                                 BasePacket packet = new BasePacket(conn.incomingStream.Get(header.packetSize)); | ||||
|                                 processPacket(conn, packet); | ||||
|  | ||||
|                             } | ||||
|                             catch(OverflowException) | ||||
|                             { break; } | ||||
|                         } | ||||
|                          | ||||
|                         //Send packets | ||||
|                         if (conn != null) | ||||
|                             conn.flushQueuedSendPackets(); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 //Don't waste CPU if isn't needed | ||||
|                 if (mConnections.Count == 0) | ||||
|                     Thread.Sleep(2000); | ||||
|                 else | ||||
|                     Thread.Sleep(100); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void processPacket(ClientConnection client, BasePacket packet) | ||||
|         public void processPacket(ClientConnection client, BasePacket packet) | ||||
|         { | ||||
|             Player player = null; | ||||
|             if (client.owner != 0 && mPlayers.ContainsKey(client.owner)) | ||||
| @@ -89,268 +43,272 @@ namespace FFXIVClassic_Lobby_Server | ||||
|             if (packet.header.isEncrypted == 0x01)                        | ||||
|                 BasePacket.decryptPacket(client.blowfish, ref packet); | ||||
|  | ||||
|  | ||||
|             List<SubPacket> subPackets = packet.getSubpackets(); | ||||
|             foreach (SubPacket subpacket in subPackets) | ||||
|             { | ||||
|                 //Console.WriteLine(client.getAddress()); | ||||
|                 switch (subpacket.header.opcode) | ||||
|                 {              | ||||
|                     //Initial | ||||
|                     case 0x0000: | ||||
|                         BasePacket init = InitPacket.buildPacket(0, Utils.UnixTimeStampUTC()); | ||||
|                         BasePacket reply2 = new BasePacket("./packets/login/login2.bin");                         | ||||
|  | ||||
|                         //Already Handshaked | ||||
|                         if (client.owner != 0) | ||||
|                         { | ||||
|                             using (MemoryStream mem = new MemoryStream(reply2.data)) | ||||
|                             { | ||||
|                                 using (BinaryWriter binReader = new BinaryWriter(mem)) | ||||
|                                 { | ||||
|                                     binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); | ||||
|                                     binReader.Write(player.actorID); | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             client.queuePacket(init); | ||||
|                             client.queuePacket(reply2); | ||||
|                             break; | ||||
|                         } | ||||
|  | ||||
|                         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) | ||||
|                                 {} | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         if (actorID == 0) | ||||
|                             break;                         | ||||
|  | ||||
|                         //Second connection | ||||
|                         if (mPlayers.ContainsKey(actorID)) | ||||
|                             player = mPlayers[actorID]; | ||||
|                 if (subpacket.header.type == 0x01) | ||||
|                 {                                    | ||||
|                     BasePacket reply2 = new BasePacket("./packets/login/login2.bin"); | ||||
|  | ||||
|                     //Already Handshaked | ||||
|                     if (client.owner != 0) | ||||
|                     { | ||||
|                         using (MemoryStream mem = new MemoryStream(reply2.data)) | ||||
|                         { | ||||
|                             using (BinaryWriter binReader = new BinaryWriter(mem)) | ||||
|                             { | ||||
|                                 binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); | ||||
|                                 binReader.Write(actorID); | ||||
|                                 binReader.Write(player.actorID); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); | ||||
|  | ||||
|                         if (player == null) | ||||
|                         { | ||||
|                             player = new Player(actorID);                             | ||||
|                             mPlayers[actorID] = player; | ||||
|                             client.owner = actorID; | ||||
|                             client.connType = 0; | ||||
|                             player.setConnection1(client); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             client.owner = actorID; | ||||
|                             client.connType = 1; | ||||
|                             player.setConnection2(client); | ||||
|                         } | ||||
|  | ||||
|                         //Get Character info | ||||
|                         //Create player actor | ||||
|                         client.queuePacket(init); | ||||
|                          | ||||
|                         client.queuePacket(reply2); | ||||
|                         break; | ||||
|                     //Ping | ||||
|                     case 0x0001: | ||||
|                         //subpacket.debugPrintSubPacket(); | ||||
|                         PingPacket pingPacket = new PingPacket(subpacket.data); | ||||
|                         client.queuePacket(BasePacket.createPacket(PongPacket.buildPacket(player.actorID, pingPacket.time), true, false)); | ||||
|                     } | ||||
|  | ||||
|                     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) | ||||
|                             { } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (actorID == 0) | ||||
|                         break; | ||||
|                     //Unknown | ||||
|                     case 0x0002: | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|               | ||||
|                         BasePacket reply5 = new BasePacket("./packets/login/login5.bin"); | ||||
|                         BasePacket reply6 = new BasePacket("./packets/login/login6_data.bin"); | ||||
|                         BasePacket reply7 = new BasePacket("./packets/login/login7_data.bin"); | ||||
|                         BasePacket reply8 = new BasePacket("./packets/login/login8_data.bin"); | ||||
|                         BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); | ||||
|                         BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); | ||||
|                         BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); | ||||
|                         BasePacket reply12 = new BasePacket("./packets/login/login12.bin"); | ||||
|  | ||||
|                         BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); | ||||
|                         BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); | ||||
|                     //Second connection | ||||
|                     if (mPlayers.ContainsKey(actorID)) | ||||
|                         player = mPlayers[actorID]; | ||||
|  | ||||
| #region replaceid | ||||
|                         currancy.replaceActorID(player.actorID); | ||||
|                         keyitems.replaceActorID(player.actorID); | ||||
|                     using (MemoryStream mem = new MemoryStream(reply2.data)) | ||||
|                     { | ||||
|                         using (BinaryWriter binReader = new BinaryWriter(mem)) | ||||
|                         { | ||||
|                             binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); | ||||
|                             binReader.Write(actorID); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                         reply5.replaceActorID(player.actorID); | ||||
|                         reply6.replaceActorID(player.actorID); | ||||
|                         reply7.replaceActorID(player.actorID); | ||||
|                         reply8.replaceActorID(player.actorID); | ||||
|                         reply9.replaceActorID(player.actorID); | ||||
|                         reply10.replaceActorID(player.actorID); | ||||
|                         reply11.replaceActorID(player.actorID); | ||||
|                         reply12.replaceActorID(player.actorID); | ||||
| #endregion | ||||
|                     if (player == null) | ||||
|                     { | ||||
|                         player = new Player(actorID); | ||||
|                         mPlayers[actorID] = player; | ||||
|                         client.owner = actorID; | ||||
|                         client.connType = 0; | ||||
|                         player.setConnection1(client); | ||||
|                     Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         client.owner = actorID; | ||||
|                         client.connType = 1; | ||||
|                         player.setConnection2(client); | ||||
|                     } | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); | ||||
|                     //Get Character info | ||||
|                     //Create player actor | ||||
|                     client.queuePacket(reply2); | ||||
|                     break; | ||||
|                 } | ||||
|                 else if (subpacket.header.type == 0x07) | ||||
|                 { | ||||
|                     BasePacket init = InitPacket.buildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC()); | ||||
|                     client.queuePacket(init); | ||||
|                 } | ||||
|                 else if (subpacket.header.type == 0x03) | ||||
|                 { | ||||
|                     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)); | ||||
|                             break; | ||||
|                         //Unknown | ||||
|                         case 0x0002: | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|  | ||||
|                         client.queuePacket(reply5); | ||||
|                             BasePacket reply5 = new BasePacket("./packets/login/login5.bin"); | ||||
|                             BasePacket reply6 = new BasePacket("./packets/login/login6_data.bin"); | ||||
|                             BasePacket reply7 = new BasePacket("./packets/login/login7_data.bin"); | ||||
|                             BasePacket reply8 = new BasePacket("./packets/login/login8_data.bin"); | ||||
|                             BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); | ||||
|                             BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); | ||||
|                             BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); | ||||
|                             BasePacket reply12 = new BasePacket("./packets/login/login12.bin"); | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false)); | ||||
|                             BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); | ||||
|                             BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); | ||||
|  | ||||
|                         client.queuePacket(reply6); | ||||
|                             #region replaceid | ||||
|                             currancy.replaceActorID(player.actorID); | ||||
|                             keyitems.replaceActorID(player.actorID); | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(SetActorPositionPacket.buildPacket(player.actorID, player.actorID, SetActorPositionPacket.INNPOS_X, SetActorPositionPacket.INNPOS_Y, SetActorPositionPacket.INNPOS_Z, SetActorPositionPacket.INNPOS_ROT, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(player.getActor().createSpeedPacket(player.actorID), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(player.getActor().createStatePacket(player.actorID), true, false));               | ||||
|                             reply5.replaceActorID(player.actorID); | ||||
|                             reply6.replaceActorID(player.actorID); | ||||
|                             reply7.replaceActorID(player.actorID); | ||||
|                             reply8.replaceActorID(player.actorID); | ||||
|                             reply9.replaceActorID(player.actorID); | ||||
|                             reply10.replaceActorID(player.actorID); | ||||
|                             reply11.replaceActorID(player.actorID); | ||||
|                             reply12.replaceActorID(player.actorID); | ||||
|                             #endregion | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false)); | ||||
|  | ||||
|                         ////////ITEMS//////// | ||||
|                         client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); | ||||
|                             client.queuePacket(reply5); | ||||
|  | ||||
| #region itemsetup | ||||
|                             client.queuePacket(BasePacket.createPacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false)); | ||||
|  | ||||
|                         //TEST | ||||
|                         List<Item> items = new List<Item>(); | ||||
|                         items.Add(new Item(1337, 8030920, 5)); //Leather Jacket | ||||
|                         items.Add(new Item(1338, 8013626, 1)); //Chocobo Mask | ||||
|                         items.Add(new Item(1339, 5030402, 2)); //Thyrus | ||||
|                         items.Add(new Item(1340, 8013635, 3)); //Dalamud Horn | ||||
|                         items.Add(new Item(1341, 10100132, 4)); //Savage Might 4 | ||||
|                         items.Add(new Item(1342, 8032407, 6)); //Green Summer Halter (Female) | ||||
|                         items.Add(new Item(1343, 8051307, 7)); //Green Summer Tanga (Female) | ||||
|                         items.Add(new Item(1344, 8050766, 8)); //Flame Private's Saroul | ||||
|                             client.queuePacket(reply6); | ||||
|  | ||||
|                         int count = 0; | ||||
|                          | ||||
|                         items[2].isHighQuality = true; | ||||
|                         items[0].durability = 9999; | ||||
|                         items[0].spiritbind = 10000; | ||||
|                         items[0].materia1 = 6; | ||||
|                         items[0].materia2 = 7; | ||||
|                         items[0].materia3 = 8; | ||||
|                         items[0].materia4 = 9; | ||||
|                         items[0].materia5 = 10; | ||||
|                         items[1].durability = 9999; | ||||
|                         items[2].durability = 0xFFFFFFF; | ||||
|                         items[3].durability = 9999; | ||||
|                         items[4].quantity = 99; | ||||
|                             client.queuePacket(BasePacket.createPacket(SetActorPositionPacket.buildPacket(player.actorID, player.actorID, SetActorPositionPacket.INNPOS_X, SetActorPositionPacket.INNPOS_Y, SetActorPositionPacket.INNPOS_Z, SetActorPositionPacket.INNPOS_ROT, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(player.getActor().createSpeedPacket(player.actorID), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(player.getActor().createStatePacket(player.actorID), true, false)); | ||||
|  | ||||
|                         //Reused | ||||
|                         SubPacket endInventory = InventorySetEndPacket.buildPacket(player.actorID); | ||||
|                         SubPacket beginInventory = InventorySetBeginPacket.buildPacket(player.actorID, 200, 00); | ||||
|                         SubPacket setInventory = InventoryItemPacket.buildPacket(player.actorID, items, ref count); | ||||
|                             client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); | ||||
|  | ||||
|                         List<SubPacket> setinvPackets = new List<SubPacket>(); | ||||
|                         setinvPackets.Add(beginInventory); | ||||
|                         setinvPackets.Add(setInventory); | ||||
|                         setinvPackets.Add(endInventory); | ||||
| #endregion | ||||
|                             ////////ITEMS//////// | ||||
|                             client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); | ||||
|                          | ||||
|                         //client.queuePacket(currancy); | ||||
|                         //client.queuePacket(keyitems); | ||||
|                             #region itemsetup | ||||
|  | ||||
| #region equipsetup | ||||
|                         EquipmentSetupPacket initialEqupmentPacket = new EquipmentSetupPacket(); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_BODY, 5); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_HEAD, 3); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERSHIRT, 6); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERGARMENT, 7); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_MAINHAND, 2); | ||||
|                         initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_LEGS, 8); | ||||
| #endregion | ||||
|                             //TEST | ||||
|                             List<Item> items = new List<Item>(); | ||||
|                             items.Add(new Item(1337, 8030920, 5)); //Leather Jacket | ||||
|                             items.Add(new Item(1338, 8013626, 1)); //Chocobo Mask | ||||
|                             items.Add(new Item(1339, 5030402, 2)); //Thyrus | ||||
|                             items.Add(new Item(1340, 8013635, 3)); //Dalamud Horn | ||||
|                             items.Add(new Item(1341, 10100132, 4)); //Savage Might 4 | ||||
|                             items.Add(new Item(1342, 8032407, 6)); //Green Summer Halter (Female) | ||||
|                             items.Add(new Item(1343, 8051307, 7)); //Green Summer Tanga (Female) | ||||
|                             items.Add(new Item(1344, 8050766, 8)); //Flame Private's Saroul | ||||
|  | ||||
|                         //Equip Init | ||||
|                         client.queuePacket(BasePacket.createPacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(player.actorID), true, false)); | ||||
|                         client.queuePacket(BasePacket.createPacket(InventorySetEndPacket.buildPacket(player.actorID), true, false)); | ||||
|                             int count = 0; | ||||
|  | ||||
|                         client.queuePacket(BasePacket.createPacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false)); | ||||
|                         ////////ITEMS//////// | ||||
|                             items[2].isHighQuality = true; | ||||
|                             items[0].durability = 9999; | ||||
|                             items[0].spiritbind = 10000; | ||||
|                             items[0].materia1 = 6; | ||||
|                             items[0].materia2 = 7; | ||||
|                             items[0].materia3 = 8; | ||||
|                             items[0].materia4 = 9; | ||||
|                             items[0].materia5 = 10; | ||||
|                             items[1].durability = 9999; | ||||
|                             items[2].durability = 0xFFFFFFF; | ||||
|                             items[3].durability = 9999; | ||||
|                             items[4].quantity = 99; | ||||
|  | ||||
|                         //The rest of hardcode | ||||
|                         client.queuePacket(reply7); | ||||
|                         client.queuePacket(reply8); | ||||
|                         client.queuePacket(reply9); | ||||
|                         client.queuePacket(reply10); | ||||
|                         //client.queuePacket(reply11); | ||||
|                         client.queuePacket(reply12); | ||||
|                             //Reused | ||||
|                             SubPacket endInventory = InventorySetEndPacket.buildPacket(player.actorID); | ||||
|                             SubPacket beginInventory = InventorySetBeginPacket.buildPacket(player.actorID, 200, 00); | ||||
|                             SubPacket setInventory = InventoryItemPacket.buildPacket(player.actorID, items, ref count); | ||||
|  | ||||
|                         inn.addActorToZone(player.getActor()); | ||||
|                             List<SubPacket> setinvPackets = new List<SubPacket>(); | ||||
|                             setinvPackets.Add(beginInventory); | ||||
|                             setinvPackets.Add(setInventory); | ||||
|                             setinvPackets.Add(endInventory); | ||||
|                             #endregion | ||||
|  | ||||
|                         break; | ||||
|                     //Chat Received | ||||
|                     case 0x0003:                         | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|                         break; | ||||
|                     //Update Position | ||||
|                     case 0x00CA: | ||||
|                             client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); | ||||
|  | ||||
|                             //client.queuePacket(currancy); | ||||
|                             //client.queuePacket(keyitems); | ||||
|  | ||||
|                             #region equipsetup | ||||
|                             EquipmentSetupPacket initialEqupmentPacket = new EquipmentSetupPacket(); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_BODY, 5); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_HEAD, 3); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERSHIRT, 6); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERGARMENT, 7); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_MAINHAND, 2); | ||||
|                             initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_LEGS, 8); | ||||
|                             #endregion | ||||
|  | ||||
|                             //Equip Init | ||||
|                             client.queuePacket(BasePacket.createPacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(player.actorID), true, false)); | ||||
|                             client.queuePacket(BasePacket.createPacket(InventorySetEndPacket.buildPacket(player.actorID), true, false)); | ||||
|  | ||||
|                             client.queuePacket(BasePacket.createPacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false)); | ||||
|                             ////////ITEMS//////// | ||||
|  | ||||
|                             //The rest of hardcode | ||||
|                             client.queuePacket(reply7); | ||||
|                             client.queuePacket(reply8); | ||||
|                             client.queuePacket(reply9); | ||||
|                             client.queuePacket(reply10); | ||||
|                             //client.queuePacket(reply11); | ||||
|                             client.queuePacket(reply12); | ||||
|  | ||||
|                             inn.addActorToZone(player.getActor()); | ||||
|  | ||||
|                             break; | ||||
|                         //Chat Received | ||||
|                         case 0x0003: | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|                             break; | ||||
|                         //Update Position | ||||
|                         UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); | ||||
|                         player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); | ||||
|                         case 0x00CA: | ||||
|                             //Update Position | ||||
|                             UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); | ||||
|                             player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); | ||||
|  | ||||
|                         //Update Instance | ||||
|                         List<BasePacket> instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); | ||||
|                         foreach (BasePacket bp in instanceUpdatePackets) | ||||
|                             client.queuePacket(bp); | ||||
|                             //Update Instance | ||||
|                             List<BasePacket> instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); | ||||
|                             foreach (BasePacket bp in instanceUpdatePackets) | ||||
|                                 client.queuePacket(bp); | ||||
|  | ||||
|                         break; | ||||
|                     //Set Target  | ||||
|                     case 0x00CD: | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|                             break; | ||||
|                         //Set Target  | ||||
|                         case 0x00CD: | ||||
|                             //subpacket.debugPrintSubPacket(); | ||||
|  | ||||
|                         SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); | ||||
|                         player.getActor().currentTarget = setTarget.actorID; | ||||
|                         client.queuePacket(BasePacket.createPacket(SetActorTargetAnimatedPacket.buildPacket(player.actorID, player.actorID, setTarget.actorID), true, false)); | ||||
| 				        break; | ||||
|                     //Lock Target | ||||
|                     case 0x00CC: | ||||
|                         LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); | ||||
|                         player.getActor().currentLockedTarget = lockTarget.actorID; | ||||
|                         break; | ||||
|                     //Start Script | ||||
|                     case 0x012D: | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|                         //StartScriptPacket startScript = new StartScriptPacket(subpacket.data); | ||||
|                         //client.queuePacket(new BasePacket("./packets/script/bed.bin")); | ||||
|                         client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); | ||||
|                         break; | ||||
|                     //Script Result | ||||
|                     case 0x012E: | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
| 				        processScriptResult(subpacket);				     | ||||
| 				        break; | ||||
|                     case 0x012F: | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|                          | ||||
|                         break; | ||||
|                     default: | ||||
|                         Log.debug(String.Format("Unknown command 0x{0:X} received.", subpacket.header.opcode)); | ||||
|                         subpacket.debugPrintSubPacket(); | ||||
|                         break; | ||||
|                             SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); | ||||
|                             player.getActor().currentTarget = setTarget.actorID; | ||||
|                             client.queuePacket(BasePacket.createPacket(SetActorTargetAnimatedPacket.buildPacket(player.actorID, player.actorID, setTarget.actorID), true, false)); | ||||
|                             break; | ||||
|                         //Lock Target | ||||
|                         case 0x00CC: | ||||
|                             LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); | ||||
|                             player.getActor().currentLockedTarget = lockTarget.actorID; | ||||
|                             break; | ||||
|                         //Start Script | ||||
|                         case 0x012D: | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|                             //StartScriptPacket startScript = new StartScriptPacket(subpacket.data); | ||||
|                             //client.queuePacket(new BasePacket("./packets/script/bed.bin")); | ||||
|                             client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); | ||||
|                             break; | ||||
|                         //Script Result | ||||
|                         case 0x012E: | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|                             processScriptResult(subpacket); | ||||
|                             break; | ||||
|                         case 0x012F: | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|  | ||||
|                             break; | ||||
|                         default: | ||||
|                             Log.debug(String.Format("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode)); | ||||
|                             subpacket.debugPrintSubPacket(); | ||||
|                             break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ using System.Threading; | ||||
| using FFXIVClassic_Lobby_Server.common; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Lobby_Server.packets; | ||||
| using System.IO; | ||||
|  | ||||
| namespace FFXIVClassic_Lobby_Server | ||||
| { | ||||
| @@ -62,8 +63,7 @@ namespace FFXIVClassic_Lobby_Server | ||||
|             Console.ForegroundColor = ConsoleColor.Gray; | ||||
|  | ||||
|             mProcessor = new PacketProcessor(mConnectedPlayerList, mConnectionList); | ||||
|             mProcessorThread = new Thread(new ThreadStart(mProcessor.update)); | ||||
|             mProcessorThread.Start(); | ||||
|  | ||||
|             //mGameThread = new Thread(new ThreadStart(mProcessor.update)); | ||||
|             //mGameThread.Start(); | ||||
|             return true; | ||||
| @@ -117,32 +117,10 @@ namespace FFXIVClassic_Lobby_Server | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private Player findPlayerBySocket(Socket s) | ||||
|         { | ||||
|             lock (mConnectedPlayerList) | ||||
|             { | ||||
|                 foreach (KeyValuePair<uint,Player> p in mConnectedPlayerList) | ||||
|                 { | ||||
|                     if ((p.Value.getConnection1().socket.RemoteEndPoint as IPEndPoint).Address.Equals((s.RemoteEndPoint as IPEndPoint).Address)) | ||||
|                     { | ||||
|                         return p.Value; | ||||
|                     } | ||||
|  | ||||
|                     if ((p.Value.getConnection2().socket.RemoteEndPoint as IPEndPoint).Address.Equals((s.RemoteEndPoint as IPEndPoint).Address)) | ||||
|                     { | ||||
|                         return p.Value; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         private Player findPlayerByClientConnection(ClientConnection conn) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         }  | ||||
|  | ||||
|         /// <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;             | ||||
| @@ -152,10 +130,32 @@ namespace FFXIVClassic_Lobby_Server | ||||
|                 int bytesRead = conn.socket.EndReceive(result); | ||||
|                 if (bytesRead > 0) | ||||
|                 { | ||||
|                     conn.processIncoming(bytesRead); | ||||
|                     int offset = 0; | ||||
|  | ||||
|                     //Queue the next receive | ||||
|                     conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn); | ||||
|                     //Build packets until can no longer or out of data | ||||
|                     while(true) | ||||
|                     {                         | ||||
|                         BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead); | ||||
|                         //If can't build packet, break, else process another | ||||
|                         if (basePacket == null)                         | ||||
|                             break;                         | ||||
|                         else                         | ||||
|                             mProcessor.processPacket(conn, basePacket);                         | ||||
|                     } | ||||
|                      | ||||
|                     //Not all bytes consumed, transfer leftover to beginning | ||||
|                     if (offset < bytesRead)                     | ||||
|                         Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset); | ||||
|  | ||||
|                     //Build any queued subpackets into basepackets and send | ||||
|                     conn.flushQueuedSendPackets(); | ||||
|                      | ||||
|                     if (offset < bytesRead)                     | ||||
|                         //Need offset since not all bytes consumed | ||||
|                         conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(receiveCallback), conn); | ||||
|                     else                         | ||||
|                         //All bytes consumed, full buffer available | ||||
|                         conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
| @@ -181,8 +181,35 @@ namespace FFXIVClassic_Lobby_Server | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|         /// <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; | ||||
|  | ||||
|             newPacket = new BasePacket(buffer, ref offset); | ||||
|  | ||||
|             return newPacket; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         public void sendPacket(string path, int conn) | ||||
|         { | ||||
|   | ||||
| @@ -13,10 +13,15 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|     public struct SubPacketHeader | ||||
|     { | ||||
|         public ushort       subpacketSize; | ||||
|         public ushort       unknown0; //Always 0x03 | ||||
|         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;  | ||||
| @@ -26,9 +31,11 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|  | ||||
|     public class SubPacket | ||||
|     { | ||||
|         public const int SUBPACKET_SIZE = 0x20; | ||||
|         public const int SUBPACKET_SIZE = 0x10; | ||||
|         public const int GAMEMESSAGE_SIZE = 0x10; | ||||
|  | ||||
|         public SubPacketHeader  header; | ||||
|         public GameMessageHeader gameMessage; | ||||
|         public byte[]           data; | ||||
|  | ||||
|         public unsafe SubPacket(byte[] bytes, ref int offset) | ||||
| @@ -41,11 +48,27 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|                 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"); | ||||
|  | ||||
|             data = new byte[header.subpacketSize - SUBPACKET_SIZE]; | ||||
|             Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length); | ||||
|             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; | ||||
|         } | ||||
| @@ -53,21 +76,23 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|         public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) | ||||
|         { | ||||
|             this.header = new SubPacketHeader(); | ||||
|             header.opcode = opcode; | ||||
|             this.gameMessage = new GameMessageHeader(); | ||||
|  | ||||
|             gameMessage.opcode = opcode; | ||||
|             header.sourceId = sourceId; | ||||
|             header.targetId = targetId; | ||||
|  | ||||
|             header.timestamp = Utils.UnixTimeStampUTC(); | ||||
|             gameMessage.timestamp = Utils.UnixTimeStampUTC(); | ||||
|  | ||||
|             header.unknown0 = 0x03; | ||||
|             header.type = 0x03; | ||||
|             header.unknown1 = 0x00; | ||||
|             header.unknown4 = 0x14; | ||||
|             header.unknown5 = 0x00; | ||||
|             header.unknown6 = 0x00; | ||||
|             gameMessage.unknown4 = 0x14; | ||||
|             gameMessage.unknown5 = 0x00; | ||||
|             gameMessage.unknown6 = 0x00; | ||||
|  | ||||
|             this.data = data; | ||||
|  | ||||
|             header.subpacketSize = (ushort)(0x20 + data.Length); | ||||
|             header.subpacketSize = (ushort)(SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length); | ||||
|         } | ||||
|  | ||||
|         public byte[] getHeaderBytes() | ||||
| @@ -82,11 +107,27 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|             return arr; | ||||
|         } | ||||
|  | ||||
|         public byte[] getGameMessageBytes() | ||||
|         { | ||||
|             int size = Marshal.SizeOf(gameMessage); | ||||
|             byte[] arr = new byte[size]; | ||||
|  | ||||
|             IntPtr ptr = Marshal.AllocHGlobal(size); | ||||
|             Marshal.StructureToPtr(gameMessage, ptr, true); | ||||
|             Marshal.Copy(ptr, arr, 0, size); | ||||
|             Marshal.FreeHGlobal(ptr); | ||||
|             return arr; | ||||
|         } | ||||
|  | ||||
|         public byte[] getBytes() | ||||
|         { | ||||
|             byte[] outBytes = new byte[header.subpacketSize]; | ||||
|             Array.Copy(getHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE); | ||||
|             Array.Copy(data, 0, outBytes, SUBPACKET_SIZE, data.Length); | ||||
|  | ||||
|             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; | ||||
|         } | ||||
|  | ||||
| @@ -94,8 +135,12 @@ namespace FFXIVClassic_Lobby_Server.packets | ||||
|         { | ||||
| #if DEBUG | ||||
|             Console.BackgroundColor = ConsoleColor.DarkRed; | ||||
|             Console.WriteLine("Size: 0x{0:X}, Opcode: 0x{1:X}", header.subpacketSize, header.opcode);             | ||||
|             Console.WriteLine("Size: 0x{0:X}", header.subpacketSize); | ||||
|             if (header.type == 0x03) | ||||
|                 Console.WriteLine("Opcode: 0x{0:X}", gameMessage.opcode); | ||||
|             Console.WriteLine("{0}", Utils.ByteArrayToHex(getHeaderBytes())); | ||||
|             if (header.type == 0x03) | ||||
|                 Console.WriteLine("{0}", Utils.ByteArrayToHex(getGameMessageBytes())); | ||||
|             Console.BackgroundColor = ConsoleColor.DarkMagenta; | ||||
|             Console.WriteLine("{0}", Utils.ByteArrayToHex(data)); | ||||
|             Console.BackgroundColor = ConsoleColor.Black; | ||||
|   | ||||
| @@ -10,9 +10,9 @@ namespace FFXIVClassic_Map_Server.packets.send.login | ||||
| { | ||||
|     class InitPacket | ||||
|     { | ||||
|         public static BasePacket buildPacket(uint unknown, uint time) | ||||
|         public static BasePacket buildPacket(uint actorID, uint time) | ||||
|         { | ||||
|             byte[] data = new byte[18]; | ||||
|             byte[] data = new byte[0x18]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
| @@ -26,7 +26,7 @@ namespace FFXIVClassic_Map_Server.packets.send.login | ||||
|                         binWriter.Write((uint)0); | ||||
|                         binWriter.Write((uint)0xFFFFFD7F); | ||||
|  | ||||
|                         binWriter.Write((uint)unknown); | ||||
|                         binWriter.Write((uint)actorID); | ||||
|                         binWriter.Write((uint)time); | ||||
|                     } | ||||
|                     catch (Exception) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user