feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
This commit is contained in:
8
ServerCore/LuBan/Base/BeanBase.cs
Normal file
8
ServerCore/LuBan/Base/BeanBase.cs
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
namespace Luban
|
||||
{
|
||||
public abstract class BeanBase : ITypeId
|
||||
{
|
||||
public abstract int GetTypeId();
|
||||
}
|
||||
}
|
||||
1445
ServerCore/LuBan/Base/ByteBuf.cs
Normal file
1445
ServerCore/LuBan/Base/ByteBuf.cs
Normal file
@ -0,0 +1,1445 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Luban
|
||||
{
|
||||
|
||||
public enum EDeserializeError
|
||||
{
|
||||
OK,
|
||||
NOT_ENOUGH,
|
||||
EXCEED_SIZE,
|
||||
// UNMARSHAL_ERR,
|
||||
}
|
||||
|
||||
public class SerializationException : Exception
|
||||
{
|
||||
public SerializationException() { }
|
||||
public SerializationException(string msg) : base(msg) { }
|
||||
|
||||
public SerializationException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct SegmentSaveState
|
||||
{
|
||||
public SegmentSaveState(int readerIndex, int writerIndex)
|
||||
{
|
||||
ReaderIndex = readerIndex;
|
||||
WriterIndex = writerIndex;
|
||||
}
|
||||
|
||||
public int ReaderIndex { get; }
|
||||
|
||||
public int WriterIndex { get; }
|
||||
}
|
||||
|
||||
public sealed class ByteBuf : ICloneable, IEquatable<ByteBuf>
|
||||
{
|
||||
public ByteBuf()
|
||||
{
|
||||
Bytes = Array.Empty<byte>();
|
||||
ReaderIndex = WriterIndex = 0;
|
||||
}
|
||||
|
||||
public ByteBuf(int capacity)
|
||||
{
|
||||
Bytes = capacity > 0 ? new byte[capacity] : Array.Empty<byte>();
|
||||
ReaderIndex = 0;
|
||||
WriterIndex = 0;
|
||||
}
|
||||
|
||||
public ByteBuf(byte[] bytes)
|
||||
{
|
||||
Bytes = bytes;
|
||||
ReaderIndex = 0;
|
||||
WriterIndex = Capacity;
|
||||
}
|
||||
|
||||
public ByteBuf(byte[] bytes, int readIndex, int writeIndex)
|
||||
{
|
||||
Bytes = bytes;
|
||||
ReaderIndex = readIndex;
|
||||
WriterIndex = writeIndex;
|
||||
}
|
||||
|
||||
public ByteBuf(int capacity, Action<ByteBuf> releaser) : this(capacity)
|
||||
{
|
||||
_releaser = releaser;
|
||||
}
|
||||
|
||||
public static ByteBuf Wrap(byte[] bytes)
|
||||
{
|
||||
return new ByteBuf(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public void Replace(byte[] bytes)
|
||||
{
|
||||
Bytes = bytes;
|
||||
ReaderIndex = 0;
|
||||
WriterIndex = Capacity;
|
||||
}
|
||||
|
||||
public void Replace(byte[] bytes, int beginPos, int endPos)
|
||||
{
|
||||
Bytes = bytes;
|
||||
ReaderIndex = beginPos;
|
||||
WriterIndex = endPos;
|
||||
}
|
||||
|
||||
public int ReaderIndex { get; set; }
|
||||
|
||||
public int WriterIndex { get; set; }
|
||||
|
||||
private readonly Action<ByteBuf> _releaser;
|
||||
|
||||
public int Capacity => Bytes.Length;
|
||||
|
||||
public int Size { get { return WriterIndex - ReaderIndex; } }
|
||||
|
||||
public bool Empty => WriterIndex <= ReaderIndex;
|
||||
|
||||
public bool NotEmpty => WriterIndex > ReaderIndex;
|
||||
|
||||
|
||||
public void AddWriteIndex(int add)
|
||||
{
|
||||
WriterIndex += add;
|
||||
}
|
||||
|
||||
public void AddReadIndex(int add)
|
||||
{
|
||||
ReaderIndex += add;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1819 // 属性不应返回数组
|
||||
public byte[] Bytes { get; private set; }
|
||||
#pragma warning restore CA1819 // 属性不应返回数组
|
||||
|
||||
public byte[] CopyData()
|
||||
{
|
||||
var n = Remaining;
|
||||
if (n > 0)
|
||||
{
|
||||
var arr = new byte[n];
|
||||
Buffer.BlockCopy(Bytes, ReaderIndex, arr, 0, n);
|
||||
return arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
}
|
||||
|
||||
public int Remaining { get { return WriterIndex - ReaderIndex; } }
|
||||
|
||||
public void DiscardReadBytes()
|
||||
{
|
||||
WriterIndex -= ReaderIndex;
|
||||
Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex);
|
||||
ReaderIndex = 0;
|
||||
}
|
||||
|
||||
public int NotCompactWritable { get { return Capacity - WriterIndex; } }
|
||||
|
||||
public void WriteBytesWithoutSize(byte[] bs)
|
||||
{
|
||||
WriteBytesWithoutSize(bs, 0, bs.Length);
|
||||
}
|
||||
|
||||
public void WriteBytesWithoutSize(byte[] bs, int offset, int len)
|
||||
{
|
||||
EnsureWrite(len);
|
||||
Buffer.BlockCopy(bs, offset, Bytes, WriterIndex, len);
|
||||
WriterIndex += len;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ReaderIndex = WriterIndex = 0;
|
||||
}
|
||||
|
||||
private const int MIN_CAPACITY = 16;
|
||||
|
||||
private static int PropSize(int initSize, int needSize)
|
||||
{
|
||||
for (int i = Math.Max(initSize, MIN_CAPACITY); ; i <<= 1)
|
||||
{
|
||||
if (i >= needSize)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureWrite0(int size)
|
||||
{
|
||||
var needSize = WriterIndex + size - ReaderIndex;
|
||||
if (needSize < Capacity)
|
||||
{
|
||||
WriterIndex -= ReaderIndex;
|
||||
Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex);
|
||||
ReaderIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int newCapacity = PropSize(Capacity, needSize);
|
||||
var newBytes = new byte[newCapacity];
|
||||
WriterIndex -= ReaderIndex;
|
||||
Buffer.BlockCopy(Bytes, ReaderIndex, newBytes, 0, WriterIndex);
|
||||
ReaderIndex = 0;
|
||||
Bytes = newBytes;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void EnsureWrite(int size)
|
||||
{
|
||||
if (WriterIndex + size > Capacity)
|
||||
{
|
||||
EnsureWrite0(size);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void EnsureRead(int size)
|
||||
{
|
||||
if (ReaderIndex + size > WriterIndex)
|
||||
{
|
||||
throw new SerializationException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool CanRead(int size)
|
||||
{
|
||||
return (ReaderIndex + size <= WriterIndex);
|
||||
}
|
||||
|
||||
public void Append(byte x)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = x;
|
||||
}
|
||||
|
||||
public void WriteBool(bool b)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = (byte)(b ? 1 : 0);
|
||||
}
|
||||
|
||||
public bool ReadBool()
|
||||
{
|
||||
EnsureRead(1);
|
||||
return Bytes[ReaderIndex++] != 0;
|
||||
}
|
||||
|
||||
public void WriteByte(byte x)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = x;
|
||||
}
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
EnsureRead(1);
|
||||
return Bytes[ReaderIndex++];
|
||||
}
|
||||
|
||||
|
||||
public void WriteShort(short x)
|
||||
{
|
||||
if (x >= 0)
|
||||
{
|
||||
if (x < 0x80)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = (byte)x;
|
||||
return;
|
||||
}
|
||||
else if (x < 0x4000)
|
||||
{
|
||||
EnsureWrite(2);
|
||||
Bytes[WriterIndex + 1] = (byte)x;
|
||||
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
|
||||
WriterIndex += 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
EnsureWrite(3);
|
||||
Bytes[WriterIndex] = 0xff;
|
||||
Bytes[WriterIndex + 2] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
WriterIndex += 3;
|
||||
}
|
||||
|
||||
public short ReadShort()
|
||||
{
|
||||
EnsureRead(1);
|
||||
int h = Bytes[ReaderIndex];
|
||||
if (h < 0x80)
|
||||
{
|
||||
ReaderIndex++;
|
||||
return (short)h;
|
||||
}
|
||||
else if (h < 0xc0)
|
||||
{
|
||||
EnsureRead(2);
|
||||
int x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
|
||||
ReaderIndex += 2;
|
||||
return (short)x;
|
||||
}
|
||||
else if ((h == 0xff))
|
||||
{
|
||||
EnsureRead(3);
|
||||
int x = (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
ReaderIndex += 3;
|
||||
return (short)x;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SerializationException();
|
||||
}
|
||||
}
|
||||
|
||||
public short ReadFshort()
|
||||
{
|
||||
EnsureRead(2);
|
||||
short x;
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[ReaderIndex])
|
||||
{
|
||||
x = *(short*)b;
|
||||
}
|
||||
}
|
||||
#else
|
||||
x = (short)((Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex]);
|
||||
|
||||
#endif
|
||||
ReaderIndex += 2;
|
||||
return x;
|
||||
}
|
||||
|
||||
public void WriteFshort(short x)
|
||||
{
|
||||
EnsureWrite(2);
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[WriterIndex])
|
||||
{
|
||||
*(short*)b = x;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Bytes[WriterIndex] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
#endif
|
||||
WriterIndex += 2;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteInt(int x)
|
||||
{
|
||||
WriteUint((uint)x);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int ReadInt()
|
||||
{
|
||||
return (int)ReadUint();
|
||||
}
|
||||
|
||||
|
||||
public void WriteUint(uint x)
|
||||
{
|
||||
// 如果有修改,记得也把 EndWriteSegment改了
|
||||
// 0 111 1111
|
||||
if (x < 0x80)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = (byte)x;
|
||||
}
|
||||
else if (x < 0x4000) // 10 11 1111, -
|
||||
{
|
||||
EnsureWrite(2);
|
||||
Bytes[WriterIndex + 1] = (byte)x;
|
||||
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
|
||||
WriterIndex += 2;
|
||||
}
|
||||
else if (x < 0x200000) // 110 1 1111, -,-
|
||||
{
|
||||
EnsureWrite(3);
|
||||
Bytes[WriterIndex + 2] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0);
|
||||
WriterIndex += 3;
|
||||
}
|
||||
else if (x < 0x10000000) // 1110 1111,-,-,-
|
||||
{
|
||||
EnsureWrite(4);
|
||||
Bytes[WriterIndex + 3] = (byte)x;
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0);
|
||||
WriterIndex += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureWrite(5);
|
||||
Bytes[WriterIndex] = 0xf0;
|
||||
Bytes[WriterIndex + 4] = (byte)x;
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 24);
|
||||
WriterIndex += 5;
|
||||
}
|
||||
}
|
||||
|
||||
public uint ReadUint()
|
||||
{
|
||||
///
|
||||
/// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets
|
||||
EnsureRead(1);
|
||||
uint h = Bytes[ReaderIndex];
|
||||
if (h < 0x80)
|
||||
{
|
||||
ReaderIndex++;
|
||||
return h;
|
||||
}
|
||||
else if (h < 0xc0)
|
||||
{
|
||||
EnsureRead(2);
|
||||
uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
|
||||
ReaderIndex += 2;
|
||||
return x;
|
||||
}
|
||||
else if (h < 0xe0)
|
||||
{
|
||||
EnsureRead(3);
|
||||
uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
ReaderIndex += 3;
|
||||
return x;
|
||||
}
|
||||
else if (h < 0xf0)
|
||||
{
|
||||
|
||||
EnsureRead(4);
|
||||
uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
|
||||
ReaderIndex += 4;
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureRead(5);
|
||||
uint x = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4];
|
||||
ReaderIndex += 5;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void WriteUint_Unsafe(uint x)
|
||||
{
|
||||
// 0 111 1111
|
||||
if (x < 0x80)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = (byte)(x << 1);
|
||||
}
|
||||
else if (x < 0x4000)// 10 11 1111, -
|
||||
{
|
||||
EnsureWrite(2);
|
||||
|
||||
fixed (byte* wb = &Bytes[WriterIndex])
|
||||
{
|
||||
*(uint*)(wb) = (x << 2 | 0b01);
|
||||
}
|
||||
|
||||
WriterIndex += 2;
|
||||
}
|
||||
else if (x < 0x200000) // 110 1 1111, -,-
|
||||
{
|
||||
EnsureWrite(3);
|
||||
|
||||
fixed (byte* wb = &Bytes[WriterIndex])
|
||||
{
|
||||
*(uint*)(wb) = (x << 3 | 0b011);
|
||||
}
|
||||
WriterIndex += 3;
|
||||
}
|
||||
else if (x < 0x10000000) // 1110 1111,-,-,-
|
||||
{
|
||||
EnsureWrite(4);
|
||||
fixed (byte* wb = &Bytes[WriterIndex])
|
||||
{
|
||||
*(uint*)(wb) = (x << 4 | 0b0111);
|
||||
}
|
||||
WriterIndex += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureWrite(5);
|
||||
fixed (byte* wb = &Bytes[WriterIndex])
|
||||
{
|
||||
*(uint*)(wb) = (x << 5 | 0b01111);
|
||||
}
|
||||
WriterIndex += 5;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe uint ReadUint_Unsafe()
|
||||
{
|
||||
///
|
||||
/// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets
|
||||
EnsureRead(1);
|
||||
uint h = Bytes[ReaderIndex];
|
||||
if ((h & 0b1) == 0b0)
|
||||
{
|
||||
ReaderIndex++;
|
||||
return (h >> 1);
|
||||
}
|
||||
else if ((h & 0b11) == 0b01)
|
||||
{
|
||||
EnsureRead(2);
|
||||
fixed (byte* rb = &Bytes[ReaderIndex])
|
||||
{
|
||||
ReaderIndex += 2;
|
||||
return (*(uint*)rb) >> 2;
|
||||
}
|
||||
}
|
||||
else if ((h & 0b111) == 0b011)
|
||||
{
|
||||
EnsureRead(3);
|
||||
fixed (byte* rb = &Bytes[ReaderIndex])
|
||||
{
|
||||
ReaderIndex += 3;
|
||||
return (*(uint*)rb) >> 3;
|
||||
}
|
||||
}
|
||||
else if ((h & 0b1111) == 0b0111)
|
||||
{
|
||||
EnsureRead(4);
|
||||
fixed (byte* rb = &Bytes[ReaderIndex])
|
||||
{
|
||||
ReaderIndex += 4;
|
||||
return (*(uint*)rb) >> 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureRead(5);
|
||||
fixed (byte* rb = &Bytes[ReaderIndex])
|
||||
{
|
||||
ReaderIndex += 5;
|
||||
return (*(uint*)rb) >> 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int ReadFint()
|
||||
{
|
||||
EnsureRead(4);
|
||||
int x;
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[ReaderIndex])
|
||||
{
|
||||
x = *(int*)b;
|
||||
}
|
||||
}
|
||||
#else
|
||||
x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
|
||||
|
||||
#endif
|
||||
ReaderIndex += 4;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
public void WriteFint(int x)
|
||||
{
|
||||
EnsureWrite(4);
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[WriterIndex])
|
||||
{
|
||||
*(int*)b = x;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Bytes[WriterIndex] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 24);
|
||||
#endif
|
||||
WriterIndex += 4;
|
||||
}
|
||||
|
||||
public int ReadFint_Safe()
|
||||
{
|
||||
EnsureRead(4);
|
||||
int x;
|
||||
|
||||
x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
|
||||
|
||||
ReaderIndex += 4;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
public void WriteFint_Safe(int x)
|
||||
{
|
||||
EnsureWrite(4);
|
||||
Bytes[WriterIndex] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 24);
|
||||
WriterIndex += 4;
|
||||
}
|
||||
|
||||
public void WriteLong(long x)
|
||||
{
|
||||
WriteUlong((ulong)x);
|
||||
}
|
||||
|
||||
public long ReadLong()
|
||||
{
|
||||
return (long)ReadUlong();
|
||||
}
|
||||
|
||||
public void WriteNumberAsLong(double x)
|
||||
{
|
||||
WriteLong((long)x);
|
||||
}
|
||||
|
||||
public double ReadLongAsNumber()
|
||||
{
|
||||
return ReadLong();
|
||||
}
|
||||
|
||||
private void WriteUlong(ulong x)
|
||||
{
|
||||
// 0 111 1111
|
||||
if (x < 0x80)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = (byte)x;
|
||||
}
|
||||
else if (x < 0x4000) // 10 11 1111, -
|
||||
{
|
||||
EnsureWrite(2);
|
||||
Bytes[WriterIndex + 1] = (byte)x;
|
||||
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
|
||||
WriterIndex += 2;
|
||||
}
|
||||
else if (x < 0x200000) // 110 1 1111, -,-
|
||||
{
|
||||
EnsureWrite(3);
|
||||
Bytes[WriterIndex + 2] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0);
|
||||
WriterIndex += 3;
|
||||
}
|
||||
else if (x < 0x10000000) // 1110 1111,-,-,-
|
||||
{
|
||||
EnsureWrite(4);
|
||||
Bytes[WriterIndex + 3] = (byte)x;
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0);
|
||||
WriterIndex += 4;
|
||||
}
|
||||
else if (x < 0x800000000L) // 1111 0xxx,-,-,-,-
|
||||
{
|
||||
EnsureWrite(5);
|
||||
Bytes[WriterIndex + 4] = (byte)x;
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex] = (byte)((x >> 32) | 0xf0);
|
||||
WriterIndex += 5;
|
||||
}
|
||||
else if (x < 0x40000000000L) // 1111 10xx,
|
||||
{
|
||||
EnsureWrite(6);
|
||||
Bytes[WriterIndex + 5] = (byte)x;
|
||||
Bytes[WriterIndex + 4] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 32);
|
||||
Bytes[WriterIndex] = (byte)((x >> 40) | 0xf8);
|
||||
WriterIndex += 6;
|
||||
}
|
||||
else if (x < 0x200000000000L) // 1111 110x,
|
||||
{
|
||||
EnsureWrite(7);
|
||||
Bytes[WriterIndex + 6] = (byte)x;
|
||||
Bytes[WriterIndex + 5] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 4] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 32);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 40);
|
||||
Bytes[WriterIndex] = (byte)((x >> 48) | 0xfc);
|
||||
WriterIndex += 7;
|
||||
}
|
||||
else if (x < 0x100000000000000L) // 1111 1110
|
||||
{
|
||||
EnsureWrite(8);
|
||||
Bytes[WriterIndex + 7] = (byte)x;
|
||||
Bytes[WriterIndex + 6] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 5] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 4] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 32);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 40);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 48);
|
||||
Bytes[WriterIndex] = 0xfe;
|
||||
WriterIndex += 8;
|
||||
}
|
||||
else // 1111 1111
|
||||
{
|
||||
EnsureWrite(9);
|
||||
Bytes[WriterIndex] = 0xff;
|
||||
Bytes[WriterIndex + 8] = (byte)x;
|
||||
Bytes[WriterIndex + 7] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 6] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 5] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex + 4] = (byte)(x >> 32);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 40);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 48);
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 56);
|
||||
WriterIndex += 9;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong ReadUlong()
|
||||
{
|
||||
EnsureRead(1);
|
||||
uint h = Bytes[ReaderIndex];
|
||||
if (h < 0x80)
|
||||
{
|
||||
ReaderIndex++;
|
||||
return h;
|
||||
}
|
||||
else if (h < 0xc0)
|
||||
{
|
||||
EnsureRead(2);
|
||||
uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
|
||||
ReaderIndex += 2;
|
||||
return x;
|
||||
}
|
||||
else if (h < 0xe0)
|
||||
{
|
||||
EnsureRead(3);
|
||||
uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
ReaderIndex += 3;
|
||||
return x;
|
||||
}
|
||||
else if (h < 0xf0)
|
||||
{
|
||||
EnsureRead(4);
|
||||
uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
|
||||
ReaderIndex += 4;
|
||||
return x;
|
||||
}
|
||||
else if (h < 0xf8)
|
||||
{
|
||||
EnsureRead(5);
|
||||
uint xl = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | (Bytes[ReaderIndex + 4]);
|
||||
uint xh = h & 0x07;
|
||||
ReaderIndex += 5;
|
||||
return ((ulong)xh << 32) | xl;
|
||||
}
|
||||
else if (h < 0xfc)
|
||||
{
|
||||
EnsureRead(6);
|
||||
uint xl = ((uint)Bytes[ReaderIndex + 2] << 24) | ((uint)(Bytes[ReaderIndex + 3] << 16)) | ((uint)Bytes[ReaderIndex + 4] << 8) | (Bytes[ReaderIndex + 5]);
|
||||
uint xh = ((h & 0x03) << 8) | Bytes[ReaderIndex + 1];
|
||||
ReaderIndex += 6;
|
||||
return ((ulong)xh << 32) | xl;
|
||||
}
|
||||
else if (h < 0xfe)
|
||||
{
|
||||
EnsureRead(7);
|
||||
uint xl = ((uint)Bytes[ReaderIndex + 3] << 24) | ((uint)(Bytes[ReaderIndex + 4] << 16)) | ((uint)Bytes[ReaderIndex + 5] << 8) | (Bytes[ReaderIndex + 6]);
|
||||
uint xh = ((h & 0x01) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
ReaderIndex += 7;
|
||||
return ((ulong)xh << 32) | xl;
|
||||
}
|
||||
else if (h < 0xff)
|
||||
{
|
||||
EnsureRead(8);
|
||||
uint xl = ((uint)Bytes[ReaderIndex + 4] << 24) | ((uint)(Bytes[ReaderIndex + 5] << 16)) | ((uint)Bytes[ReaderIndex + 6] << 8) | (Bytes[ReaderIndex + 7]);
|
||||
uint xh = /*((h & 0x01) << 24) |*/ ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
|
||||
ReaderIndex += 8;
|
||||
return ((ulong)xh << 32) | xl;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureRead(9);
|
||||
uint xl = ((uint)Bytes[ReaderIndex + 5] << 24) | ((uint)(Bytes[ReaderIndex + 6] << 16)) | ((uint)Bytes[ReaderIndex + 7] << 8) | (Bytes[ReaderIndex + 8]);
|
||||
uint xh = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)Bytes[ReaderIndex + 2] << 16) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4];
|
||||
ReaderIndex += 9;
|
||||
return ((ulong)xh << 32) | xl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void WriteFlong(long x)
|
||||
{
|
||||
EnsureWrite(8);
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[WriterIndex])
|
||||
{
|
||||
*(long*)b = x;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
Bytes[WriterIndex] = (byte)x;
|
||||
Bytes[WriterIndex + 1] = (byte)(x >> 8);
|
||||
Bytes[WriterIndex + 2] = (byte)(x >> 16);
|
||||
Bytes[WriterIndex + 3] = (byte)(x >> 24);
|
||||
Bytes[WriterIndex + 4] = (byte)(x >> 32);
|
||||
Bytes[WriterIndex + 5] = (byte)(x >> 40);
|
||||
Bytes[WriterIndex + 6] = (byte)(x >> 48);
|
||||
Bytes[WriterIndex + 7] = (byte)(x >> 56);
|
||||
#endif
|
||||
WriterIndex += 8;
|
||||
}
|
||||
|
||||
public long ReadFlong()
|
||||
{
|
||||
EnsureRead(8);
|
||||
long x;
|
||||
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[ReaderIndex])
|
||||
{
|
||||
x = *(long*)b;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int xl = (Bytes[ReaderIndex + 3] << 24) | ((Bytes[ReaderIndex + 2] << 16)) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
|
||||
int xh = (Bytes[ReaderIndex + 7] << 24) | (Bytes[ReaderIndex + 6] << 16) | (Bytes[ReaderIndex + 5] << 8) | Bytes[ReaderIndex + 4];
|
||||
x = ((long)xh << 32) | (long)xl;
|
||||
#endif
|
||||
ReaderIndex += 8;
|
||||
return x;
|
||||
}
|
||||
|
||||
private static unsafe void Copy8(byte* dst, byte* src)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
dst[4] = src[4];
|
||||
dst[5] = src[5];
|
||||
dst[6] = src[6];
|
||||
dst[7] = src[7];
|
||||
}
|
||||
|
||||
private static unsafe void Copy4(byte* dst, byte* src)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
|
||||
//const bool isLittleEndian = true;
|
||||
public void WriteFloat(float x)
|
||||
{
|
||||
EnsureWrite(4);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[WriterIndex])
|
||||
{
|
||||
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
if ((long)b % 4 == 0)
|
||||
{
|
||||
*(float*)b = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy4(b, (byte*)&x);
|
||||
}
|
||||
#else
|
||||
*(float*)b = x;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//if (!BitConverter.IsLittleEndian)
|
||||
//{
|
||||
// Array.Reverse(data, endPos, 4);
|
||||
//}
|
||||
WriterIndex += 4;
|
||||
}
|
||||
|
||||
public float ReadFloat()
|
||||
{
|
||||
EnsureRead(4);
|
||||
//if (!BitConverter.IsLittleEndian)
|
||||
//{
|
||||
// Array.Reverse(data, beginPos, 4);
|
||||
//}
|
||||
float x;
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[ReaderIndex])
|
||||
{
|
||||
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
if ((long)b % 4 == 0)
|
||||
{
|
||||
x = *(float*)b;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((int*)&x) = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
|
||||
}
|
||||
#else
|
||||
x = *(float*)b;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ReaderIndex += 4;
|
||||
return x;
|
||||
}
|
||||
|
||||
public void WriteDouble(double x)
|
||||
{
|
||||
EnsureWrite(8);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[WriterIndex])
|
||||
{
|
||||
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
if ((long)b % 8 == 0)
|
||||
{
|
||||
*(double*)b = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy8(b, (byte*)&x);
|
||||
}
|
||||
#else
|
||||
*(double*)b = x;
|
||||
#endif
|
||||
}
|
||||
//if (!BitConverter.IsLittleEndian)
|
||||
//{
|
||||
// Array.Reverse(data, endPos, 8);
|
||||
//}
|
||||
}
|
||||
|
||||
WriterIndex += 8;
|
||||
}
|
||||
|
||||
public double ReadDouble()
|
||||
{
|
||||
EnsureRead(8);
|
||||
//if (!BitConverter.IsLittleEndian)
|
||||
//{
|
||||
// Array.Reverse(data, beginPos, 8);
|
||||
//}
|
||||
double x;
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* b = &Bytes[ReaderIndex])
|
||||
{
|
||||
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
|
||||
if ((long)b % 8 == 0)
|
||||
{
|
||||
x = *(double*)b;
|
||||
}
|
||||
else
|
||||
{
|
||||
int low = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
|
||||
int high = (b[4]) | (b[5] << 8) | (b[6] << 16) | (b[7] << 24);
|
||||
*((long*)&x) = ((long)high << 32) | (uint)low;
|
||||
}
|
||||
#else
|
||||
x = *(double*)b;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ReaderIndex += 8;
|
||||
return x;
|
||||
}
|
||||
|
||||
public void WriteSize(int n)
|
||||
{
|
||||
WriteUint((uint)n);
|
||||
}
|
||||
|
||||
public int ReadSize()
|
||||
{
|
||||
return (int)ReadUint();
|
||||
}
|
||||
|
||||
// marshal int
|
||||
// n -> (n << 1) ^ (n >> 31)
|
||||
// Read
|
||||
// (x >>> 1) ^ ((x << 31) >> 31)
|
||||
// (x >>> 1) ^ -(n&1)
|
||||
public void WriteSint(int x)
|
||||
{
|
||||
WriteUint(((uint)x << 1) ^ ((uint)x >> 31));
|
||||
}
|
||||
|
||||
public int ReadSint()
|
||||
{
|
||||
uint x = ReadUint();
|
||||
return (int)((x >> 1) ^ ((x & 1) << 31));
|
||||
}
|
||||
|
||||
|
||||
// marshal long
|
||||
// n -> (n << 1) ^ (n >> 63)
|
||||
// Read
|
||||
// (x >>> 1) ^((x << 63) >> 63)
|
||||
// (x >>> 1) ^ -(n&1L)
|
||||
public void WriteSlong(long x)
|
||||
{
|
||||
WriteUlong(((ulong)x << 1) ^ ((ulong)x >> 63));
|
||||
}
|
||||
|
||||
public long ReadSlong()
|
||||
{
|
||||
long x = ReadLong();
|
||||
return ((long)((ulong)x >> 1) ^ ((x & 1) << 63));
|
||||
}
|
||||
|
||||
public void WriteString(string x)
|
||||
{
|
||||
var n = x != null ? Encoding.UTF8.GetByteCount(x) : 0;
|
||||
WriteSize(n);
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureWrite(n);
|
||||
Encoding.UTF8.GetBytes(x, 0, x.Length, Bytes, WriterIndex);
|
||||
WriterIndex += n;
|
||||
}
|
||||
}
|
||||
|
||||
// byte[], [start, end)
|
||||
public static Func<byte[], int, int, string> StringCacheFinder { get; set; }
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
var n = ReadSize();
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureRead(n);
|
||||
string s;
|
||||
|
||||
if (StringCacheFinder == null)
|
||||
{
|
||||
s = Encoding.UTF8.GetString(Bytes, ReaderIndex, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 只缓存比较小的字符串
|
||||
s = StringCacheFinder(Bytes, ReaderIndex, n);
|
||||
}
|
||||
ReaderIndex += n;
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] x)
|
||||
{
|
||||
var n = x != null ? x.Length : 0;
|
||||
WriteSize(n);
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureWrite(n);
|
||||
x.CopyTo(Bytes, WriterIndex);
|
||||
WriterIndex += n;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ReadBytes()
|
||||
{
|
||||
var n = ReadSize();
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureRead(n);
|
||||
var x = new byte[n];
|
||||
Buffer.BlockCopy(Bytes, ReaderIndex, x, 0, n);
|
||||
ReaderIndex += n;
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
}
|
||||
|
||||
// 以下是一些特殊类型
|
||||
|
||||
internal void SkipBytes()
|
||||
{
|
||||
int n = ReadSize();
|
||||
EnsureRead(n);
|
||||
ReaderIndex += n;
|
||||
}
|
||||
|
||||
|
||||
public void WriteByteBufWithSize(ByteBuf o)
|
||||
{
|
||||
int n = o.Size;
|
||||
if (n > 0)
|
||||
{
|
||||
WriteSize(n);
|
||||
WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteByteBufWithoutSize(ByteBuf o)
|
||||
{
|
||||
int n = o.Size;
|
||||
if (n > 0)
|
||||
{
|
||||
WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryReadByte(out byte x)
|
||||
{
|
||||
if (CanRead(1))
|
||||
{
|
||||
x = Bytes[ReaderIndex++];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public EDeserializeError TryDeserializeInplaceByteBuf(int maxSize, ByteBuf inplaceTempBody)
|
||||
{
|
||||
//if (!CanRead(1)) { return EDeserializeError.NOT_ENOUGH; }
|
||||
int oldReadIndex = ReaderIndex;
|
||||
bool commit = false;
|
||||
try
|
||||
{
|
||||
int n;
|
||||
int h = Bytes[ReaderIndex];
|
||||
if (h < 0x80)
|
||||
{
|
||||
ReaderIndex++;
|
||||
n = h;
|
||||
}
|
||||
else if (h < 0xc0)
|
||||
{
|
||||
if (!CanRead(2)) { return EDeserializeError.NOT_ENOUGH; }
|
||||
n = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
|
||||
ReaderIndex += 2;
|
||||
}
|
||||
else if (h < 0xe0)
|
||||
{
|
||||
if (!CanRead(3)) { return EDeserializeError.NOT_ENOUGH; }
|
||||
n = ((h & 0x1f) << 16) | (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
ReaderIndex += 3;
|
||||
}
|
||||
else if (h < 0xf0)
|
||||
{
|
||||
if (!CanRead(4)) { return EDeserializeError.NOT_ENOUGH; }
|
||||
n = ((h & 0x0f) << 24) | (Bytes[ReaderIndex + 1] << 16) | (Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
|
||||
ReaderIndex += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EDeserializeError.EXCEED_SIZE;
|
||||
}
|
||||
|
||||
if (n > maxSize)
|
||||
{
|
||||
return EDeserializeError.EXCEED_SIZE;
|
||||
}
|
||||
if (Remaining < n)
|
||||
{
|
||||
return EDeserializeError.NOT_ENOUGH;
|
||||
}
|
||||
|
||||
int inplaceReadIndex = ReaderIndex;
|
||||
ReaderIndex += n;
|
||||
|
||||
inplaceTempBody.Replace(Bytes, inplaceReadIndex, ReaderIndex);
|
||||
commit = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!commit)
|
||||
{
|
||||
ReaderIndex = oldReadIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return EDeserializeError.OK;
|
||||
}
|
||||
|
||||
public void WriteRawTag(byte b1)
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex++] = b1;
|
||||
}
|
||||
|
||||
public void WriteRawTag(byte b1, byte b2)
|
||||
{
|
||||
EnsureWrite(2);
|
||||
Bytes[WriterIndex] = b1;
|
||||
Bytes[WriterIndex + 1] = b2;
|
||||
WriterIndex += 2;
|
||||
}
|
||||
|
||||
public void WriteRawTag(byte b1, byte b2, byte b3)
|
||||
{
|
||||
EnsureWrite(3);
|
||||
Bytes[WriterIndex] = b1;
|
||||
Bytes[WriterIndex + 1] = b2;
|
||||
Bytes[WriterIndex + 2] = b3;
|
||||
WriterIndex += 3;
|
||||
}
|
||||
|
||||
#region segment
|
||||
|
||||
|
||||
public void BeginWriteSegment(out int oldSize)
|
||||
{
|
||||
oldSize = Size;
|
||||
EnsureWrite(1);
|
||||
WriterIndex += 1;
|
||||
}
|
||||
|
||||
public void EndWriteSegment(int oldSize)
|
||||
{
|
||||
int startPos = ReaderIndex + oldSize;
|
||||
int segmentSize = WriterIndex - startPos - 1;
|
||||
|
||||
// 0 111 1111
|
||||
if (segmentSize < 0x80)
|
||||
{
|
||||
Bytes[startPos] = (byte)segmentSize;
|
||||
}
|
||||
else if (segmentSize < 0x4000) // 10 11 1111, -
|
||||
{
|
||||
EnsureWrite(1);
|
||||
Bytes[WriterIndex] = Bytes[startPos + 1];
|
||||
Bytes[startPos + 1] = (byte)segmentSize;
|
||||
|
||||
Bytes[startPos] = (byte)((segmentSize >> 8) | 0x80);
|
||||
WriterIndex += 1;
|
||||
}
|
||||
else if (segmentSize < 0x200000) // 110 1 1111, -,-
|
||||
{
|
||||
EnsureWrite(2);
|
||||
Bytes[WriterIndex + 1] = Bytes[startPos + 2];
|
||||
Bytes[startPos + 2] = (byte)segmentSize;
|
||||
|
||||
Bytes[WriterIndex] = Bytes[startPos + 1];
|
||||
Bytes[startPos + 1] = (byte)(segmentSize >> 8);
|
||||
|
||||
Bytes[startPos] = (byte)((segmentSize >> 16) | 0xc0);
|
||||
WriterIndex += 2;
|
||||
}
|
||||
else if (segmentSize < 0x10000000) // 1110 1111,-,-,-
|
||||
{
|
||||
EnsureWrite(3);
|
||||
Bytes[WriterIndex + 2] = Bytes[startPos + 3];
|
||||
Bytes[startPos + 3] = (byte)segmentSize;
|
||||
|
||||
Bytes[WriterIndex + 1] = Bytes[startPos + 2];
|
||||
Bytes[startPos + 2] = (byte)(segmentSize >> 8);
|
||||
|
||||
Bytes[WriterIndex] = Bytes[startPos + 1];
|
||||
Bytes[startPos + 1] = (byte)(segmentSize >> 16);
|
||||
|
||||
Bytes[startPos] = (byte)((segmentSize >> 24) | 0xe0);
|
||||
WriterIndex += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SerializationException("exceed max segment size");
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadSegment(out int startIndex, out int segmentSize)
|
||||
{
|
||||
EnsureRead(1);
|
||||
int h = Bytes[ReaderIndex++];
|
||||
|
||||
startIndex = ReaderIndex;
|
||||
|
||||
if (h < 0x80)
|
||||
{
|
||||
segmentSize = h;
|
||||
ReaderIndex += segmentSize;
|
||||
}
|
||||
else if (h < 0xc0)
|
||||
{
|
||||
EnsureRead(1);
|
||||
segmentSize = ((h & 0x3f) << 8) | Bytes[ReaderIndex];
|
||||
int endPos = ReaderIndex + segmentSize;
|
||||
Bytes[ReaderIndex] = Bytes[endPos];
|
||||
ReaderIndex += segmentSize + 1;
|
||||
}
|
||||
else if (h < 0xe0)
|
||||
{
|
||||
EnsureRead(2);
|
||||
segmentSize = ((h & 0x1f) << 16) | ((int)Bytes[ReaderIndex] << 8) | Bytes[ReaderIndex + 1];
|
||||
int endPos = ReaderIndex + segmentSize;
|
||||
Bytes[ReaderIndex] = Bytes[endPos];
|
||||
Bytes[ReaderIndex + 1] = Bytes[endPos + 1];
|
||||
ReaderIndex += segmentSize + 2;
|
||||
}
|
||||
else if (h < 0xf0)
|
||||
{
|
||||
EnsureRead(3);
|
||||
segmentSize = ((h & 0x0f) << 24) | ((int)Bytes[ReaderIndex] << 16) | ((int)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
|
||||
int endPos = ReaderIndex + segmentSize;
|
||||
Bytes[ReaderIndex] = Bytes[endPos];
|
||||
Bytes[ReaderIndex + 1] = Bytes[endPos + 1];
|
||||
Bytes[ReaderIndex + 2] = Bytes[endPos + 2];
|
||||
ReaderIndex += segmentSize + 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SerializationException("exceed max size");
|
||||
}
|
||||
if (ReaderIndex > WriterIndex)
|
||||
{
|
||||
throw new SerializationException("segment data not enough");
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadSegment(ByteBuf buf)
|
||||
{
|
||||
ReadSegment(out int startPos, out var size);
|
||||
buf.Bytes = Bytes;
|
||||
buf.ReaderIndex = startPos;
|
||||
buf.WriterIndex = startPos + size;
|
||||
}
|
||||
|
||||
public void EnterSegment(out SegmentSaveState saveState)
|
||||
{
|
||||
ReadSegment(out int startPos, out int size);
|
||||
|
||||
saveState = new SegmentSaveState(ReaderIndex, WriterIndex);
|
||||
ReaderIndex = startPos;
|
||||
WriterIndex = startPos + size;
|
||||
}
|
||||
|
||||
public void LeaveSegment(SegmentSaveState saveState)
|
||||
{
|
||||
ReaderIndex = saveState.ReaderIndex;
|
||||
WriterIndex = saveState.WriterIndex;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string[] datas = new string[WriterIndex - ReaderIndex];
|
||||
for (var i = ReaderIndex; i < WriterIndex; i++)
|
||||
{
|
||||
datas[i - ReaderIndex] = Bytes[i].ToString("X2");
|
||||
}
|
||||
return string.Join(".", datas);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is ByteBuf other) && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(ByteBuf other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Size != other.Size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0, n = Size; i < n; i++)
|
||||
{
|
||||
if (Bytes[ReaderIndex + i] != other.Bytes[other.ReaderIndex + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new ByteBuf(CopyData());
|
||||
}
|
||||
|
||||
|
||||
public static ByteBuf FromString(string value)
|
||||
{
|
||||
var ss = value.Split(',');
|
||||
byte[] data = new byte[ss.Length];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = byte.Parse(ss[i]);
|
||||
}
|
||||
return new ByteBuf(data);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 17;
|
||||
for (int i = ReaderIndex; i < WriterIndex; i++)
|
||||
{
|
||||
hash = hash * 23 + Bytes[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
_releaser?.Invoke(this);
|
||||
}
|
||||
|
||||
#if SUPPORT_PUERTS_ARRAYBUF
|
||||
// -- add for puerts
|
||||
public Puerts.ArrayBuffer ReadArrayBuffer()
|
||||
{
|
||||
return new Puerts.ArrayBuffer(ReadBytes());
|
||||
}
|
||||
|
||||
public void WriteArrayBuffer(Puerts.ArrayBuffer bytes)
|
||||
{
|
||||
WriteBytes(bytes.Bytes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
7
ServerCore/LuBan/Base/ITypeId.cs
Normal file
7
ServerCore/LuBan/Base/ITypeId.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Luban
|
||||
{
|
||||
public interface ITypeId
|
||||
{
|
||||
int GetTypeId();
|
||||
}
|
||||
}
|
||||
52
ServerCore/LuBan/Base/StringUtil.cs
Normal file
52
ServerCore/LuBan/Base/StringUtil.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Luban
|
||||
{
|
||||
public static class StringUtil
|
||||
{
|
||||
public static string ToStr(object o)
|
||||
{
|
||||
return ToStr(o, new StringBuilder());
|
||||
}
|
||||
|
||||
public static string ToStr(object o, StringBuilder sb)
|
||||
{
|
||||
foreach (var p in o.GetType().GetFields())
|
||||
{
|
||||
|
||||
sb.Append($"{p.Name} = {p.GetValue(o)},");
|
||||
}
|
||||
|
||||
foreach (var p in o.GetType().GetProperties())
|
||||
{
|
||||
sb.Append($"{p.Name} = {p.GetValue(o)},");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string ArrayToString<T>(T[] arr)
|
||||
{
|
||||
return "[" + string.Join(",", arr) + "]";
|
||||
}
|
||||
|
||||
|
||||
public static string CollectionToString<T>(IEnumerable<T> arr)
|
||||
{
|
||||
return "[" + string.Join(",", arr) + "]";
|
||||
}
|
||||
|
||||
|
||||
public static string CollectionToString<TK, TV>(IDictionary<TK, TV> dic)
|
||||
{
|
||||
var sb = new StringBuilder('{');
|
||||
foreach (var e in dic)
|
||||
{
|
||||
sb.Append(e.Key).Append(':');
|
||||
sb.Append(e.Value).Append(',');
|
||||
}
|
||||
sb.Append('}');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user