From a81d6bb26a5ada783fbeecc6a72cd1b7f2d37542 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Tue, 6 Oct 2015 00:39:18 -0400 Subject: [PATCH] Implemented equipment packets as well as actor name/appearance packets. Appearance and name is now retrieved for the chara id. --- FFXIVClassic Map Server/Database.cs | 26 +- .../FFXIVClassic Map Server.csproj | 5 + FFXIVClassic Map Server/PacketProcessor.cs | 67 ++- ...FXIVClassic Map Server.vshost.exe.manifest | 11 - .../bin/Debug/packets/login/login6_data.bin | Bin 2992 -> 2584 bytes .../bin/Debug/packets/login/login7_data.bin | Bin 3040 -> 2784 bytes FFXIVClassic Map Server/common/Blowfish.cs | 442 ++++++++++++++++-- FFXIVClassic Map Server/dataobjects/Actor.cs | 97 ++-- .../dataobjects/Appearance.cs | 143 ++++++ FFXIVClassic Map Server/dataobjects/Player.cs | 13 +- .../send/Actor/SetActorAppearancePacket.cs | 15 +- .../packets/send/Actor/SetActorNamePacket.cs | 1 - .../inventory/InventoryBeginChangePacket.cs | 20 + .../inventory/InventoryEndChangePacket.cs | 20 + .../inventory/InventorySetBeginPacket.cs | 2 +- .../inventory/SetInitialEquipmentPacket.cs | 98 ++++ 16 files changed, 862 insertions(+), 98 deletions(-) delete mode 100644 FFXIVClassic Map Server/bin/Debug/FFXIVClassic Map Server.vshost.exe.manifest create mode 100644 FFXIVClassic Map Server/dataobjects/Appearance.cs create mode 100644 FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryBeginChangePacket.cs create mode 100644 FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryEndChangePacket.cs create mode 100644 FFXIVClassic Map Server/packets/send/Actor/inventory/SetInitialEquipmentPacket.cs diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index ccb966bf..8b2600ce 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -64,7 +64,7 @@ namespace FFXIVClassic_Lobby_Server } } - public static Character getCharacter(uint userId, uint charId) + public static Character getCharacter(uint charId) { using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) { @@ -72,7 +72,7 @@ namespace FFXIVClassic_Lobby_Server try { conn.Open(); - chara = conn.Query("SELECT * FROM characters WHERE id=@CharaId and userId=@UserId", new { UserId = userId, CharaId = charId }).SingleOrDefault(); + chara = conn.Query("SELECT * FROM characters WHERE id=@CharaId", new { CharaId = charId }).SingleOrDefault(); } catch (MySqlException e) { @@ -86,5 +86,27 @@ namespace FFXIVClassic_Lobby_Server } } + public static Appearance getAppearance(uint charaId) + { + using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + Appearance appearance = null; + try + { + conn.Open(); + appearance = conn.Query("SELECT * FROM characters_appearance WHERE characterId=@CharaId", new { CharaId = charaId }).SingleOrDefault(); + } + catch (MySqlException e) + { + } + finally + { + conn.Dispose(); + } + + return appearance; + } + } + } } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 9598507e..70a5ce68 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -67,6 +67,7 @@ + @@ -75,10 +76,14 @@ + + + + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 6d40e112..7d0381f8 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -15,6 +15,7 @@ using FFXIVClassic_Map_Server.packets.receive; using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send.login; using FFXIVClassic_Map_Server.packets.send.Actor.inventory; +using FFXIVClassic_Map_Server.packets.send.Actor; namespace FFXIVClassic_Lobby_Server { @@ -165,8 +166,8 @@ namespace FFXIVClassic_Lobby_Server //Get Character info //Create player actor - client.sendPacketQueue.Add(init); - client.sendPacketQueue.Add(reply2); + client.queuePacket(init); + client.queuePacket(reply2); break; //Ping case 0x0001: @@ -177,9 +178,6 @@ namespace FFXIVClassic_Lobby_Server //Unknown case 0x0002: subpacket.debugPrintSubPacket(); - - BasePacket setMapPacket = BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false); - BasePacket setPlayerActorPacket = BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false); BasePacket reply5 = new BasePacket("./packets/login/login5.bin"); BasePacket reply6 = new BasePacket("./packets/login/login6_data.bin"); @@ -192,6 +190,7 @@ namespace FFXIVClassic_Lobby_Server BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); +#region replaceid setinv.replaceActorID(player.actorID); currancy.replaceActorID(player.actorID); keyitems.replaceActorID(player.actorID); @@ -201,20 +200,31 @@ namespace FFXIVClassic_Lobby_Server reply7.replaceActorID(player.actorID); reply8.replaceActorID(player.actorID); reply9.replaceActorID(player.actorID); +#endregion - client.sendPacketQueue.Add(setMapPacket); - client.sendPacketQueue.Add(setPlayerActorPacket); - client.sendPacketQueue.Add(reply5); - client.sendPacketQueue.Add(reply6); - + client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false)); + client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); + client.queuePacket(reply5); + client.queuePacket(reply6); + client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); + client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); + + ////////ITEMS//////// + client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); + +#region itemsetup + //TEST List items = new List(); - items.Add(new Item(1337, 8030920, 0)); //Leather Jacket + 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 int count = 0; @@ -240,20 +250,37 @@ namespace FFXIVClassic_Lobby_Server setinvPackets.Add(beginInventory); setinvPackets.Add(setInventory); setinvPackets.Add(endInventory); +#endregion - BasePacket setInvBasePacket = BasePacket.createPacket(setinvPackets, true, false); - client.sendPacketQueue.Add(setInvBasePacket); + client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); + //client.queuePacket(setinv); + //client.queuePacket(currancy); + //client.queuePacket(keyitems); - //client.sendPacketQueue.Add(setinv); - //client.sendPacketQueue.Add(currancy); - //client.sendPacketQueue.Add(keyitems); +#region equipsetup + SetInitialEquipmentPacket initialEqupmentPacket = new SetInitialEquipmentPacket(); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.SLOT_BODY, 5); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.SLOT_HEAD, 3); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.SLOT_UNDERSHIRT, 6); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.SLOT_UNDERGARMENT, 7); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.SLOT_MAINHAND, 2); + initialEqupmentPacket.setItem(SetInitialEquipmentPacket.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.sendPacketQueue.Add(reply7); - client.sendPacketQueue.Add(reply8); - client.sendPacketQueue.Add(reply9); - client.sendPacketQueue.Add(reply10); + 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); break; //Chat Received diff --git a/FFXIVClassic Map Server/bin/Debug/FFXIVClassic Map Server.vshost.exe.manifest b/FFXIVClassic Map Server/bin/Debug/FFXIVClassic Map Server.vshost.exe.manifest deleted file mode 100644 index 061c9ca9..00000000 --- a/FFXIVClassic Map Server/bin/Debug/FFXIVClassic Map Server.vshost.exe.manifest +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/FFXIVClassic Map Server/bin/Debug/packets/login/login6_data.bin b/FFXIVClassic Map Server/bin/Debug/packets/login/login6_data.bin index 51c9898010048308af69e80e72456ba61d37e9cf..95c8e4c28a769b5454cadf5d57dff85a232ab842 100644 GIT binary patch delta 21 ccmdlWK0}0^k%56hf=gf{dm{7Z8!Q{x05LHI4*&oF delta 353 zcmbOsvO%1kk%56>1GmgZ_C)4-4Mt`LN6pzxAk6UK(mxS~Yd~2B28$OD0zfn~hyVf* z4bo@-;Q=!fNPzKz2w0AVfdPoXa;zY6kqaDbAQ}kRAru1#l;(ueTu_>ufuSDEzEk%58X0T(aBN!jjq){L9^7%y=F09eHbEC2ui delta 138 zcmaDL`anE{k%58X0k;&xN!jjq)VqW_WPvp9q5+NC|_*iw6N98YHgF h@Q)z^L!BR7-Q> 0); data[i + 1] = (byte)(xl >> 8); data[i + 2] = (byte)(xl >> 16); @@ -56,9 +318,9 @@ namespace FFXIVClassic_Lobby_Server.common for (int i = offset; i < offset + length; i += 8) { - int xl = (data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24); - int xr = (data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24); - blowfish_decipher(ref xl, ref xr, P); + uint xl = (uint)((data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24)); + uint xr = (uint)((data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24)); + blowfish_decipher(ref xl, ref xr); data[i + 0] = (byte)(xl >> 0); data[i + 1] = (byte)(xl >> 8); data[i + 2] = (byte)(xl >> 16); @@ -69,6 +331,130 @@ namespace FFXIVClassic_Lobby_Server.common data[i + 7] = (byte)(xr >> 24); } } + + private UInt32 F(UInt32 x) + { + UInt16 a; + UInt16 b; + UInt16 c; + UInt16 d; + UInt32 y; + + d = (UInt16)(x & 0x00FF); + x >>= 8; + c = (UInt16)(x & 0x00FF); + x >>= 8; + b = (UInt16)(x & 0x00FF); + x >>= 8; + a = (UInt16)(x & 0x00FF); + //y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d]; + y = S[0,a] + S[1,b]; + y = y ^ S[2,c]; + y = y + S[3,d]; + + return y; + } + + private void blowfish_encipher(ref UInt32 xl, ref UInt32 xr) + { + UInt32 temp; + Int32 i; + + for (i = 0; i < N; ++i) { + xl = xl ^ P[i]; + xr = F(xl) ^ xr; + + temp = xl; + xl = xr; + xr = temp; + } + + temp = xl; + xl = xr; + xr = temp; + + xr = xr ^ P[N]; + xl = xl ^ P[N + 1]; + + } + + private void blowfish_decipher(ref UInt32 xl, ref UInt32 xr) + { + UInt32 temp; + Int32 i; + + for (i = N + 1; i > 1; --i) { + xl = xl ^ P[i]; + xr = F(xl) ^ xr; + + /* Exchange xl and xr */ + temp = xl; + xl = xr; + xr = temp; + } + + /* Exchange xl and xr */ + temp = xl; + xl = xr; + xr = temp; + + xr = xr ^ P[1]; + xl = xl ^ P[0]; + + } + + private int initializeBlowfish(byte [] key) + { + Int16 i; + Int16 j; + Int16 k; + + int data; + uint datal; + uint datar; + + Buffer.BlockCopy(P_values, 0, P, 0, P_values.Length); + Buffer.BlockCopy(S_values, 0, S, 0, S_values.Length); + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | (SByte)key[j]; + j = (short)(j + 1); + if (j >= key.Length) + { + j = 0; + } + } + P[i] = P[i] ^ (uint)data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + blowfish_encipher(ref datal, ref datar); + + P[i] = datal; + P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + blowfish_encipher(ref datal, ref datar); + S[i,j] = datal; + S[i,j + 1] = datar; + } + } + + return 0; + } + } - -} \ No newline at end of file +} diff --git a/FFXIVClassic Map Server/dataobjects/Actor.cs b/FFXIVClassic Map Server/dataobjects/Actor.cs index b85910aa..f349aabc 100644 --- a/FFXIVClassic Map Server/dataobjects/Actor.cs +++ b/FFXIVClassic Map Server/dataobjects/Actor.cs @@ -1,4 +1,10 @@ -using System; +using FFXIVClassic_Lobby_Server; +using FFXIVClassic_Lobby_Server.common; +using FFXIVClassic_Lobby_Server.dataobjects; +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server.packets.send.Actor; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,38 +12,40 @@ using System.Text; namespace FFXIVClassic_Map_Server.dataobjects { class Actor - { - enum Appearance { - MODEL, - SIZE, - COLORINFO, - FACEINFO, - HIGHLIGHT_HAIR, - VOICE, - WEAPON1, - WEAPON2, - WEAPON3, - HEADGEAR, - BODYGEAR, - LEGSGEAR, - HANDSGEAR, - FEETGEAR, - WAISTGEAR, - UNKNOWN1, - R_EAR, - L_EAR, - UNKNOWN2, - UNKNOWN3, - R_FINGER, - L_FINGER - } + { + public const int SIZE = 0; + public const int COLORINFO = 1; + public const int FACEINFO = 2; + public const int HIGHLIGHT_HAIR = 3; + public const int VOICE = 4; + public const int WEAPON1 = 5; + public const int WEAPON2 = 6; + public const int WEAPON3 = 7; + public const int UNKNOWN1 = 8; + public const int UNKNOWN2 = 9; + public const int UNKNOWN3 = 10; + public const int UNKNOWN4 = 11; + public const int HEADGEAR = 12; + public const int BODYGEAR = 13; + public const int LEGSGEAR = 14; + public const int HANDSGEAR = 15; + public const int FEETGEAR = 16; + public const int WAISTGEAR = 17; + public const int UNKNOWN5 = 18; + public const int R_EAR = 19; + public const int L_EAR = 20; + public const int UNKNOWN6 = 21; + public const int UNKNOWN7 = 22; + public const int R_FINGER = 23; + public const int L_FINGER = 24; public uint actorID; public uint displayNameID; public string customDisplayName; - public uint[] appearanceIDs; + public uint modelID; + public uint[] appearanceIDs = new uint[0x1D]; public float positionX, positionY, positionZ; public float oldPositionX, oldPositionY, oldPositionZ; @@ -49,5 +57,40 @@ namespace FFXIVClassic_Map_Server.dataobjects actorID = id; } + public void setPlayerAppearance() + { + Appearance appearance = Database.getAppearance(actorID); + + modelID = Appearance.getTribeModel(appearance.tribe); + appearanceIDs[SIZE] = appearance.size; + appearanceIDs[COLORINFO] = (uint)(appearance.skinColor | (appearance.hairColor << 10) | (appearance.eyeColor << 20)); + appearanceIDs[FACEINFO] = PrimitiveConversion.ToUInt32(appearance.getFaceInfo()); + appearanceIDs[HIGHLIGHT_HAIR] = (uint)(appearance.hairHighlightColor | appearance.hairStyle << 10); + appearanceIDs[VOICE] = appearance.voice; + appearanceIDs[WEAPON1] = appearance.mainHand; + appearanceIDs[WEAPON2] = appearance.offHand; + appearanceIDs[HEADGEAR] = appearance.head; + appearanceIDs[BODYGEAR] = appearance.body; + appearanceIDs[LEGSGEAR] = appearance.legs; + appearanceIDs[HANDSGEAR] = appearance.hands; + appearanceIDs[FEETGEAR] = appearance.feet; + appearanceIDs[WAISTGEAR] = appearance.waist; + appearanceIDs[R_EAR] = appearance.rightEar; + appearanceIDs[L_EAR] = appearance.leftEar; + appearanceIDs[R_FINGER] = appearance.rightFinger; + appearanceIDs[L_FINGER] = appearance.leftFinger; + } + + public SubPacket createNamePacket(uint playerActorID) + { + return SetActorNamePacket.buildPacket(playerActorID, actorID, displayNameID, displayNameID == 0xFFFFFFFF ? customDisplayName : ""); + } + + public SubPacket createAppearancePacket(uint playerActorID) + { + SetActorAppearancePacket setappearance = new SetActorAppearancePacket(modelID, appearanceIDs); + return setappearance.buildPacket(playerActorID, actorID); + } + } } diff --git a/FFXIVClassic Map Server/dataobjects/Appearance.cs b/FFXIVClassic Map Server/dataobjects/Appearance.cs new file mode 100644 index 00000000..6abb0c37 --- /dev/null +++ b/FFXIVClassic Map Server/dataobjects/Appearance.cs @@ -0,0 +1,143 @@ +using FFXIVClassic_Lobby_Server.common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Lobby_Server.dataobjects +{ + class Appearance + { + //////////// + //Chara Info + public byte tribe = 0; + public byte size = 0; + public byte voice = 0; + public ushort skinColor = 0; + + public ushort hairStyle = 0; + public ushort hairColor = 0; + public ushort hairHighlightColor = 0; + public ushort eyeColor = 0; + public byte characteristicsColor = 0; + + public byte faceType = 0; + public byte faceEyebrows = 0; + public byte faceEyeShape = 0; + public byte faceIrisSize = 0; + public byte faceNose = 0; + public byte faceMouth = 0; + public byte faceFeatures = 0; + public byte characteristics = 0; + public byte ears = 0; + + public uint mainHand = 0; + public uint offHand = 0; + + public uint head = 0; + public uint body = 0; + public uint legs = 0; + public uint hands = 0; + public uint feet = 0; + public uint waist = 0; + public uint rightEar = 0; + public uint leftEar = 0; + public uint rightFinger = 0; + public uint leftFinger = 0; + //Chara Info + //////////// + + public struct FaceInfo + { + [BitfieldLength(5)] + public uint characteristics; + [BitfieldLength(3)] + public uint characteristicsColor; + [BitfieldLength(6)] + public uint type; + [BitfieldLength(2)] + public uint ears; + [BitfieldLength(2)] + public uint mouth; + [BitfieldLength(2)] + public uint features; + [BitfieldLength(3)] + public uint nose; + [BitfieldLength(3)] + public uint eyeShape; + [BitfieldLength(1)] + public uint irisSize; + [BitfieldLength(3)] + public uint eyebrows; + [BitfieldLength(2)] + public uint unknown; + } + + public FaceInfo getFaceInfo() + { + FaceInfo faceInfo = new FaceInfo(); + faceInfo.characteristics = characteristics; + faceInfo.characteristicsColor = characteristicsColor; + faceInfo.type = faceType; + faceInfo.ears = ears; + faceInfo.features = faceFeatures; + faceInfo.eyebrows = faceEyebrows; + faceInfo.eyeShape = faceEyeShape; + faceInfo.irisSize = faceIrisSize; + faceInfo.mouth = faceMouth; + faceInfo.nose = faceNose; + return faceInfo; + } + + public static UInt32 getTribeModel(byte tribe) + { + switch (tribe) + { + //Hyur Midlander Male + case 1: + default: + return 1; + + //Hyur Midlander Female + case 2: + return 2; + + //Elezen Male + case 4: + case 6: + return 3; + + //Elezen Female + case 5: + case 7: + return 4; + + //Lalafell Male + case 8: + case 10: + return 5; + + //Lalafell Female + case 9: + case 11: + return 6; + + //Miqo'te Female + case 12: + case 13: + return 8; + + //Roegadyn Male + case 14: + case 15: + return 7; + + //Hyur Highlander Male + case 3: + return 9; + } + } + + } +} diff --git a/FFXIVClassic Map Server/dataobjects/Player.cs b/FFXIVClassic Map Server/dataobjects/Player.cs index 61ece6da..9632421d 100644 --- a/FFXIVClassic Map Server/dataobjects/Player.cs +++ b/FFXIVClassic Map Server/dataobjects/Player.cs @@ -27,7 +27,8 @@ namespace FFXIVClassic_Map_Server.dataobjects public Player(uint actorId) { this.actorID = actorId; - createPlayerActor(actorId, null); + Character chara = Database.getCharacter(actorId); + createPlayerActor(actorId, chara); } public void addConnection(ClientConnection conn) @@ -72,9 +73,19 @@ namespace FFXIVClassic_Map_Server.dataobjects return conn1; } + public Actor getActor() + { + return playerActor; + } + public void createPlayerActor(uint actorId, Character chara) { playerActor = new Actor(actorId); + + playerActor.displayNameID = 0xFFFFFFFF; + playerActor.customDisplayName = chara.name; + playerActor.setPlayerAppearance(); + actorInstanceList.Add(playerActor); } diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorAppearancePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorAppearancePacket.cs index 2dcf56c3..09f427ac 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorAppearancePacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorAppearancePacket.cs @@ -38,14 +38,15 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public uint modelID; public uint[] appearanceIDs; - public SetActorAppearancePacket(uint monsterModelID) + public SetActorAppearancePacket(uint modelID) { - modelID = monsterModelID; - appearanceIDs = new uint[22]; + this.modelID = modelID; + appearanceIDs = new uint[0x1D]; } - public SetActorAppearancePacket(uint[] appearanceTable) + public SetActorAppearancePacket(uint modelID, uint[] appearanceTable) { + this.modelID = modelID; appearanceIDs = appearanceTable; } @@ -58,7 +59,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor using (BinaryWriter binWriter = new BinaryWriter(mem)) { binWriter.Write((uint)modelID); - for (int i = 0; i < 0x1A; i++) + for (int i = 0; i <= 0x1A; i++) { binWriter.Write((uint)i); binWriter.Write((uint)appearanceIDs[i]); @@ -68,12 +69,12 @@ namespace FFXIVClassic_Map_Server.packets.send.actor binWriter.Write((uint) 0x1C); binWriter.Write((uint) 0x00); } - data = mem.GetBuffer(); + } SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data); return packet; - } + } } } diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs index 7caf46d2..6274e641 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs @@ -32,7 +32,6 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor } } - data = mem.GetBuffer(); } SubPacket packet = new SubPacket(OPCODE, playerActorID, targetActorID, data); diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryBeginChangePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryBeginChangePacket.cs new file mode 100644 index 00000000..862f0eea --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryBeginChangePacket.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.Actor.inventory +{ + class InventoryBeginChangePacket + { + public const ushort OPCODE = 0x016D; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint playerActorID) + { + return new SubPacket(OPCODE, playerActorID, playerActorID, new byte[8]); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryEndChangePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryEndChangePacket.cs new file mode 100644 index 00000000..6d031497 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryEndChangePacket.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.Actor.inventory +{ + class InventoryEndChangePacket + { + public const ushort OPCODE = 0x016E; + public const uint PACKET_SIZE = 0x28; + + public static SubPacket buildPacket(uint playerActorID) + { + return new SubPacket(OPCODE, playerActorID, playerActorID, new byte[8]); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs index 2887cab9..0327af2e 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs @@ -16,7 +16,7 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory public const ushort CODE_ITEMS = 0x0000; public const ushort CODE_CURRANCYITEMS = 0x0063; public const ushort CODE_KEYITEMS = 0x0064; - public const ushort CODE_EQUIPMENT = 0x00FE; + public const ushort CODE_EQUIPMENT = 0x00FE; public static SubPacket buildPacket(uint playerActorID, ushort size, ushort code) { diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/SetInitialEquipmentPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/SetInitialEquipmentPacket.cs new file mode 100644 index 00000000..f21f3ae1 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/SetInitialEquipmentPacket.cs @@ -0,0 +1,98 @@ +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.inventory +{ + class SetInitialEquipmentPacket + { + public const ushort OPCODE = 0x014E; + public const uint PACKET_SIZE = 0x58; + + public const uint UNEQUIPPED = 0xFFFFFFFF; + + public const int SLOT_MAINHAND = 0x00; + public const int SLOT_OFFHAND = 0x01; + public const int SLOT_THROWINGWEAPON = 0x04; + public const int SLOT_PACK = 0x05; + public const int SLOT_POUCH = 0x06; + public const int SLOT_HEAD = 0x08; + public const int SLOT_UNDERSHIRT = 0x09; + public const int SLOT_BODY = 0x0A; + public const int SLOT_UNDERGARMENT = 0x0B; + public const int SLOT_LEGS = 0x0C; + public const int SLOT_HANDS = 0x0D; + public const int SLOT_BOOTS = 0x0E; + public const int SLOT_WAIST = 0x0F; + public const int SLOT_NECK = 0x10; + public const int SLOT_EARS = 0x11; + public const int SLOT_WRISTS = 0x13; + public const int SLOT_RIGHTFINGER = 0x15; + public const int SLOT_LEFTFINGER = 0x16; + + private uint[] equipment = new uint[0x17]; + + public SetInitialEquipmentPacket() + { + for (int i = 0; i < equipment.Length; i++) + equipment[i] = UNEQUIPPED; //We will use this as "Unequipped" + } + + public void setItem(int slot, uint itemSlot) + { + if (slot >= equipment.Length) + return; + + equipment[slot] = itemSlot; + } + + public List buildPackets(uint playerActorID) + { + List packets = new List(); + int packetCount = 0; + int runningCount = 0; + byte[] data = new byte[PACKET_SIZE - 0x20]; + MemoryStream mem = new MemoryStream(data); + BinaryWriter binWriter = new BinaryWriter(mem); + + for (int i = 0; i < equipment.Length; i++) + { + if (equipment[i] == UNEQUIPPED) + continue; + + binWriter.Write((UInt16)i); + binWriter.Write((UInt32)equipment[i]); + + packetCount++; + runningCount++; + + //Create another packet + if (runningCount >= 8) + { + packetCount = 0; + binWriter.Write((UInt32)8); + binWriter.Dispose(); + mem.Dispose(); + packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data)); + data = new byte[PACKET_SIZE - 0x20]; + mem = new MemoryStream(data); + binWriter = new BinaryWriter(mem); + } + } + + //Create any leftover subpacket + binWriter.BaseStream.Seek(0x30, SeekOrigin.Begin); + binWriter.Write((UInt32)packetCount); + binWriter.Dispose(); + mem.Dispose(); + packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data)); + + return packets; + } + + } +}