mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
add encoder for tempEntities
This commit is contained in:
parent
c064439b4e
commit
450300c1b0
12 changed files with 667 additions and 68 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -229,9 +229,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bit-buffer": {
|
"bit-buffer": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.3.tgz",
|
||||||
"integrity": "sha512-et8MIvMW4fqwgseIq0SLjyjbhmypVSBcb+4Zd/+2CkYTDsh/yWXEosXrHaCvrTdYzkeeBJraypggmE3XKPlUAw=="
|
"integrity": "sha512-Ugsj2ZD23YKb4cCasdBD4l1Oy4eI/752hnCMAmZO62P+oS1emCqNMlkex02ppGWgKHTS6sfzFeUbPD6VWd+s1w=="
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
|
"version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"jsnext:main": "build/es6/index.js",
|
"jsnext:main": "build/es6/index.js",
|
||||||
"module": "build/es6/index.js",
|
"module": "build/es6/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bit-buffer": "^0.2.0",
|
"bit-buffer": "^0.2.3",
|
||||||
"clone": "^2.1.0",
|
"clone": "^2.1.0",
|
||||||
"minimist": "1.1.x",
|
"minimist": "1.1.x",
|
||||||
"snappyjs": "^0.5.0"
|
"snappyjs": "^0.5.0"
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export class SendPropDefinition {
|
||||||
|
|
||||||
public inspect() {
|
public inspect() {
|
||||||
const data: any = {
|
const data: any = {
|
||||||
fromTable: this.ownerTableName,
|
ownerTableName: this.ownerTableName,
|
||||||
name: this.name,
|
name: this.name,
|
||||||
type: SendPropType[this.type],
|
type: SendPropType[this.type],
|
||||||
flags: this.flags,
|
flags: this.flags,
|
||||||
|
|
@ -90,7 +90,7 @@ export enum SendPropType {
|
||||||
export enum SendPropFlag {
|
export enum SendPropFlag {
|
||||||
SPROP_UNSIGNED = (1 << 0), // Unsigned integer data.
|
SPROP_UNSIGNED = (1 << 0), // Unsigned integer data.
|
||||||
SPROP_COORD = (1 << 1), // If this is set, the float/vector is treated like a world coordinate.
|
SPROP_COORD = (1 << 1), // If this is set, the float/vector is treated like a world coordinate.
|
||||||
// Note that the bit count is ignored in this case.
|
// Note that the bit count is ignored in this case.
|
||||||
SPROP_NOSCALE = (1 << 2), // For floating point, don't scale into range, just take value as is.
|
SPROP_NOSCALE = (1 << 2), // For floating point, don't scale into range, just take value as is.
|
||||||
SPROP_ROUNDDOWN = (1 << 3), // For floating point, limit high value to range minus one bit unit
|
SPROP_ROUNDDOWN = (1 << 3), // For floating point, limit high value to range minus one bit unit
|
||||||
SPROP_ROUNDUP = (1 << 4), // For floating point, limit low value to range minus one bit unit
|
SPROP_ROUNDUP = (1 << 4), // For floating point, limit low value to range minus one bit unit
|
||||||
|
|
@ -98,18 +98,18 @@ export enum SendPropFlag {
|
||||||
SPROP_EXCLUDE = (1 << 6), // This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
SPROP_EXCLUDE = (1 << 6), // This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
||||||
SPROP_XYZE = (1 << 7), // Use XYZ/Exponent encoding for vectors.
|
SPROP_XYZE = (1 << 7), // Use XYZ/Exponent encoding for vectors.
|
||||||
SPROP_INSIDEARRAY = (1 << 8), // This tells us that the property is inside an array, so it shouldn't be put into the
|
SPROP_INSIDEARRAY = (1 << 8), // This tells us that the property is inside an array, so it shouldn't be put into the
|
||||||
// flattened property list. Its array will point at it when it needs to.
|
// flattened property list. Its array will point at it when it needs to.
|
||||||
SPROP_PROXY_ALWAYS_YES = (1 << 9), // Set for datatable props using one of the default datatable proxies like
|
SPROP_PROXY_ALWAYS_YES = (1 << 9), // Set for datatable props using one of the default datatable proxies like
|
||||||
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
||||||
SPROP_CHANGES_OFTEN = (1 << 10), // this is an often changed field, moved to head of sendtable so it gets a small index
|
SPROP_CHANGES_OFTEN = (1 << 10), // this is an often changed field, moved to head of sendtable so it gets a small index
|
||||||
SPROP_IS_A_VECTOR_ELEM = (1 << 11), // Set automatically if SPROP_VECTORELEM is used.
|
SPROP_IS_A_VECTOR_ELEM = (1 << 11), // Set automatically if SPROP_VECTORELEM is used.
|
||||||
SPROP_COLLAPSIBLE = (1 << 12), // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
SPROP_COLLAPSIBLE = (1 << 12), // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
||||||
// (ie: for all automatically-chained base classes).
|
// (ie: for all automatically-chained base classes).
|
||||||
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
||||||
// trouble of walking the hierarchy more than necessary.
|
// trouble of walking the hierarchy more than necessary.
|
||||||
SPROP_COORD_MP = (1 << 13), // Like SPROP_COORD, but special handling for multiplayer games
|
SPROP_COORD_MP = (1 << 13), // Like SPROP_COORD, but special handling for multiplayer games
|
||||||
SPROP_COORD_MP_LOWPRECISION = (1 << 14), // Like SPROP_COORD, but special handling for multiplayer games
|
SPROP_COORD_MP_LOWPRECISION = (1 << 14), // Like SPROP_COORD, but special handling for multiplayer games
|
||||||
// where the fractional component only gets a 3 bits instead of 5
|
// where the fractional component only gets a 3 bits instead of 5
|
||||||
SPROP_COORD_MP_INTEGRAL = (1 << 15), // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
SPROP_COORD_MP_INTEGRAL = (1 << 15), // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
||||||
SPROP_VARINT = (1 << 5),
|
SPROP_VARINT = (1 << 5),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
src/DynamicBitStream.ts
Normal file
30
src/DynamicBitStream.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {BitStream, BitView} from 'bit-buffer';
|
||||||
|
|
||||||
|
class DynamicBitView extends BitView {
|
||||||
|
protected _view: Uint8Array;
|
||||||
|
|
||||||
|
setBits(offset: number, value: number, bits: number) {
|
||||||
|
const available = (this.byteLength * 8 - offset);
|
||||||
|
|
||||||
|
if (bits > available) {
|
||||||
|
this.grow();
|
||||||
|
}
|
||||||
|
return super.setBits(offset, value, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
grow() {
|
||||||
|
const newView = new Uint8Array(this.byteLength * 2);
|
||||||
|
newView.set(this._view);
|
||||||
|
this._view = newView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DynamicBitStream extends BitStream {
|
||||||
|
constructor(initialByteSize: number = 16 * 1024) {
|
||||||
|
super(new DynamicBitView(new ArrayBuffer(initialByteSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
get length() {
|
||||||
|
return this.view.byteLength * 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ export function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stre
|
||||||
stream.writeBoolean(true);
|
stream.writeBoolean(true);
|
||||||
const index = allProps.findIndex(propDef => propDef.fullName === prop.definition.fullName);
|
const index = allProps.findIndex(propDef => propDef.fullName === prop.definition.fullName);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error('Unknown definition for property');
|
throw new Error(`Unknown definition for property ${prop.definition.fullName} in ${sendTable.name}`);
|
||||||
}
|
}
|
||||||
writeFieldIndex(index, stream, lastIndex);
|
writeFieldIndex(index, stream, lastIndex);
|
||||||
lastIndex = index;
|
lastIndex = index;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {ParsePacketEntities} from '../Packet/PacketEntities';
|
||||||
import {PacketHandler, voidEncoder} from '../Packet/Parser';
|
import {PacketHandler, voidEncoder} from '../Packet/Parser';
|
||||||
import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds';
|
import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds';
|
||||||
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
|
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
|
||||||
import {ParseTempEntities} from '../Packet/TempEntities';
|
import {EncodeTempEntities, ParseTempEntities} from '../Packet/TempEntities';
|
||||||
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../Packet/UpdateStringTable';
|
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../Packet/UpdateStringTable';
|
||||||
import {EncodeUserMessage, ParseUserMessage} from '../Packet/UserMessage';
|
import {EncodeUserMessage, ParseUserMessage} from '../Packet/UserMessage';
|
||||||
import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData';
|
import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData';
|
||||||
|
|
@ -67,7 +67,7 @@ export class Packet extends Parser {
|
||||||
[PacketTypeId.packetEntities,
|
[PacketTypeId.packetEntities,
|
||||||
{parser: ParsePacketEntities, encoder: voidEncoder}],
|
{parser: ParsePacketEntities, encoder: voidEncoder}],
|
||||||
[PacketTypeId.tempEntities,
|
[PacketTypeId.tempEntities,
|
||||||
{parser: ParseTempEntities, encoder: voidEncoder}],
|
{parser: ParseTempEntities, encoder: EncodeTempEntities}],
|
||||||
[PacketTypeId.preFetch,
|
[PacketTypeId.preFetch,
|
||||||
make('preFetch', 'index{14}')],
|
make('preFetch', 'index{14}')],
|
||||||
[PacketTypeId.menu,
|
[PacketTypeId.menu,
|
||||||
|
|
|
||||||
|
|
@ -2,47 +2,78 @@ import {BitStream} from 'bit-buffer';
|
||||||
import {Match} from '../../Data/Match';
|
import {Match} from '../../Data/Match';
|
||||||
import {TempEntitiesPacket} from '../../Data/Packet';
|
import {TempEntitiesPacket} from '../../Data/Packet';
|
||||||
import {PacketEntity, PVS} from '../../Data/PacketEntity';
|
import {PacketEntity, PVS} from '../../Data/PacketEntity';
|
||||||
import {getEntityUpdate} from '../EntityDecoder';
|
import {encodeEntityUpdate, getEntityUpdate} from '../EntityDecoder';
|
||||||
import {readVarInt} from '../readBitVar';
|
import {readVarInt, writeVarInt} from '../readBitVar';
|
||||||
|
import {DynamicBitStream} from '../../DynamicBitStream';
|
||||||
|
|
||||||
export function ParseTempEntities(stream: BitStream, match: Match, skip: boolean = false): TempEntitiesPacket { // 10: classInfo
|
export function ParseTempEntities(stream: BitStream, match: Match, skip: boolean = false): TempEntitiesPacket { // 10: classInfo
|
||||||
const entityCount = stream.readBits(8);
|
const entityCount = stream.readUint8();
|
||||||
const length = readVarInt(stream);
|
const length = readVarInt(stream);
|
||||||
const end = stream.index + length;
|
const entityData = stream.readBitStream(length);
|
||||||
|
|
||||||
let entity: PacketEntity | null = null;
|
let entity: PacketEntity | null = null;
|
||||||
const entities: PacketEntity[] = [];
|
const entities: PacketEntity[] = [];
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
for (let i = 0; i < entityCount; i++) {
|
for (let i = 0; i < entityCount; i++) {
|
||||||
const delay = (stream.readBoolean()) ? stream.readUint8() / 100 : 0; // unused it seems
|
const delay = (entityData.readBoolean()) ? entityData.readUint8() / 100 : 0; // unused it seems
|
||||||
if (stream.readBoolean()) {
|
if (entityData.readBoolean()) {
|
||||||
const classId = stream.readBits(match.classBits);
|
const classId = entityData.readBits(match.classBits);
|
||||||
const serverClass = match.serverClasses[classId - 1];
|
const serverClass = match.serverClasses[classId - 1];
|
||||||
|
if (!serverClass) {
|
||||||
|
throw new Error(`Unknown serverClass ${classId}`);
|
||||||
|
}
|
||||||
// no clue why the -1 but it works
|
// no clue why the -1 but it works
|
||||||
// maybe because world (id=0) can never be temp
|
|
||||||
// but it's not like the -1 saves any space
|
|
||||||
const sendTable = match.getSendTable(serverClass.dataTable);
|
const sendTable = match.getSendTable(serverClass.dataTable);
|
||||||
entity = new PacketEntity(serverClass, 0, PVS.ENTER);
|
entity = new PacketEntity(serverClass, 0, PVS.ENTER);
|
||||||
entity.delay = delay;
|
entity.delay = delay;
|
||||||
entity.props = getEntityUpdate(sendTable, stream);
|
entity.props = getEntityUpdate(sendTable, entityData);
|
||||||
entities.push(entity);
|
entities.push(entity);
|
||||||
} else {
|
} else {
|
||||||
if (entity) {
|
if (entity) {
|
||||||
const updatedProps = getEntityUpdate(match.getSendTable(entity.serverClass.dataTable), stream);
|
const updatedProps = getEntityUpdate(match.getSendTable(entity.serverClass.dataTable), entityData);
|
||||||
entity.applyPropUpdate(updatedProps);
|
entity.applyPropUpdate(updatedProps);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('no entity set to update');
|
throw new Error('no entity set to update');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end - stream.index > 8) {
|
if (entityData.bitsLeft > 8) {
|
||||||
throw new Error('unexpected content after TempEntities');
|
throw new Error(`unexpected content after TempEntities ${entityData.bitsLeft} bits`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.index = end;
|
|
||||||
return {
|
return {
|
||||||
packetType: 'tempEntities',
|
packetType: 'tempEntities',
|
||||||
entities,
|
entities,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function EncodeTempEntities(packet: TempEntitiesPacket, stream: BitStream, match: Match) {
|
||||||
|
stream.writeUint8(packet.entities.length);
|
||||||
|
|
||||||
|
const entityStream = new DynamicBitStream();
|
||||||
|
for (const entity of packet.entities) {
|
||||||
|
if (entity.delay) {
|
||||||
|
entityStream.writeBoolean(true);
|
||||||
|
entityStream.writeUint8(Math.round(entity.delay * 100));
|
||||||
|
} else {
|
||||||
|
entityStream.writeBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityStream.writeBoolean(true);
|
||||||
|
|
||||||
|
const classId = match.serverClasses.findIndex(serverClass => serverClass && serverClass.name === entity.serverClass.name) + 1;
|
||||||
|
entityStream.writeBits(classId, match.classBits);
|
||||||
|
|
||||||
|
const sendTable = match.getSendTable(entity.serverClass.dataTable);
|
||||||
|
|
||||||
|
encodeEntityUpdate(entity.props, sendTable, entityStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
const entityDataLength = entityStream.index;
|
||||||
|
entityStream.index = 0;
|
||||||
|
|
||||||
|
writeVarInt(entityDataLength, stream);
|
||||||
|
|
||||||
|
stream.writeBitStream(entityStream, entityDataLength);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export class SendPropParser {
|
||||||
case SendPropType.DPT_Array:
|
case SendPropType.DPT_Array:
|
||||||
return SendPropParser.readArray(propDefinition, stream);
|
return SendPropParser.readArray(propDefinition, stream);
|
||||||
}
|
}
|
||||||
throw new Error('Unknown property type');
|
throw new Error(`Unknown property type ${propDefinition.type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readInt(propDefinition: SendPropDefinition, stream: BitStream) {
|
public static readInt(propDefinition: SendPropDefinition, stream: BitStream) {
|
||||||
|
|
|
||||||
17
src/tests/unit/DynamicBitStreamTest.ts
Normal file
17
src/tests/unit/DynamicBitStreamTest.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import {DynamicBitStream} from '../../DynamicBitStream';
|
||||||
|
|
||||||
|
suite('DynamitcBitStream', () => {
|
||||||
|
test('write grow', () => {
|
||||||
|
const stream = new DynamicBitStream(2);
|
||||||
|
stream.writeBits(0, 15);
|
||||||
|
stream.writeBits(17, 16);
|
||||||
|
|
||||||
|
assert.equal(stream.length, 32);
|
||||||
|
assert.equal(stream.index, 31);
|
||||||
|
|
||||||
|
stream.index = 18;
|
||||||
|
|
||||||
|
assert.equal(stream.readBits(2), 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
import {BitStream} from 'bit-buffer';
|
import {BitStream} from 'bit-buffer';
|
||||||
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||||
import {readFileSync} from 'fs';
|
import {readFileSync} from 'fs';
|
||||||
import {SendTable} from '../../../../Data/SendTable';
|
|
||||||
import {encodeEntityUpdate, getEntityUpdate} from '../../../../Parser/EntityDecoder';
|
import {encodeEntityUpdate, getEntityUpdate} from '../../../../Parser/EntityDecoder';
|
||||||
import {SendProp, SendPropValue} from '../../../../Data/SendProp';
|
import {SendProp, SendPropValue} from '../../../../Data/SendProp';
|
||||||
import {SendPropDefinition, SendPropType} from '../../../../Data/SendPropDefinition';
|
import {SendPropType} from '../../../../Data/SendPropDefinition';
|
||||||
import {PacketEntity} from '../../../../Data/PacketEntity';
|
|
||||||
import {Vector} from '../../../../Data/Vector';
|
|
||||||
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
|
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
|
||||||
import {SendPropParser} from '../../../../Parser/SendPropParser';
|
import {SendPropParser} from '../../../../Parser/SendPropParser';
|
||||||
|
import {hydrateEntity, hydrateTable} from './hydrate';
|
||||||
|
|
||||||
const data = [
|
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];
|
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];
|
||||||
|
|
@ -18,46 +16,15 @@ const sendTableData = JSON.parse(readFileSync(__dirname + '/../../../data/sendTa
|
||||||
const sendTable = hydrateTable(sendTableData);
|
const sendTable = hydrateTable(sendTableData);
|
||||||
const entity = hydrateEntity(entityData);
|
const entity = hydrateEntity(entityData);
|
||||||
|
|
||||||
function hydrateEntity(entityData): PacketEntity {
|
export function decodeUpdate(stream: BitStream) {
|
||||||
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);
|
return getEntityUpdate(sendTable, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeUpdate(props: SendProp[], stream: BitStream) {
|
export function encodeUpdate(props: SendProp[], stream: BitStream) {
|
||||||
encodeEntityUpdate(props, sendTable, stream);
|
encodeEntityUpdate(props, sendTable, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function encodeProp(prop: SendProp) {
|
function encodeProp(prop: SendProp) {
|
||||||
return function (value: SendPropValue, stream: BitStream) {
|
return function (value: SendPropValue, stream: BitStream) {
|
||||||
return SendPropEncoder.encode(value, prop.definition, stream);
|
return SendPropEncoder.encode(value, prop.definition, stream);
|
||||||
|
|
|
||||||
514
src/tests/unit/Parser/Packet/TempEntitiesTest.ts
Normal file
514
src/tests/unit/Parser/Packet/TempEntitiesTest.ts
Normal file
|
|
@ -0,0 +1,514 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||||
|
import {EncodeTempEntities, ParseTempEntities} from '../../../../Parser/Packet/TempEntities';
|
||||||
|
import {Match} from '../../../../Data/Match';
|
||||||
|
import {hydrateEntity, hydrateTable} from './hydrate';
|
||||||
|
import {ServerClass} from '../../../../Data/ServerClass';
|
||||||
|
import {TempEntitiesPacket} from '../../../../Data/Packet';
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
2,
|
||||||
|
142,
|
||||||
|
1,
|
||||||
|
150,
|
||||||
|
10,
|
||||||
|
68,
|
||||||
|
56,
|
||||||
|
43,
|
||||||
|
176,
|
||||||
|
245,
|
||||||
|
5,
|
||||||
|
254,
|
||||||
|
253,
|
||||||
|
192,
|
||||||
|
96,
|
||||||
|
20,
|
||||||
|
194,
|
||||||
|
14,
|
||||||
|
8,
|
||||||
|
252,
|
||||||
|
95];
|
||||||
|
|
||||||
|
const entityData = [
|
||||||
|
{
|
||||||
|
'serverClass': {
|
||||||
|
'id': 164,
|
||||||
|
'name': 'CTEPlayerAnimEvent',
|
||||||
|
'dataTable': 'DT_TEPlayerAnimEvent'
|
||||||
|
},
|
||||||
|
'entityIndex': 0,
|
||||||
|
'props': [
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iPlayerIndex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 7,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TEPlayerAnimEvent'
|
||||||
|
},
|
||||||
|
'value': 17
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'inPVS': false,
|
||||||
|
'pvs': 1,
|
||||||
|
'delay': 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'serverClass': {
|
||||||
|
'id': 178,
|
||||||
|
'name': 'CTETFParticleEffect',
|
||||||
|
'dataTable': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'entityIndex': 0,
|
||||||
|
'props': [
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[0]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'value': 1004
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[1]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'value': -2016
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[2]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'value': 561
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iParticleSystemIndex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 16,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'value': 472
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'definition': {
|
||||||
|
'type': 0,
|
||||||
|
'name': 'entindex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 11,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
'value': 2047
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'inPVS': false,
|
||||||
|
'pvs': 1,
|
||||||
|
'delay': 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const sendTableData = {
|
||||||
|
'name': 'DT_TEPlayerAnimEvent',
|
||||||
|
'props': [
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iPlayerIndex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 7,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TEPlayerAnimEvent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iEvent',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 6,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TEPlayerAnimEvent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_nData',
|
||||||
|
'flags': 0,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 12,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TEPlayerAnimEvent'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'cachedFlattenedProps': []
|
||||||
|
};
|
||||||
|
const sendTableData2 = {
|
||||||
|
'name': 'DT_TETFParticleEffect',
|
||||||
|
'props': [
|
||||||
|
{
|
||||||
|
'type': 6,
|
||||||
|
'name': 'baseclass',
|
||||||
|
'flags': 4096,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 0,
|
||||||
|
'table': {
|
||||||
|
'name': 'DT_BaseTempEntity',
|
||||||
|
'props': [],
|
||||||
|
'cachedFlattenedProps': []
|
||||||
|
},
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[0]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[1]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecOrigin[2]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecStart[0]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecStart[1]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_vecStart[2]',
|
||||||
|
'flags': 32772,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 2,
|
||||||
|
'name': 'm_vecAngles',
|
||||||
|
'flags': 0,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 360,
|
||||||
|
'bitCount': 7,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iParticleSystemIndex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 16,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'entindex',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 11,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iAttachType',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 5,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_iAttachmentPointIndex',
|
||||||
|
'flags': 0,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_bResetParticles',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 1,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_bCustomColors',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 1,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 2,
|
||||||
|
'name': 'm_CustomColors.m_vecColor1',
|
||||||
|
'flags': 0,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 1,
|
||||||
|
'bitCount': 8,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 2,
|
||||||
|
'name': 'm_CustomColors.m_vecColor2',
|
||||||
|
'flags': 0,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 1,
|
||||||
|
'bitCount': 8,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_bControlPoint1',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 1,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 0,
|
||||||
|
'name': 'm_ControlPoint1.m_eParticleAttachment',
|
||||||
|
'flags': 1,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 5,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_ControlPoint1.m_vecOffset[0]',
|
||||||
|
'flags': 8196,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_ControlPoint1.m_vecOffset[1]',
|
||||||
|
'flags': 8196,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 1,
|
||||||
|
'name': 'm_ControlPoint1.m_vecOffset[2]',
|
||||||
|
'flags': 8196,
|
||||||
|
'excludeDTName': null,
|
||||||
|
'lowValue': 0,
|
||||||
|
'highValue': 0,
|
||||||
|
'bitCount': 32,
|
||||||
|
'table': null,
|
||||||
|
'numElements': 0,
|
||||||
|
'arrayProperty': null,
|
||||||
|
'ownerTableName': 'DT_TETFParticleEffect'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'cachedFlattenedProps': []
|
||||||
|
};
|
||||||
|
const sendTable = hydrateTable(sendTableData);
|
||||||
|
const sendTable2 = hydrateTable(sendTableData2);
|
||||||
|
const expected = {
|
||||||
|
packetType: 'tempEntities',
|
||||||
|
entities: entityData.map(hydrateEntity)
|
||||||
|
};
|
||||||
|
|
||||||
|
const match = new Match();
|
||||||
|
match.serverClasses.length = 348;
|
||||||
|
match.serverClasses[164] = new ServerClass(164, 'CTEPlayerAnimEvent', 'DT_TEPlayerAnimEvent');
|
||||||
|
match.serverClasses[178] = new ServerClass(178, 'CTETFParticleEffect', 'DT_TETFParticleEffect');
|
||||||
|
match.sendTables.set(sendTable.name, sendTable);
|
||||||
|
match.sendTables.set(sendTable2.name, sendTable2);
|
||||||
|
|
||||||
|
function parse(stream: BitStream) {
|
||||||
|
return ParseTempEntities(stream, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
function encode(value: TempEntitiesPacket, stream: BitStream) {
|
||||||
|
EncodeTempEntities(value, stream, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
suite('TempEntities', () => {
|
||||||
|
test('Parse tempEntities', () => {
|
||||||
|
assertParser(parse, getStream(data), expected, 166);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Encode tempEntities', () => {
|
||||||
|
assertEncoder(parse, encode, expected, 166);
|
||||||
|
});
|
||||||
|
});
|
||||||
40
src/tests/unit/Parser/Packet/hydrate.ts
Normal file
40
src/tests/unit/Parser/Packet/hydrate.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import {SendProp} from '../../../../Data/SendProp';
|
||||||
|
import {PacketEntity} from '../../../../Data/PacketEntity';
|
||||||
|
import {SendPropDefinition, SendPropType} from '../../../../Data/SendPropDefinition';
|
||||||
|
import {Vector} from '../../../../Data/Vector';
|
||||||
|
import {SendTable} from '../../../../Data/SendTable';
|
||||||
|
|
||||||
|
export 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;
|
||||||
|
});
|
||||||
|
if (typeof entityData.delay !== 'undefined') {
|
||||||
|
entity.delay = entityData.delay;
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hydrateTable(tableData): SendTable {
|
||||||
|
const table = new SendTable(tableData.name);
|
||||||
|
table.props = tableData.props.map(propDataDefinition);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue