public void Write(PacketLogEntry entry) { if (entry == null) { throw new ArgumentNullException(nameof(entry)); } if (!Servers.ContainsKey(entry.ServerId)) { throw new ArgumentException("Invalid server ID.", nameof(entry)); } if (!Messages.Game.OpCodeToName.ContainsKey(entry.OpCode)) { throw new ArgumentException("Invalid opcode.", nameof(entry)); } if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } _writer.WriteInt64(new DateTimeOffset(entry.Timestamp).ToUnixTimeMilliseconds()); _writer.WriteInt32(entry.ServerId); _writer.WriteByte((byte)entry.Direction); _writer.WriteUInt16(entry.OpCode); _writer.WriteUInt16((ushort)entry.Payload.Count); _writer.WriteBytes(entry.Payload.ToArray()); }
bool HandleSpawnMe(GameClient client, Direction direction, RawPacket packet) { // Automatically join a chat channel when logging in. _log.Info("Making client {0} join chat channel {1} with password {2}", client.EndPoint, ChatChannelName, ChatChannelPassword); using (var writer = new TeraBinaryWriter()) { writer.WriteUInt16((ushort)(PacketHeader.HeaderSize + sizeof(ushort) * 2)); writer.WriteUInt16(ChatChannelPassword); writer.WriteString(ChatChannelName); client.SendToServer(new RawPacket("C_JOIN_PRIVATE_CHANNEL") { Payload = writer.ToArray() }); } // Let's request an absurdly low visibility range. _log.Info("Setting visibility range for client {0} to {1}", client.EndPoint, VisibilityRange); client.SendToServer(new CSetVisibleRangePacket { Range = VisibilityRange }); return(true); }
internal static void WriteHeader(PacketHeader header, byte[] buffer) { using var writer = new TeraBinaryWriter(buffer); writer.WriteUInt16((ushort)(header.Length + PacketHeader.HeaderSize)); writer.WriteUInt16(header.OpCode); }
public PacketLogWriter(MessageTables messages, ServerInfo[] servers, string directory, string fileNameFormat, bool compress) { if (servers == null) { throw new ArgumentNullException(nameof(servers)); } if (servers.Any(x => x == null)) { throw new ArgumentException("A null server was given.", nameof(servers)); } if (fileNameFormat == null) { throw new ArgumentNullException(nameof(fileNameFormat)); } IsCompressed = compress; Messages = messages ?? throw new ArgumentNullException(nameof(messages)); Servers = servers.ToDictionary(x => x.Id); Directory.CreateDirectory(directory); Stream stream = File.Open( Path.Combine(directory, DateTime.Now.ToString(fileNameFormat) + ".pkt"), FileMode.Create, FileAccess.Write); var magic = PacketLogEntry.Magic.ToArray(); stream.Write(magic, 0, magic.Length); stream.WriteByte((byte)(compress ? 6 : 0)); if (compress) { stream = new DeflateStream(stream, CompressionLevel.Optimal); } _writer = new TeraBinaryWriter(stream); _writer.WriteUInt32(Version); _writer.WriteByte((byte)messages.Region); _writer.WriteUInt32(messages.Game.Version); _writer.WriteUInt32((uint)servers.Length); foreach (var server in servers) { _writer.WriteInt32(server.Id); _writer.WriteString(server.Name); _writer.WriteBoolean(server.RealEndPoint.AddressFamily == AddressFamily.InterNetworkV6); _writer.WriteBytes(server.RealEndPoint.Address.GetAddressBytes()); _writer.WriteUInt16((ushort)server.RealEndPoint.Port); _writer.WriteBytes(server.ProxyEndPoint.Address.GetAddressBytes()); _writer.WriteUInt16((ushort)server.ProxyEndPoint.Port); } }
void SerializeObject(TeraBinaryWriter writer, object source) { var fields = GetPacketFields <ReflectionPacketFieldInfo>(source.GetType()); var offsets = new List <(ReflectionPacketFieldInfo, int)>(); foreach (var info in fields) { if (info.IsByteArray) { offsets.Add((info, writer.Position)); writer.WriteUInt16(0); writer.WriteUInt16((ushort)((List <byte>)info.Property .GetValue(source)).Count); } else if (info.IsArray) { writer.WriteUInt16( (ushort)((IList)info.Property.GetValue(source)).Count); offsets.Add((info, writer.Position)); writer.WriteUInt16(0); } else if (info.IsString) { offsets.Add((info, writer.Position)); writer.WriteUInt16(0); } else { info.PrimitiveSerializer(writer, info.Property.GetValue(source)); } } foreach (var(info, offset) in offsets) { if (info.IsByteArray) { var list = (List <byte>)info.Property.GetValue(source); if (list.Count == 0) { continue; } writer.Seek(offset, (w, op) => w.WriteOffset(op)); writer.WriteBytes(list.ToArray()); } else if (info.IsArray) { var list = (IList)info.Property.GetValue(source); if (list.Count == 0) { continue; } writer.Seek(offset, (w, op) => w.WriteOffset(op)); for (var i = 0; i < list.Count; i++) { var pos = writer.Position; writer.WriteOffset(pos); writer.WriteUInt16(0); SerializeObject(writer, list[i]); if (i != list.Count - 1) { writer.Seek(pos + sizeof(ushort), (w, op) => w.WriteOffset(op)); } } } else { writer.Seek(offset, (w, op) => w.WriteOffset(op)); writer.WriteString((string)info.Property.GetValue(source) ?? string.Empty); } } }
static void SerializePrimitive(TeraBinaryWriter writer, object value) { var type = value.GetType(); if (type.IsEnum) { type = type.GetEnumUnderlyingType(); } if (type == typeof(bool)) { writer.WriteBoolean((bool)value); } else if (type == typeof(byte)) { writer.WriteByte((byte)value); } else if (type == typeof(sbyte)) { writer.WriteSByte((sbyte)value); } else if (type == typeof(ushort)) { writer.WriteUInt16((ushort)value); } else if (type == typeof(short)) { writer.WriteInt16((short)value); } else if (type == typeof(uint)) { writer.WriteUInt32((uint)value); } else if (type == typeof(int)) { writer.WriteInt32((int)value); } else if (type == typeof(ulong)) { writer.WriteUInt64((ulong)value); } else if (type == typeof(long)) { writer.WriteInt64((long)value); } else if (type == typeof(float)) { writer.WriteSingle((float)value); } else if (type == typeof(Vector3)) { writer.WriteVector3((Vector3)value); } else if (type == typeof(EntityId)) { writer.WriteEntityId((EntityId)value); } else if (type == typeof(SkillId)) { writer.WriteSkillId((SkillId)value); } else if (type == typeof(Angle)) { writer.WriteAngle((Angle)value); } else { throw Assert.Unreachable(); } }
void SerializeObject(TeraBinaryWriter writer, object source) { var fields = GetPacketFields(source.GetType()); var counts = new Dictionary <string, int>(); var offsets = new Dictionary <string, int>(); foreach (var info in fields.Where(x => x.IsPrimitive)) { if (info.IsCount) { counts.Add(info.Property.Name, writer.Position); } else if (info.IsOffset) { offsets.Add(info.Property.Name, writer.Position); } if (info.IsCount || info.IsOffset) { writer.WriteUInt16(0); } else { SerializePrimitive(writer, info.Property.GetValue(source)); } } foreach (var info in fields.Where(x => !x.IsPrimitive)) { var type = info.Property.PropertyType; var value = info.Property.GetValue(source); var array = value as Array; var noOffset = array != null && array.Length == 0; writer.Seek(offsets[info.Property.Name + OffsetNameSuffix], (w, op) => w.WriteUInt16((ushort)(noOffset ? 0 : op + PacketHeader.HeaderSize))); if (type.IsArray) { writer.Seek(counts[info.Property.Name + CountNameSuffix], (w, op) => w.WriteUInt16((ushort)array.Length)); var elemType = type.GetElementType(); if (elemType.IsEnum) { elemType = elemType.GetEnumUnderlyingType(); } var markers = new Stack <int>(); for (var i = 0; i < array.Length; i++) { var isLast = i == array.Length - 1; if (!IsByte(elemType)) { writer.WriteUInt16((ushort)(writer.Position + PacketHeader.HeaderSize)); if (!isLast) { markers.Push(writer.Position); } writer.WriteUInt16(0); } var elem = array.GetValue(i); if (elemType.IsPrimitive) { SerializePrimitive(writer, elem); } else { SerializeObject(writer, elem); } if (!IsByte(elemType) && !isLast) { markers.Push(writer.Position); } } if (!IsByte(elemType)) { for (var i = 0; i < markers.Count / 2; i++) { var afterElemPos = markers.Pop(); var nextPos = markers.Pop(); writer.Seek(nextPos, (w, op) => w.WriteUInt16((ushort)(afterElemPos + PacketHeader.HeaderSize))); } } } else { writer.WriteString((string)value); } } }