mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
add encoder for datatable message
This commit is contained in:
parent
00a3b82d4a
commit
b94a79ab6d
7 changed files with 161 additions and 5 deletions
|
|
@ -5,6 +5,7 @@ export type SendTableName = string;
|
||||||
export class SendTable {
|
export class SendTable {
|
||||||
public name: SendTableName;
|
public name: SendTableName;
|
||||||
public props: SendPropDefinition[];
|
public props: SendPropDefinition[];
|
||||||
|
public needsDecoder: boolean;
|
||||||
private cachedFlattenedProps: SendPropDefinition[];
|
private cachedFlattenedProps: SendPropDefinition[];
|
||||||
|
|
||||||
constructor(name) {
|
constructor(name) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import {BitStream} from 'bit-buffer';
|
||||||
|
|
||||||
export const DataTableHandler: MessageHandler<DataTablesMessage> = {
|
export const DataTableHandler: MessageHandler<DataTablesMessage> = {
|
||||||
parseMessage: (stream: BitStream) => {
|
parseMessage: (stream: BitStream) => {
|
||||||
|
const s = stream.index;
|
||||||
|
|
||||||
const tick = stream.readInt32();
|
const tick = stream.readInt32();
|
||||||
|
|
||||||
const length = stream.readInt32();
|
const length = stream.readInt32();
|
||||||
|
|
@ -21,6 +23,7 @@ export const DataTableHandler: MessageHandler<DataTablesMessage> = {
|
||||||
const tableName = messageStream.readASCIIString();
|
const tableName = messageStream.readASCIIString();
|
||||||
const numProps = messageStream.readBits(10);
|
const numProps = messageStream.readBits(10);
|
||||||
const table = new SendTable(tableName);
|
const table = new SendTable(tableName);
|
||||||
|
table.needsDecoder = needsDecoder;
|
||||||
|
|
||||||
// get props metadata
|
// get props metadata
|
||||||
let arrayElementProp;
|
let arrayElementProp;
|
||||||
|
|
@ -106,10 +109,20 @@ export const DataTableHandler: MessageHandler<DataTablesMessage> = {
|
||||||
serverClasses.push(new ServerClass(classId, className, dataTable));
|
serverClasses.push(new ServerClass(classId, className, dataTable));
|
||||||
}
|
}
|
||||||
|
|
||||||
const bitsLeft = (this.length * 8) - messageStream.index;
|
if (messageStream.bitsLeft > 7) {
|
||||||
if (bitsLeft > 7 || bitsLeft < 0) {
|
throw new Error('unexpected remaining data in datatable (' + messageStream.bitsLeft + ' bits)');
|
||||||
throw new Error('unexpected remaining data in datatable (' + bitsLeft + ' bits)');
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// const e = stream.index;
|
||||||
|
// stream.index = s;
|
||||||
|
// const d = {
|
||||||
|
// type: MessageType.DataTables,
|
||||||
|
// tick,
|
||||||
|
// tables,
|
||||||
|
// serverClasses,
|
||||||
|
// };
|
||||||
|
// require('fs').writeFileSync('src/tests/data/dataTableResult.json.gz', require('zlib').gzipSync(JSON.stringify(d)));
|
||||||
|
// process.exit();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: MessageType.DataTables,
|
type: MessageType.DataTables,
|
||||||
|
|
@ -120,6 +133,79 @@ export const DataTableHandler: MessageHandler<DataTablesMessage> = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
encodeMessage: (message, stream) => {
|
encodeMessage: (message, stream) => {
|
||||||
throw new Error('Not implemented');
|
stream.writeUint32(message.tick);
|
||||||
|
|
||||||
|
const lengthStart = stream.index;
|
||||||
|
stream.index += 32;
|
||||||
|
|
||||||
|
const dataStart = stream.index;
|
||||||
|
|
||||||
|
for (const table of message.tables) {
|
||||||
|
stream.writeBoolean(true);
|
||||||
|
stream.writeBoolean(table.needsDecoder);
|
||||||
|
stream.writeASCIIString(table.name);
|
||||||
|
const numPropsStart = stream.index;
|
||||||
|
stream.index += 10;
|
||||||
|
|
||||||
|
let numProps = 0;
|
||||||
|
for (const definition of table.props) {
|
||||||
|
if (definition.arrayProperty) {
|
||||||
|
encodeSendPropDefinition(stream, definition.arrayProperty);
|
||||||
|
numProps++;
|
||||||
|
}
|
||||||
|
encodeSendPropDefinition(stream, definition);
|
||||||
|
numProps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const propDataEnd = stream.index;
|
||||||
|
stream.index = numPropsStart;
|
||||||
|
stream.writeBits(numProps, 10);
|
||||||
|
stream.index = propDataEnd;
|
||||||
|
}
|
||||||
|
stream.writeBoolean(false);
|
||||||
|
|
||||||
|
stream.writeUint16(message.serverClasses.length);
|
||||||
|
|
||||||
|
for (const serverClass of message.serverClasses) {
|
||||||
|
stream.writeUint16(serverClass.id);
|
||||||
|
stream.writeASCIIString(serverClass.name);
|
||||||
|
stream.writeASCIIString(serverClass.dataTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataEnd = stream.index;
|
||||||
|
|
||||||
|
stream.index = lengthStart;
|
||||||
|
|
||||||
|
const byteLength = Math.ceil((dataEnd - dataStart) / 8);
|
||||||
|
stream.writeUint32(byteLength);
|
||||||
|
|
||||||
|
// align to byte;
|
||||||
|
stream.index = dataStart + byteLength * 8;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function encodeSendPropDefinition(stream: BitStream, definition: SendPropDefinition) {
|
||||||
|
stream.writeBits(definition.type, 5);
|
||||||
|
stream.writeASCIIString(definition.name);
|
||||||
|
stream.writeBits(definition.flags, 16);
|
||||||
|
|
||||||
|
if (definition.type === SendPropType.DPT_DataTable) {
|
||||||
|
if (!definition.table) {
|
||||||
|
throw new Error('Missing linked table');
|
||||||
|
}
|
||||||
|
stream.writeASCIIString(definition.table.name);
|
||||||
|
} else {
|
||||||
|
if (definition.isExcludeProp()) {
|
||||||
|
if (!definition.excludeDTName) {
|
||||||
|
throw new Error('Missing linked table');
|
||||||
|
}
|
||||||
|
stream.writeASCIIString(definition.excludeDTName);
|
||||||
|
} else if (definition.type === SendPropType.DPT_Array) {
|
||||||
|
stream.writeBits(definition.numElements, 10);
|
||||||
|
} else {
|
||||||
|
stream.writeFloat32(definition.lowValue);
|
||||||
|
stream.writeFloat32(definition.highValue);
|
||||||
|
stream.writeBits(definition.bitCount, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
src/tests/data/dataTableData.bin
Normal file
BIN
src/tests/data/dataTableData.bin
Normal file
Binary file not shown.
BIN
src/tests/data/dataTableResult.json.gz
Normal file
BIN
src/tests/data/dataTableResult.json.gz
Normal file
Binary file not shown.
69
src/tests/unit/Parser/Message/DataTableTest.ts
Normal file
69
src/tests/unit/Parser/Message/DataTableTest.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
|
||||||
|
import {readFileSync} from 'fs';
|
||||||
|
import {ParserState} from '../../../../Data/ParserState';
|
||||||
|
import {gunzipSync} from 'zlib';
|
||||||
|
import {DataTableHandler} from '../../../../Parser/Message/DataTable';
|
||||||
|
import {DataTablesMessage} from '../../../../Data/Message';
|
||||||
|
import {hydrateTable} from '../Packet/hydrate';
|
||||||
|
import {ServerClass} from '../../../../Data/ServerClass';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import {deepEqual} from 'assert';
|
||||||
|
|
||||||
|
const data = Array.from(readFileSync(__dirname + '/../../../data/dataTableData.bin').values());
|
||||||
|
const expectedRaw = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/dataTableResult.json.gz')).toString('utf8')) as DataTablesMessage;
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
type: expectedRaw.type,
|
||||||
|
tick: expectedRaw.tick,
|
||||||
|
serverClasses: expectedRaw.serverClasses.map(serverClass => new ServerClass(serverClass.id, serverClass.name, serverClass.dataTable)),
|
||||||
|
tables: expectedRaw.tables.map(hydrateTable)
|
||||||
|
};
|
||||||
|
|
||||||
|
const getParserState = () => {
|
||||||
|
return new ParserState();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handler = DataTableHandler;
|
||||||
|
|
||||||
|
function parser(stream) {
|
||||||
|
const result = handler.parseMessage(stream, getParserState());
|
||||||
|
delete result.rawData;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function encoder(message, stream) {
|
||||||
|
handler.encodeMessage(message, stream, getParserState());
|
||||||
|
}
|
||||||
|
|
||||||
|
suite('DataTable', () => {
|
||||||
|
test('Parse DataTable message', () => {
|
||||||
|
assertParser(parser, getStream(data), expectedRaw, 947888);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Encode DataTable message', () => {
|
||||||
|
const length = 947888;
|
||||||
|
const stream = new BitStream(new ArrayBuffer(length + 64000));
|
||||||
|
|
||||||
|
encoder(expected, stream);
|
||||||
|
|
||||||
|
const pos = stream.index;
|
||||||
|
|
||||||
|
if (length) {
|
||||||
|
assert.equal(stream.index, length, 'Unexpected number of bits used for encoding');
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.index = 0;
|
||||||
|
|
||||||
|
const result = parser(stream);
|
||||||
|
assert.deepEqual(result.serverClasses, expected.serverClasses, 'Re-decoded value not equal to original value');
|
||||||
|
assert.deepEqual(result.tick, expected.tick, 'Re-decoded value not equal to original value');
|
||||||
|
assert.deepEqual(result.type, expected.type, 'Re-decoded value not equal to original value');
|
||||||
|
for (let i = 0; i < result.tables.length; i++) {
|
||||||
|
const resultTable = JSON.parse(JSON.stringify(result.tables[i]));
|
||||||
|
const expectedTable = expectedRaw.tables[i];
|
||||||
|
assert.deepEqual(resultTable, expectedTable, 'Re-decoded value not equal to original value');
|
||||||
|
}
|
||||||
|
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -31,7 +31,6 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
|
||||||
stream.index = 0;
|
stream.index = 0;
|
||||||
|
|
||||||
const result = parser(stream);
|
const result = parser(stream);
|
||||||
deepEqual(result, data);
|
|
||||||
if (!deepEqual(result, data)) {
|
if (!deepEqual(result, data)) {
|
||||||
assert.deepEqual(result, data, 'Re-decoded value not equal to original value' + message);
|
assert.deepEqual(result, data, 'Re-decoded value not equal to original value' + message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ export function propDataDefinition(propData): SendPropDefinition {
|
||||||
|
|
||||||
export function hydrateTable(tableData): SendTable {
|
export function hydrateTable(tableData): SendTable {
|
||||||
const table = new SendTable(tableData.name);
|
const table = new SendTable(tableData.name);
|
||||||
|
table.needsDecoder = tableData.needsDecoder;
|
||||||
table.props = tableData.props.map(propDataDefinition);
|
table.props = tableData.props.map(propDataDefinition);
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue