mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
add encoder for sendprops
This commit is contained in:
parent
44394b0320
commit
ca2083c64a
7 changed files with 336 additions and 58 deletions
|
|
@ -1,43 +1,8 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {BSPDecalPacket} from '../../Data/Packet';
|
import {BSPDecalPacket} from '../../Data/Packet';
|
||||||
import {Vector} from '../../Data/Vector';
|
import {Vector} from '../../Data/Vector';
|
||||||
|
import {SendPropParser} from '../SendPropParser';
|
||||||
export function getCoord(stream: BitStream): number {
|
import {SendPropEncoder} from '../SendPropEncoder';
|
||||||
const hasInt = stream.readBoolean();
|
|
||||||
const hasFract = stream.readBoolean();
|
|
||||||
let value = 0;
|
|
||||||
if (hasInt || hasFract) {
|
|
||||||
const sign = stream.readBoolean();
|
|
||||||
if (hasInt) {
|
|
||||||
value += stream.readBits(14) + 1;
|
|
||||||
}
|
|
||||||
if (hasFract) {
|
|
||||||
value += stream.readBits(5) * (1 / 32);
|
|
||||||
}
|
|
||||||
if (sign) {
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function encodeCoord(value: number, stream: BitStream) {
|
|
||||||
const abs = Math.abs(value);
|
|
||||||
const intPart = Math.floor(abs);
|
|
||||||
const fractPart = abs % 1;
|
|
||||||
stream.writeBoolean(intPart !== 0);
|
|
||||||
stream.writeBoolean(fractPart !== 0);
|
|
||||||
if (intPart || fractPart) {
|
|
||||||
stream.writeBoolean(value < 0);
|
|
||||||
if (intPart) {
|
|
||||||
stream.writeBits(intPart - 1, 14);
|
|
||||||
}
|
|
||||||
if (fractPart) {
|
|
||||||
stream.writeBits(fractPart * 32, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getVecCoord(stream: BitStream): Vector {
|
export function getVecCoord(stream: BitStream): Vector {
|
||||||
const hasX = stream.readBoolean();
|
const hasX = stream.readBoolean();
|
||||||
|
|
@ -45,9 +10,9 @@ export function getVecCoord(stream: BitStream): Vector {
|
||||||
const hasZ = stream.readBoolean();
|
const hasZ = stream.readBoolean();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: hasX ? getCoord(stream) : 0,
|
x: hasX ? SendPropParser.readBitCoord(stream) : 0,
|
||||||
y: hasY ? getCoord(stream) : 0,
|
y: hasY ? SendPropParser.readBitCoord(stream) : 0,
|
||||||
z: hasZ ? getCoord(stream) : 0,
|
z: hasZ ? SendPropParser.readBitCoord(stream) : 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,13 +22,13 @@ export function encodeVecCoord(vector: Vector, stream: BitStream) {
|
||||||
stream.writeBoolean(vector.z !== 0);
|
stream.writeBoolean(vector.z !== 0);
|
||||||
|
|
||||||
if (vector.x !== 0) {
|
if (vector.x !== 0) {
|
||||||
encodeCoord(vector.x, stream);
|
SendPropEncoder.writeBitCoord(vector.x, stream);
|
||||||
}
|
}
|
||||||
if (vector.y !== 0) {
|
if (vector.y !== 0) {
|
||||||
encodeCoord(vector.y, stream);
|
SendPropEncoder.writeBitCoord(vector.y, stream);
|
||||||
}
|
}
|
||||||
if (vector.z !== 0) {
|
if (vector.z !== 0) {
|
||||||
encodeCoord(vector.z, stream);
|
SendPropEncoder.writeBitCoord(vector.z, stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
163
src/Parser/SendPropEncoder.ts
Normal file
163
src/Parser/SendPropEncoder.ts
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {SendPropArrayValue, SendPropValue} from '../Data/SendProp';
|
||||||
|
import {SendPropDefinition, SendPropFlag, SendPropType} from '../Data/SendPropDefinition';
|
||||||
|
import {Vector} from '../Data/Vector';
|
||||||
|
import {logBase2} from '../Math';
|
||||||
|
import {makeUnsigned, writeVarInt} from './readBitVar';
|
||||||
|
import {bitNormalFactor} from './SendPropParser';
|
||||||
|
|
||||||
|
export class SendPropEncoder {
|
||||||
|
public static encode(value: SendPropValue, propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
switch (propDefinition.type) {
|
||||||
|
case SendPropType.DPT_Int:
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new Error('Invalid value for DPT_Int');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeInt(value, propDefinition, stream);
|
||||||
|
case SendPropType.DPT_Vector:
|
||||||
|
if (!(value instanceof Vector)) {
|
||||||
|
throw new Error('Invalid value for DPT_Vector');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeVector(value, propDefinition, stream);
|
||||||
|
case SendPropType.DPT_VectorXY:
|
||||||
|
if (!(value instanceof Vector)) {
|
||||||
|
throw new Error('Invalid value for DPT_Vector');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeVectorXY(value, propDefinition, stream);
|
||||||
|
case SendPropType.DPT_Float:
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new Error('Invalid value for DPT_Int');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeFloat(value, propDefinition, stream);
|
||||||
|
case SendPropType.DPT_String:
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
throw new Error('Invalid value for DPT_Int');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeString(value, stream);
|
||||||
|
case SendPropType.DPT_Array:
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
throw new Error('Invalid value for DPT_Int');
|
||||||
|
}
|
||||||
|
return SendPropEncoder.writeArray(value, propDefinition, stream);
|
||||||
|
}
|
||||||
|
throw new Error('Unknown property type');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeInt(value: number, propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
if (propDefinition.hasFlag(SendPropFlag.SPROP_VARINT)) {
|
||||||
|
return writeVarInt(value, stream, !propDefinition.hasFlag(SendPropFlag.SPROP_UNSIGNED));
|
||||||
|
} else {
|
||||||
|
if (propDefinition.hasFlag(SendPropFlag.SPROP_UNSIGNED)) {
|
||||||
|
return stream.writeBits(value, propDefinition.bitCount);
|
||||||
|
} else {
|
||||||
|
return stream.writeBits(makeUnsigned(value), propDefinition.bitCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeArray(value: SendPropArrayValue[], propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
const numBits = logBase2(propDefinition.numElements) + 1;
|
||||||
|
|
||||||
|
stream.writeBits(value.length, numBits);
|
||||||
|
if (!propDefinition.arrayProperty) {
|
||||||
|
throw new Error('Array of undefined type');
|
||||||
|
}
|
||||||
|
for (const arrayValue of value) {
|
||||||
|
SendPropEncoder.encode(arrayValue, propDefinition.arrayProperty, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeString(value: string, stream: BitStream) {
|
||||||
|
// +1 for null
|
||||||
|
stream.writeBits(value.length + 1, 9);
|
||||||
|
stream.writeASCIIString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeVector(value: Vector, propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
SendPropEncoder.writeFloat(value.x, propDefinition, stream);
|
||||||
|
SendPropEncoder.writeFloat(value.y, propDefinition, stream);
|
||||||
|
SendPropEncoder.writeFloat(value.z, propDefinition, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeVectorXY(value: Vector, propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
SendPropEncoder.writeFloat(value.x, propDefinition, stream);
|
||||||
|
SendPropEncoder.writeFloat(value.y, propDefinition, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeFloat(value: number, propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD)) {
|
||||||
|
return SendPropEncoder.writeBitCoord(value, stream);
|
||||||
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP)) {
|
||||||
|
return SendPropEncoder.writeBitCoordMP(value, stream, false, false);
|
||||||
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_LOWPRECISION)) {
|
||||||
|
return SendPropEncoder.writeBitCoordMP(value, stream, false, true);
|
||||||
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_INTEGRAL)) {
|
||||||
|
return SendPropEncoder.writeBitCoordMP(value, stream, true, false);
|
||||||
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NOSCALE)) {
|
||||||
|
return stream.writeFloat32(value);
|
||||||
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NORMAL)) {
|
||||||
|
return SendPropEncoder.writeBitNormal(value, stream);
|
||||||
|
} else {
|
||||||
|
const percentage = (value - propDefinition.lowValue) / (propDefinition.highValue - propDefinition.lowValue);
|
||||||
|
const raw = Math.round(percentage * ((1 << propDefinition.bitCount) - 1));
|
||||||
|
stream.writeBits(raw, propDefinition.bitCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeBitNormal(value: number, stream: BitStream) {
|
||||||
|
stream.writeBoolean(value < 0);
|
||||||
|
const abs = Math.abs(value);
|
||||||
|
const fractPart = abs % 1;
|
||||||
|
const fractVal = Math.round(fractPart / bitNormalFactor);
|
||||||
|
stream.writeBits(fractVal, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeBitCoord(value: number, stream: BitStream) {
|
||||||
|
const abs = Math.abs(value);
|
||||||
|
const intPart = Math.floor(abs);
|
||||||
|
const fractPart = abs % 1;
|
||||||
|
stream.writeBoolean(intPart !== 0);
|
||||||
|
stream.writeBoolean(fractPart !== 0);
|
||||||
|
if (intPart || fractPart) {
|
||||||
|
stream.writeBoolean(value < 0);
|
||||||
|
if (intPart) {
|
||||||
|
stream.writeBits(intPart - 1, 14);
|
||||||
|
}
|
||||||
|
if (fractPart) {
|
||||||
|
stream.writeBits(fractPart * 32, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static writeBitCoordMP(value: number, stream: BitStream, isIntegral: boolean, isLowPrecision: boolean) {
|
||||||
|
const abs = Math.abs(value);
|
||||||
|
const intPart = Math.floor(abs);
|
||||||
|
const fractPart = abs % 1;
|
||||||
|
const inBounds = intPart < Math.pow(2, 11);
|
||||||
|
stream.writeBoolean(inBounds);
|
||||||
|
stream.writeBoolean(intPart > 0);
|
||||||
|
|
||||||
|
if (isIntegral) {
|
||||||
|
if (intPart) {
|
||||||
|
stream.writeBoolean(value < 0);
|
||||||
|
|
||||||
|
if (inBounds) {
|
||||||
|
stream.writeBits(intPart - 1, 11);
|
||||||
|
} else {
|
||||||
|
stream.writeBits(intPart - 1, 14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stream.writeBoolean(value < 0);
|
||||||
|
if (intPart) {
|
||||||
|
if (inBounds) {
|
||||||
|
stream.writeBits(intPart - 1, 11);
|
||||||
|
} else {
|
||||||
|
stream.writeBits(intPart - 1, 14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fractVal = Math.round(fractPart / (1 / (1 << (isLowPrecision ? 3 : 5))));
|
||||||
|
stream.writeBits(fractVal, isLowPrecision ? 3 : 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,8 @@ import {Vector} from '../Data/Vector';
|
||||||
import {logBase2} from '../Math';
|
import {logBase2} from '../Math';
|
||||||
import {readVarInt} from './readBitVar';
|
import {readVarInt} from './readBitVar';
|
||||||
|
|
||||||
|
export const bitNormalFactor = (1 / ((1 << 11) - 1));
|
||||||
|
|
||||||
export class SendPropParser {
|
export class SendPropParser {
|
||||||
public static decode(propDefinition: SendPropDefinition, stream: BitStream): SendPropValue {
|
public static decode(propDefinition: SendPropDefinition, stream: BitStream): SendPropValue {
|
||||||
switch (propDefinition.type) {
|
switch (propDefinition.type) {
|
||||||
|
|
@ -72,11 +74,11 @@ export class SendPropParser {
|
||||||
if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD)) {
|
if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD)) {
|
||||||
return SendPropParser.readBitCoord(stream);
|
return SendPropParser.readBitCoord(stream);
|
||||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP)) {
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP)) {
|
||||||
return SendPropParser.readBitCoordMP(propDefinition, stream, false, false);
|
return SendPropParser.readBitCoordMP(stream, false, false);
|
||||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_LOWPRECISION)) {
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_LOWPRECISION)) {
|
||||||
return SendPropParser.readBitCoordMP(propDefinition, stream, false, true);
|
return SendPropParser.readBitCoordMP(stream, false, true);
|
||||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_INTEGRAL)) {
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP_INTEGRAL)) {
|
||||||
return SendPropParser.readBitCoordMP(propDefinition, stream, true, false);
|
return SendPropParser.readBitCoordMP(stream, true, false);
|
||||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NOSCALE)) {
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NOSCALE)) {
|
||||||
return stream.readFloat32();
|
return stream.readFloat32();
|
||||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NORMAL)) {
|
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NORMAL)) {
|
||||||
|
|
@ -91,7 +93,7 @@ export class SendPropParser {
|
||||||
public static readBitNormal(stream: BitStream) {
|
public static readBitNormal(stream: BitStream) {
|
||||||
const isNegative = stream.readBoolean();
|
const isNegative = stream.readBoolean();
|
||||||
const fractVal = stream.readBits(11);
|
const fractVal = stream.readBits(11);
|
||||||
const value = fractVal * (1 / ((1 << 11) - 1));
|
const value = fractVal * bitNormalFactor;
|
||||||
return (isNegative) ? -value : value;
|
return (isNegative) ? -value : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,14 +105,14 @@ export class SendPropParser {
|
||||||
const isNegative = stream.readBoolean();
|
const isNegative = stream.readBoolean();
|
||||||
const intVal = (hasIntVal) ? stream.readBits(14) + 1 : 0;
|
const intVal = (hasIntVal) ? stream.readBits(14) + 1 : 0;
|
||||||
const fractVal = (hasFractVal) ? stream.readBits(5) : 0;
|
const fractVal = (hasFractVal) ? stream.readBits(5) : 0;
|
||||||
const value = intVal + fractVal * (1 / (1 << 5));
|
const value = intVal + fractVal * (1 / 32);
|
||||||
return (isNegative) ? -value : value;
|
return (isNegative) ? -value : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readBitCoordMP(propDefinition: SendPropDefinition, stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): number {
|
public static readBitCoordMP(stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): number {
|
||||||
let value = 0;
|
let value = 0;
|
||||||
let isNegative = false;
|
let isNegative = false;
|
||||||
const inBounds = stream.readBoolean();
|
const inBounds = stream.readBoolean();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {logBase2} from '../Math';
|
import {logBase2} from '../Math';
|
||||||
|
|
||||||
function makeUnsigned(value: number, signed?: boolean) {
|
export function makeUnsigned(value: number, signed?: boolean) {
|
||||||
if (signed) {
|
if (signed) {
|
||||||
const signBit = value < 0 ? 1 : 0;
|
const signBit = value < 0 ? 1 : 0;
|
||||||
return ((value ^ -signBit) << 1) + signBit;
|
return ((value ^ -signBit) << 1) + signBit;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||||
import {
|
import {
|
||||||
EncodeBSPDecal, encodeCoord, encodeVecCoord, getCoord, getVecCoord,
|
EncodeBSPDecal, encodeVecCoord, getVecCoord,
|
||||||
ParseBSPDecal
|
ParseBSPDecal
|
||||||
} from '../../../../Parser/Packet/BSPDecal';
|
} from '../../../../Parser/Packet/BSPDecal';
|
||||||
|
import {SendPropParser} from '../../../../Parser/SendPropParser';
|
||||||
|
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
|
||||||
|
|
||||||
const data = [239, 236, 208, 85, 33, 127, 128, 9, 8];
|
const data = [239, 236, 208, 85, 33, 127, 128, 9, 8];
|
||||||
|
|
||||||
suite('BSPDecal', () => {
|
suite('BSPDecal', () => {
|
||||||
test('getCoord', () => {
|
test('getCoord', () => {
|
||||||
assertParser(getCoord, getStream([157, 29, 186]), -948, 17);
|
assertParser(SendPropParser.readBitCoord, getStream([157, 29, 186]), -948, 17);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getVecCoord', () => {
|
test('getVecCoord', () => {
|
||||||
|
|
@ -21,11 +23,11 @@ suite('BSPDecal', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('encodeCoord', () => {
|
test('encodeCoord', () => {
|
||||||
assertEncoder(getCoord, encodeCoord, 5, 17);
|
assertEncoder(SendPropParser.readBitCoord, SendPropEncoder.writeBitCoord, 5, 17);
|
||||||
assertEncoder(getCoord, encodeCoord, -5, 17);
|
assertEncoder(SendPropParser.readBitCoord, SendPropEncoder.writeBitCoord, -5, 17);
|
||||||
assertEncoder(getCoord, encodeCoord, 0.09375, 8);
|
assertEncoder(SendPropParser.readBitCoord, SendPropEncoder.writeBitCoord, 0.09375, 8);
|
||||||
assertEncoder(getCoord, encodeCoord, -6.09375, 22);
|
assertEncoder(SendPropParser.readBitCoord, SendPropEncoder.writeBitCoord, -6.09375, 22);
|
||||||
assertEncoder(getCoord, encodeCoord, 0, 2);
|
assertEncoder(SendPropParser.readBitCoord, SendPropEncoder.writeBitCoord, 0, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('encodeVecCoord', () => {
|
test('encodeVecCoord', () => {
|
||||||
|
|
|
||||||
146
src/tests/unit/Parser/SendPropEncoderTest.ts
Normal file
146
src/tests/unit/Parser/SendPropEncoderTest.ts
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {assertEncoder, assertParser, getStream} from './Packet/PacketTest';
|
||||||
|
import {readBitVar, readVarInt, writeBitVar, writeVarInt} from '../../../Parser/readBitVar';
|
||||||
|
import {SendPropParser} from '../../../Parser/SendPropParser';
|
||||||
|
import {SendPropDefinition, SendPropFlag, SendPropType} from '../../../Data/SendPropDefinition';
|
||||||
|
import {SendPropEncoder} from '../../../Parser/SendPropEncoder';
|
||||||
|
|
||||||
|
function basicIntReader(bitCount: number, signed: boolean) {
|
||||||
|
return (stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Int, '', signed ? 0 : SendPropFlag.SPROP_UNSIGNED, '');
|
||||||
|
definition.bitCount = bitCount;
|
||||||
|
return SendPropParser.decode(
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function basicIntWriter(bitCount: number, signed: boolean) {
|
||||||
|
return (value: number, stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Int, '', signed ? 0 : SendPropFlag.SPROP_UNSIGNED, '');
|
||||||
|
definition.bitCount = bitCount;
|
||||||
|
return SendPropEncoder.encode(
|
||||||
|
value,
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function readString(stream: BitStream) {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_String, '', 0, '');
|
||||||
|
return SendPropParser.decode(definition, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeString(value: string, stream: BitStream) {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_String, '', 0, '');
|
||||||
|
return SendPropEncoder.encode(value, definition, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayReader(arrayType: SendPropType, length: number, arrayFlags: number = 0, arrayBitSize: number = 0) {
|
||||||
|
return (stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Array, '', 0, '');
|
||||||
|
definition.numElements = length;
|
||||||
|
definition.arrayProperty = new SendPropDefinition(arrayType, '', arrayFlags, '');
|
||||||
|
definition.arrayProperty.bitCount = arrayBitSize;
|
||||||
|
return SendPropParser.decode(
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayWriter(arrayType: SendPropType, length: number, arrayFlags: number = 0, arrayBitSize: number = 0) {
|
||||||
|
return (value: any[], stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Array, '', 0, '');
|
||||||
|
definition.numElements = length;
|
||||||
|
definition.arrayProperty = new SendPropDefinition(arrayType, '', arrayFlags, '');
|
||||||
|
definition.arrayProperty.bitCount = arrayBitSize;
|
||||||
|
return SendPropEncoder.encode(
|
||||||
|
value,
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function floatReader(flags: number, bitCount: number = 0, lowValue: number = 0, highValue: number = 0) {
|
||||||
|
return (stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Float, '', flags, '');
|
||||||
|
definition.bitCount = bitCount;
|
||||||
|
definition.lowValue = lowValue;
|
||||||
|
definition.highValue = highValue;
|
||||||
|
return SendPropParser.decode(
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function floatWriter(flags: number, bitCount: number = 0, lowValue: number = 0, highValue: number = 0) {
|
||||||
|
return (value: number, stream: BitStream) => {
|
||||||
|
const definition = new SendPropDefinition(SendPropType.DPT_Float, '', flags, '');
|
||||||
|
definition.bitCount = bitCount;
|
||||||
|
definition.lowValue = lowValue;
|
||||||
|
definition.highValue = highValue;
|
||||||
|
return SendPropEncoder.encode(
|
||||||
|
value,
|
||||||
|
definition,
|
||||||
|
stream
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
suite('SendPropEncoder', () => {
|
||||||
|
test('basic int', () => {
|
||||||
|
assertEncoder(basicIntReader(9, false), basicIntWriter(9, false), 61, 9);
|
||||||
|
assertEncoder(basicIntReader(9, true), basicIntWriter(9, true), -61, 9);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('string', () => {
|
||||||
|
assertEncoder(readString, writeString, 'foobar', (7 * 8) + 9);
|
||||||
|
assertEncoder(readString, writeString, '', 8 + 9);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('array', () => {
|
||||||
|
assertEncoder(arrayReader(SendPropType.DPT_Int, 2, 0, 5),
|
||||||
|
arrayWriter(SendPropType.DPT_Int, 2, SendPropFlag.SPROP_UNSIGNED, 5),
|
||||||
|
[12, 14], 12);
|
||||||
|
assertEncoder(arrayReader(SendPropType.DPT_Int, 2, 0, 5),
|
||||||
|
arrayWriter(SendPropType.DPT_Int, 2, 0, 5),
|
||||||
|
[12, -14], 12);
|
||||||
|
assertEncoder(arrayReader(SendPropType.DPT_Int, 9, 0, 5),
|
||||||
|
arrayWriter(SendPropType.DPT_Int, 9, 0, 5),
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9], 5 * 9 + 4);
|
||||||
|
assertEncoder(arrayReader(SendPropType.DPT_String, 2),
|
||||||
|
arrayWriter(SendPropType.DPT_String, 2),
|
||||||
|
['foo', 'bar'], (4 * 8 + 9) * 2 + 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('floats', () => {
|
||||||
|
assertEncoder(floatReader(0, 12, 0, 128), floatWriter(0, 12, 0, 128), 61.01489621489622, 12);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD), floatWriter(SendPropFlag.SPROP_COORD), 12.5, 22);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD), floatWriter(SendPropFlag.SPROP_COORD), -12, 17);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD), floatWriter(SendPropFlag.SPROP_COORD), .5, 8);
|
||||||
|
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP), floatWriter(SendPropFlag.SPROP_COORD_MP), 12.5, 19);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP), floatWriter(SendPropFlag.SPROP_COORD_MP), .5, 8);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP), floatWriter(SendPropFlag.SPROP_COORD_MP), -0.5, 8);
|
||||||
|
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), floatWriter(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), 12.5, 17);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), floatWriter(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), .5, 6);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), floatWriter(SendPropFlag.SPROP_COORD_MP_LOWPRECISION), -0.5, 6);
|
||||||
|
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_INTEGRAL), floatWriter(SendPropFlag.SPROP_COORD_MP_INTEGRAL), 12, 14);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_INTEGRAL), floatWriter(SendPropFlag.SPROP_COORD_MP_INTEGRAL), -12, 14);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_COORD_MP_INTEGRAL), floatWriter(SendPropFlag.SPROP_COORD_MP_INTEGRAL), 0, 2);
|
||||||
|
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_NOSCALE), floatWriter(SendPropFlag.SPROP_NOSCALE), 12.5, 32);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_NOSCALE), floatWriter(SendPropFlag.SPROP_NOSCALE), .5, 32);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_NOSCALE), floatWriter(SendPropFlag.SPROP_NOSCALE), -0.5, 32);
|
||||||
|
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_NORMAL), floatWriter(SendPropFlag.SPROP_NORMAL), .5002442598925256, 12);
|
||||||
|
assertEncoder(floatReader(SendPropFlag.SPROP_NORMAL), floatWriter(SendPropFlag.SPROP_NORMAL), -0.5002442598925256, 12);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue