private void ReadChunkHeader(Bitstream stream) { header = new ChunkedHeader(); header.IsFile = stream.ReadBool(); if (header.IsFile) { var filenameLength = stream.ReadUInt32(); var filename = new byte[filenameLength + 1]; // semantically wrong. should be // 0x104 stream.Read(filename, 0, (int) filenameLength); // and then read to end of string filename[filenameLength] = 0; // whatever header.Filename = Encoding.UTF8.GetString(filename); throw new NotImplementedException(); } header.IsCompressed = stream.ReadBool(); if (header.IsCompressed) { header.DecompressedLength = stream.ReadBits(26); } header.ByteLength = stream.ReadBits(26); header.ChunkCount = (header.ByteLength + DotaGameConnection.BYTES_PER_CHUNK - 1)/ DotaGameConnection.BYTES_PER_CHUNK; Receiving = true; dataIn = new byte[header.ByteLength]; dataReceived = new bool[header.ChunkCount]; countReceived = 0; }
private UpdateFlag ReadHeader(ref uint id, Bitstream stream) { var value = stream.ReadBits(6); if ((value & 0x30) > 0) { var a = (value >> 4) & 3; var b = (uint) ((a == 3) ? 16 : 0); value = (stream.ReadBits((byte) (4*a + b)) << 4) | (value & 0xF); } id = unchecked(id + value + 1); var flags = UpdateFlag.None; if (!stream.ReadBool()) { if (stream.ReadBool()) { flags |= UpdateFlag.EnterPvs; } } else { flags |= UpdateFlag.LeavePvs; if (stream.ReadBool()) { flags |= UpdateFlag.Delete; } } return flags; }
private string ReadKeyIfIncluded(Bitstream stream, List<string> keyHistory) { var has_key = stream.ReadBool(); if (!has_key) { return null; } var is_substring = stream.ReadBool(); string key; if (!is_substring) { key = stream.ReadString(); } else { var fromIndex = (int) stream.ReadBits(5); var fromLength = (int) stream.ReadBits(5); key = keyHistory[fromIndex].Substring(0, fromLength); key += stream.ReadString(); } if (keyHistory.Count == KEY_HISTORY_SIZE) { keyHistory.RemoveAt(0); } keyHistory.Add(key); return key; }
public Message? Receive(Bitstream stream) { var hasData = stream.ReadBool(); if (!hasData) { return null; } if (stream.ReadBool()) { return ReadChunk(stream); } return ReadSingle(stream); }
public float UnpackFloat(PropertyInfo info, Bitstream stream) { var flags = info.Flags; if (flags.HasFlag(PropertyInfo.MultiFlag.Coord)) { return UnpackFloatCoord(stream); } if (flags.HasFlag(PropertyInfo.MultiFlag.CoordMp)) { return UnpackFloatCoordMp(stream, FloatType.None); } if (flags.HasFlag(PropertyInfo.MultiFlag.CoordMpLowPrecision)) { return UnpackFloatCoordMp(stream, FloatType.LowPrecision); } if (flags.HasFlag(PropertyInfo.MultiFlag.CoordMpIntegral)) { return UnpackFloatCoordMp(stream, FloatType.Integral); } if (flags.HasFlag(PropertyInfo.MultiFlag.NoScale)) { return UnpackFloatNoScale(stream); } if (flags.HasFlag(PropertyInfo.MultiFlag.Normal)) { return UnpackFloatNormal(stream); } if (flags.HasFlag(PropertyInfo.MultiFlag.CellCoord)) { return UnpackFloatCellCoord(info, stream, FloatType.None); } if (flags.HasFlag(PropertyInfo.MultiFlag.CellCoordLowPrecision)) { return UnpackFloatCellCoord(info, stream, FloatType.LowPrecision); } if (flags.HasFlag(PropertyInfo.MultiFlag.CellCoordIntegral)) { return UnpackFloatCellCoord(info, stream, FloatType.Integral); } var dividend = stream.ReadBits(info.NumBits); var divisor = (uint) (1 << info.NumBits) - 1; var f = ((float) dividend)/divisor; var range = info.HighValue - info.LowValue; return f*range + info.LowValue; }
private Message? ReadChunk(Bitstream stream) { var offset = stream.ReadBits(18); var count = stream.ReadBits(3); if (offset == 0) { ReadChunkHeader(stream); } var byteOffset = offset*DotaGameConnection.BYTES_PER_CHUNK; uint byteCount; if (offset + count < header.ChunkCount) { byteCount = count*DotaGameConnection.BYTES_PER_CHUNK; } else { byteCount = header.ByteLength - byteOffset; } stream.Read(dataIn, (int) byteOffset, (int) byteCount); for (var i = offset; i < offset + count; ++i) { if (!dataReceived[i]) { dataReceived[i] = true; ++countReceived; } } if (countReceived == header.ChunkCount) { Receiving = false; return new Message { IsCompressed = header.IsCompressed, DecompressedLength = header.DecompressedLength, Data = dataIn }; } return null; }
public void Update(Bitstream stream, uint baseline, bool updateBaseline, uint updated, bool isDelta) { var id = uint.MaxValue; uint found = 0; while (found < updated) { var flags = ReadHeader(ref id, stream); if (flags.HasFlag(UpdateFlag.EnterPvs)) { ReadEnterPvs(id, baseline, updateBaseline, stream); } else if (flags.HasFlag(UpdateFlag.LeavePvs)) { if (flags.HasFlag(UpdateFlag.Delete)) { Delete(id); } } else { ReadUpdate(id, stream); } ++found; } if (isDelta) { while (stream.ReadBool()) { id = stream.ReadBits(11); Delete(id); } } }
public uint UnpackInt(PropertyInfo info, Bitstream stream) { var flags = info.Flags; if (flags.HasFlag(PropertyInfo.MultiFlag.EncodedAgainstTickcount)) { if (flags.HasFlag(PropertyInfo.MultiFlag.Unsigned)) { return stream.ReadVarUInt(); } var value = stream.ReadVarUInt(); return unchecked((uint) ((-(value & 1)) ^ (value >> 1))); } var numBits = info.NumBits; var isUnsigned = Convert.ToUInt32(flags.HasFlag(PropertyInfo.MultiFlag.Unsigned)); var signer = (0x80000000 >> (32 - numBits)) & unchecked((isUnsigned - 1)); { var value = stream.ReadBits(numBits) ^ signer; return value - signer; } }
public string UnpackString(PropertyInfo info, Bitstream stream) { var length = stream.ReadBits(9); var buffer = new byte[length]; stream.Read(buffer, 0, (int) length); return new string((from byte b in buffer select (char) b).ToArray<char>()); }
public VectorXy UnpackVectorXy(PropertyInfo info, Bitstream stream) { var x = UnpackFloat(info, stream); var y = UnpackFloat(info, stream); return new VectorXy(x, y); }
public Vector UnpackVector(PropertyInfo info, Bitstream stream) { var x = UnpackFloat(info, stream); var y = UnpackFloat(info, stream); float z; if (info.Flags.HasFlag(PropertyInfo.MultiFlag.Normal)) { var sign = stream.ReadBool(); var f = x*x + y*y; if (1 >= f) { z = 0; } else { z = (float) Math.Sqrt(1 - f); } if (sign) { z *= -1; } } else { z = UnpackFloat(info, stream); } return new Vector(x, y, z); }
private float UnpackFloatCellCoord(PropertyInfo info, Bitstream stream, FloatType type) { var value = stream.ReadBits(info.NumBits); float f = value; if ((value >> 31) > 0) { f *= -1; } if (type == FloatType.None) { var fraction = stream.ReadBits(5); return f + 0.03125f*fraction; } if (type == FloatType.LowPrecision) { var fraction = stream.ReadBits(3); return f + 0.125f*fraction; } if (type == FloatType.Integral) { return f; } throw new InvalidOperationException("Unknown float type"); }
private float UnpackFloatNormal(Bitstream stream) { var sign = stream.ReadBool(); var value = stream.ReadBits(NORMAL_FRACTIONAL_BITS); var f = (float) (value*NORMAL_RESOLUTION); if (sign) { f *= -1; } return f; }
private uint ReadFieldNumber(uint lastField, Bitstream stream) { if (stream.ReadBool()) { return unchecked(lastField + 1); } var value = stream.ReadVarUInt(); if (value == 0x3FFF) { return uint.MaxValue; } return unchecked(lastField + value + 1); }
private float UnpackFloatCoord(Bitstream stream) { var hasInteger = stream.ReadBool(); var hasFraction = stream.ReadBool(); if (hasInteger || hasFraction) { var sign = stream.ReadBool(); uint integer = 0; if (hasInteger) { integer = stream.ReadBits(COORD_INTEGER_BITS) + 1; } uint fraction = 0; if (hasFraction) { fraction = stream.ReadBits(COORD_FRACTIONAL_BITS); } var f = (float) (integer + fraction*COORD_RESOLUTION); if (sign) { f *= -1; } return f; } return 0; }
private byte[] ReadValueIfIncluded(Bitstream stream, bool userDataFixedSize, uint userDataSizeBits) { var has_value = stream.ReadBool(); if (!has_value) { return null; } uint length; uint bitLength; if (userDataFixedSize) { length = (userDataSizeBits + 7)/8; bitLength = userDataSizeBits; } else { length = stream.ReadBits(14); bitLength = 8*length; } return stream.ReadManyBits(bitLength); }
private void ReadEnterPvs(uint id, uint baseline, bool update_baseline, Bitstream stream) { var clazz = state.Classes[(int) stream.ReadBits(ClassBitLength)]; var serial = stream.ReadBits(10); Create(id, clazz, baseline); ReadAndUnpackFields(state.Slots[id].Entity, stream); if (update_baseline) { state.Slots[id].Baselines[1 - baseline] = state.Slots[id].Entity.Copy(); } }
private void ReadUpdate(uint id, Bitstream stream) { var entity = state.Slots[id].Entity; ReadAndUnpackFields(entity, stream); }
private Message ReadSingle(Bitstream stream) { var isCompressed = stream.ReadBool(); if (isCompressed) { var uncompressed_length = stream.ReadBits(26); var length = stream.ReadBits(18); var data = new byte[length]; stream.Read(data, 0, (int) length); return new Message { IsCompressed = false, Data = new SnappyDecompressor().Decompress(data, 0, data.Length) }; } else { var length = stream.ReadBits(18); var data = new byte[length]; stream.Read(data, 0, (int) length); return new Message { IsCompressed = false, Data = data }; } }
private void ReadAndUnpackFields(Entity entity, Bitstream stream) { var fields = ReadFieldList(stream); foreach (var field in fields) { entity.Properties[(int) field].Update(state.ClientTick, unpacker, stream); } }
public void UnpackArray(uint tick, List<Property> elements, PropertyInfo info, Bitstream stream) { var countBits = MiscMath.Log2(info.NumElements + 1); var count = stream.ReadBits(countBits); if (elements.Count > count) { elements.RemoveRange(0, elements.Count - (int) count); } else { while (elements.Count < count) { elements.Add(Property.For(info.ArrayProp)); } } foreach (var element in elements) { element.Update(tick, this, stream); } }
private float UnpackFloatCoordMp(Bitstream stream, FloatType type) { throw new NotImplementedException(); }
public ulong UnpackInt64(PropertyInfo info, Bitstream stream) { if (info.Flags.HasFlag(PropertyInfo.MultiFlag.EncodedAgainstTickcount)) { return stream.ReadVarUInt(); } var negate = false; var secondBits = (byte) (info.NumBits - 32); if (!info.Flags.HasFlag(PropertyInfo.MultiFlag.Unsigned)) { --secondBits; if (stream.ReadBool()) { negate = true; } } ulong a = stream.ReadBits(32); ulong b = stream.ReadBits(secondBits); var value = (b << 32) | a; if (negate) { value = unchecked((ulong) ((long) value*-1)); } return value; }
private float UnpackFloatNoScale(Bitstream stream) { var data = stream.ReadManyBits(32); return BitConverter.ToSingle(data, 0); }
private void WriteUserCmd(UserCmd cmd, UserCmd last, Bitstream stream) { if (cmd.Command != last.Command + 1) { stream.WriteBool(true); stream.WriteUInt32(cmd.Command); } else { stream.WriteBool(false); } if (cmd.Tick != last.Tick + 1) { stream.WriteBool(true); stream.WriteUInt32(cmd.Tick); } else { stream.WriteBool(false); } if (cmd.ViewAngles.X != last.ViewAngles.X) { stream.WriteBool(true); stream.WriteFloat(cmd.ViewAngles.X); } else { stream.WriteBool(false); } if (cmd.ViewAngles.X != last.ViewAngles.X) { stream.WriteBool(true); stream.WriteFloat(cmd.ViewAngles.X); } else { stream.WriteBool(false); } if (cmd.ViewAngles.Z != last.ViewAngles.Z) { stream.WriteBool(true); stream.WriteFloat(cmd.ViewAngles.Z); } else { stream.WriteBool(false); } if (cmd.ForwardMove != last.ForwardMove) { stream.WriteBool(true); stream.WriteFloat(cmd.ForwardMove); } else { stream.WriteBool(false); } if (cmd.SideMove != last.SideMove) { stream.WriteBool(true); stream.WriteFloat(cmd.SideMove); } else { stream.WriteBool(false); } if (cmd.UpMove != last.UpMove) { stream.WriteBool(true); stream.WriteFloat(cmd.UpMove); } else { stream.WriteBool(false); } if (cmd.Buttons != last.Buttons) { stream.WriteBool(true); stream.WriteUInt32(cmd.Buttons); } else { stream.WriteBool(false); } if (cmd.Impulse != last.Impulse) { stream.WriteBool(true); stream.WriteByte(cmd.Impulse); } else { stream.WriteBool(false); } if (cmd.CrosshairTrace != last.CrosshairTrace) { stream.WriteBool(true); stream.WriteBitVec3Coord(cmd.CrosshairTrace); } else { stream.WriteBool(false); } if (cmd.CursorUnitEntIndex != last.CursorUnitEntIndex) { stream.WriteBool(true); stream.WriteBits(cmd.CursorUnitEntIndex, 11); } else { stream.WriteBool(false); } if (cmd.QueryEntIndex != last.QueryEntIndex) { stream.WriteBool(true); stream.WriteBits(cmd.QueryEntIndex, 11); } else { stream.WriteBool(false); } if (cmd.CursorUnitEntIndex != last.CursorUnitEntIndex) { stream.WriteBool(true); stream.WriteBits(cmd.CursorUnitEntIndex, 11); if (cmd.QueryEntIndex != last.QueryEntIndex) { stream.WriteBool(true); stream.WriteBits(cmd.QueryEntIndex, 11); } else { stream.WriteBool(false); } } else { stream.WriteBool(false); } if (cmd.MouseDx != last.MouseDx) { stream.WriteBool(true); stream.WriteUInt16(cmd.MouseDx); } else { stream.WriteBool(false); } if (cmd.MouseDy != last.MouseDy) { stream.WriteBool(true); stream.WriteUInt16(cmd.MouseDy); } else { stream.WriteBool(false); } if (cmd.Offset3c != last.Offset3c) { stream.WriteBool(true); stream.WriteUInt16(cmd.Offset3c); } else { stream.WriteBool(false); } // 0x44 to 0x74 inclusive if (cmd.OrderId != last.OrderId) { stream.WriteBool(true); stream.WriteInt16(cmd.OrderId); stream.WriteInt16((short) cmd.Order.Value.SelectedUnits.Length); foreach (var entity in cmd.Order.Value.SelectedUnits) { stream.WriteBits(entity, 11); } stream.WriteInt16(cmd.Order.Value.OrderType); stream.WriteInt16(cmd.Order.Value.EntityIndex1); stream.WriteBitVec3Coord(cmd.Order.Value.PreparedOrderPoint); stream.WriteBits(cmd.Order.Value.BaseNpcHandle, 11); stream.WriteBool(cmd.Order.Value.QueueOrder); } else { stream.WriteBool(false); } if (cmd.CameraX != last.CameraX || cmd.CameraY != last.CameraY) { stream.WriteBool(true); stream.WriteUInt16(cmd.CameraX); stream.WriteUInt16(cmd.CameraY); } else { stream.WriteBool(false); } if (cmd.ClickBehavior != last.ClickBehavior) { stream.WriteBool(true); stream.WriteByte(cmd.ClickBehavior); } else { stream.WriteBool(false); } if (cmd.SpectatorStatsSomething != last.SpectatorStatsSomething) { stream.WriteBool(true); stream.WriteByte(cmd.SpectatorStatsSomething); } else { stream.WriteBool(false); } if (cmd.ShopModeSomething != last.ShopModeSomething) { stream.WriteBool(true); stream.WriteByte(cmd.ShopModeSomething); } else { stream.WriteBool(false); } if (cmd.HudStatsDropdownCategoryIndex != last.HudStatsDropdownCategoryIndex) { stream.WriteBool(true); stream.WriteByte(cmd.HudStatsDropdownCategoryIndex); } else { stream.WriteBool(false); } if (cmd.HudStatsDropdownSortMethod != last.HudStatsDropdownSortMethod) { stream.WriteBool(true); stream.WriteByte(cmd.HudStatsDropdownSortMethod); } else { stream.WriteBool(false); } }
private List<uint> ReadFieldList(Bitstream stream) { var fields = new List<uint>(); var field = uint.MaxValue; field = ReadFieldNumber(field, stream); while (field != uint.MaxValue) { fields.Add(field); field = ReadFieldNumber(field, stream); } return fields; }