diff --git a/.gitignore b/.gitignore index f01e314a..d03fb113 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ Blowfish/Debug/ Debug/ FFXIVClassic_Lobby_Server.opensdf FFXIVClassic_Lobby_Server.sdf +FFXIVClassic Lobby Server/obj/ +FFXIVClassic Lobby Server/bin/ diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 56e0932c..eee44060 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -115,6 +115,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 37233416..2632cc4c 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -277,6 +277,9 @@ namespace FFXIVClassic_Lobby_Server break; case 0x012F: subpacket.debugPrintSubPacket(); + ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data); + if (paramRequest.paramName.Equals("charaWork/exp")) + player.getActor().sendCharaExpInfo(); break; /* RECRUITMENT */ //Start Recruiting diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index fc6e9a60..c830cc61 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -26,6 +26,27 @@ namespace FFXIVClassic_Map_Server.Actors { class Player : Character { + public const int CLASSID_PUG = 2; + public const int CLASSID_GLA = 3; + public const int CLASSID_MRD = 4; + public const int CLASSID_ARC = 7; + public const int CLASSID_LNC = 8; + public const int CLASSID_THM = 22; + public const int CLASSID_CNJ = 23; + + public const int CLASSID_CRP = 29; + public const int CLASSID_BSM = 30; + public const int CLASSID_ARM = 31; + public const int CLASSID_GSM = 32; + public const int CLASSID_LTW = 33; + public const int CLASSID_WVR = 34; + public const int CLASSID_ALC = 35; + public const int CLASSID_CUL = 36; + + public const int CLASSID_MIN = 39; + public const int CLASSID_BTN = 40; + public const int CLASSID_FSH = 41; + public const int MAXSIZE_INVENTORY_NORMAL = 200; public const int MAXSIZE_INVENTORY_CURRANCY = 320; public const int MAXSIZE_INVENTORY_KEYITEMS = 500; @@ -93,6 +114,10 @@ namespace FFXIVClassic_Map_Server.Actors public uint achievementPoints; + //Property Array Request Stuff + private int lastPosition = 0; + private int lastStep = 0; + public PlayerWork playerWork = new PlayerWork(); public ConnectedPlayer playerSession; @@ -113,6 +138,39 @@ namespace FFXIVClassic_Map_Server.Actors equipment = new Equipment(this, inventories[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT); + //Set the Skill level caps of all FFXIV (classes)skills to 50 + for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++) + { + if (i != CLASSID_PUG && + i != CLASSID_MRD && + i != CLASSID_GLA && + i != CLASSID_MRD && + i != CLASSID_ARC && + i != CLASSID_LNC && + i != CLASSID_THM && + i != CLASSID_CNJ && + i != CLASSID_CRP && + i != CLASSID_BSM && + i != CLASSID_ARM && + i != CLASSID_GSM && + i != CLASSID_LTW && + i != CLASSID_WVR && + i != CLASSID_ALC && + i != CLASSID_CUL && + i != CLASSID_MIN && + i != CLASSID_BTN && + i != CLASSID_FSH) + charaWork.battleSave.skillLevelCap[i] = 0xFF; + else + charaWork.battleSave.skillLevelCap[i] = 50; + + } + + charaWork.battleSave.skillLevel[CLASSID_GLA - 1] = 32; + charaWork.battleSave.skillLevel[CLASSID_PUG - 1] = 50; + charaWork.battleSave.skillLevel[CLASSID_THM - 1] = 5; + charaWork.battleSave.skillLevel[CLASSID_MRD - 1] = 42; + charaWork.property[0] = 1; charaWork.property[1] = 1; charaWork.property[2] = 1; @@ -718,7 +776,67 @@ namespace FFXIVClassic_Map_Server.Actors public void sendCharaExpInfo() { + if (lastStep == 0) + { + int maxLength; + if ((sizeof(short) * charaWork.battleSave.skillLevel.Length)-lastPosition < 0x5E) + maxLength = (sizeof(short) * charaWork.battleSave.skillLevel.Length) - lastPosition; + else + maxLength = 0x5E; + byte[] skillLevelBuffer = new byte[maxLength]; + Buffer.BlockCopy(charaWork.battleSave.skillLevel, 0, skillLevelBuffer, 0, skillLevelBuffer.Length); + SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); + + charaInfo1.setIsArrayMode(true); + if (maxLength == 0x5E) + { + charaInfo1.addBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x0); + lastPosition += maxLength; + } + else + { + charaInfo1.addBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x3); + lastPosition = 0; + lastStep++; + } + + charaInfo1.addTarget(); + + queuePacket(charaInfo1.buildPacket(actorId, actorId)); + } + else if (lastStep == 1) + { + int maxLength; + if ((sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition < 0x5E) + maxLength = (sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition; + else + maxLength = 0x5E; + + byte[] skillCapBuffer = new byte[maxLength]; + Buffer.BlockCopy(charaWork.battleSave.skillLevelCap, lastPosition, skillCapBuffer, 0, skillCapBuffer.Length); + SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); + + + if (maxLength == 0x5E) + { + charaInfo1.setIsArrayMode(true); + charaInfo1.addBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x1); + lastPosition += maxLength; + } + else + { + charaInfo1.setIsArrayMode(false); + charaInfo1.addBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x3); + lastStep = 0; + lastPosition = 0; + } + + charaInfo1.addTarget(); + + queuePacket(charaInfo1.buildPacket(actorId, actorId)); + } + } public InventoryItem[] getGearset(ushort classId) diff --git a/FFXIVClassic Map Server/packets/receive/ParameterDataRequestPacket.cs b/FFXIVClassic Map Server/packets/receive/ParameterDataRequestPacket.cs new file mode 100644 index 00000000..7413feb8 --- /dev/null +++ b/FFXIVClassic Map Server/packets/receive/ParameterDataRequestPacket.cs @@ -0,0 +1,43 @@ +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 ParameterDataRequestPacket + { + public const ushort OPCODE = 0x012F; + public const uint PACKET_SIZE = 0x48; + + public bool invalidPacket = false; + + public uint actorID; + public string paramName; + + public ParameterDataRequestPacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try{ + actorID = binReader.ReadUInt32(); + List strList = new List(); + byte curByte; + while ((curByte = binReader.ReadByte()) != 0 && strList.Count<=0x20) + { + strList.Add(curByte); + } + paramName = Encoding.ASCII.GetString(strList.ToArray()); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs index afb787ac..fc4c85c4 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs @@ -20,6 +20,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor private ushort runningByteTotal = 0; private byte[] data = new byte[PACKET_SIZE - 0x20]; + + private bool isArrayMode = false; private bool isMore = false; string currentTarget; @@ -93,6 +95,20 @@ namespace FFXIVClassic_Map_Server.packets.send.actor return true; } + public bool addBuffer(uint id, byte[] buffer, int index, int length, int page) + { + if (runningByteTotal + 5 + length + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES) + return false; + + binWriter.Write((byte)(length + 1)); + binWriter.Write((UInt32)id); + binWriter.Write(buffer, index, length); + binWriter.Write((byte)page); + runningByteTotal += (ushort)(6 + length); + + return true; + } + public bool addProperty(FFXIVClassic_Map_Server.Actors.Actor actor, string name) { string[] split = name.Split('.'); @@ -159,6 +175,11 @@ namespace FFXIVClassic_Map_Server.packets.send.actor } } + public void setIsArrayMode(bool flag) + { + isArrayMode = flag; + } + public void setIsMore(bool flag) { isMore = flag; @@ -171,7 +192,10 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public void addTarget() { - binWriter.Write((byte)(isMore ? 0x60 + currentTarget.Length : 0x82 + currentTarget.Length)); + if (isArrayMode) + binWriter.Write((byte)(0xA4 + currentTarget.Length)); + else + binWriter.Write((byte)(isMore ? 0x60 + currentTarget.Length : 0x82 + currentTarget.Length)); binWriter.Write(Encoding.ASCII.GetBytes(currentTarget)); runningByteTotal += (ushort)(1 + Encoding.ASCII.GetByteCount(currentTarget)); } diff --git a/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs b/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs index f99a3640..be3e2f6b 100644 --- a/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs +++ b/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs @@ -12,11 +12,11 @@ namespace FFXIVClassic_Map_Server.utils { class ActorPropertyPacketUtil { - Actor forActor; - uint playerActorId; - List subPackets = new List(); - SetActorPropetyPacket currentActorPropertyPacket; - string currentTarget; + private Actor forActor; + private uint playerActorId; + private List subPackets = new List(); + private SetActorPropetyPacket currentActorPropertyPacket; + private string currentTarget; public ActorPropertyPacketUtil(string firstTarget, Actor forActor, uint playerActorId) {