diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ClientConnection.cs index a05365fb..3d80990b 100644 --- a/FFXIVClassic Map Server/ClientConnection.cs +++ b/FFXIVClassic Map Server/ClientConnection.cs @@ -31,6 +31,11 @@ namespace FFXIVClassic_Lobby_Server sendPacketQueue.Add(packet); } + public void queuePacket(SubPacket subpacket, bool isAuthed, bool isEncrypted) + { + sendPacketQueue.Add(BasePacket.createPacket(subpacket, isAuthed, isEncrypted)); + } + public void flushQueuedSendPackets() { if (!socket.Connected) diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index d1ea6b6c..4523e232 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -90,6 +90,7 @@ + @@ -106,6 +107,7 @@ + @@ -116,11 +118,18 @@ + + + + + + + @@ -128,13 +137,13 @@ - + - + @@ -146,6 +155,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 1bd53a78..e0972573 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -27,6 +27,7 @@ using FFXIVClassic_Map_Server.packets.send.social; using FFXIVClassic_Map_Server.packets.receive.supportdesk; using FFXIVClassic_Map_Server.packets.receive.recruitment; using FFXIVClassic_Map_Server.packets.send.recruitment; +using FFXIVClassic_Map_Server.packets.send.list; namespace FFXIVClassic_Lobby_Server { @@ -52,13 +53,32 @@ namespace FFXIVClassic_Lobby_Server if (packet.header.isEncrypted == 0x01) BasePacket.decryptPacket(client.blowfish, ref packet); + // packet.debugPrintPacket(); + List subPackets = packet.getSubpackets(); foreach (SubPacket subpacket in subPackets) { if (subpacket.header.type == 0x01) - { + { + packet.debugPrintPacket(); + byte[] reply1Data = { + 0x01, 0x00, 0x00, 0x00, 0x28, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x07, 0x00, 0x00, 0x0, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0xFD, 0xFF, 0xFF, + 0x43, 0xEC, 0x00, 0xE0, 0x00, 0x0, 0x00, 0x0 + }; + + BasePacket reply1 = new BasePacket(reply1Data); BasePacket reply2 = new BasePacket("./packets/login/login2.bin"); + using (MemoryStream mem = new MemoryStream(reply1.data)) + { + using (BinaryWriter binReader = new BinaryWriter(mem)) + { + binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); + binReader.Write((UInt32)Utils.UnixTimeStampUTC()); + } + } + //Already Handshaked if (client.owner != 0) { @@ -69,9 +89,9 @@ namespace FFXIVClassic_Lobby_Server binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); binReader.Write(player.actorID); } - } + } - + client.queuePacket(reply1); client.queuePacket(reply2); break; } @@ -116,7 +136,7 @@ namespace FFXIVClassic_Lobby_Server client.owner = actorID; client.connType = 0; player.setConnection1(client); - Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); + Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); } else { @@ -127,18 +147,28 @@ namespace FFXIVClassic_Lobby_Server //Get Character info //Create player actor + reply1.debugPrintPacket(); + client.queuePacket(reply1); client.queuePacket(reply2); break; } else if (subpacket.header.type == 0x07) { - BasePacket init = InitPacket.buildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC()); - client.queuePacket(init); + //Ping? + //packet.debugPrintPacket(); + BasePacket init = Login0x7ResponsePacket.buildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC()); + //client.queuePacket(init); + } + else if (subpacket.header.type == 0x08) + { + //Response, client's current [actorID][time] + packet.debugPrintPacket(); } else if (subpacket.header.type == 0x03) { + //Normal Game Opcode switch (subpacket.gameMessage.opcode) - { + { //Ping case 0x0001: //subpacket.debugPrintSubPacket(); @@ -147,10 +177,9 @@ namespace FFXIVClassic_Lobby_Server break; //Unknown case 0x0002: - - subpacket.debugPrintSubPacket(); + BasePacket block132 = new BasePacket("./packets/tt2/4"); + BasePacket packet196 = new BasePacket("./packets/196"); - 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"); @@ -159,14 +188,15 @@ namespace FFXIVClassic_Lobby_Server 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"); + // BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); + // BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); #region replaceid //currancy.replaceActorID(player.actorID); //keyitems.replaceActorID(player.actorID); - reply5.replaceActorID(player.actorID); + block132.replaceActorID(player.actorID); + packet196.replaceActorID(player.actorID); reply6.replaceActorID(player.actorID); reply7.replaceActorID(player.actorID); reply8.replaceActorID(player.actorID); @@ -176,33 +206,44 @@ namespace FFXIVClassic_Lobby_Server reply12.replaceActorID(player.actorID); #endregion - client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); - // return; - client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1, 0xF4), true, false)); - client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false)); + client.queuePacket(SetMapPacket.buildPacket(player.actorID, 0xD1, 0xF4), true, false); + // client.queuePacket(SetMapPacket.buildPacket(player.actorID, 0x68, 0xF4), true, false); + client.queuePacket(_0x2Packet.buildPacket(player.actorID), true, false); + client.queuePacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false); + client.queuePacket(SetWeatherPacket.buildPacket(player.actorID, SetWeatherPacket.WEATHER_CLEAR), true, false); - client.queuePacket(reply5); + client.queuePacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false); - client.queuePacket(BasePacket.createPacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false)); + // client.queuePacket(reply6); + client.queuePacket(block132); BasePacket actorPacket = player.getActor().createActorSpawnPackets(player.actorID); - //actorPacket.debugPrintPacket(); + actorPacket.debugPrintPacket(); client.queuePacket(actorPacket); - client.queuePacket(reply6); - client.queuePacket(BasePacket.createPacket(new SubPacket(0xCC, player.actorID, player.actorID, File.ReadAllBytes("./packets/playerscript")),true, false)); - client.queuePacket(BasePacket.createPacket(player.getActor().createInitSubpackets(player.actorID), true, false)); - - /* - 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)); - - client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); - */ + + //Retainers + List retainerListEntries = new List(); + retainerListEntries.Add(new ListEntry(player.actorID, 0xFFFFFFFF, 0x139E, false, true, player.getActor().customDisplayName)); + retainerListEntries.Add(new ListEntry(0x23, 0x0, 0xFFFFFFFF, false, false, "TEST1")); + retainerListEntries.Add(new ListEntry(0x24, 0x0, 0xFFFFFFFF, false, false, "TEST2")); + retainerListEntries.Add(new ListEntry(0x25, 0x0, 0xFFFFFFFF, false, false, "TEST3")); + BasePacket retainerListPacket = BasePacket.createPacket(ListUtils.createRetainerList(player.actorID, 0xF4, 1, 0x800000000004e639, retainerListEntries), true, false); + client.queuePacket(retainerListPacket); + //Party + List partyListEntries = new List(); + partyListEntries.Add(new ListEntry(player.actorID, 0xFFFFFFFF, 0xFFFFFFFF, false, true, player.getActor().customDisplayName)); + partyListEntries.Add(new ListEntry(0x029B27D3, 0xFFFFFFFF, 0x195, false, true, "Valentine Bluefeather")); + BasePacket partyListPacket = BasePacket.createPacket(ListUtils.createPartyList(player.actorID, 0xF4, 1, 0x8000000000696df2, partyListEntries), true, false); + client.queuePacket(partyListPacket); + + //0x144 happens + client.queuePacket(SetActorStatusAllPacket.buildPacket(player.actorID, player.actorID, new ushort[] { 23263, 23264 }), true, false); + client.queuePacket(SetActorIconPacket.buildPacket(player.actorID, player.actorID, 0), true, false); + client.queuePacket(SetActorIsZoningPacket.buildPacket(player.actorID, player.actorID, false), true, false); + ////////ITEMS//////// - client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); + client.queuePacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false); #region itemsetup @@ -259,41 +300,57 @@ namespace FFXIVClassic_Lobby_Server #endregion //Equip Init - client.queuePacket(BasePacket.createPacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false)); + client.queuePacket(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(InventorySetEndPacket.buildPacket(player.actorID), true, false); - client.queuePacket(BasePacket.createPacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false)); - ////////ITEMS//////// + client.queuePacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false); + ////////ITEMS//////// - //The rest of hardcode - client.queuePacket(BasePacket.createPacket(SetGrandCompanyPacket.buildPacket(player.actorID, player.actorID, 0x01, 0x1B, 0x1B, 0x1B), true, false)); - client.queuePacket(BasePacket.createPacket(SetPlayerTitlePacket.buildPacket(player.actorID, player.actorID, 0x00), true, false)); - client.queuePacket(BasePacket.createPacket(SetHasChocoboPacket.buildPacket(player.actorID, true), true, false)); - client.queuePacket(BasePacket.createPacket(SetChocoboNamePacket.buildPacket(player.actorID, player.actorID, "Boco"), true, false)); - client.queuePacket(BasePacket.createPacket(SetPlayerTitlePacket.buildPacket(player.actorID, player.actorID, 0x00), true, false)); + client.queuePacket(SetGrandCompanyPacket.buildPacket(player.actorID, player.actorID, 0x01, 0x1B, 0x1B, 0x1B), true, false); + client.queuePacket(SetPlayerTitlePacket.buildPacket(player.actorID, player.actorID, 0x00), true, false); + client.queuePacket(SetCurrentJobPacket.buildPacket(player.actorID, player.actorID, 0x13), true, false); + client.queuePacket(packet196);//client.queuePacket(_0x196Packet.buildPacket(player.actorID, player.actorID), true, false); + client.queuePacket(SetChocoboNamePacket.buildPacket(player.actorID, player.actorID, "Boco"), true, false); + client.queuePacket(SetHasChocoboPacket.buildPacket(player.actorID, true), true, false); + client.queuePacket(SetHasGoobbuePacket.buildPacket(player.actorID, true), true, false); SetCompletedAchievementsPacket cheevos = new SetCompletedAchievementsPacket(); + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_BATTLE] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_CHARACTER] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_CURRENCY] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_DUNGEONS] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_EXPLORATION] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_GATHERING] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_GRAND_COMPANY] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_ITEMS] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_MATERIA] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_QUESTS] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_SEASONAL_EVENTS] = true; + cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_SYNTHESIS] = true; + client.queuePacket(cheevos.buildPacket(player.actorID), true, false); - for (int i = 0; i < cheevos.achievementFlags.Length; i++) - cheevos.achievementFlags[i] = true; + client.queuePacket(SetLatestAchievementsPacket.buildPacket(player.actorID, new uint[5]), true, false); + client.queuePacket(SetAchievementPointsPacket.buildPacket(player.actorID, 0x00), true, false); - client.queuePacket(BasePacket.createPacket(cheevos.buildPacket(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(SetLatestAchievementsPacket.buildPacket(player.actorID, new uint[5]), true, false)); - client.queuePacket(BasePacket.createPacket(SetAchievementPointsPacket.buildPacket(player.actorID, 0x00), true, false)); SetCutsceneBookPacket book = new SetCutsceneBookPacket(); - client.queuePacket(BasePacket.createPacket(book.buildPacket(player.actorID), true, false)); - //client.queuePacket(BasePacket.createPacket(SetPlayerDreamPacket.buildPacket(player.actorID, player.actorID, 0x00), true, false)); + for (int i = 0; i < book.cutsceneFlags.Length; i++) + book.cutsceneFlags[i] = true; + client.queuePacket(book.buildPacket(player.actorID), true, false); + + //client.queuePacket(SetPlayerDreamPacket.buildPacket(player.actorID, 0x0A), true, false); + + // loadTest(client, player); + // return; - client.queuePacket(BasePacket.createPacket(SetStatusPacket.buildPacket(player.actorID, player.actorID, new ushort[] { 23263, 23264 }), true, false)); BasePacket tpacket = BasePacket.createPacket(player.getActor().createInitSubpackets(player.actorID), true, false); client.queuePacket(tpacket); - + client.queuePacket(reply7); client.queuePacket(reply8); client.queuePacket(reply9); client.queuePacket(reply10); - // client.queuePacket(reply11); + // client.queuePacket(reply11); client.queuePacket(reply12); inn.addActorToZone(player.getActor()); @@ -301,10 +358,12 @@ namespace FFXIVClassic_Lobby_Server break; //Chat Received case 0x0003: + ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data); + Log.info(String.Format("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType)); subpacket.debugPrintSubPacket(); break; //Unknown - case 0x0007: + case 0x0007: break; //Update Position case 0x00CA: @@ -335,7 +394,7 @@ namespace FFXIVClassic_Lobby_Server case 0x012D: subpacket.debugPrintSubPacket(); CommandStartRequestPacket commandStart = new CommandStartRequestPacket(subpacket.data); - + client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); break; //Script Result @@ -346,11 +405,11 @@ namespace FFXIVClassic_Lobby_Server case 0x012F: subpacket.debugPrintSubPacket(); break; - /* RECRUITMENT */ + /* RECRUITMENT */ //Start Recruiting case 0x01C3: StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data); - client.queuePacket(BasePacket.createPacket(StartRecruitingResponse.buildPacket(player.actorID, true), true, false)); + client.queuePacket(BasePacket.createPacket(StartRecruitingResponse.buildPacket(player.actorID, true), true, false)); break; //End Recruiting case 0x01C4: @@ -362,7 +421,7 @@ namespace FFXIVClassic_Lobby_Server break; //Search Recruiting case 0x01C7: - RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data); + RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data); break; //Get Recruitment Details case 0x01C8: @@ -374,12 +433,12 @@ namespace FFXIVClassic_Lobby_Server 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)); + client.queuePacket(BasePacket.createPacket(CurrentRecruitmentDetailsPacket.buildPacket(player.actorID, details), true, false)); break; //Accepted Recruiting case 0x01C6: subpacket.debugPrintSubPacket(); - break; + break; /* SOCIAL STUFF */ case 0x01C9: AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data); @@ -412,17 +471,17 @@ namespace FFXIVClassic_Lobby_Server //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)); + 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)); + 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)); + 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: @@ -442,6 +501,8 @@ namespace FFXIVClassic_Lobby_Server break; } } + else + packet.debugPrintPacket(); } } @@ -481,143 +542,19 @@ namespace FFXIVClassic_Lobby_Server } - /* - public void sendTeleportSequence(ClientConnection client, uint levelId, float x, float y, float z, float angle) + private void loadTest(ClientConnection client, ConnectedPlayer player) { - BasePacket reply1 = new BasePacket("./packets/move/move1.bin"); - BasePacket reply2 = new BasePacket("./packets/move/move2.bin"); - BasePacket reply3 = new BasePacket("./packets/move/move3.bin"); - BasePacket reply4 = new BasePacket("./packets/move/move4.bin"); - BasePacket reply5 = new BasePacket("./packets/move/move5.bin"); - BasePacket reply6 = new BasePacket("./packets/move/move6.bin"); - BasePacket reply7 = new BasePacket("./packets/move/move7.bin"); - BasePacket reply8 = new BasePacket("./packets/move/move8.bin"); - BasePacket reply9 = new BasePacket("./packets/move/move9.bin"); + string sequence = "6789abcdefghijklmnopqrsuvwxy"; + //10 for just login + for (int i = 7; i < sequence.Length; i++) + { - client.queuePacket(reply1); - client.queuePacket(reply2); - client.queuePacket(reply3); - client.queuePacket(reply4); - client.queuePacket(reply5); - client.queuePacket(reply6); - client.queuePacket(reply7); - client.queuePacket(reply8); - client.queuePacket(reply9); + BasePacket packet = new BasePacket("./packets/tt2/" + sequence[i]); + packet.replaceActorID(player.actorID); + client.queuePacket(packet); + + } + } - - { - CCompositePacket result; - - { - CSetMusicPacket packet; - packet.SetSourceId(PLAYER_ID); - packet.SetTargetId(PLAYER_ID); - packet.SetMusicId(zone->backgroundMusicId); - result.AddPacket(packet.ToPacketData()); - } - - { - CSetWeatherPacket packet; - packet.SetSourceId(PLAYER_ID); - packet.SetTargetId(PLAYER_ID); - packet.SetWeatherId(CSetWeatherPacket::WEATHER_CLEAR); - result.AddPacket(packet.ToPacketData()); - } - - { - CSetMapPacket packet; - packet.SetSourceId(PLAYER_ID); - packet.SetTargetId(PLAYER_ID); - packet.SetMapId(levelId); - result.AddPacket(packet.ToPacketData()); - } - - QueuePacket(0, result.ToPacketData()); - } - - QueuePacket(0, PacketData(std::begin(g_client0_moor11), std::end(g_client0_moor11))); - QueuePacket(0, PacketData(std::begin(g_client0_moor12), std::end(g_client0_moor12))); - - { - PacketData outgoingPacket(std::begin(g_client0_moor13), std::end(g_client0_moor13)); - - { - const uint32 setInitialPositionBase = 0x360; - - CSetInitialPositionPacket setInitialPosition; - setInitialPosition.SetSourceId(PLAYER_ID); - setInitialPosition.SetTargetId(PLAYER_ID); - setInitialPosition.SetX(x); - setInitialPosition.SetY(y); - setInitialPosition.SetZ(z); - setInitialPosition.SetAngle(angle); - auto setInitialPositionPacket = setInitialPosition.ToPacketData(); - - memcpy(outgoingPacket.data() + setInitialPositionBase, setInitialPositionPacket.data(), setInitialPositionPacket.size()); - } - - QueuePacket(0, outgoingPacket); - } - - QueuePacket(0, GetInventoryInfo()); - QueuePacket(0, PacketData(std::begin(g_client0_moor21), std::end(g_client0_moor21))); - //QueuePacket(0, PacketData(std::begin(g_client0_moor22), std::end(g_client0_moor22))); - - if(!m_zoneMasterCreated) - { - //Zone Master - QueuePacket(0, PacketData(std::begin(g_client0_moor23), std::end(g_client0_moor23))); - - /* - QueuePacket(0, PacketData(std::begin(g_client0_moor24), std::end(g_client0_moor24))); - QueuePacket(0, PacketData(std::begin(g_client0_moor25), std::end(g_client0_moor25))); - - QueuePacket(0, PacketData(std::begin(g_client0_moor26), std::end(g_client0_moor26))); - QueuePacket(0, PacketData(std::begin(g_client0_moor27), std::end(g_client0_moor27))); - QueuePacket(0, PacketData(std::begin(g_client0_moor28), std::end(g_client0_moor28))); - QueuePacket(0, PacketData(std::begin(g_client0_moor29), std::end(g_client0_moor29))); - - QueuePacket(0, PacketData(std::begin(g_client0_moor30), std::end(g_client0_moor30))); - QueuePacket(0, PacketData(std::begin(g_client0_moor31), std::end(g_client0_moor31))); - - QueuePacket(0, PacketData(std::begin(g_client0_moor32), std::end(g_client0_moor32))); - QueuePacket(0, PacketData(std::begin(g_client0_moor33), std::end(g_client0_moor33))); - QueuePacket(0, PacketData(std::begin(g_client0_moor34), std::end(g_client0_moor34))); - QueuePacket(0, PacketData(std::begin(g_client0_moor35), std::end(g_client0_moor35))); - QueuePacket(0, PacketData(std::begin(g_client0_moor36), std::end(g_client0_moor36))); - QueuePacket(0, PacketData(std::begin(g_client0_moor37), std::end(g_client0_moor37))); - */ - //Enables chat? - // QueuePacket(0, PacketData(std::begin(g_client0_moor38), std::end(g_client0_moor38))); - /* - { - CCompositePacket packet; - packet.AddPacket(PacketData(std::begin(g_client0_moor38), std::end(g_client0_moor38))); - QueuePacket(0, packet.ToPacketData()); - } - - // QueuePacket(0, PacketData(std::begin(g_client0_moor39), std::end(g_client0_moor39))); - - // QueuePacket(0, PacketData(std::begin(g_client0_moor40), std::end(g_client0_moor40))); - - - - m_zoneMasterCreated = true; - } - - if(zone != nullptr) - { - for(const auto& actorInfo : zone->actors) - { - SpawnNpc(actorInfo.id, actorInfo.baseModelId, actorInfo.nameStringId, - std::get<0>(actorInfo.pos), std::get<1>(actorInfo.pos), std::get<2>(actorInfo.pos), 0); - } - } - - m_curMap = levelId; - m_posX = x; - m_posY = y; - m_posZ = z; - }*/ } } diff --git a/FFXIVClassic Map Server/common/Utils.cs b/FFXIVClassic Map Server/common/Utils.cs index 3d85fcb3..32004392 100644 --- a/FFXIVClassic Map Server/common/Utils.cs +++ b/FFXIVClassic Map Server/common/Utils.cs @@ -52,9 +52,19 @@ namespace FFXIVClassic_Lobby_Server.common DateTime zuluTime = currentTime.ToUniversalTime(); DateTime unixEpoch = new DateTime(1970, 1, 1); unixTimeStamp = (UInt32)(zuluTime.Subtract(unixEpoch)).TotalSeconds; + + return unixTimeStamp; + } - return 0x55555555; - //return unixTimeStamp; + public static UInt64 MilisUnixTimeStampUTC() + { + UInt64 unixTimeStamp; + DateTime currentTime = DateTime.Now; + DateTime zuluTime = currentTime.ToUniversalTime(); + DateTime unixEpoch = new DateTime(1970, 1, 1); + unixTimeStamp = (UInt64)(zuluTime.Subtract(unixEpoch)).TotalMilliseconds; + + return unixTimeStamp; } public static uint MurmurHash2(string key, uint seed) diff --git a/FFXIVClassic Map Server/dataobjects/Actor.cs b/FFXIVClassic Map Server/dataobjects/Actor.cs index e6ccb255..292c9b86 100644 --- a/FFXIVClassic Map Server/dataobjects/Actor.cs +++ b/FFXIVClassic Map Server/dataobjects/Actor.cs @@ -94,6 +94,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public SubPacket createSpawnPositonPacket(uint playerActorID, uint spawnType) { return SetActorPositionPacket.buildPacket(actorID, playerActorID, SetActorPositionPacket.INNPOS_X, SetActorPositionPacket.INNPOS_Y, SetActorPositionPacket.INNPOS_Z, SetActorPositionPacket.INNPOS_ROT, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE); + //return SetActorPositionPacket.buildPacket(actorID, playerActorID, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE); } public SubPacket createPositionUpdatePacket(uint playerActorID) @@ -113,6 +114,7 @@ namespace FFXIVClassic_Map_Server.dataobjects subpackets.Add(createSpawnPositonPacket(playerActorID, 0xFF)); subpackets.Add(createAppearancePacket(playerActorID)); subpackets.Add(createNamePacket(playerActorID)); + subpackets.Add(_0xFPacket.buildPacket(playerActorID, playerActorID)); subpackets.Add(createStatePacket(playerActorID)); //subpackets.Add(createScriptBindPacket(playerActorID)); return BasePacket.createPacket(subpackets, true, false); diff --git a/FFXIVClassic Map Server/packets/BasePacket.cs b/FFXIVClassic Map Server/packets/BasePacket.cs index fd2e2c62..e99cd081 100644 --- a/FFXIVClassic Map Server/packets/BasePacket.cs +++ b/FFXIVClassic Map Server/packets/BasePacket.cs @@ -18,8 +18,7 @@ namespace FFXIVClassic_Lobby_Server.packets public ushort reserved; public ushort packetSize; public ushort numSubpackets; - public uint unknown1; //Id? - public uint unknown2; //Usually 0x13B + public ulong timestamp; //Miliseconds } public class BasePacket{ @@ -46,8 +45,13 @@ namespace FFXIVClassic_Lobby_Server.packets int packetSize = header.packetSize; - data = new byte[packetSize - BASEPACKET_SIZE]; - Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE); + 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 @@ -155,7 +159,7 @@ namespace FFXIVClassic_Lobby_Server.packets while (binreader.BaseStream.Position + 4 < data.Length) { uint read = binreader.ReadUInt32(); - if (read == 0x029B2941) //Original ID + if (read == 0x029B2941 || read == 0x02977DC7 || read == 0x0297D2C8 || read == 0x0230d573 || read == 0x23317df || read == 0x23344a3) //Original ID { binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin); binWriter.Write(actorID); @@ -200,6 +204,7 @@ namespace FFXIVClassic_Lobby_Server.packets header.isEncrypted = isEncrypted?(byte)1:(byte)0; header.numSubpackets = (ushort)subpackets.Count; header.packetSize = BASEPACKET_SIZE; + header.timestamp = Utils.MilisUnixTimeStampUTC(); //Get packet size foreach (SubPacket subpacket in subpackets) @@ -232,6 +237,7 @@ namespace FFXIVClassic_Lobby_Server.packets header.isEncrypted = isEncrypted ? (byte)1 : (byte)0; header.numSubpackets = (ushort)1; header.packetSize = BASEPACKET_SIZE; + header.timestamp = Utils.MilisUnixTimeStampUTC(); //Get packet size header.packetSize += subpacket.header.subpacketSize; @@ -260,6 +266,7 @@ namespace FFXIVClassic_Lobby_Server.packets header.isEncrypted = isEncrypted ? (byte)1 : (byte)0; header.numSubpackets = (ushort)1; header.packetSize = BASEPACKET_SIZE; + header.timestamp = Utils.MilisUnixTimeStampUTC(); //Get packet size header.packetSize += (ushort)data.Length; diff --git a/FFXIVClassic Map Server/packets/receive/ChatMessagePacket.cs b/FFXIVClassic Map Server/packets/receive/ChatMessagePacket.cs new file mode 100644 index 00000000..2b3e85f5 --- /dev/null +++ b/FFXIVClassic Map Server/packets/receive/ChatMessagePacket.cs @@ -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.receive +{ + class ChatMessagePacket + { + public float posX; + public float posY; + public float posZ; + public float posRot; + + public uint logType; + + public string message; + + public bool invalidPacket = false; + + public ChatMessagePacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try{ + binReader.ReadUInt64(); + posX = binReader.ReadSingle(); + posY = binReader.ReadSingle(); + posZ = binReader.ReadSingle(); + posRot = binReader.ReadSingle(); + logType = binReader.ReadUInt32(); + message = Encoding.ASCII.GetString(binReader.ReadBytes(0x200)).Trim(new [] { '\0' }); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorIconPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorIconPacket.cs new file mode 100644 index 00000000..03649d46 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorIconPacket.cs @@ -0,0 +1,35 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.actor +{ + class SetActorIconPacket + { + public const uint DISCONNECTING = 0x00010000; + public const uint ISGM = 0x00020000; + public const uint ISAFK = 0x00000100; + + public const ushort OPCODE = 0x0145; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint playerActorID, uint targetActorID, uint iconCode) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)iconCode); + } + } + + return new SubPacket(OPCODE, playerActorID, targetActorID, data); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorIsZoningPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorIsZoningPacket.cs new file mode 100644 index 00000000..4ab3d1a2 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorIsZoningPacket.cs @@ -0,0 +1,22 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.actor +{ + class SetActorIsZoningPacket + { + public const ushort OPCODE = 0x017B; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint playerActorID, uint targetActorID, bool isDimmed) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + data[0] = (byte)(isDimmed ? 1 : 0); + return new SubPacket(OPCODE, playerActorID, targetActorID, data); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorPositionPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorPositionPacket.cs index ccd40006..23b3965d 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorPositionPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorPositionPacket.cs @@ -36,7 +36,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor using (BinaryWriter binWriter = new BinaryWriter(mem)) { binWriter.Write((Int32)0); - binWriter.Write((Int32)sourceActorID); + binWriter.Write((Int32)0); binWriter.Write((Single)x); binWriter.Write((Single)y); binWriter.Write((Single)z); diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetStatusPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorStatusAllPacket.cs similarity index 96% rename from FFXIVClassic Map Server/packets/send/Actor/SetStatusPacket.cs rename to FFXIVClassic Map Server/packets/send/Actor/SetActorStatusAllPacket.cs index e204f19e..27409ea0 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetStatusPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorStatusAllPacket.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace FFXIVClassic_Map_Server.packets.send.actor { - class SetStatusPacket + class SetActorStatusAllPacket { public const ushort OPCODE = 0x0179; public const uint PACKET_SIZE = 0x48; diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorStatusPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorStatusPacket.cs new file mode 100644 index 00000000..c47f5353 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorStatusPacket.cs @@ -0,0 +1,32 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.actor +{ + class SetActorStatusPacket + { + public const ushort OPCODE = 0x0177; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint playerActorID, uint targetActorID, ushort index, ushort statusCode) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt16)index); + binWriter.Write((UInt16)statusCode); + } + } + + return new SubPacket(OPCODE, playerActorID, targetActorID, data); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/_0xFPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/_0xFPacket.cs new file mode 100644 index 00000000..b3a61ddc --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/_0xFPacket.cs @@ -0,0 +1,31 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.actor +{ + class _0xFPacket + { + public const ushort OPCODE = 0x000F; + public const uint PACKET_SIZE = 0x38; + + public static SubPacket buildPacket(uint playerActorID, uint targetActorID) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + + } + } + + return new SubPacket(OPCODE, playerActorID, targetActorID, data); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/list/ListBeginPacket.cs b/FFXIVClassic Map Server/packets/send/list/ListBeginPacket.cs index 971ef01a..3d24a700 100644 --- a/FFXIVClassic Map Server/packets/send/list/ListBeginPacket.cs +++ b/FFXIVClassic Map Server/packets/send/list/ListBeginPacket.cs @@ -13,7 +13,7 @@ namespace FFXIVClassic_Map_Server.packets.send.list public const ushort OPCODE = 0x017D; public const uint PACKET_SIZE = 0x40; - public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong id, ulong listId, uint numEntries) + public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, ulong listId, int numEntries) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -23,7 +23,7 @@ namespace FFXIVClassic_Map_Server.packets.send.list { //Write List Header binWriter.Write((UInt64)locationCode); - binWriter.Write((UInt64)id); + binWriter.Write((UInt64)sequenceId); //Write List Info binWriter.Write((UInt64)listId); binWriter.Write((UInt32)numEntries); diff --git a/FFXIVClassic Map Server/packets/send/list/ListEndPacket.cs b/FFXIVClassic Map Server/packets/send/list/ListEndPacket.cs index e429271a..b85a6d17 100644 --- a/FFXIVClassic Map Server/packets/send/list/ListEndPacket.cs +++ b/FFXIVClassic Map Server/packets/send/list/ListEndPacket.cs @@ -1,6 +1,7 @@ using FFXIVClassic_Lobby_Server.packets; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,11 +11,25 @@ namespace FFXIVClassic_Map_Server.packets.send.list class ListEndPacket { public const ushort OPCODE = 0x017E; - public const uint PACKET_SIZE = 0x28; + public const uint PACKET_SIZE = 0x38; - public static SubPacket buildPacket(uint playerActorID, ulong listId) + public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, ulong listId) { - return new SubPacket(OPCODE, 0, playerActorID, BitConverter.GetBytes(listId)); + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + //Write List Header + binWriter.Write((UInt64)locationCode); + binWriter.Write((UInt64)sequenceId); + //Write List Info + binWriter.Write((UInt64)listId); + } + } + + return new SubPacket(OPCODE, playerActorID, playerActorID, data); } } diff --git a/FFXIVClassic Map Server/packets/send/list/ListEntriesEndPacket.cs b/FFXIVClassic Map Server/packets/send/list/ListEntriesEndPacket.cs index 9334d223..13ef33c6 100644 --- a/FFXIVClassic Map Server/packets/send/list/ListEntriesEndPacket.cs +++ b/FFXIVClassic Map Server/packets/send/list/ListEntriesEndPacket.cs @@ -13,7 +13,7 @@ namespace FFXIVClassic_Map_Server.packets.send.list public const ushort OPCODE = 0x017F; public const uint PACKET_SIZE = 0x1B8; - public static SubPacket buildPacket(uint playerActorID, uint locationCode, uint id, uint numInPacket) + public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, List entries, int offset) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -23,17 +23,25 @@ namespace FFXIVClassic_Map_Server.packets.send.list { //Write List Header binWriter.Write((UInt64)locationCode); - binWriter.Write((UInt64)id); + binWriter.Write((UInt64)sequenceId); //Write Entries - uint max = 8; - if (numInPacket < 8) - max = numInPacket; + int max = 8; + if (entries.Count-offset < 8) + max = entries.Count - offset; for (int i = 0; i < max; i++) { + binWriter.Seek(0x10 + (0x30 * i), SeekOrigin.Begin); + ListEntry entry = entries[i]; + binWriter.Write((UInt32)entry.actorId); + binWriter.Write((UInt32)entry.unknown1); + binWriter.Write((UInt32)entry.unknown2); + binWriter.Write((Byte)(entry.flag1? 1 : 0)); + binWriter.Write((Byte)(entry.isOnline? 1 : 0)); + binWriter.Write(Encoding.ASCII.GetBytes(entry.name), 0, Encoding.ASCII.GetByteCount(entry.name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(entry.name)); } //Write Count - binWriter.Seek(0x30 * 8, SeekOrigin.Begin); + binWriter.Seek(0x10 + (0x30 * 8), SeekOrigin.Begin); binWriter.Write(max); } } diff --git a/FFXIVClassic Map Server/packets/send/list/ListEntry.cs b/FFXIVClassic Map Server/packets/send/list/ListEntry.cs new file mode 100644 index 00000000..9a6ac250 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/list/ListEntry.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.list +{ + class ListEntry + { + public uint actorId; + public uint unknown1; + public uint unknown2; + public bool flag1; + public bool isOnline; + public string name; + + public ListEntry(uint actorId, uint unknown1, uint unknown2, bool flag1, bool isOnline, string name) + { + this.actorId = actorId; + this.unknown1 = unknown1; + this.unknown2 = unknown2; + this.flag1 = flag1; + this.isOnline = isOnline; + this.name = name; + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/list/ListStartPacket.cs b/FFXIVClassic Map Server/packets/send/list/ListStartPacket.cs index 53c21806..9535703b 100644 --- a/FFXIVClassic Map Server/packets/send/list/ListStartPacket.cs +++ b/FFXIVClassic Map Server/packets/send/list/ListStartPacket.cs @@ -17,7 +17,7 @@ namespace FFXIVClassic_Map_Server.packets.send.list public const ushort OPCODE = 0x017C; public const uint PACKET_SIZE = 0x98; - public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong id, ulong listId, uint numEntries) + public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, ulong listId, uint listTypeId, int numEntries) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -27,11 +27,10 @@ namespace FFXIVClassic_Map_Server.packets.send.list { //Temp stuff string name = ""; - uint listTypeId = 0x4E22; //Write list header binWriter.Write((UInt64)locationCode); - binWriter.Write((UInt64)id); + binWriter.Write((UInt64)sequenceId); //Write list id binWriter.Write((UInt64)3); @@ -47,6 +46,8 @@ namespace FFXIVClassic_Map_Server.packets.send.list binWriter.Write((UInt32)0xFFFFFFFF); binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name)); + binWriter.Seek(0x64, SeekOrigin.Begin); + binWriter.Write((UInt32)0x6D); binWriter.Write((UInt32)0x6D); binWriter.Write((UInt32)0x6D); diff --git a/FFXIVClassic Map Server/packets/send/list/ListUtils.cs b/FFXIVClassic Map Server/packets/send/list/ListUtils.cs new file mode 100644 index 00000000..09866ddd --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/list/ListUtils.cs @@ -0,0 +1,44 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.list +{ + class ListUtils + { + + public static List createList(uint actorId, uint locationCode, ulong sequenceId, ulong listId, uint listTypeId, List listEntries) + { + List subpacketList = new List(); + subpacketList.Add(ListStartPacket.buildPacket(actorId, locationCode, sequenceId, listId, listTypeId, listEntries.Count)); + subpacketList.Add(ListBeginPacket.buildPacket(actorId, locationCode, sequenceId, listId, listEntries.Count)); + subpacketList.Add(ListEntriesEndPacket.buildPacket(actorId, locationCode, sequenceId, listEntries, 0)); + subpacketList.Add(ListEndPacket.buildPacket(actorId, locationCode, sequenceId, listId)); + return subpacketList; + } + + public static List createRetainerList(uint actorId, uint locationCode, ulong sequenceId, ulong listId, List listEntries) + { + List subpacketList = new List(); + subpacketList.Add(ListStartPacket.buildPacket(actorId, locationCode, sequenceId, listId, ListStartPacket.TYPEID_RETAINER, listEntries.Count)); + subpacketList.Add(ListBeginPacket.buildPacket(actorId, locationCode, sequenceId, listId, listEntries.Count)); + subpacketList.Add(ListEntriesEndPacket.buildPacket(actorId, locationCode, sequenceId, listEntries, 0)); + subpacketList.Add(ListEndPacket.buildPacket(actorId, locationCode, sequenceId, listId)); + return subpacketList; + } + + public static List createPartyList(uint actorId, uint locationCode, ulong sequenceId, ulong listId, List listEntries) + { + List subpacketList = new List(); + subpacketList.Add(ListStartPacket.buildPacket(actorId, locationCode, sequenceId, listId, ListStartPacket.TYPEID_PARTY, listEntries.Count)); + subpacketList.Add(ListBeginPacket.buildPacket(actorId, locationCode, sequenceId, listId, listEntries.Count)); + subpacketList.Add(ListEntriesEndPacket.buildPacket(actorId, locationCode, sequenceId, listEntries, 0)); + subpacketList.Add(ListEndPacket.buildPacket(actorId, locationCode, sequenceId, listId)); + return subpacketList; + } + + } +} diff --git a/FFXIVClassic Map Server/packets/send/login/0x7ResponsePacket.cs b/FFXIVClassic Map Server/packets/send/login/0x7ResponsePacket.cs new file mode 100644 index 00000000..c4cbde84 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/login/0x7ResponsePacket.cs @@ -0,0 +1,41 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.login +{ + class Login0x7ResponsePacket + { + public static BasePacket buildPacket(uint actorID, uint time) + { + byte[] data = new byte[0x18]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + try + { + binWriter.Write((short)0x18); + binWriter.Write((short)0x8); + binWriter.Write((uint)0); + binWriter.Write((uint)0); + binWriter.Write((uint)0xFFFFFD7F); + + binWriter.Write((uint)actorID); + binWriter.Write((uint)time); + } + catch (Exception) + { + } + } + } + + return BasePacket.createPacket(data, false, false); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/player/SendAchievementRatePacket.cs b/FFXIVClassic Map Server/packets/send/player/SendAchievementRatePacket.cs new file mode 100644 index 00000000..dd821f51 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/player/SendAchievementRatePacket.cs @@ -0,0 +1,33 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.player +{ + class SendAchievementRatePacket + { + public const ushort OPCODE = 0x019F; + public const uint PACKET_SIZE = 0x30; + + public static SubPacket buildPacket(uint playerActorID, uint achievementId, uint progressCount, uint progressFlags) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)achievementId); + binWriter.Write((UInt32)progressCount); + binWriter.Write((UInt32)progressFlags); + } + } + + return new SubPacket(OPCODE, playerActorID, playerActorID, data); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/player/SetCurrentJobPacket.cs b/FFXIVClassic Map Server/packets/send/player/SetCurrentJobPacket.cs new file mode 100644 index 00000000..6e4aad85 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/player/SetCurrentJobPacket.cs @@ -0,0 +1,20 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.player +{ + class SetCurrentJobPacket + { + public const ushort OPCODE = 0x01A4; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint sourceActorID, uint targetActorID, uint jobId) + { + return new SubPacket(OPCODE, sourceActorID, targetActorID, BitConverter.GetBytes((uint)jobId)); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/player/_0x196Packet.cs b/FFXIVClassic Map Server/packets/send/player/_0x196Packet.cs new file mode 100644 index 00000000..7be6e752 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/player/_0x196Packet.cs @@ -0,0 +1,32 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send.player +{ + class _0x196Packet + { + public const ushort OPCODE = 0x0196; + public const uint PACKET_SIZE = 0x38; + + public static SubPacket buildPacket(uint playerActorID, uint targetActorID) + { + byte[] data = new byte[PACKET_SIZE - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Seek(0xE, SeekOrigin.Begin); + binWriter.Write((Byte)0x01); + } + } + + return new SubPacket(OPCODE, playerActorID, targetActorID, data); + } + } +}