1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-03 16:44:12 +02:00

add encoder for packet message

This commit is contained in:
Robin Appelman 2017-09-24 17:16:57 +02:00
commit 5241059fd2
8 changed files with 180 additions and 22 deletions

View file

@ -38,7 +38,7 @@ export class Parser {
return this.header;
}
public * getPackets(): Iterable<Packet> {
public * getPackets(): IterableIterator<Packet> {
// ensure that we are past the header
this.getHeader();
const messages = this.getMessages();
@ -48,13 +48,12 @@ export class Parser {
}
private * getMessages(): Iterable<Message> {
let hasNext: boolean = true;
while (hasNext) {
while (true) {
const message = this.readMessage(this.stream, this.parserState);
if (!message) {
hasNext = false;
} else {
if (message) {
yield message;
} else {
return;
}
}
}

View file

@ -4,8 +4,8 @@ import {EncodeClassInfo, ParseClassInfo} from '../Packet/ClassInfo';
import {EncodeCreateStringTable, ParseCreateStringTable} from '../Packet/CreateStringTable';
import {EncodeGameEvent, ParseGameEvent} from '../Packet/GameEvent';
import {EncodeGameEventList, ParseGameEventList} from '../Packet/GameEventList';
import {ParsePacketEntities} from '../Packet/PacketEntities';
import {PacketHandler, voidEncoder} from '../Packet/Parser';
import {EncodePacketEntities, ParsePacketEntities} from '../Packet/PacketEntities';
import {PacketHandler} from '../Packet/Parser';
import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds';
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
import {EncodeTempEntities, ParseTempEntities} from '../Packet/TempEntities';
@ -67,7 +67,7 @@ const handlers: PacketHandlerMap = new Map<PacketTypeId, PacketHandler<IPacket>>
[PacketTypeId.gameEvent,
{parser: ParseGameEvent, encoder: EncodeGameEvent}],
[PacketTypeId.packetEntities,
{parser: ParsePacketEntities, encoder: voidEncoder}],
{parser: ParsePacketEntities, encoder: EncodePacketEntities}],
[PacketTypeId.tempEntities,
{parser: ParseTempEntities, encoder: EncodeTempEntities}],
[PacketTypeId.preFetch,
@ -107,10 +107,10 @@ export const PacketMessageHandler: MessageHandler<PacketMessage> = {
while (messageStream.bitsLeft > 6) { // last 6 bits for NOOP
const type = messageStream.readBits(6) as PacketTypeId;
if (type !== 0) {
const parser = handlers.get(type);
if (parser) {
const handler = handlers.get(type);
if (handler) {
const skip = state.skippedPackets.indexOf(type) !== -1;
const packet = parser.parser(messageStream, state, skip);
const packet = handler.parser(messageStream, state, skip);
packets.push(packet);
} else {
throw new Error(`Unknown packet type ${type} just parsed a ${PacketTypeId[lastPacketType]}`);
@ -131,7 +131,55 @@ export const PacketMessageHandler: MessageHandler<PacketMessage> = {
sequenceOut
};
},
encodeMessage: (message, stream) => {
throw new Error('Not implemented');
encodeMessage: (message: PacketMessage, stream: BitStream, state: ParserState) => {
stream.writeUint32(message.tick);
stream.writeUint32(message.flags);
for (let j = 0; j < 2; j++) {
stream.writeFloat32(message.viewOrigin[j].x);
stream.writeFloat32(message.viewOrigin[j].y);
stream.writeFloat32(message.viewOrigin[j].z);
stream.writeFloat32(message.viewAngles[j].x);
stream.writeFloat32(message.viewAngles[j].y);
stream.writeFloat32(message.viewAngles[j].z);
stream.writeFloat32(message.localViewAngles[j].x);
stream.writeFloat32(message.localViewAngles[j].y);
stream.writeFloat32(message.localViewAngles[j].z);
}
stream.writeUint32(message.sequenceIn);
stream.writeUint32(message.sequenceOut);
const lengthStart = stream.index;
stream.index += 32;
const dataStart = stream.index;
for (const packet of message.packets) {
const type = PacketTypeId[packet.packetType];
stream.writeBits(type, 6);
const handler = handlers.get(type);
if (handler) {
handler.encoder(packet, stream, state);
} else {
throw new Error(`No handler for packet type ${packet.packetType}`);
}
}
stream.writeBits(0, 6);
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;
}
};

View file

@ -192,7 +192,7 @@ export function ParsePacketEntities(stream: BitStream, state: ParserState, skip:
export function EncodePacketEntities(packet: PacketEntitiesPacket, stream: BitStream, state: ParserState) {
stream.writeBits(packet.maxEntries, 11);
const isDelta = packet.removedEntities.length > 0;
const isDelta = packet.delta > 0;
stream.writeBoolean(isDelta);
if (isDelta) {
stream.writeInt32(packet.delta);

View file

@ -76,5 +76,7 @@ export function EncodeTempEntities(packet: TempEntitiesPacket, stream: BitStream
writeVarInt(entityDataLength, stream);
stream.writeBitStream(entityStream, entityDataLength);
if (entityDataLength > 0) {
stream.writeBitStream(entityStream, entityDataLength);
}
}

View file

@ -0,0 +1 @@
{"0":8,"1":85,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":50,"81":21,"82":0,"83":0,"84":50,"85":21,"86":0,"87":0,"88":185,"89":1,"90":0,"91":0,"92":67,"93":148,"94":42,"95":0,"96":64,"97":121,"98":1,"99":88,"100":128,"101":118,"102":193,"103":77,"104":170,"105":0,"106":0,"107":78,"108":192,"109":206,"110":0,"111":8,"112":194,"113":59,"114":103,"115":31,"116":99,"117":7,"118":22,"119":142,"120":5,"121":26,"122":3,"123":246,"124":7,"125":2,"126":0,"127":132,"128":162,"129":84,"130":1,"131":0,"132":0,"133":132,"134":231,"135":87,"136":249,"137":255,"138":96,"139":96,"140":188,"141":64,"142":64,"143":51,"144":240,"145":127,"146":0,"147":13,"148":65,"149":120,"150":172,"151":197,"152":89,"153":158,"154":192,"155":198,"156":161,"157":136,"158":89,"159":199,"160":227,"161":129,"162":3,"163":8,"164":207,"165":195,"166":152,"167":26,"168":30,"169":24,"170":35,"171":18,"172":57,"173":3,"174":16,"175":158,"176":120,"177":235,"178":222,"179":132,"180":129,"181":105,"182":70,"183":137,"184":85,"185":2,"186":106,"187":0,"188":194,"189":155,"190":116,"191":175,"192":97,"193":6,"194":166,"195":13,"196":6,"197":184,"198":2,"199":118,"200":5,"201":208,"202":0,"203":132,"204":103,"205":127,"206":159,"207":45,"208":13,"209":172,"210":27,"211":15,"212":116,"213":38,"214":212,"215":0,"216":132,"217":165,"218":160,"219":236,"220":117,"221":117,"222":130,"223":49,"224":144,"225":82,"226":32,"227":13,"228":64,"229":88,"230":10,"231":202,"232":94,"233":87,"234":39,"235":44,"236":3,"237":128,"238":5,"239":202,"240":186,"241":26,"242":203,"243":8,"244":149,"245":66,"246":0,"247":194,"248":178,"249":78,"250":120,"251":253,"252":62,"253":131,"254":6,"255":32,"256":44,"257":176,"258":5,"259":47,"260":162,"261":35,"262":223,"263":7,"264":210,"265":0,"266":132,"267":151,"268":255,"269":61,"270":105,"271":78,"272":180,"273":6,"274":214,"275":13,"276":156,"277":1,"278":8,"279":235,"280":40,"281":241,"282":183,"283":154,"284":140,"285":90,"286":192,"287":82,"288":0,"289":64,"290":88,"291":46,"292":200,"293":159,"294":52,"295":102,"296":212,"297":0,"298":196,"299":99,"300":3,"301":62,"302":7,"303":202,"304":0,"305":132,"306":5,"307":182,"308":224,"309":69,"310":116,"311":196,"312":254,"313":64,"314":90,"315":87,"316":99,"317":127,"318":229,"319":22,"320":8,"321":64,"322":88,"323":79,"324":202,"325":111,"326":101,"327":38,"328":22,"329":3,"330":94,"331":5,"332":206,"333":0,"334":132,"335":181,"336":157,"337":236,"338":150,"339":108,"340":228,"341":224,"342":64,"343":26,"344":148,"345":28,"346":17,"347":145,"348":20,"349":66,"350":46,"351":68,"352":250,"353":88,"354":48,"355":161,"356":64,"357":162,"358":58,"359":32,"360":180,"361":24,"362":16,"363":56,"364":15,"365":192,"366":144,"367":99,"368":132,"369":1,"370":42,"371":159,"372":72,"373":89,"374":96,"375":88,"376":14,"377":167,"378":29,"379":91,"380":120,"381":112,"382":160,"383":243,"384":207,"385":171,"386":76,"387":169,"388":56,"389":34,"390":40,"391":154,"392":237,"393":62,"394":122,"395":67,"396":101,"397":170,"398":1,"399":40,"400":1,"401":129,"402":164,"403":243,"404":88,"405":0,"406":67,"407":164,"408":44,"409":48,"410":3,"411":147,"412":7,"413":213,"414":239,"415":50,"416":49,"417":0,"418":81,"419":12,"420":145,"421":178,"422":192,"423":232,"424":249,"425":60,"426":175,"427":27,"428":168,"429":139,"430":32,"431":82,"432":22,"433":24,"434":223,"435":159,"436":195,"437":109,"438":7,"439":70,"440":164,"441":44,"442":48,"443":48,"444":255,"445":195,"446":27,"447":140,"448":244,"449":136,"450":197,"451":30,"452":23,"453":0,"454":76,"455":206,"456":17,"457":7,"458":12,"459":71,"460":34,"461":100,"462":22,"463":50,"464":136,"465":32,"466":0,"467":101,"468":16,"469":201,"470":220,"471":36,"472":230,"473":1,"474":16,"475":41,"476":11,"477":108,"478":20,"479":229,"480":4,"481":241,"482":131,"483":130,"484":10,"485":8,"486":68,"487":68,"488":164,"489":44,"490":48,"491":78,"492":184,"493":91,"494":100,"495":141,"496":12,"497":5,"498":64,"499":164,"500":44,"501":176,"502":88,"503":144,"504":243,"505":195,"506":12,"507":14,"508":60,"509":48,"510":0,"511":17,"512":41,"513":11,"514":44,"515":19,"516":241,"517":26,"518":241,"519":91,"520":195,"521":48,"522":125,"523":213,"524":103,"525":11,"526":56,"527":209,"528":83,"529":64,"530":17,"531":184,"532":0}

View file

@ -0,0 +1,64 @@
{
"type": 2,
"packets": [
{
"packetType": "netTick",
"tick": 43601,
"frameTime": 1509,
"stdDev": 352
},
{
"packetType": "packetEntities",
"entities": [],
"removedEntities": [],
"maxEntries": 1047,
"delta": 43597,
"baseLine": 0,
"updatedBaseLine": false
},
{
"packetType": "tempEntities",
"entities": []
}
],
"tick": 21768,
"flags": 0,
"viewOrigin": [
{
"x": 0,
"y": 0,
"z": 0
},
{
"x": 0,
"y": 0,
"z": 0
}
],
"viewAngles": [
{
"x": 0,
"y": 0,
"z": 0
},
{
"x": 0,
"y": 0,
"z": 0
}
],
"localViewAngles": [
{
"x": 0,
"y": 0,
"z": 0
},
{
"x": 0,
"y": 0,
"z": 0
}
],
"sequenceIn": 5426,
"sequenceOut": 5426
}

View file

@ -0,0 +1,43 @@
import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
import {readFileSync} from 'fs';
import {PacketMessageHandler} from '../../../../Parser/Message/Packet';
import {ParserState} from '../../../../Data/ParserState';
import {PacketTypeId} from '../../../../Data/Packet';
const data = Object.values(JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageData.json', 'utf8')));
const expected = JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageResult.json', 'utf8'));
const getParserState = (fastMode) => {
const state = new ParserState();
// fast mode allows us not to bother with complicated entity parser state
state.skippedPackets = fastMode ? [
PacketTypeId.packetEntities,
PacketTypeId.tempEntities,
PacketTypeId.entityMessage,
] : [];
return state;
};
const handler = PacketMessageHandler;
function parser(stream) {
const result = handler.parseMessage(stream, getParserState(true));
delete result.rawData;
return result;
}
function encoder(message, stream) {
handler.encodeMessage(message, stream, getParserState(false));
}
suite('Packet', () => {
test('Parse packet message', () => {
assertParser(parser, getStream(data), expected, 4264);
});
test('Encode packet message', () => {
// shorted since empty entity list encoded, instead of skipping over entities
assertEncoder(parser, encoder, expected, 920, '');
});
});

View file

@ -3,6 +3,7 @@ import {BitStream} from 'bit-buffer';
import {Packet} from '../../../../Data/Packet';
import {deepEqual} from '../../deepEqual';
import {isObject} from 'util';
import {ParserState} from '../../../../Data/ParserState';
export function getStream(data: string | number[]) {
if (typeof data === 'string') {
@ -14,12 +15,12 @@ export function getStream(data: string | number[]) {
}
}
export type Encoder = (data: any, stream: BitStream) => void;
export type Encoder = (data: any, stream: BitStream, state?) => void;
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0, message: string = '') {
export function assertEncoder(parser: Parser, encoder: Encoder, data: any, length: number = 0, message: string = '', state?: ParserState) {
const stream = new BitStream(new ArrayBuffer(length + 64000));
encoder(data as Packet, stream);
encoder(data as Packet, stream, state);
const pos = stream.index;
@ -37,11 +38,11 @@ export function assertEncoder(parser: Parser, encoder: Encoder, data: any, lengt
assert.equal(stream.index, pos, 'Number of bits used for encoding and parsing not equal' + message);
}
export type Parser = (stream: BitStream, match?) => any;
export type Parser = (stream: BitStream, state?) => any;
export function assertParser(parser: Parser, stream: BitStream, expected: any, length: number) {
export function assertParser(parser: Parser, stream: BitStream, expected: any, length: number, state?: ParserState) {
const start = stream.index;
const result = parser(stream);
const result = parser(stream, state);
if (!deepEqual(result, expected)) {
assert.deepEqual(result, expected);
}