1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-04 00:54:14 +02:00

add entity update encoder

This commit is contained in:
Robin Appelman 2017-09-04 23:01:48 +02:00
commit c064439b4e
11 changed files with 1786 additions and 43 deletions

View file

@ -53,4 +53,15 @@ export class PacketEntity {
}
return result;
}
public applyPropUpdate(props: SendProp[]) {
for (const prop of props) {
const existingProp = this.getPropByDefinition(prop.definition);
if (existingProp) {
existingProp.value = prop.value;
} else {
this.props.push(prop);
}
}
}
}

View file

@ -53,6 +53,27 @@ export class SendPropDefinition {
return data;
}
get fullName() {
return `${this.ownerTableName}.${this.name}`;
}
get allFlags() {
return SendPropDefinition.formatFlags(this.flags);
}
static formatFlags(flags: number) {
let names: string[] = [];
for (const name in SendPropFlag) {
const flagValue = <SendPropFlag | string>SendPropFlag[name];
if (typeof flagValue === 'number') {
if (flags & flagValue) {
names.push(name);
}
}
}
return names;
}
}
export enum SendPropType {

View file

@ -48,7 +48,7 @@ export class SendTable {
}
}
get flattenedProps() {
get flattenedProps(): SendPropDefinition[] {
if (this.cachedFlattenedProps.length === 0) {
this.flatten();
}

View file

@ -1,39 +1,54 @@
import {BitStream} from 'bit-buffer';
import {PacketEntity} from '../Data/PacketEntity';
import {SendProp} from '../Data/SendProp';
import {SendTable} from '../Data/SendTable';
import {readUBitVar} from './readBitVar';
import {readBitVar, writeBitVar} from './readBitVar';
import {SendPropParser} from './SendPropParser';
import {SendPropEncoder} from './SendPropEncoder';
export function applyEntityUpdate(entity: PacketEntity, sendTable: SendTable, stream: BitStream): PacketEntity {
export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[] {
let index = -1;
const allProps = sendTable.flattenedProps;
index = readFieldIndex(stream, index);
while (index !== -1) {
const props: SendProp[] = [];
while (stream.readBoolean()) {
index = readFieldIndex(stream, index);
if (index >= 4096 || index > allProps.length) {
throw new Error('prop index out of bounds while applying update for ' + sendTable.name + ' got ' + index
+ ' property only has ' + allProps.length + ' properties');
}
const propDefinition = allProps[index];
const existingProp = entity.getPropByDefinition(propDefinition);
const prop = existingProp ? existingProp : new SendProp(propDefinition);
const prop = new SendProp(propDefinition);
prop.value = SendPropParser.decode(propDefinition, stream);
if (!existingProp) {
entity.props.push(prop);
}
index = readFieldIndex(stream, index);
props.push(prop);
}
return entity;
return props;
}
export function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stream: BitStream) {
const allProps = sendTable.flattenedProps;
let lastIndex = -1;
for (const prop of props) {
stream.writeBoolean(true);
const index = allProps.findIndex(propDef => propDef.fullName === prop.definition.fullName);
if (index === -1) {
throw new Error('Unknown definition for property');
}
writeFieldIndex(index, stream, lastIndex);
lastIndex = index;
if (prop.value !== null) {
SendPropEncoder.encode(prop.value, prop.definition, stream);
}
}
stream.writeBoolean(false);
}
function readFieldIndex(stream: BitStream, lastIndex: number): number {
if (!stream.readBoolean()) {
return -1;
}
const diff = readUBitVar(stream);
const diff = readBitVar(stream);
return lastIndex + diff + 1;
}
function writeFieldIndex(index: number, stream: BitStream, lastIndex: number) {
const diff = index - lastIndex - 1;
writeBitVar(diff, stream);
}

View file

@ -3,7 +3,7 @@ import {Match} from '../../Data/Match';
import {PacketEntitiesPacket} from '../../Data/Packet';
import {EntityId, PacketEntity, PVS} from '../../Data/PacketEntity';
import {SendProp} from '../../Data/SendProp';
import {applyEntityUpdate} from '../EntityDecoder';
import {getEntityUpdate} from '../EntityDecoder';
import {readUBitVar} from '../readBitVar';
const pvsMap = {
@ -39,7 +39,7 @@ function readEnterPVS(stream: BitStream, entityId: EntityId, match: Match): Pack
const staticBaseLine = match.staticBaseLines[serverClass.id];
if (staticBaseLine) {
staticBaseLine.index = 0;
applyEntityUpdate(entity, sendTable, staticBaseLine);
entity.props = getEntityUpdate(sendTable, staticBaseLine);
match.baseLineCache.set(serverClass, entity.clone());
// if (staticBaseLine.bitsLeft > 7) {
// console.log(staticBaseLine.length, staticBaseLine.index);
@ -85,7 +85,8 @@ export function ParsePacketEntities(stream: BitStream, match: Match, skip: boole
const pvs = readPVSType(stream);
if (pvs === PVS.ENTER) {
const packetEntity = readEnterPVS(stream, entityId, match);
applyEntityUpdate(packetEntity, match.getSendTable(packetEntity.serverClass.dataTable), stream);
const updatedProps = getEntityUpdate(match.getSendTable(packetEntity.serverClass.dataTable), stream);
packetEntity.applyPropUpdate(updatedProps);
if (updatedBaseLine) {
const newBaseLine: SendProp[] = [];
@ -96,7 +97,8 @@ export function ParsePacketEntities(stream: BitStream, match: Match, skip: boole
receivedEntities.push(packetEntity);
} else if (pvs === PVS.PRESERVE) {
const packetEntity = getPacketEntityForExisting(entityId, match, pvs);
applyEntityUpdate(packetEntity, match.getSendTable(packetEntity.serverClass.dataTable), stream);
const updatedProps = getEntityUpdate(match.getSendTable(packetEntity.serverClass.dataTable), stream);
packetEntity.applyPropUpdate(updatedProps);
receivedEntities.push(packetEntity);
} else if (match.entityClasses.has(entityId)) {
const packetEntity = getPacketEntityForExisting(entityId, match, pvs);

View file

@ -2,7 +2,8 @@ import {BitStream} from 'bit-buffer';
import {Match} from '../../Data/Match';
import {TempEntitiesPacket} from '../../Data/Packet';
import {PacketEntity, PVS} from '../../Data/PacketEntity';
import {applyEntityUpdate} from '../EntityDecoder';
import {getEntityUpdate} from '../EntityDecoder';
import {readVarInt} from '../readBitVar';
export function ParseTempEntities(stream: BitStream, match: Match, skip: boolean = false): TempEntitiesPacket { // 10: classInfo
const entityCount = stream.readBits(8);
@ -23,11 +24,12 @@ export function ParseTempEntities(stream: BitStream, match: Match, skip: boolean
const sendTable = match.getSendTable(serverClass.dataTable);
entity = new PacketEntity(serverClass, 0, PVS.ENTER);
entity.delay = delay;
applyEntityUpdate(entity, sendTable, stream);
entity.props = getEntityUpdate(sendTable, stream);
entities.push(entity);
} else {
if (entity) {
applyEntityUpdate(entity, match.getSendTable(entity.serverClass.dataTable), stream);
const updatedProps = getEntityUpdate(match.getSendTable(entity.serverClass.dataTable), stream);
entity.applyPropUpdate(updatedProps);
} else {
throw new Error('no entity set to update');
}
@ -44,16 +46,3 @@ export function ParseTempEntities(stream: BitStream, match: Match, skip: boolean
entities,
};
}
function readVarInt(stream: BitStream) {
let result = 0;
for (let run = 0; run < 35; run += 7) {
const byte = stream.readUint8();
result |= ((byte & 0x7F) << run);
if ((byte >> 7) === 0) {
return result;
}
}
return result;
}

View file

@ -0,0 +1,771 @@
{
"name": "DT_WORLD",
"props": [
{
"type": 6,
"name": "baseclass",
"flags": 4096,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": {
"name": "DT_BaseEntity",
"props": [
{
"type": 6,
"name": "AnimTimeMustBeFirst",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": {
"name": "DT_AnimTimeMustBeFirst",
"props": [
{
"type": 0,
"name": "m_flAnimTime",
"flags": 1025,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_AnimTimeMustBeFirst"
}
],
"cachedFlattenedProps": []
},
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_flSimulationTime",
"flags": 1025,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 2,
"name": "m_vecOrigin",
"flags": 9216,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_ubInterpolationFrame",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 2,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_nModelIndex",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 6,
"name": "m_Collision",
"flags": 512,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": {
"name": "DT_CollisionProperty",
"props": [
{
"type": 2,
"name": "m_vecMinsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecMaxsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecMins",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecMaxs",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 0,
"name": "m_nSolidType",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 0,
"name": "m_usSolidFlags",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 10,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 0,
"name": "m_nSurroundType",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 0,
"name": "m_triggerBloat",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecSpecifiedSurroundingMinsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecSpecifiedSurroundingMaxsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecSpecifiedSurroundingMins",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
{
"type": 2,
"name": "m_vecSpecifiedSurroundingMaxs",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
}
],
"cachedFlattenedProps": []
},
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_nRenderFX",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_nRenderMode",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_fEffects",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 10,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_clrRender",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_iTeamNum",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 6,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_CollisionGroup",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 5,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 1,
"name": "m_flElasticity",
"flags": 8196,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 1,
"name": "m_flShadowCastDistance",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 4096,
"bitCount": 12,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_hOwnerEntity",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_hEffectEntity",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "moveparent",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_iParentAttachment",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 6,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "movetype",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 4,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "movecollide",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 2,
"name": "m_angRotation",
"flags": 1024,
"excludeDTName": null,
"lowValue": 0,
"highValue": 360,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_iTextureFrameIndex",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 6,
"name": "predictable_id",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": {
"name": "DT_PredictableId",
"props": [
{
"type": 0,
"name": "m_PredictableID",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 31,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_PredictableId"
},
{
"type": 0,
"name": "m_bIsPlayerSimulated",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_PredictableId"
}
],
"cachedFlattenedProps": []
},
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_bSimulatedEveryTick",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_bAnimatedEveryTick",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 0,
"name": "m_bAlternateSorting",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
{
"type": 6,
"name": "m_nModelIndexOverrides",
"flags": 512,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": {
"name": "m_nModelIndexOverrides",
"props": [
{
"type": 0,
"name": "000",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
{
"type": 0,
"name": "001",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
{
"type": 0,
"name": "002",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
{
"type": 0,
"name": "003",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
}
],
"cachedFlattenedProps": []
},
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
}
],
"cachedFlattenedProps": []
},
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 1,
"name": "m_flWaveHeight",
"flags": 16,
"excludeDTName": null,
"lowValue": 0.03125,
"highValue": 8,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 2,
"name": "m_WorldMins",
"flags": 8192,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 2,
"name": "m_WorldMaxs",
"flags": 8192,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 0,
"name": "m_bStartDark",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 1,
"name": "m_flMaxOccludeeArea",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 1,
"name": "m_flMinOccluderArea",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 1,
"name": "m_flMaxPropScreenSpaceWidth",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 1,
"name": "m_flMinPropScreenSpaceWidth",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 4,
"name": "m_iszDetailSpriteMaterial",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
{
"type": 0,
"name": "m_bColdWorld",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
}
]
}

View file

@ -0,0 +1,844 @@
{
"serverClass": {
"id": 326,
"name": "CWorld",
"dataTable": "DT_WORLD"
},
"entityIndex": 0,
"props": [
{
"definition": {
"type": 0,
"name": "m_flSimulationTime",
"flags": 1025,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 2,
"name": "m_vecOrigin",
"flags": 9216,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_angRotation",
"flags": 1024,
"excludeDTName": null,
"lowValue": 0,
"highValue": 360,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_vecMaxs",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 0,
"name": "m_nSolidType",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": 1
},
{
"definition": {
"type": 0,
"name": "m_usSolidFlags",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 10,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_nSurroundType",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_triggerBloat",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": 0
},
{
"definition": {
"type": 2,
"name": "m_vecSpecifiedSurroundingMinsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_vecSpecifiedSurroundingMaxsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_vecSpecifiedSurroundingMins",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_vecSpecifiedSurroundingMaxs",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 0,
"name": "000",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "001",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "002",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "003",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "m_nModelIndexOverrides"
},
"value": 0
},
{
"definition": {
"type": 2,
"name": "m_vecMinsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 2,
"name": "m_vecMaxsPreScaled",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 0,
"name": "m_ubInterpolationFrame",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 2,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_nModelIndex",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 13,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 1
},
{
"definition": {
"type": 0,
"name": "m_nRenderFX",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_nRenderMode",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_fEffects",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 10,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_clrRender",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 4294967295
},
{
"definition": {
"type": 0,
"name": "m_iTeamNum",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 6,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_CollisionGroup",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 5,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 1,
"name": "m_flElasticity",
"flags": 8196,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 1
},
{
"definition": {
"type": 1,
"name": "m_flShadowCastDistance",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 4096,
"bitCount": 12,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_hOwnerEntity",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 2097151
},
{
"definition": {
"type": 0,
"name": "m_hEffectEntity",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 2097151
},
{
"definition": {
"type": 0,
"name": "moveparent",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 21,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 2097151
},
{
"definition": {
"type": 0,
"name": "m_iParentAttachment",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 6,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "movetype",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 4,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "movecollide",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 3,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 2,
"name": "m_vecMins",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 96,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_CollisionProperty"
},
"value": {
"x": 0,
"y": 0,
"z": 0
}
},
{
"definition": {
"type": 0,
"name": "m_iTextureFrameIndex",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_bSimulatedEveryTick",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_bAnimatedEveryTick",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 0,
"name": "m_bAlternateSorting",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_BaseEntity"
},
"value": 0
},
{
"definition": {
"type": 1,
"name": "m_flWaveHeight",
"flags": 16,
"excludeDTName": null,
"lowValue": 0.03125,
"highValue": 8,
"bitCount": 8,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0.03125
},
{
"definition": {
"type": 2,
"name": "m_WorldMins",
"flags": 8192,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": {
"x": -5394,
"y": -4832,
"z": -584
}
},
{
"definition": {
"type": 2,
"name": "m_WorldMaxs",
"flags": 8192,
"excludeDTName": null,
"lowValue": 0,
"highValue": -121121.125,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": {
"x": 6450,
"y": 5248,
"z": 960
}
},
{
"definition": {
"type": 0,
"name": "m_bStartDark",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0
},
{
"definition": {
"type": 1,
"name": "m_flMaxOccludeeArea",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0
},
{
"definition": {
"type": 1,
"name": "m_flMinOccluderArea",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0
},
{
"definition": {
"type": 1,
"name": "m_flMaxPropScreenSpaceWidth",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": -1
},
{
"definition": {
"type": 1,
"name": "m_flMinPropScreenSpaceWidth",
"flags": 4,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 32,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0
},
{
"definition": {
"type": 4,
"name": "m_iszDetailSpriteMaterial",
"flags": 0,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 0,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": "detail/detailsprites_sawmill"
},
{
"definition": {
"type": 0,
"name": "m_bColdWorld",
"flags": 1,
"excludeDTName": null,
"lowValue": 0,
"highValue": 0,
"bitCount": 1,
"table": null,
"numElements": 0,
"arrayProperty": null,
"ownerTableName": "DT_WORLD"
},
"value": 0
}
],
"inPVS": false,
"pvs": 1
}

View file

@ -0,0 +1,89 @@
import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {readFileSync} from 'fs';
import {SendTable} from '../../../../Data/SendTable';
import {encodeEntityUpdate, getEntityUpdate} from '../../../../Parser/EntityDecoder';
import {SendProp, SendPropValue} from '../../../../Data/SendProp';
import {SendPropDefinition, SendPropType} from '../../../../Data/SendPropDefinition';
import {PacketEntity} from '../../../../Data/PacketEntity';
import {Vector} from '../../../../Data/Vector';
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
import {SendPropParser} from '../../../../Parser/SendPropParser';
const data = [
9, 128, 64, 64, 64, 64, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 36, 0, 64, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 128, 0, 0, 8, 0, 128, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 64, 0, 32, 0, 16, 0, 32, 240, 255, 255, 255, 31, 0, 2, 32, 48, 0, 128, 0, 0, 4, 254, 255, 127, 224, 255, 255, 7, 254, 255, 127, 0, 8, 64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 64, 64, 64, 64, 0, 32, 224, 136, 10, 248, 91, 2, 63, 18, 8, 40, 38, 3, 250, 163, 192, 126, 7, 2, 2, 0, 0, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 224, 111, 0, 0, 0, 0, 32, 192, 129, 172, 140, 46, 44, 141, 237, 133, 172, 140, 46, 44, 141, 109, 14, 78, 46, 141, 174, 108, 238, 107, 46, 236, 174, 45, 141, 141, 45, 0];
const entityData = JSON.parse(readFileSync(__dirname + '/../../../data/worldEntity.json', 'utf8'));
const sendTableData = JSON.parse(readFileSync(__dirname + '/../../../data/sendTableDTWorld.json', 'utf8'));
const sendTable = hydrateTable(sendTableData);
const entity = hydrateEntity(entityData);
function hydrateEntity(entityData): PacketEntity {
const entity = new PacketEntity(entityData.serverClass, entityData.entityIndex, entityData.pvs);
entity.props = entityData.props.map(propData => {
const prop = new SendProp(propDataDefinition(propData.definition));
if (prop.definition.type === SendPropType.DPT_Vector || prop.definition.type === SendPropType.DPT_VectorXY) {
prop.value = new Vector(propData.value.x, propData.value.y, propData.value.z);
} else {
prop.value = propData.value;
}
return prop;
});
return entity;
}
function propDataDefinition(propData): SendPropDefinition {
const prop = new SendPropDefinition(propData.type, propData.name, propData.flags, propData.ownerTableName);
prop.arrayProperty = propData.arrayProperty;
prop.numElements = propData.numElements;
prop.bitCount = propData.bitCount;
prop.excludeDTName = propData.excludeDTName;
prop.lowValue = propData.lowValue;
prop.highValue = propData.highValue;
prop.table = propData.table ? hydrateTable(propData.table) : null;
return prop;
}
function hydrateTable(tableData): SendTable {
const table = new SendTable(tableData.name);
table.props = tableData.props.map(propDataDefinition);
return table;
}
function decodeUpdate(stream: BitStream) {
return getEntityUpdate(sendTable, stream);
}
function encodeUpdate(props: SendProp[], stream: BitStream) {
encodeEntityUpdate(props, sendTable, stream);
}
function encodeProp(prop: SendProp) {
return function (value: SendPropValue, stream: BitStream) {
return SendPropEncoder.encode(value, prop.definition, stream);
};
}
function decodeProp(prop: SendProp) {
return function (stream: BitStream) {
return SendPropParser.decode(prop.definition, stream);
};
}
suite('Entity Decoder', () => {
test('Encode sendProps', () => {
for (const prop of entity.props) {
if (prop.value !== null) {
assertEncoder(decodeProp(prop), encodeProp(prop), prop.value, 0, ` for ${SendPropType[prop.definition.type]} with flags ${prop.definition.allFlags}`);
}
}
});
test('Decode entity update', () => {
assertParser(decodeUpdate, getStream(data), entity.props, 1958);
});
test('Encode userMessage', () => {
assertEncoder(decodeUpdate, encodeUpdate, entity.props, 1966);
});
});

View file

@ -2,6 +2,7 @@ import * as assert from 'assert';
import {BitStream} from 'bit-buffer';
import {Packet} from '../../../../Data/Packet';
import {deepEqual} from '../../deepEqual';
import {isObject} from 'util';
export function getStream(data: string | number[]) {
if (typeof data === 'string') {
@ -15,7 +16,7 @@ export function getStream(data: string | number[]) {
export type Encoder = (data: any, stream: BitStream) => void;
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0) {
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0, message: string = '') {
const stream = new BitStream(new ArrayBuffer(Math.max(64, length * 8)));
encoder(data as Packet, stream);
@ -23,7 +24,7 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
const pos = stream.index;
if (length) {
assert.equal(stream.index, length, 'Unexpected number of bits used for encoding');
assert.equal(stream.index, length, 'Unexpected number of bits used for encoding' + message);
}
stream.index = 0;
@ -31,9 +32,9 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
const result = parser(stream);
deepEqual(result, data);
if (!deepEqual(result, data)) {
assert.deepEqual(result, data, 'Re-decoded value not equal to original value');
assert.deepEqual(result, data, 'Re-decoded value not equal to original value' + message);
}
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal');
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal' + message);
}
export type Parser = (stream: BitStream, match?) => any;

View file

@ -61,14 +61,14 @@ suite('readBitVar', () => {
assertParser(readBitVarSigned, getStream([131, 225, 212, 14, 123]), -1011533728, 34);
});
test('writeVarInt', () => {
test('writeBitVar', () => {
assertEncoder(readBitVar, writeBitVar, 2, 6);
assertEncoder(readBitVar, writeBitVar, 94, 10);
assertEncoder(readBitVar, writeBitVar, 1632, 14);
assertEncoder(readBitVar, writeBitVar, 3283433568, 34);
});
test('writeVarInt signed', () => {
test('writeBitVar signed', () => {
assertEncoder(readBitVarSigned, writeBitVarSigned, 2, 6);
assertEncoder(readBitVarSigned, writeBitVarSigned, -94, 10);
assertEncoder(readBitVarSigned, writeBitVarSigned, 1632, 14);