diff --git a/Server/Models/Stats.cs b/Server/Models/Stats.cs index 9d759ec..1616973 100644 --- a/Server/Models/Stats.cs +++ b/Server/Models/Stats.cs @@ -171,4 +171,71 @@ namespace PSO2SERVER.Models return new DamageType(value.Mul); } } + + public struct EXPReceiver + { + // 玩家获得经验的对象 + public ObjectHeader Object; // 如果 ObjectHeader 是结构体,则可以这样使用;如果是类,需要修改或替代 + + public byte Unk1; // 未知字段 1 + public byte Unk2; // 未知字段 2 + public byte[] Unk3; // 6 字节的数组(未知数据),这部分需要额外处理 + + // 主职业获得的经验 + public ulong Gained; + + // 主职业的总经验 + public ulong Total; + + // 主职业的新子等级(?) + public ushort Level2; + + // 主职业的新等级 + public ushort Level; + + // 主职业 + public ClassType Class; // 假设 ClassType 是一个枚举类型或者结构体 + + public byte[] Pad1; // 填充字节数组(3 字节),需要额外处理 + + // 副职业获得的经验 + public ulong GainedSub; + + // 副职业的总经验 + public ulong TotalSub; + + // 副职业的新子等级(?) + public ushort Level2Sub; + + // 副职业的新等级 + public ushort LevelSub; + + // 副职业 + public ClassType Subclass; // 假设 ClassType 是一个枚举类型或者结构体 + + public byte[] Pad2; // 填充字节数组(3 字节),需要额外处理 + + // 结构体构造函数,用于初始化数组和其他默认值 + public EXPReceiver(ObjectHeader objectHeader, byte unk1, byte unk2, byte[] unk3, ulong gained, ulong total, + ushort level2, ushort level, ClassType classType, byte[] pad1, ulong gainedSub, + ulong totalSub, ushort level2Sub, ushort levelSub, ClassType subclass, byte[] pad2) + { + Object = objectHeader; + Unk1 = unk1; + Unk2 = unk2; + Unk3 = unk3 ?? new byte[6]; // 默认值为6字节数组 + Gained = gained; + Total = total; + Level2 = level2; + Level = level; + Class = classType; + Pad1 = pad1 ?? new byte[3]; // 默认值为3字节数组 + GainedSub = gainedSub; + TotalSub = totalSub; + Level2Sub = level2Sub; + LevelSub = levelSub; + Subclass = subclass; + Pad2 = pad2 ?? new byte[3]; // 默认值为3字节数组 + } + } } diff --git a/Server/Party/PartyManager.cs b/Server/Party/PartyManager.cs index 1f2ec80..55d32ad 100644 --- a/Server/Party/PartyManager.cs +++ b/Server/Party/PartyManager.cs @@ -5,11 +5,11 @@ using System.Text; namespace PSO2SERVER.Party { - class PartyManager + public class PartyManager { - private static readonly PartyManager instance = new PartyManager(); + public static readonly PartyManager instance = new PartyManager(); - private Dictionary parties = new Dictionary(); // Key: Party, Value: Name? (for now) + public Dictionary parties = new Dictionary(); // Key: Party, Value: Name? (for now) public static PartyManager Instance { @@ -19,7 +19,7 @@ namespace PSO2SERVER.Party } } - private PartyManager() + public PartyManager() { Logger.WriteInternal("[PTY] PartyManager 初始化完成."); } diff --git a/Server/Protocol/Handlers/06-PlayerStatusHandler/06-01-DealDamage.cs b/Server/Protocol/Handlers/06-PlayerStatusHandler/06-01-DealDamage.cs new file mode 100644 index 0000000..f779d9e --- /dev/null +++ b/Server/Protocol/Handlers/06-PlayerStatusHandler/06-01-DealDamage.cs @@ -0,0 +1,38 @@ +using System; +using PSO2SERVER.Models; +using PSO2SERVER.Protocol.Packets; + +namespace PSO2SERVER.Protocol.Handlers +{ + [PacketHandlerAttr(0x06, 0x01)] + public class DealDamage : PacketHandler + { + public unsafe struct DealDamagePacket + { + /// Object that inflicted the damage. + public ObjectHeader Inflicter; + /// Object that received the damage. + public ObjectHeader Target; + public uint Attack_id; + public ulong Unk2; + /// Hitbox ID (?). + public uint Hitbox_id; + /// Hit x position. + public Half X_pos; + /// Hit y position. + public Half Y_pos; + /// Hit z position. + public Half Z_pos; + + public ushort unk4; + public ulong unk5; + public fixed byte unk6[0x18]; + } + + public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) + { + var info = string.Format("[<--] 接收到的数据 (hex): {0} 字节", data.Length); + Logger.WriteHex(info, data); + } + } +} diff --git a/Server/Protocol/PacketWriter.cs b/Server/Protocol/PacketWriter.cs index 5d0e114..92d7592 100644 --- a/Server/Protocol/PacketWriter.cs +++ b/Server/Protocol/PacketWriter.cs @@ -303,7 +303,7 @@ namespace PSO2SERVER.Protocol } // 写入 Half 类型(16 位浮动点数) - public void Write(Half value) + public void WriteHalf(Half value) { Write(Half.GetBytes(value)); // 写入 2 个字节 } diff --git a/Server/Protocol/Packets/04-ObjectRelatedPacket/04-0F-EnemyKilledPacket.cs b/Server/Protocol/Packets/04-ObjectRelatedPacket/04-0F-EnemyKilledPacket.cs index b0fbe62..8840913 100644 --- a/Server/Protocol/Packets/04-ObjectRelatedPacket/04-0F-EnemyKilledPacket.cs +++ b/Server/Protocol/Packets/04-ObjectRelatedPacket/04-0F-EnemyKilledPacket.cs @@ -45,7 +45,23 @@ namespace PSO2SERVER.Protocol.Packets public override byte[] Build() { var pkt = new PacketWriter(); - pkt.Write(X_pos); + pkt.WriteStruct(Receiver); + pkt.WriteStruct(Dmg_target); + pkt.WriteStruct(Dmg_inflicter); + pkt.Write(Damage_id); + pkt.Write(Dmg_amount); + pkt.Write(New_hp); + pkt.Write(Hitbox_id); + pkt.WriteHalf(X_pos); + pkt.WriteHalf(Y_pos); + pkt.WriteHalf(Z_pos); + pkt.Write(unk1); + pkt.Write(unk2); + pkt.Write(unk3); + pkt.Write(unk4); + pkt.Write(unk5); + pkt.Write(unk6); + pkt.Write(unk7); return pkt.ToArray(); } diff --git a/Server/Protocol/Packets/04-ObjectRelatedPacket/04-52-DamageReceivePacket.cs b/Server/Protocol/Packets/04-ObjectRelatedPacket/04-52-DamageReceivePacket.cs index 8c41aff..acfbba9 100644 --- a/Server/Protocol/Packets/04-ObjectRelatedPacket/04-52-DamageReceivePacket.cs +++ b/Server/Protocol/Packets/04-ObjectRelatedPacket/04-52-DamageReceivePacket.cs @@ -8,6 +8,33 @@ namespace PSO2SERVER.Protocol.Packets { public class DamageReceivePacket : Packet { + /// Player that receives this packet. + public ObjectHeader Receiver { get; set; } = new ObjectHeader(); + /// Object that receives this damage. + public ObjectHeader Dmg_target { get; set; } = new ObjectHeader(); + /// Object that deals this damage. + public ObjectHeader Dmg_inflicter { get; set; } = new ObjectHeader(); + /// Inflicted damage ID. + public uint Damage_id { get; set; } = 0; + /// How much damage was inflicted. + public int Dmg_amount { get; set; } = 0; + /// New HP. + public uint New_hp { get; set; } = 0; + /// Hitbox ID (?). + public uint Hitbox_id { get; set; } = 0; + /// Hit x position. + public Half X_pos { get; set; } = 0; + /// Hit y position. + public Half Y_pos { get; set; } = 0; + /// Hit z position. + public Half Z_pos { get; set; } = 0; + public ushort unk1 { get; set; } = 0; + public ushort unk2 { get; set; } = 0; + public ushort unk3 { get; set; } = 0; + public ushort unk4 { get; set; } = 0; + public ushort unk5 { get; set; } = 0; + public ushort unk6 { get; set; } = 0; + public ushort unk7 { get; set; } = 0; public DamageReceivePacket() { @@ -18,12 +45,29 @@ namespace PSO2SERVER.Protocol.Packets public override byte[] Build() { var pkt = new PacketWriter(); + pkt.WriteStruct(Receiver); + pkt.WriteStruct(Dmg_target); + pkt.WriteStruct(Dmg_inflicter); + pkt.Write(Damage_id); + pkt.Write(Dmg_amount); + pkt.Write(New_hp); + pkt.Write(Hitbox_id); + pkt.WriteHalf(X_pos); + pkt.WriteHalf(Y_pos); + pkt.WriteHalf(Z_pos); + pkt.Write(unk1); + pkt.Write(unk2); + pkt.Write(unk3); + pkt.Write(unk4); + pkt.Write(unk5); + pkt.Write(unk6); + pkt.Write(unk7); return pkt.ToArray(); } public override PacketHeader GetHeader() { - return new PacketHeader(0x04, 0x52, PacketFlags.None); + return new PacketHeader(0x04, 0x52, PacketFlags.OBJECT_RELATED); } #endregion diff --git a/Server/Protocol/Packets/06-PlayerStatusPacket/06-05-GainedEXPPacket.cs b/Server/Protocol/Packets/06-PlayerStatusPacket/06-05-GainedEXPPacket.cs index ab9ee1c..81e5032 100644 --- a/Server/Protocol/Packets/06-PlayerStatusPacket/06-05-GainedEXPPacket.cs +++ b/Server/Protocol/Packets/06-PlayerStatusPacket/06-05-GainedEXPPacket.cs @@ -1,16 +1,47 @@ using PSO2SERVER.Models; +using PSO2SERVER.Party; using System; using System.Collections.Generic; using System.Linq; using System.Text; +using static Mysqlx.Notice.Warning.Types; namespace PSO2SERVER.Protocol.Packets { public class GainedEXPPacket : Packet { + /// Packet receiver. + public ObjectHeader sender { get; set; } = new ObjectHeader(); + /// All players that gained EXP. + public List receivers { get; set; } = new List(); - public GainedEXPPacket() + public GainedEXPPacket(Client c, ulong gainedxp) { + sender = new ObjectHeader((uint)c._account.AccountId, ObjectType.Player); + + foreach (Client cl in PartyManager.instance.GetCurrentPartyForClient(c).getMembers()) + { + EXPReceiver receiver = new EXPReceiver + { + Object = new ObjectHeader((uint)cl._account.AccountId, ObjectType.Player), + //Unk1 = unk1, + //Unk2 = unk2, + //Unk3 = unk3 ?? new byte[6], // 默认值为6字节数组 + Gained = gainedxp, + //Total = total, + //Level2 = level2, + //Level = level, + Class = cl.Character.Jobs.mainClass, + //Pad1 = pad1 ?? new byte[3], // 默认值为3字节数组 + //GainedSub = gainedSub, + //TotalSub = totalSub, + //Level2Sub = level2Sub, + //LevelSub = levelSub, + //Subclass = subclass, + //Pad2 = pad2 ?? new byte[3], // 默认值为3字节数组 + }; + receivers.Add(receiver); + } } #region implemented abstract members of Packet @@ -18,12 +49,18 @@ namespace PSO2SERVER.Protocol.Packets public override byte[] Build() { var pkt = new PacketWriter(); + pkt.WriteStruct(sender); + pkt.WriteMagic((uint)receivers.Count, 0x7C49, 0x9E); + foreach (var entry in receivers) + { + pkt.WriteStruct(entry); + } return pkt.ToArray(); } public override PacketHeader GetHeader() { - return new PacketHeader(0x06, 0x05, PacketFlags.None); + return new PacketHeader(0x06, 0x05, PacketFlags.PACKED); } #endregion diff --git a/Server/Protocol/Packets/0E-PartyPacket/0E-02-PartyInitPacket.cs b/Server/Protocol/Packets/0E-PartyPacket/0E-02-PartyInitPacket.cs index 9f88d86..115b9ba 100644 --- a/Server/Protocol/Packets/0E-PartyPacket/0E-02-PartyInitPacket.cs +++ b/Server/Protocol/Packets/0E-PartyPacket/0E-02-PartyInitPacket.cs @@ -97,8 +97,6 @@ namespace PSO2SERVER.Protocol.Packets entries[i].id = new ObjectHeader((uint)players[i].Account.AccountId, ObjectType.Player); // Header of player entries[i].nickname = players[i].Account.Nickname; entries[i].char_name = players[i].Name; - //writer.WriteUtf16(players[i].Name, 0xD863, 0xA9); - //writer.WriteUtf16(players[i].Accounts.Nickname, 0xD863, 0xA9); entries[i].level = (byte)players[i].Jobs.entries.hunter.level; entries[i].sublevel = (byte)players[i].Jobs.entries.hunter.level2; entries[i].mainClass = players[i].Jobs.mainClass; diff --git a/Server/Server.csproj b/Server/Server.csproj index c50bac1..192627e 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -187,6 +187,7 @@ +