using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; using PSO2SERVER.Models; using PSO2SERVER.Zone; namespace PSO2SERVER.Protocol { public class PacketWriter : BinaryWriter { public PacketWriter() : base(new MemoryStream()) { } public PacketWriter(Stream s) : base(s) { } public void WriteMagic(uint magic, uint xor, uint sub) { var encoded = (magic + sub) ^ xor; Write(encoded); } public void WriteMagic(int magic, uint xor, uint sub) { uint newmagic = (uint)magic; WriteMagic(newmagic, xor, sub); } public void WriteAscii(string str, uint xor, uint sub) { if((str == null) || (str == "") || (str.Length == 0)) { WriteMagic(0, xor, sub); //if (str.Length == 0) //{ //} } else { // Magic, followed by string, followed by null terminator, // followed by padding characters if needed. var charCount = (uint) str.Length; var padding = 4 - (charCount & 3); WriteMagic(charCount + 1, xor, sub); Write(Encoding.ASCII.GetBytes(str)); for (var i = 0; i < padding; i++) Write((byte) 0); } } //public void WriteAscii(AsciiString str, uint xor, uint sub) //{ // if (str == null || str.Length == 0) // { // // 如果 AsciiString 为空或长度为 0,写入 magic,长度为 0 // WriteMagic(0, xor, sub); // } // else // { // // Magic, followed by string, followed by null terminator, // // followed by padding characters if needed. // var charCount = (uint)str.Length; // var padding = (4 - (charCount + 1) % 4) % 4; // +1 用于计算 null 终结符的空间 // // 写入 Magic 值(charCount + 1:包括 null 终结符) // WriteMagic(charCount + 1, xor, sub); // // 写入字符串的字节数据 // Write(str.ToBytes()); // // 填充 null 字节以保证 4 字节对齐 // for (var i = 0; i < padding; i++) // { // Write((byte)0); // } // } //} public void WriteUtf16(string str, uint xor, uint sub) { if ((str == null) || (str == "") || (str.Length == 0)) { WriteMagic(0, xor, sub); } else { // Magic, followed by string, followed by null terminator, // followed by a padding character if needed. var charCount = (uint) str.Length + 1; var padding = (charCount & 1); WriteMagic(charCount, xor, sub); Write(Encoding.GetEncoding("UTF-16").GetBytes(str)); Write((ushort) 0); if (padding != 0) Write((ushort) 0); } } public void WriteFixedLengthASCII(string str, int charCount) { var writeAmount = Math.Min(str.Length, charCount); var paddingAmount = charCount - writeAmount; if (writeAmount > 0) { var chopped = writeAmount != str.Length ? str.Substring(0, writeAmount) : str; Write(Encoding.GetEncoding("ASCII").GetBytes(chopped)); } if (paddingAmount > 0) { for (var i = 0; i < paddingAmount; i++) Write((byte) 0); } } public void WriteFixedLengthUtf16(string str, int charCount) { var writeAmount = Math.Min(str.Length, charCount); var paddingAmount = charCount - writeAmount; if (writeAmount > 0) { var chopped = writeAmount != str.Length ? str.Substring(0, writeAmount) : str; Write(Encoding.GetEncoding("UTF-16").GetBytes(chopped)); } if (paddingAmount > 0) { for (var i = 0; i < paddingAmount; i++) Write((ushort) 0); } } internal void WritePosition(PSOLocation location) { Write(Helper.FloatToHalfPrecision(location.RotX)); Write(Helper.FloatToHalfPrecision(location.RotY)); Write(Helper.FloatToHalfPrecision(location.RotZ)); Write(Helper.FloatToHalfPrecision(location.RotW)); Write(Helper.FloatToHalfPrecision(location.PosX)); Write(Helper.FloatToHalfPrecision(location.PosY)); Write(Helper.FloatToHalfPrecision(location.PosZ)); } public void WriteAccountHeader(uint AccountId) { Write(AccountId); Write((uint) 0); Write((ushort)ObjectType.Player); Write((ushort) 0); } public unsafe void WriteStruct(T structure) where T : struct { try { // 获取结构体的大小 int size = Marshal.SizeOf(); // 可以开启日志记录写入操作 //Logger.Write($"写入 {size} 字节, 结构体: {structure}"); // 创建字节数组用于存放结构体数据 var strArr = new byte[size]; // 固定字节数组,以便进行结构体转换 fixed (byte* ptr = strArr) { // 将结构体数据写入到字节数组 Marshal.StructureToPtr(structure, (IntPtr)ptr, false); } // 将字节数组写入到目标位置,可能是文件、网络等 Write(strArr); } catch (Exception ex) { // 处理错误,比如结构体转换异常或写入异常 // Logger.Error($"WriteStruct 处理异常: {ex.Message}"); throw new InvalidOperationException("结构体写入过程中发生错误", ex); } } // 新增的 WriteStructArray 方法 public unsafe void WriteStructArray(T[] structures) where T : struct { int totalSize = Marshal.SizeOf(typeof(T)) * structures.Length; var strArr = new byte[totalSize]; fixed (byte* ptr = strArr) { for (int i = 0; i < structures.Length; i++) { byte* currentPtr = ptr + (i * Marshal.SizeOf(typeof(T))); Marshal.StructureToPtr(structures[i], (IntPtr)currentPtr, false); } } Write(strArr); } public byte[] ToArray() { var ms = (MemoryStream) BaseStream; return ms.ToArray(); } public void WriteBytes(byte b, uint count) { for(int i = 0; i < count; i++) { Write(b); } } public void WriteByteArray(byte[] b) { Write(b); } public void WriteUintArray(uint[] array) { foreach (var item in array) { Write(item); } } public void WriteIntArray(int[] array) { foreach (var item in array) { Write(item); } } public void WriteUshortArray(ushort[] array) { foreach (var item in array) { Write(item); } } public void WriteShortArray(short[] array) { foreach (var item in array) { Write(item); } } public void WriteFloatArray(float[] array) { foreach (var item in array) { Write(item); } } public void WriteObjectHeader(ObjectHeader obj) { Write(obj.ID); Write(obj.Padding); Write((ushort)obj.ObjectType); Write(obj.MapID); } public void WriteObjectHeaderArray(ObjectHeader[] objlist) { foreach (var obj in objlist) { WriteObjectHeader(obj); } } public void WriteObjectHeaderList(List objlist) { foreach (var obj in objlist) { WriteObjectHeader(obj); // 直接写入每个 ObjectHeader 对象 } } // 支持 Guid 类型 public void WriteGuid(Guid guid) { Write(guid.ToByteArray()); } // 支持 DateTime 类型 public void WriteDateTime(DateTime dateTime) { var timestamp = new DateTimeOffset(dateTime).ToUnixTimeSeconds(); Write(timestamp); } // 支持 List public void WriteList(IEnumerable collection) where T : struct { // 判断集合是否是 FixedList if (collection is FixedList fixedList) { //Logger.Write($"{fixedList.Capacity}"); // 遍历 FixedList 的整个容量,即使它没有满 for (int i = 0; i < fixedList.Capacity; i++) { WriteStruct(fixedList[i]); } } else { // 如果是普通的 List 或其他实现了 IEnumerable 的集合,正常迭代 foreach (var item in collection) { WriteStruct(item); } } } // 支持 2D 数组 public void Write2DIntArray(int[,] array) { for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { Write(array[i, j]); } } } // 支持 2D 数组 public void Write2DUIntArray(uint[,] array) { for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { Write(array[i, j]); } } } // 写入 Half 类型(16 位浮动点数) public void WriteHalf(Half value) { Write(Half.GetBytes(value)); // 写入 2 个字节 } // 自动识别并写入枚举类型 public void WriteEnum(object value) { // 确保传入的是枚举类型 if (value is Enum enumValue) { // 获取枚举的底层类型(byte、int 等) Type underlyingType = Enum.GetUnderlyingType(value.GetType()); // 将枚举值转换为底层类型的数值 object underlyingValue = Convert.ChangeType(enumValue, underlyingType); // 根据底层类型进行写入 if (underlyingType == typeof(byte)) { Write((byte)underlyingValue); } else if (underlyingType == typeof(short)) { Write((short)underlyingValue); } else if (underlyingType == typeof(int)) { Write((int)underlyingValue); } else if (underlyingType == typeof(long)) { Write((long)underlyingValue); } else { throw new InvalidOperationException("Unsupported enum underlying type."); } } else { throw new ArgumentException("The value is not an enum type."); } } } }