PSO2SERVER/Server/Packets/PacketReader.cs
2024-09-11 17:13:00 +08:00

111 lines
3.1 KiB
C#

using PSO2SERVER.Models;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace PSO2SERVER.Packets
{
public class PacketReader : BinaryReader
{
public PacketReader(Stream s) : base(s)
{
}
public PacketReader(byte[] bytes) : base(new MemoryStream(bytes))
{
}
public PacketReader(byte[] bytes, uint position, uint size)
: base(new MemoryStream(bytes, (int) position, (int) size))
{
}
public uint ReadMagic(uint xor, uint sub)
{
return (ReadUInt32() ^ xor) - sub;
}
public string ReadAscii(uint xor, uint sub)
{
var magic = ReadMagic(xor, sub);
if (magic == 0)
{
return "";
}
var charCount = magic - 1;
var padding = 4 - (charCount & 3);
var data = ReadBytes((int) charCount);
for (var i = 0; i < padding; i++)
ReadByte();
return Encoding.ASCII.GetString(data);
}
public string ReadFixedLengthAscii(uint charCount)
{
var data = ReadBytes((int) charCount);
var str = Encoding.ASCII.GetString(data);
var endAt = str.IndexOf('\0');
if (endAt == -1)
return str;
return str.Substring(0, endAt);
}
public string ReadUtf16(uint xor, uint sub)
{
var magic = ReadMagic(xor, sub);
if (magic == 0)
{
return "";
}
var charCount = magic - 1;
var padding = (magic & 1);
var data = ReadBytes((int) (charCount*2));
ReadUInt16();
if (padding != 0)
ReadUInt16();
return Encoding.GetEncoding("UTF-16").GetString(data);
}
public string ReadFixedLengthUtf16(int charCount)
{
var data = ReadBytes(charCount*2);
var str = Encoding.GetEncoding("UTF-16").GetString(data);
var endAt = str.IndexOf('\0');
if (endAt == -1)
return str;
return str.Substring(0, endAt);
}
public T ReadStruct<T>() where T : struct
{
var structBytes = new byte[Marshal.SizeOf(typeof (T))];
Read(structBytes, 0, structBytes.Length);
return Helper.ByteArrayToStructure<T>(structBytes);
}
public PSOLocation ReadEntityPosition()
{
PSOLocation pos = new PSOLocation()
{
RotX = Helper.FloatFromHalfPrecision(ReadUInt16()),
RotY = Helper.FloatFromHalfPrecision(ReadUInt16()),
RotZ = Helper.FloatFromHalfPrecision(ReadUInt16()),
RotW = Helper.FloatFromHalfPrecision(ReadUInt16()),
PosX = Helper.FloatFromHalfPrecision(ReadUInt16()),
PosY = Helper.FloatFromHalfPrecision(ReadUInt16()),
PosZ = Helper.FloatFromHalfPrecision(ReadUInt16()),
};
return pos;
}
}
}