You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

208 lines
5.9 KiB

/*
Sog 游戏基础库
2016 by zouwei
*/
using System;
using System.Net;
using System.Text;
using System.Collections.Generic;
using ProtoCSStruct;
namespace Sog
{
public class ProtoCSStructPacker
{
private Dictionary<int, IStructMessageParser> m_typeMessageParser = new Dictionary<int, IStructMessageParser>();
public ProtoCSStructPacker()
{
}
//最小8
public int GetHeaderLength()
{
return 8;
}
public int GetFullHeaderLength()
{
return 16;
}
//打包头
public int PackHeader(MessageHeader header, byte[] headerBytes)
{
// serverId最高位置1, 表示数据压缩
if (header.isZip && header.ServerID <= 0x00FFFFFF)
{
header.ServerID |= 0x80000000;
}
//小字节序
if(header.ObjectID == 0)
{
headerBytes[0] = (byte)(header.Length % 256);
headerBytes[1] = (byte)(header.Length / 256);
headerBytes[2] = (byte)(header.Type % 256);
headerBytes[3] = (byte)(header.Type / 256);
Span<byte> pbServerID = new Span<byte>(headerBytes, 4, 4);
BitConverter.TryWriteBytes(pbServerID, header.ServerID);
return 8;
}
else
{
headerBytes[0] = (byte)(header.Length % 256);
headerBytes[1] = (byte)(header.Length / 256);
//最高位置1
int newType = header.Type | 0x00008000;
headerBytes[2] = (byte)(newType % 256);
headerBytes[3] = (byte)(newType / 256);
Span<byte> pbServerID = new Span<byte>(headerBytes, 4, 4);
BitConverter.TryWriteBytes(pbServerID, header.ServerID);
Span<byte> pbObjectID = new Span<byte>(headerBytes,8,8);
BitConverter.TryWriteBytes(pbObjectID, header.ObjectID);
return 16;
}
}
//解包头
public int UnPackHeader(byte[] data, int offset, int length, ref MessageHeader header)
{
int byte0 = data[offset + 0];
int byte1 = data[offset + 1];
int byte2 = data[offset + 2];
int byte3 = data[offset + 3];
header.Length = byte1 * 256 + byte0;
header.Type = byte3 * 256 + byte2;
uint serverId = BitConverter.ToUInt32(data, offset + 4);
if ((serverId & 0x80000000) > 0)
{
// 去掉首字节最高位
serverId &= 0x7FFFFFFF;
header.isZip = true;
}
header.ServerID = serverId;
bool haveObjectID = (header.Type & 0x00008000) > 0;
if (!haveObjectID)
{
return 8;
}
//头有16字节
if (length < 16)
{
return 0;
}
//去掉最高位
header.Type &= 0x00007fff;
header.ObjectID = BitConverter.ToInt64(data, offset + 8);
return 16;
}
public virtual bool UnpackMessage(MessageData message, out StructPacket packet)
{
try
{
IStructMessageParser parser;
m_typeMessageParser.TryGetValue(message.Header.Type,out parser);
packet = new StructPacket();
packet.Header = message.Header;
if (parser != null)
{
parser.ParseFrom(message.Buffer.Data, message.Buffer.Length);
}
else
{
TraceLog.Error("protocsstruct decode package type {0} error, can not find StructMessageParser,please register it first!"
, message.Header.Type);
return false;
}
packet.Parser = parser;
//packet.MsgID = message.Header.Type;
return true;
}
catch(Exception error)
{
TraceLog.Error("protocsstruct decode package type {0} error, {1}", message.Header.Type, error.Message);
packet = null;
throw;
}
return false;
}
public bool PackMessage<T>(ref T structMessage, ref MessageData message) where T : struct, IStructMessage<T>
{
try
{
int size = structMessage.CalculateSize();
message.MallocData(size);
CodedOutputStream ouput = new CodedOutputStream(message.Buffer.Data);
structMessage.WriteTo(ouput);
message.Header.Length = size;
return true;
}
catch (Exception error)
{
TraceLog.Error("protocsstruct encode package type {0} error, {1}", message.Header.Type, error.Message);
throw;
}
return false;
}
//需要注册,提高效率
public void RegisterProtoType(int iMsgID, object obj)
{
IStructMessageParser parser = (IStructMessageParser)obj;
if(m_typeMessageParser.ContainsKey(iMsgID))
{
IStructMessageParser oldparser = m_typeMessageParser[iMsgID];
TraceLog.Error("protocsstruct RegisterProtoType msgId {0} duplicate,registed name {1} new name {2}"
, iMsgID, oldparser.GetMessageName(), parser.GetMessageName());
return;
}
m_typeMessageParser.Add(iMsgID, parser);
TraceLog.Trace("protocsstruct RegisterProtoType msgId {0} ,register name {1} StructSizeof {2}"
, iMsgID, parser.GetMessageName(), parser.GetStructSizeof());
}
}
}