using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text; using ProtoBuf; using Thousandto.Core.Base; namespace Thousandto.Plugins.Common { /// /// ProtoBuf工具 /// public class ProtoBufUtils { //多线程使用 public static object WriteLocker = new object(); public static object ReadLocker = new object(); //计数器(作为单个消息子结构体临时id) private static int _counter = 0; //long 最大值 private const long Int64Max = 9223372036854775807; //int 最大值 private const int Int32Max = 2147483647; //缓存 private static byte[] _bytesCache = new byte[256 * 1024]; //当前写入位置 private static int _writePos = 0; //UTF8编码 private static readonly UTF8Encoding Encoding = new UTF8Encoding(); //子结构体字典 private static Dictionary SubItemInfoDic = new Dictionary(23); //当前反序列化后的byte数组 private static byte[] _readbytes = null; //==================================================[Write]=================================================== //初始化重置 public static void InitWriteData() { _writePos = 0; _counter = 0; } //获取子结构体临时id public static int GetSubItemInfoId() { return ++_counter; } //1.设置一个位置空长度(这里默认都设置1个byte) public static void SetEmptyLength(int SubItemInfoId)//, int Count = 1) { if (!SubItemInfoDic.ContainsKey(SubItemInfoId)) { SubItemInfo msgInfo = new SubItemInfo { LBeginIndex = _writePos, LCount = 1 }; SubItemInfoDic.Add(SubItemInfoId, msgInfo); } else { var subItemInfo = SubItemInfoDic[SubItemInfoId]; subItemInfo.LBeginIndex = _writePos; subItemInfo.LCount = 1; } //for (int i = 0; i < Count; i++) //{ _bytesCache[_writePos++] = 0; //} } //设置子结构体的开始索引 public static void SetVBeginIndex(int SubItemInfoId) { if (!SubItemInfoDic.ContainsKey(SubItemInfoId)) { Debug.LogError("Error SetBeginIndex"); return; } SubItemInfoDic[SubItemInfoId].VBeginIndex = _writePos; } //设置子结构体的结束索引 public static void SetVEndIndex(int SubItemInfoId) { if (!SubItemInfoDic.ContainsKey(SubItemInfoId)) { Debug.LogError("Error SetEndIndex"); return; } SubItemInfoDic[SubItemInfoId].VEndIndex = _writePos; } //检查真实长度是否大于一个byte的存储,如果大于就需要整体偏移,最后设置真实的长度 public static int CheckAndSetLength(int SubItemInfoId) { if (!SubItemInfoDic.ContainsKey(SubItemInfoId)) { Debug.LogError("Error CheckAndSetLength"); return 0; } int length = 1; SubItemInfo subItemInfo = SubItemInfoDic[SubItemInfoId]; int realLength = subItemInfo.VEndIndex - subItemInfo.VBeginIndex; int lengthIndex = subItemInfo.LBeginIndex; if (realLength > 127) { if (realLength > 16383) { //偏移2个位置 Move(lengthIndex + 1, lengthIndex + 3, realLength); length = 3; } else { //偏移1个位置 Move(lengthIndex + 1, lengthIndex + 2, realLength); length = 2; } } //设置真实的长度 do { _bytesCache[lengthIndex++] = (byte)(realLength & 0x7F | 0x80); } while ((realLength >>= 7) != 0); _bytesCache[lengthIndex - 1] &= 0x7F; return length; } //byte数组中的内容整体移动 private static void Move(int srcOffset, int desOffset, int count) { Buffer.BlockCopy(_bytesCache, srcOffset, _bytesCache, desOffset, count); _writePos += desOffset - srcOffset; } //获取数据 public static byte[] GetData() { var bytes = GetByteArrFormPool(_writePos); Buffer.BlockCopy(_bytesCache, 0, bytes, 0, _writePos); return bytes; } //从缓存池获取bytes private static byte[] GetByteArrFormPool(int length) { return BytesPool.GetBytes(length); } //回收bytes public static void Free(byte[] bytes) { BytesPool.Free(bytes); } //写内容头 public static void WriteHeader(int fieldNumber, WireType wireType) { uint header = (((uint)fieldNumber) << 3) | (((uint)wireType) & 7); WriteUInt32Variant(header); } //=========[T-V]======== //可变长度Variant 32位 private static uint Zig(int value) { return (uint)((value << 1) ^ (value >> 31)); } //可变长度Variant 64位 private static ulong Zig(long value) { return (ulong)((value << 1) ^ (value >> 63)); } //可变长度write type = 0 private static void WriteUInt32Variant(uint value) { do { _bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80); } while ((value >>= 7) != 0); _bytesCache[_writePos - 1] &= 0x7F; } //可变长度write type = 0 private static void WriteUInt64Variant(ulong value) { do { _bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80); } while ((value >>= 7) != 0); _bytesCache[_writePos - 1] &= 0x7F; } //bool public static void WriteBoolean(int fieldNumber, bool value) { WriteHeader(fieldNumber, WireType.Variant); WriteUInt32Variant(value ? (uint)1 : (uint)0); } //int32 public static void WriteInt32(int fieldNumber, int value) { WriteHeader(fieldNumber, WireType.Variant); if (value >= 0) WriteUInt32Variant((uint)value); else { _bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 7 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 14 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 21 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 28 & 0xF); } } //int64 public static void WriteInt64(int fieldNumber, long value) { WriteHeader(fieldNumber, WireType.Variant); if (value >= 0) WriteUInt64Variant((ulong)value); else { _bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 7 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 14 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 21 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 28 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 35 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 42 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 49 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)(value >> 56 & 0x7F | 0x80); _bytesCache[_writePos++] = (byte)1; } } //uint32 public static void WriteUint32(int fieldNumber, uint value) { WriteHeader(fieldNumber, WireType.Variant); WriteUInt32Variant(value); } //uint64 public static void WriteUint64(int fieldNumber, ulong value) { WriteHeader(fieldNumber, WireType.Variant); WriteUInt64Variant(value); } //sint32 public static void WriteSint32(int fieldNumber, int value) { WriteHeader(fieldNumber, WireType.Variant); WriteUInt32Variant(Zig(value)); } //sint64 public static void WriteSint64(int fieldNumber, long value) { WriteHeader(fieldNumber, WireType.Variant); WriteUInt64Variant(Zig(value)); } //=========[固定32位]======== //32位写入byte数组 private static void WriteInt32ToBuffer(uint value) { _bytesCache[_writePos++] = (byte)value; _bytesCache[_writePos++] = (byte)(value >> 8); _bytesCache[_writePos++] = (byte)(value >> 16); _bytesCache[_writePos++] = (byte)(value >> 24); } //Fixed32 public static void WriteFixed32(int fieldNumber, uint value) { WriteHeader(fieldNumber, WireType.Fixed32); WriteInt32ToBuffer(value); } //float public static void WriteFloat(int fieldNumber, float value) { WriteHeader(fieldNumber, WireType.Fixed32); WriteInt32ToBuffer(MathLib.Float2Uint(value)); } //=========[固定64位]======== //64位写入byte数组 private static void WriteInt64ToBuffer(ulong value) { _bytesCache[_writePos++] = (byte)value; _bytesCache[_writePos++] = (byte)(value >> 8); _bytesCache[_writePos++] = (byte)(value >> 16); _bytesCache[_writePos++] = (byte)(value >> 24); _bytesCache[_writePos++] = (byte)(value >> 32); _bytesCache[_writePos++] = (byte)(value >> 40); _bytesCache[_writePos++] = (byte)(value >> 48); _bytesCache[_writePos++] = (byte)(value >> 56); } //Fixed64 public static void WriteFixed64(int fieldNumber, ulong value) { WriteHeader(fieldNumber, WireType.Fixed64); WriteInt64ToBuffer(value); } //double public static void WriteDouble(int fieldNumber, double value) { WriteHeader(fieldNumber, WireType.Fixed64); WriteInt64ToBuffer(MathLib.Double2Ulong(value)); } //==========[T-L-V]======= //string public static void WriteString(int fieldNumber, string value) { if (value == null) { WriteHeader(fieldNumber, WireType.String); WriteUInt32Variant(0); return; } int len = value.Length; if (len == 0) { WriteHeader(fieldNumber, WireType.String); WriteUInt32Variant(0); return; } WriteHeader(fieldNumber, WireType.String); int predicted = Encoding.GetByteCount(value); WriteUInt32Variant((uint)predicted); Encoding.GetBytes(value, 0, value.Length, _bytesCache, _writePos); _writePos += predicted; } //byte[] public static void WriteBytes(int fieldNumber, byte[] value) { if (value == null) { return; } int len = value.Length; if (len == 0) { WriteHeader(fieldNumber, WireType.String); WriteUInt32Variant(0); return; } Buffer.BlockCopy(value, 0, _bytesCache, _writePos, len); _writePos += len; } //==================================================[Read]=================================================== //可变长度Variant 32位 private static int Zag(uint ziggedValue) { int value = (int)ziggedValue; return ((value >> 1) & Int32Max) ^ (-(value & 0x01)); } //可变长度Variant 64位 private static long Zag(ulong ziggedValue) { long value = (long)ziggedValue; return ((value >> 1) & ~Int64Max) ^ (-(value & 0x01L)); } //初始化重置 public static void InitReadData(byte[] bytes, ref int readPos) { _readbytes = bytes; readPos = 0; } //field_number 不能为负数 public static int ReadFieldNumber(ref int readPos) { int fieldNumber = 0; int count = 1; fieldNumber = (_readbytes[readPos] >> 3) & 0x4F; while (_readbytes[readPos] >> 7 == 1) { fieldNumber |= (_readbytes[++readPos] & 0x7F) << (count++ * 7 - 3); }; ++readPos; return fieldNumber; } //bool public static bool ReadBoolean(ref int readPos) { return _readbytes[readPos++] == 1; } //Int32 public static int ReadInt32(ref int readPos) { //容错处理 return (int)ReadInt64(ref readPos); //int result = 0; //int count = 1; //result = _readbytes[readPos] & 0x7F; //while (_readbytes[readPos] >> 7 == 1) //{ // result |= (_readbytes[++readPos] & 0x7F) << (count++ * 7); //}; //++readPos; //if(result < 0) //{ // Debug.LogError(result +","+readPos); // DebugBytes(_readbytes); //} //return result; } //Int64 public static long ReadInt64(ref int readPos) { long result = 0; int count = 1; result = _readbytes[readPos] & 0x7F; while (_readbytes[readPos] >> 7 == 1) { result |= (long)(_readbytes[++readPos] & 0x7F) << (count++ * 7); }; ++readPos; return result; } //Uint32 public static uint ReadUint32(ref int readPos) { uint result = 0; int count = 1; result = (uint)(_readbytes[readPos] & 0x7F); while (_readbytes[readPos] >> 7 == 1) { result |= (uint)(_readbytes[++readPos] & 0x7F) << (count++ * 7); }; ++readPos; return result; } //Uint64 public static ulong ReadUint64(ref int readPos) { ulong result = 0; int count = 1; result = (ulong)(_readbytes[readPos] & 0x7F); while (_readbytes[readPos] >> 7 == 1) { result |= (ulong)(_readbytes[++readPos] & 0x7F) << (count++ * 7); }; ++readPos; return result; } //sint32 public static int ReadSint32(ref int readPos) { return Zag(ReadUint32(ref readPos)); } //sint64 public static long ReadSint64(ref int readPos) { return Zag(ReadUint64(ref readPos)); } //Fixed32 public static uint ReadFixed32(ref int readPos) { return (uint)_readbytes[readPos++] | (uint)_readbytes[readPos++] << 8 | (uint)_readbytes[readPos++] << 16 | (uint)_readbytes[readPos++] << 24; } //float public static float ReadFloat(ref int readPos) { uint value = ReadFixed32(ref readPos); return MathLib.Uint2Float(value); } //Fixed64 public static ulong ReadFixed64(ref int readPos) { return _readbytes[readPos++] | (ulong)_readbytes[readPos++] << 8 | (ulong)_readbytes[readPos++] << 16 | (ulong)_readbytes[readPos++] << 24 | (ulong)_readbytes[readPos++] << 32 | (ulong)_readbytes[readPos++] << 40 | (ulong)_readbytes[readPos++] << 48 | (ulong)_readbytes[readPos++] << 56; } //double public static double ReadDouble(ref int readPos) { ulong value = ReadFixed64(ref readPos); return MathLib.Ulong2Double(value); } //=================T-L-V //string public static string ReadString(ref int readPos) { int len = ReadInt32(ref readPos); if (len == 0) { return ""; } string s = Encoding.GetString(_readbytes, readPos, len); readPos += len; return s; } //bytes public static byte[] ReadBytes(ref int readPos) { int len = ReadInt32(ref readPos); if (len == 0) { return null; } byte[] bytes = new byte[len]; Buffer.BlockCopy(_readbytes, readPos, bytes, 0, len); readPos += len; return bytes; } public static void DebugBytes() { DebugBytes(GetData()); } public static void DebugBytes(byte[] bytes) { if (bytes != null && bytes.Length > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { sb.Append(bytes[i]); sb.Append(" "); } Debug.Log(sb.ToString()); return; } Debug.Log(string.Empty); } public static byte[] Serialize(IMessageInfo msg) { lock (WriteLocker) { InitWriteData(); int headLength = msg.WriteMessage(1) + 1; var bytes = GetByteArrFormPool(_writePos - headLength); Buffer.BlockCopy(_bytesCache, headLength, bytes, 0, _writePos - headLength); return bytes; } } public static void Deserialize(IMessageInfo msg, byte[] bytes) { lock (ReadLocker) { int readPos = 0; InitReadData(bytes, ref readPos); msg.ReadMessage(ref readPos, bytes.Length); } } //子结构体信息 private class SubItemInfo { //L: 开始索引 public int LBeginIndex = 0; //L: 预留长度 public int LCount = 0; //V: 开始索引 public int VBeginIndex = 0; //V: 结束索引 public int VEndIndex = 0; } //byte数组对象池 private class BytesPool { //bytes缓存 public static Dictionary _cacheByteDic = new Dictionary(); private static int _size = 0; public static byte[] GetBytes(int length) { byte[] bytes = null; if (!_cacheByteDic.TryGetValue(length, out bytes)) { return new byte[length]; } _cacheByteDic.Remove(length); return bytes; } public static void Free(byte[] bytes) { if (bytes != null) { int length = bytes.Length; if (_size + length > 1048576) { var iter = _cacheByteDic.GetEnumerator(); int maxLength = 0; while (iter.MoveNext()) { int itemLength = iter.Current.Value.Length; if (itemLength > maxLength) { maxLength = itemLength; } } _cacheByteDic.Remove(maxLength); } if (!_cacheByteDic.ContainsKey(length)) { _cacheByteDic.Add(length, bytes); _size += length; } } } } } }