diff --git a/Server/ConsoleSystem.cs b/Server/ConsoleSystem.cs index a0a2324..0ebc428 100644 --- a/Server/ConsoleSystem.cs +++ b/Server/ConsoleSystem.cs @@ -704,7 +704,7 @@ namespace PSO2SERVER var fakeChar = new Character { - CharacterId = 12345678 + new Random().Next(), + CharacterID = 12345678 + new Random().Next(), Player = fakePlayer, Name = playerName, Looks = client.Character.Looks, diff --git a/Server/Models/Character.cs b/Server/Models/Character.cs index a82c377..c9ab99d 100644 --- a/Server/Models/Character.cs +++ b/Server/Models/Character.cs @@ -261,7 +261,7 @@ namespace PSO2SERVER.Models [Key] public int Id { get; set; } - public int CharacterId { get; set; } + public int CharacterID { get; set; } public int player_id { get; set; } public uint unk1 { get; set; } public uint voice_type { get; set; } diff --git a/Server/Models/PSO2Item.cs b/Server/Models/PSO2Item.cs index 132de52..2bccb12 100644 --- a/Server/Models/PSO2Item.cs +++ b/Server/Models/PSO2Item.cs @@ -34,8 +34,6 @@ namespace PSO2SERVER.Models [StructLayout(LayoutKind.Explicit)] public struct Items { - [FieldOffset(0)] - public PSO2ItemNone None; [FieldOffset(0)] public PSO2ItemWeapon Weapon; [FieldOffset(0)] @@ -46,8 +44,10 @@ namespace PSO2SERVER.Models public PSO2ItemCamo Camo; [FieldOffset(0)] public PSO2ItemUnit Unit; - [FieldOffset(0)] - public byte[] Unknown; + //[FieldOffset(0)] + //public byte[] Unknown; + //[FieldOffset(0)] + //public PSO2ItemNone None; } [StructLayout(LayoutKind.Sequential, Pack = 1)] diff --git a/Server/Packets/Handlers/03-ServerHandler/03-10-DoItMaybe.cs b/Server/Packets/Handlers/03-ServerHandler/03-10-DoItMaybe.cs deleted file mode 100644 index 5f2b7c1..0000000 --- a/Server/Packets/Handlers/03-ServerHandler/03-10-DoItMaybe.cs +++ /dev/null @@ -1,25 +0,0 @@ -using PSO2SERVER.Packets.PSOPackets; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PSO2SERVER.Packets.Handlers -{ - [PacketHandlerAttr(0x03, 0x10)] - public class DoItMaybe : PacketHandler - { - #region implemented abstract members of PacketHandler - - public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) - { - if (context.User == null || context.Character == null) - return; - - context.SendPacket(new LoadingScreenRemovePacket()); - } - - #endregion - } -} diff --git a/Server/Packets/Handlers/03-ServerHandler/03-10-MapLoaded.cs b/Server/Packets/Handlers/03-ServerHandler/03-10-MapLoaded.cs new file mode 100644 index 0000000..e4acad2 --- /dev/null +++ b/Server/Packets/Handlers/03-ServerHandler/03-10-MapLoaded.cs @@ -0,0 +1,45 @@ +using PSO2SERVER.Models; +using PSO2SERVER.Packets.PSOPackets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PSO2SERVER.Packets.Handlers +{ + [PacketHandlerAttr(0x03, 0x10)] + public class MapLoaded : PacketHandler + { + [StructLayout(LayoutKind.Sequential)] + public struct MapLoadedPacket + { + /// Loaded zone object. + public ObjectHeader MapObject; + + /// Unknown data, 32 bytes. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public byte[] Unk; + + // 可选构造函数 + public MapLoadedPacket(ObjectHeader mapObject) + { + MapObject = mapObject; + Unk = new byte[0x20]; + } + } + + #region implemented abstract members of PacketHandler + + public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) + { + if (context.User == null || context.Character == null) + return; + + context.SendPacket(new LoadingScreenRemovePacket()); + } + + #endregion + } +} diff --git a/Server/Packets/Handlers/0B-QuestHandler/0B-19-QuestDifficultyRequestHandler.cs b/Server/Packets/Handlers/0B-QuestHandler/0B-19-QuestDifficultyRequestHandler.cs index 3bedecd..b805f4f 100644 --- a/Server/Packets/Handlers/0B-QuestHandler/0B-19-QuestDifficultyRequestHandler.cs +++ b/Server/Packets/Handlers/0B-QuestHandler/0B-19-QuestDifficultyRequestHandler.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace PSO2SERVER.Packets.Handlers { - [PacketHandlerAttr(0xB, 0x19)] + [PacketHandlerAttr(0x0B, 0x19)] class QuestDifficultyRequestHandler : PacketHandler { public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) diff --git a/Server/Packets/Handlers/0E-PartyHandler/0E-0C-QuestCounterHandler.cs b/Server/Packets/Handlers/0E-PartyHandler/0E-0C-QuestCounterHandler.cs index 6bcd8af..69943ff 100644 --- a/Server/Packets/Handlers/0E-PartyHandler/0E-0C-QuestCounterHandler.cs +++ b/Server/Packets/Handlers/0E-PartyHandler/0E-0C-QuestCounterHandler.cs @@ -4,7 +4,7 @@ using PSO2SERVER.Packets.PSOPackets; namespace PSO2SERVER.Packets.Handlers { - [PacketHandlerAttr(0xE, 0xC)] + [PacketHandlerAttr(0x0E, 0x0C)] class QuestDifficultyStartHandler : PacketHandler { // Go go maximum code duplication (for now) diff --git a/Server/Packets/Handlers/11-ClientHandler/11-04-CharacterSelected.cs b/Server/Packets/Handlers/11-ClientHandler/11-04-CharacterSelected.cs index 54d4bdb..a0c940b 100644 --- a/Server/Packets/Handlers/11-ClientHandler/11-04-CharacterSelected.cs +++ b/Server/Packets/Handlers/11-ClientHandler/11-04-CharacterSelected.cs @@ -22,19 +22,19 @@ namespace PSO2SERVER.Packets.Handlers public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) { + if (context.User == null) + return; + var reader = new PacketReader(data, position, size); var pkt = reader.ReadStruct(); //Logger.Write("id {0}", charId); - if (context.User == null) - return; - if (context.Character == null) // On character create, this is already set. { using (var db = new ServerEf()) { - var character = db.Characters.Where(c => c.CharacterId == pkt.CharId).First(); + var character = db.Characters.Where(c => c.CharacterID == pkt.CharId).First(); if (character == null || character.Player.PlayerId != context.User.PlayerId) { diff --git a/Server/Packets/Handlers/11-ClientHandler/11-05-CharacterCreate.cs b/Server/Packets/Handlers/11-ClientHandler/11-05-CharacterCreate.cs index d726367..509838b 100644 --- a/Server/Packets/Handlers/11-ClientHandler/11-05-CharacterCreate.cs +++ b/Server/Packets/Handlers/11-ClientHandler/11-05-CharacterCreate.cs @@ -4,8 +4,6 @@ using PSO2SERVER.Models; using PSO2SERVER.Packets.PSOPackets; using PSO2SERVER.Database; using System.Linq; -using System; -using System.Runtime.InteropServices; namespace PSO2SERVER.Packets.Handlers { @@ -20,30 +18,27 @@ namespace PSO2SERVER.Packets.Handlers return; - PacketWriter w = new PacketWriter(); var reader = new PacketReader(data, position, size); var info = string.Format("[<--] 接收到的数据 (hex): "); Logger.WriteHex(info, data); - var setting = reader.ReadStruct(); - var name = reader.ReadFixedLengthUtf16(16);//玩家名称 宽字符 - var looks = reader.ReadStruct(); - var unk3 = reader.ReadUInt32(); - var jobs = reader.ReadStruct(); - w.WriteStruct(jobs); - Logger.WriteHex(info, w.ToArray()); - //Logger.WriteInternal("[CHR] {0} 创建了名为 {1} 的新角色.", context.User.Username, name); + reader.ReadBytes(12); // 12 unknown bytes + reader.ReadByte(); // VoiceType + reader.ReadBytes(5); // 5 unknown bytes + reader.ReadUInt16(); // VoiceData + var name = reader.ReadFixedLengthUtf16(16); + + reader.BaseStream.Seek(0x4, SeekOrigin.Current); // Padding + var looks = reader.ReadStruct(); + var jobs = reader.ReadStruct(); + + Logger.WriteInternal("[CHR] {0} 创建了名为 {1} 的新角色.", context.User.Username, name); var newCharacter = new Character { - unk1 = setting.unk1, - voice_type = setting.voice_type, - unk2 = setting.unk2, - voice_pitch = setting.voice_pitch, Name = name, - Looks = looks, - unk3 = unk3, Jobs = jobs, + Looks = looks, Player = context.User }; @@ -55,16 +50,14 @@ namespace PSO2SERVER.Packets.Handlers if (existingCharacters.Count > 0) { // Increment ID if characters already exist - newCharacter.CharacterId = existingCharacters.Max(c => c.CharacterId) + 1; + newCharacter.CharacterID = existingCharacters.Max(c => c.CharacterID) + 1; } else { // Start with ID 1 if no characters exist - newCharacter.CharacterId = 1; + newCharacter.CharacterID = 1; } - newCharacter.player_id = context.User.PlayerId; - //Logger.Write("newCharacter.CharacterId {0} {1}", newCharacter.CharacterId, context.User.PlayerId); db.Characters.Add(newCharacter); diff --git a/Server/Packets/Handlers/11-ClientHandler/11-06-DeleteCharacter.cs b/Server/Packets/Handlers/11-ClientHandler/11-06-DeleteCharacter.cs index b722564..9dad9d4 100644 --- a/Server/Packets/Handlers/11-ClientHandler/11-06-DeleteCharacter.cs +++ b/Server/Packets/Handlers/11-ClientHandler/11-06-DeleteCharacter.cs @@ -22,7 +22,7 @@ namespace PSO2SERVER.Packets.Handlers { foreach (var character in db.Characters) - if (character.CharacterId == id) + if (character.CharacterID == id) { db.Characters.Remove(character); db.ChangeTracker.DetectChanges(); diff --git a/Server/Packets/Handlers/11-ClientHandler/11-1D-GuildInfoRequest.cs b/Server/Packets/Handlers/11-ClientHandler/11-1D-GuildInfoRequest.cs index 4ad1828..3aca2ce 100644 --- a/Server/Packets/Handlers/11-ClientHandler/11-1D-GuildInfoRequest.cs +++ b/Server/Packets/Handlers/11-ClientHandler/11-1D-GuildInfoRequest.cs @@ -22,11 +22,11 @@ namespace PSO2SERVER.Packets.Handlers foreach (var client in ServerApp.Instance.Server.Clients) { - if (client.Character.CharacterId == id) + if (client.Character.CharacterID == id) { var infoPacket = new GuildInfoPacket(context.Character); context.SendPacket(infoPacket); - Logger.Write("[NFO] Sent guild info to " + client.Character.CharacterId); + Logger.Write("[NFO] Sent guild info to " + client.Character.CharacterID); break; } } diff --git a/Server/Packets/Handlers/PacketHandler.cs b/Server/Packets/Handlers/PacketHandler.cs index 0fc7dd6..68c9fde 100644 --- a/Server/Packets/Handlers/PacketHandler.cs +++ b/Server/Packets/Handlers/PacketHandler.cs @@ -27,35 +27,60 @@ namespace PSO2SERVER.Packets.Handlers public static void LoadPacketHandlers() { - var handlers = (from t in Assembly.GetExecutingAssembly().GetTypes() - where t.IsClass && t.Namespace == "PSO2SERVER.Packets.Handlers" && - t.IsSubclassOf(typeof(PacketHandler)) - let attrs = (PacketHandlerAttr[])t.GetCustomAttributes(typeof(PacketHandlerAttr), false) - where attrs.Length > 0 - select new - { - attrs[0].Type, - attrs[0].Subtype, - HandlerType = t - }).ToList(); - - // Sort handlers by Type and Subtype - handlers = handlers.OrderBy(h => h.Type).ThenBy(h => h.Subtype).ToList(); - - foreach (var handler in handlers) + try { - Logger.WriteInternal("[数据] 数据包 0x{0:X2} - 0x{1:X2} 处理已载入 {2} ." - , handler.Type - , handler.Subtype - , handler.HandlerType.Name + var handlers = (from t in Assembly.GetExecutingAssembly().GetTypes() + where t.IsClass && t.Namespace == "PSO2SERVER.Packets.Handlers" && + t.IsSubclassOf(typeof(PacketHandler)) + let attrs = (PacketHandlerAttr[])t.GetCustomAttributes(typeof(PacketHandlerAttr), false) + where attrs.Length > 0 + select new + { + attrs[0].Type, + attrs[0].Subtype, + HandlerType = t + }).ToList(); + + // Sort handlers by Type and Subtype + handlers = handlers.OrderBy(h => h.Type).ThenBy(h => h.Subtype).ToList(); + + foreach (var handler in handlers) + { + Logger.WriteInternal("[数据] 数据包 0x{0:X2} - 0x{1:X2} 处理已载入 {2}.", + handler.Type, + handler.Subtype, + handler.HandlerType.Name ); - ushort packetTypeUShort = Helper.PacketTypeToUShort(handler.Type, handler.Subtype); - if (!Handlers.ContainsKey(packetTypeUShort)) - { - Handlers.Add(packetTypeUShort, (PacketHandler)Activator.CreateInstance(handler.HandlerType)); + ushort packetTypeUShort = Helper.PacketTypeToUShort(handler.Type, handler.Subtype); + if (!Handlers.ContainsKey(packetTypeUShort)) + { + // Create instance and add to dictionary + var handlerInstance = (PacketHandler)Activator.CreateInstance(handler.HandlerType); + Handlers.Add(packetTypeUShort, handlerInstance); + } + else + { + Logger.WriteInternal("[警告] 数据包 0x{0:X2} - 0x{1:X2} 已存在处理器 {2}.", + handler.Type, + handler.Subtype, + handler.HandlerType.Name + ); + } } } + catch (ReflectionTypeLoadException ex) + { + // Log the exception details + foreach (var loaderException in ex.LoaderExceptions) + { + Logger.WriteInternal("[错误] 加载类型时出现异常: {0}", loaderException.Message); + } + } + catch (Exception ex) + { + Logger.WriteInternal("[错误] 发生异常: {0}", ex.Message); + } } /// diff --git a/Server/Packets/PSOPackets/08-SpawnPacket/08-04-CharacterSpawnPacket.cs b/Server/Packets/PSOPackets/08-SpawnPacket/08-04-CharacterSpawnPacket.cs index 38f6b40..44d10ef 100644 --- a/Server/Packets/PSOPackets/08-SpawnPacket/08-04-CharacterSpawnPacket.cs +++ b/Server/Packets/PSOPackets/08-SpawnPacket/08-04-CharacterSpawnPacket.cs @@ -38,43 +38,36 @@ namespace PSO2SERVER.Packets.PSOPackets var writer = new PacketWriter(); // Player header - writer.WritePlayerHeader((uint) _character.Player.PlayerId); + writer.WritePlayerHeader((uint)_character.Player.PlayerId); // Spawn position writer.Write(Position); - writer.Write((ushort) 0); // padding? + writer.Write((ushort)0); // padding? writer.WriteFixedLengthASCII("Character", 32); - writer.Write((ushort) 1); // 0x44 - writer.Write((ushort) 0); // 0x46 - writer.Write((uint) 602); // 0x48 - writer.Write((uint) 1); // 0x4C - writer.Write((uint) 53); // 0x50 - writer.Write((uint) 0); // 0x54 - - writer.Write((uint) (IsItMe ? 0x2F : 0x27)); // 0x58 - writer.Write((ushort) 0); // 0x5C - writer.Write((ushort) 0); // 0x5E - - writer.Write((uint)_character.CharacterId); - writer.Write((uint)_character.player_id); - writer.Write(_character.voice_type); - writer.Write((uint)_character.voice_pitch); - //writer.Write((uint)_character.CharacterId); // player ID copy - //writer.Write((uint)0); // "char array ugggghhhhh" according to PolarisLegacy - //writer.Write((uint)0); // "voiceParam_unknown4" - //writer.Write((uint)0); // "voiceParam_unknown8" + writer.Write((ushort)1); // 0x44 + writer.Write((ushort)0); // 0x46 + writer.Write((uint)602); // 0x48 + writer.Write((uint)1); // 0x4C + writer.Write((uint)53); // 0x50 + writer.Write((uint)0); // 0x54 + writer.Write((uint)(IsItMe ? 47 : 39)); // 0x58 + writer.Write((ushort)559); // 0x5C + writer.Write((ushort)306); // 0x5E + writer.Write((uint)_character.Player.PlayerId); // player ID copy + writer.Write((uint)0); // "char array ugggghhhhh" according to PolarisLegacy + writer.Write((uint)0); // "voiceParam_unknown4" + writer.Write((uint)0); // "voiceParam_unknown8" writer.WriteFixedLengthUtf16(_character.Name, 16); writer.Write((uint)0); // 0x90 writer.WriteStruct(_character.Looks); writer.WriteStruct(_character.Jobs); writer.WriteFixedLengthUtf16("", 32); // title? - - writer.Write((uint) 0); // 0x204 - writer.Write((uint) 0); // gmflag? + writer.Write((uint)0); // 0x204 + writer.Write((uint)0); // gmflag? writer.WriteFixedLengthUtf16(_character.Player.Nickname, 16); // nickname, maybe not 16 chars? for (var i = 0; i < 64; i++) - writer.Write((byte) 0); + writer.Write((byte)0); return writer.ToArray(); } diff --git a/Server/Packets/PSOPackets/11-ClientPacket/11-03-CharacterListPacket.cs b/Server/Packets/PSOPackets/11-ClientPacket/11-03-CharacterListPacket.cs index 138fba2..ecbe841 100644 --- a/Server/Packets/PSOPackets/11-ClientPacket/11-03-CharacterListPacket.cs +++ b/Server/Packets/PSOPackets/11-ClientPacket/11-03-CharacterListPacket.cs @@ -3,6 +3,7 @@ using PSO2SERVER.Models; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Runtime.Remoting.Contexts; using System.Text; @@ -26,43 +27,6 @@ namespace PSO2SERVER.Packets.PSOPackets private int _PlayerId; - /// - /// Available characters. - /// - public Character[] Characters { get; set; } - - //public Item[][] EquippedItems { get; set; } = new Item[10][]; - - /// - /// Character play times. - /// - public uint[] PlayTimes { get; set; } = new uint[30]; - - /// - /// Character deletion flags (flag, deletion timestamp). - /// - public (uint Flag, uint Timestamp)[] DeletionFlags { get; set; } = new (uint, uint)[30]; - - /// - /// Character ship transfer flags. - /// - public (uint Flag, uint Transfer)[] TransferFlags { get; set; } = new (uint, uint)[30]; - - /// - /// Account accessory flag (?). - /// - public ushort AccountAccessory { get; set; } - - /// - /// Login survey flag. - /// - public uint LoginSurvey { get; set; } - - /// - /// Ad flag (on global 12 star unit ad). - /// - public uint Ad { get; set; } - public CharacterListPacket(int PlayerId) { _PlayerId = PlayerId; @@ -78,7 +42,7 @@ namespace PSO2SERVER.Packets.PSOPackets { var chars = db.Characters .Where(w => w.Player.PlayerId == _PlayerId) - .OrderBy(o => o.CharacterId) // TODO: Order by last played + .OrderBy(o => o.CharacterID) // TODO: Order by last played .Select(s => s); writer.Write((uint)chars.Count()); // Number of characters @@ -88,19 +52,20 @@ namespace PSO2SERVER.Packets.PSOPackets foreach (var ch in chars) { - writer.Write(ch.CharacterId); - writer.Write(ch.player_id); - writer.Write(ch.unk1); - writer.Write(ch.voice_type); - writer.Write(ch.unk2); - writer.Write(ch.voice_pitch); + writer.Write((uint)ch.CharacterID); + writer.Write((uint)_PlayerId); + + for (var i = 0; i < 0x10; i++) + writer.Write((byte)0); + writer.WriteFixedLengthUtf16(ch.Name, 16); writer.Write((uint)0); - writer.WriteStruct(ch.Looks); + + writer.WriteStruct(ch.Looks); // Note: Pre-Episode 4 created looks doesn't seem to work anymore writer.WriteStruct(ch.Jobs); - for (var i = 0; i < 0x90; i++) - writer.Write((byte)0); + for (var i = 0; i < 0xFC; i++) + writer.Write((byte)3); } } diff --git a/Server/Packets/PSOPackets/1C-AlliancePacket/1C-1F-GuildInfoPacket.cs b/Server/Packets/PSOPackets/1C-AlliancePacket/1C-1F-GuildInfoPacket.cs index 14b4d6d..8fbdf48 100644 --- a/Server/Packets/PSOPackets/1C-AlliancePacket/1C-1F-GuildInfoPacket.cs +++ b/Server/Packets/PSOPackets/1C-AlliancePacket/1C-1F-GuildInfoPacket.cs @@ -24,7 +24,7 @@ namespace PSO2SERVER.Packets.PSOPackets writer.Write((byte) 0); // Character ID - writer.Write((uint) _character.CharacterId); + writer.Write((uint) _character.CharacterID); // Padding? for (var i = 0; i < 4; i++) diff --git a/Server/Packets/PacketWriter.cs b/Server/Packets/PacketWriter.cs index b0fbfb8..f0f013c 100644 --- a/Server/Packets/PacketWriter.cs +++ b/Server/Packets/PacketWriter.cs @@ -162,5 +162,10 @@ namespace PSO2SERVER.Packets Write(b); } } + + internal void WriteFixedLengthUtf16(int i, int v) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/Server/Server.csproj b/Server/Server.csproj index 7c3a322..5e77e66 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -172,7 +172,7 @@ - + diff --git a/数据对比/角色/extra.bin b/数据对比/角色/extra.bin new file mode 100644 index 0000000..701bcca Binary files /dev/null and b/数据对比/角色/extra.bin differ diff --git a/数据对比/角色/job-1-人类-猎人.bin b/数据对比/角色/job-1-人类-猎人.bin index 228e2d1..b94b79b 100644 Binary files a/数据对比/角色/job-1-人类-猎人.bin and b/数据对比/角色/job-1-人类-猎人.bin differ diff --git a/数据对比/角色/job-2-人类-猎人.bin b/数据对比/角色/job-2-人类-猎人.bin new file mode 100644 index 0000000..9ac6b6d Binary files /dev/null and b/数据对比/角色/job-2-人类-猎人.bin differ diff --git a/数据对比/角色/look-2-人类-猎人.bin b/数据对比/角色/look-2-人类-猎人.bin new file mode 100644 index 0000000..6e98e43 Binary files /dev/null and b/数据对比/角色/look-2-人类-猎人.bin differ