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

include /build

This commit is contained in:
Bryan C 2020-07-02 18:42:25 +08:00
commit 132ab1b47a
220 changed files with 9059 additions and 1 deletions

5
build/Parser/EntityDecoder.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { SendProp } from '../Data/SendProp';
import { SendTable } from '../Data/SendTable';
export declare function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[];
export declare function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stream: BitStream): void;

View file

@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const SendProp_1 = require("../Data/SendProp");
const readBitVar_1 = require("./readBitVar");
const SendPropEncoder_1 = require("./SendPropEncoder");
const SendPropParser_1 = require("./SendPropParser");
function getEntityUpdate(sendTable, stream) {
let index = -1;
const allProps = sendTable.flattenedProps;
const props = new Map();
let lastIndex = -1;
while (stream.readBoolean()) {
lastIndex = index;
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 (lastProp: ${lastIndex})`);
}
const propDefinition = allProps[index];
const prop = new SendProp_1.SendProp(propDefinition);
prop.value = SendPropParser_1.SendPropParser.decode(propDefinition, stream);
props.set(propDefinition.fullName, prop);
}
return Array.from(props.values());
}
exports.getEntityUpdate = getEntityUpdate;
function encodeEntityUpdate(props, sendTable, stream) {
const allProps = sendTable.flattenedProps;
props.sort((propA, propB) => {
const indexA = allProps.findIndex((propDef) => propDef.fullName === propA.definition.fullName);
const indexB = allProps.findIndex((propDef) => propDef.fullName === propB.definition.fullName);
return indexA - indexB;
});
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 ${prop.definition.fullName} in ${sendTable.name}`);
}
if (index < lastIndex) {
throw new Error(`Property index not incremental while encoding ` +
`${prop.definition.fullName} after ${allProps[lastIndex].fullName} ` +
`in ${sendTable.name} (current: ${index}, last: ${lastIndex})`);
}
writeFieldIndex(index, stream, lastIndex);
lastIndex = index;
if (prop.value !== null) {
SendPropEncoder_1.SendPropEncoder.encode(prop.value, prop.definition, stream);
}
}
stream.writeBoolean(false);
}
exports.encodeEntityUpdate = encodeEntityUpdate;
function readFieldIndex(stream, lastIndex) {
const diff = readBitVar_1.readBitVar(stream);
return lastIndex + diff + 1;
}
function writeFieldIndex(index, stream, lastIndex) {
const diff = index - lastIndex - 1;
readBitVar_1.writeBitVar(diff, stream);
}
//# sourceMappingURL=EntityDecoder.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"EntityDecoder.js","sourceRoot":"","sources":["../../src/Parser/EntityDecoder.ts"],"names":[],"mappings":"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"}

4
build/Parser/Header.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { Header } from '../Data/Header';
export declare function parseHeader(stream: BitStream): Header;
export declare function encodeHeader(header: Header, stream: BitStream): void;

33
build/Parser/Header.js Normal file
View file

@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function parseHeader(stream) {
return {
type: stream.readASCIIString(8),
version: stream.readInt32(),
protocol: stream.readInt32(),
server: stream.readASCIIString(260),
nick: stream.readASCIIString(260),
map: stream.readASCIIString(260),
game: stream.readASCIIString(260),
duration: stream.readFloat32(),
ticks: stream.readInt32(),
frames: stream.readInt32(),
sigon: stream.readInt32()
};
}
exports.parseHeader = parseHeader;
function encodeHeader(header, stream) {
stream.writeASCIIString(header.type, 8);
stream.writeUint32(header.version);
stream.writeUint32(header.protocol);
stream.writeASCIIString(header.server, 260);
stream.writeASCIIString(header.nick, 260);
stream.writeASCIIString(header.map, 260);
stream.writeASCIIString(header.game, 260);
stream.writeFloat32(header.duration);
stream.writeUint32(header.ticks);
stream.writeUint32(header.frames);
stream.writeUint32(header.sigon);
}
exports.encodeHeader = encodeHeader;
//# sourceMappingURL=Header.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/Parser/Header.ts"],"names":[],"mappings":";;AAGA,SAAgB,WAAW,CAAC,MAAiB;IAC5C,OAAO;QACN,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAC/B,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE;QAC3B,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE;QAC5B,MAAM,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;QACnC,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;QACjC,GAAG,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;QAChC,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE;QAC9B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;QACzB,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE;QAC1B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;KACzB,CAAC;AACH,CAAC;AAdD,kCAcC;AAED,SAAgB,YAAY,CAAC,MAAc,EAAE,MAAiB;IAC7D,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAZD,oCAYC"}

7
build/Parser/Message/ConsoleCmd.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
import { ConsoleCmdMessage, MessageHandler } from '../../Data/Message';
import { ConsoleCmdPacket } from '../../Data/Packet';
import { Parser } from './Parser';
export declare class ConsoleCmd extends Parser {
parse(): ConsoleCmdPacket[];
}
export declare const ConsoleCmdHandler: MessageHandler<ConsoleCmdMessage>;

View file

@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const text_encoding_shim_1 = require("text-encoding-shim");
const Message_1 = require("../../Data/Message");
const Parser_1 = require("./Parser");
class ConsoleCmd extends Parser_1.Parser {
parse() {
return [{
packetType: 'consoleCmd',
command: this.stream.readUTF8String()
}];
}
}
exports.ConsoleCmd = ConsoleCmd;
exports.ConsoleCmdHandler = {
parseMessage: (stream) => {
const tick = stream.readInt32();
const length = stream.readInt32();
const messageStream = stream.readBitStream(length * 8);
return {
type: Message_1.MessageType.ConsoleCmd,
tick,
rawData: messageStream,
command: messageStream.readUTF8String()
};
},
encodeMessage: (message, stream) => {
stream.writeUint32(message.tick);
const byteLength = (new text_encoding_shim_1.TextEncoder('utf-8').encode(message.command)).length + 1; // +1 for null termination
stream.writeUint32(byteLength);
stream.writeUTF8String(message.command);
}
};
//# sourceMappingURL=ConsoleCmd.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"ConsoleCmd.js","sourceRoot":"","sources":["../../../src/Parser/Message/ConsoleCmd.ts"],"names":[],"mappings":";;AACA,2DAA+C;AAC/C,gDAAkF;AAElF,qCAAgC;AAEhC,MAAa,UAAW,SAAQ,eAAM;IAC9B,KAAK;QACX,OAAO,CAAC;gBACP,UAAU,EAAE,YAAY;gBACxB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE;aACrC,CAAC,CAAC;IACJ,CAAC;CACD;AAPD,gCAOC;AAEY,QAAA,iBAAiB,GAAsC;IACnE,YAAY,EAAE,CAAC,MAAiB,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEvD,OAAO;YACN,IAAI,EAAE,qBAAW,CAAC,UAAU;YAC5B,IAAI;YACJ,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,aAAa,CAAC,cAAc,EAAE;SACvC,CAAC;IACH,CAAC;IACD,aAAa,EAAE,CAAC,OAA0B,EAAE,MAAiB,EAAE,EAAE;QAChE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEjC,MAAM,UAAU,GAAG,CAAC,IAAI,gCAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,0BAA0B;QAC5G,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;CACD,CAAC"}

2
build/Parser/Message/DataTable.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { DataTablesMessage, MessageHandler } from '../../Data/Message';
export declare const DataTableHandler: MessageHandler<DataTablesMessage>;

View file

@ -0,0 +1,205 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Message_1 = require("../../Data/Message");
const SendPropDefinition_1 = require("../../Data/SendPropDefinition");
const SendTable_1 = require("../../Data/SendTable");
const ServerClass_1 = require("../../Data/ServerClass");
exports.DataTableHandler = {
parseMessage: (stream) => {
const tick = stream.readInt32();
const length = stream.readInt32();
const messageStream = stream.readBitStream(length * 8);
// https://github.com/LestaD/SourceEngine2007/blob/43a5c90a5ada1e69ca044595383be67f40b33c61/src_main/engine/dt_common_eng.cpp#L356
// https://github.com/LestaD/SourceEngine2007/blob/43a5c90a5ada1e69ca044595383be67f40b33c61/src_main/engine/dt_recv_eng.cpp#L310
// https://github.com/PazerOP/DemoLib/blob/master/DemoLib/Commands/DemoDataTablesCommand.cs
const tables = [];
const tableMap = new Map();
while (messageStream.readBoolean()) {
const needsDecoder = messageStream.readBoolean();
const tableName = messageStream.readASCIIString();
const numProps = messageStream.readBits(10);
const table = new SendTable_1.SendTable(tableName);
table.needsDecoder = needsDecoder;
// get props metadata
let arrayElementProp;
for (let i = 0; i < numProps; i++) {
const propType = messageStream.readBits(5);
const propName = messageStream.readASCIIString();
const nFlagsBits = 16; // might be 11 (old?), 13 (new?), 16(networked) or 17(??)
const flags = messageStream.readBits(nFlagsBits);
const prop = new SendPropDefinition_1.SendPropDefinition(propType, propName, flags, tableName);
if (propType === SendPropDefinition_1.SendPropType.DPT_DataTable) {
prop.excludeDTName = messageStream.readASCIIString();
}
else {
if (prop.isExcludeProp()) {
prop.excludeDTName = messageStream.readASCIIString();
}
else if (prop.type === SendPropDefinition_1.SendPropType.DPT_Array) {
prop.numElements = messageStream.readBits(10);
}
else {
prop.lowValue = messageStream.readFloat32();
prop.highValue = messageStream.readFloat32();
prop.bitCount = messageStream.readBits(7);
}
}
if (prop.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NOSCALE)) {
if (prop.type === SendPropDefinition_1.SendPropType.DPT_Float) {
prop.originalBitCount = prop.bitCount;
prop.bitCount = 32;
}
else if (prop.type === SendPropDefinition_1.SendPropType.DPT_Vector) {
if (!prop.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NORMAL)) {
prop.originalBitCount = prop.bitCount;
prop.bitCount = 32 * 3;
}
}
}
if (arrayElementProp) {
if (prop.type !== SendPropDefinition_1.SendPropType.DPT_Array) {
throw new Error('expected prop of type array');
}
prop.arrayProperty = arrayElementProp;
arrayElementProp = null;
}
if (prop.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_INSIDEARRAY)) {
if (arrayElementProp) {
throw new Error('array element already set');
}
if (prop.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_CHANGES_OFTEN)) {
throw new Error('unexpected CHANGES_OFTEN prop in array');
}
arrayElementProp = prop;
}
else {
table.addProp(prop);
}
}
tables.push(table);
tableMap.set(table.name, table);
}
// link referenced tables
for (const table of tables) {
for (const prop of table.props) {
if (prop.type === SendPropDefinition_1.SendPropType.DPT_DataTable) {
if (prop.excludeDTName) {
const referencedTable = tableMap.get(prop.excludeDTName);
if (!referencedTable) {
throw new Error(`Unknown referenced table ${prop.excludeDTName}`);
}
prop.table = referencedTable;
prop.excludeDTName = null;
}
}
}
}
const numServerClasses = messageStream.readUint16(); // short
const serverClasses = [];
if (numServerClasses <= 0) {
throw new Error('expected one or more serverclasses');
}
for (let i = 0; i < numServerClasses; i++) {
const classId = messageStream.readUint16();
if (classId > numServerClasses) {
throw new Error('invalid class id');
}
const className = messageStream.readASCIIString();
const dataTable = messageStream.readASCIIString();
serverClasses.push(new ServerClass_1.ServerClass(classId, className, dataTable));
}
if (messageStream.bitsLeft > 7) {
throw new Error('unexpected remaining data in datatable (' + messageStream.bitsLeft + ' bits)');
}
return {
type: Message_1.MessageType.DataTables,
tick,
rawData: messageStream,
tables,
serverClasses
};
},
encodeMessage: (message, stream) => {
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, definition) {
stream.writeBits(definition.type, 5);
stream.writeASCIIString(definition.name);
stream.writeBits(definition.flags, 16);
if (definition.type === SendPropDefinition_1.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 === SendPropDefinition_1.SendPropType.DPT_Array) {
stream.writeBits(definition.numElements, 10);
}
else {
stream.writeFloat32(definition.lowValue);
stream.writeFloat32(definition.highValue);
// if (definition.originalBitCount === null || typeof definition.originalBitCount === 'undefined') {
// stream.writeBits(definition.bitCount, 7);
// } else {
// stream.writeBits(definition.originalBitCount, 7);
// }
if (definition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NOSCALE) && (definition.type === SendPropDefinition_1.SendPropType.DPT_Float ||
(definition.type === SendPropDefinition_1.SendPropType.DPT_Vector && !definition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NORMAL)))) {
if (definition.originalBitCount === null || typeof definition.originalBitCount === 'undefined') {
stream.writeBits(definition.bitCount / 3, 7);
}
else {
stream.writeBits(definition.originalBitCount, 7);
}
}
else {
stream.writeBits(definition.bitCount, 7);
}
}
}
}
//# sourceMappingURL=DataTable.js.map

File diff suppressed because one or more lines are too long

2
build/Parser/Message/Packet.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { MessageHandler, PacketMessage } from '../../Data/Message';
export declare const PacketMessageHandler: MessageHandler<PacketMessage>;

View file

@ -0,0 +1,163 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const BSPDecal_1 = require("../Packet/BSPDecal");
const ClassInfo_1 = require("../Packet/ClassInfo");
const CreateStringTable_1 = require("../Packet/CreateStringTable");
const GameEvent_1 = require("../Packet/GameEvent");
const GameEventList_1 = require("../Packet/GameEventList");
const PacketEntities_1 = require("../Packet/PacketEntities");
const ParserGenerator_1 = require("../Packet/ParserGenerator");
const ParseSounds_1 = require("../Packet/ParseSounds");
const SetConVar_1 = require("../Packet/SetConVar");
const TempEntities_1 = require("../Packet/TempEntities");
const UpdateStringTable_1 = require("../Packet/UpdateStringTable");
const UserMessage_1 = require("../Packet/UserMessage");
const VoiceData_1 = require("../Packet/VoiceData");
const VoiceInit_1 = require("../Packet/VoiceInit");
const Message_1 = require("../../Data/Message");
const Packet_1 = require("../../Data/Packet");
const Vector_1 = require("../../Data/Vector");
const handlers = new Map([
[Packet_1.PacketTypeId.file,
ParserGenerator_1.make('file', 'transferId{32}fileName{s}requested{b}')],
[Packet_1.PacketTypeId.netTick,
ParserGenerator_1.make('netTick', 'tick{32}frameTime{16}stdDev{16}')],
[Packet_1.PacketTypeId.stringCmd,
ParserGenerator_1.make('stringCmd', 'command{s}')],
[Packet_1.PacketTypeId.setConVar,
{ parser: SetConVar_1.ParseSetConVar, encoder: SetConVar_1.EncodeSetConVar }],
[Packet_1.PacketTypeId.sigOnState,
ParserGenerator_1.make('sigOnState', 'state{8}count{32}')],
[Packet_1.PacketTypeId.print,
ParserGenerator_1.make('print', 'value{s}')],
[Packet_1.PacketTypeId.serverInfo,
ParserGenerator_1.make('serverInfo', 'version{16}serverCount{32}stv{b}dedicated{b}maxCrc{32}maxClasses{16}' +
'mapHash{128}playerCount{8}maxPlayerCount{8}intervalPerTick{f32}platform{s1}' +
'game{s}map{s}skybox{s}serverName{s}replay{b}')],
[Packet_1.PacketTypeId.classInfo,
{ parser: ClassInfo_1.ParseClassInfo, encoder: ClassInfo_1.EncodeClassInfo }],
[Packet_1.PacketTypeId.setPause,
ParserGenerator_1.make('setPause', 'paused{b}')],
[Packet_1.PacketTypeId.createStringTable,
{ parser: CreateStringTable_1.ParseCreateStringTable, encoder: CreateStringTable_1.EncodeCreateStringTable }],
[Packet_1.PacketTypeId.updateStringTable,
{ parser: UpdateStringTable_1.ParseUpdateStringTable, encoder: UpdateStringTable_1.EncodeUpdateStringTable }],
[Packet_1.PacketTypeId.voiceInit,
{ parser: VoiceInit_1.ParseVoiceInit, encoder: VoiceInit_1.EncodeVoiceInit }],
[Packet_1.PacketTypeId.voiceData,
{ parser: VoiceData_1.ParseVoiceData, encoder: VoiceData_1.EncodeVoiceData }],
[Packet_1.PacketTypeId.parseSounds,
{ parser: ParseSounds_1.ParseParseSounds, encoder: ParseSounds_1.EncodeParseSounds }],
[Packet_1.PacketTypeId.setView,
ParserGenerator_1.make('setView', 'index{11}')],
[Packet_1.PacketTypeId.fixAngle,
ParserGenerator_1.make('fixAngle', 'relative{b}x{16}y{16}z{16}')],
[Packet_1.PacketTypeId.bspDecal,
{ parser: BSPDecal_1.ParseBSPDecal, encoder: BSPDecal_1.EncodeBSPDecal }],
[Packet_1.PacketTypeId.userMessage,
{ parser: UserMessage_1.ParseUserMessage, encoder: UserMessage_1.EncodeUserMessage }],
[Packet_1.PacketTypeId.entityMessage,
ParserGenerator_1.make('entityMessage', 'index{11}classId{9}length{11}data{$length}')],
[Packet_1.PacketTypeId.gameEvent,
{ parser: GameEvent_1.ParseGameEvent, encoder: GameEvent_1.EncodeGameEvent }],
[Packet_1.PacketTypeId.packetEntities,
{ parser: PacketEntities_1.ParsePacketEntities, encoder: PacketEntities_1.EncodePacketEntities }],
[Packet_1.PacketTypeId.tempEntities,
{ parser: TempEntities_1.ParseTempEntities, encoder: TempEntities_1.EncodeTempEntities }],
[Packet_1.PacketTypeId.preFetch,
ParserGenerator_1.make('preFetch', 'index{14}')],
[Packet_1.PacketTypeId.menu,
ParserGenerator_1.make('menu', 'type{u16}length{u16}data{$length*8}')],
[Packet_1.PacketTypeId.gameEventList,
{ parser: GameEventList_1.ParseGameEventList, encoder: GameEventList_1.EncodeGameEventList }],
[Packet_1.PacketTypeId.getCvarValue,
ParserGenerator_1.make('getCvarValue', 'cookie{32}value{s}')],
[Packet_1.PacketTypeId.cmdKeyValues,
ParserGenerator_1.make('cmdKeyValues', 'length{32}data{$length}')]
]);
exports.PacketMessageHandler = {
parseMessage: (stream, state) => {
const tick = stream.readInt32();
const flags = stream.readInt32();
const viewOrigin = [new Vector_1.Vector(0, 0, 0), new Vector_1.Vector(0, 0, 0)];
const viewAngles = [new Vector_1.Vector(0, 0, 0), new Vector_1.Vector(0, 0, 0)];
const localViewAngles = [new Vector_1.Vector(0, 0, 0), new Vector_1.Vector(0, 0, 0)];
for (let j = 0; j < 2; j++) {
viewOrigin[j] = new Vector_1.Vector(stream.readFloat32(), stream.readFloat32(), stream.readFloat32());
viewAngles[j] = new Vector_1.Vector(stream.readFloat32(), stream.readFloat32(), stream.readFloat32());
localViewAngles[j] = new Vector_1.Vector(stream.readFloat32(), stream.readFloat32(), stream.readFloat32());
}
const sequenceIn = stream.readInt32();
const sequenceOut = stream.readInt32();
const length = stream.readInt32();
const messageStream = stream.readBitStream(length * 8);
const packets = [];
let lastPacketType = 0;
while (messageStream.bitsLeft > 6) { // last 6 bits for NOOP
const type = messageStream.readBits(6);
if (type !== 0) {
const handler = handlers.get(type);
if (handler) {
const skip = state.skippedPackets.indexOf(type) !== -1;
const packet = handler.parser(messageStream, state, skip);
packets.push(packet);
}
else {
throw new Error(`Unknown packet type ${type} just parsed a ${Packet_1.PacketTypeId[lastPacketType]}`);
}
lastPacketType = type;
}
}
return {
type: Message_1.MessageType.Packet,
tick,
rawData: messageStream,
packets,
flags,
viewOrigin,
viewAngles,
localViewAngles,
sequenceIn,
sequenceOut
};
},
encodeMessage: (message, stream, state) => {
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 = Packet_1.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;
}
};
//# sourceMappingURL=Packet.js.map

File diff suppressed because one or more lines are too long

14
build/Parser/Message/Parser.d.ts vendored Normal file
View file

@ -0,0 +1,14 @@
import { BitStream } from 'bit-buffer';
import { MessageType } from '../../Data/Message';
import { Packet, PacketTypeId } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare abstract class Parser {
protected type: any;
protected tick: number;
protected stream: BitStream;
protected length: number;
protected state: ParserState;
protected skippedPackets: PacketTypeId[];
constructor(type: MessageType, tick: number, stream: BitStream, length: number, state: ParserState, skippedPacket?: PacketTypeId[]);
abstract parse(): Packet[];
}

View file

@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Parser {
constructor(type, tick, stream, length, state, skippedPacket = []) {
this.type = type;
this.tick = tick;
this.stream = stream;
this.length = length; // length in bytes
this.state = state;
this.skippedPackets = skippedPacket;
}
}
exports.Parser = Parser;
//# sourceMappingURL=Parser.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../../src/Parser/Message/Parser.ts"],"names":[],"mappings":";;AAKA,MAAsB,MAAM;IAQ3B,YAAY,IAAiB,EAAE,IAAY,EAAE,MAAiB,EAAE,MAAc,EAAE,KAAkB,EAAE,gBAAgC,EAAE;QACrI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,kBAAkB;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;IACrC,CAAC;CAGD;AAlBD,wBAkBC"}

2
build/Parser/Message/Stop.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { MessageHandler, StopMessage } from '../../Data/Message';
export declare const StopHandler: MessageHandler<StopMessage>;

View file

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Message_1 = require("../../Data/Message");
exports.StopHandler = {
parseMessage: (stream) => {
return {
type: Message_1.MessageType.Stop,
rawData: stream.readBitStream(0)
};
},
encodeMessage: (message, stream) => {
// noop
}
};
//# sourceMappingURL=Stop.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Stop.js","sourceRoot":"","sources":["../../../src/Parser/Message/Stop.ts"],"names":[],"mappings":";;AACA,gDAA6F;AAEhF,QAAA,WAAW,GAAgC;IACvD,YAAY,EAAE,CAAC,MAAiB,EAAE,EAAE;QACnC,OAAO;YACN,IAAI,EAAE,qBAAW,CAAC,IAAI;YACtB,OAAO,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;SAChC,CAAC;IACH,CAAC;IACD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClC,OAAO;IACR,CAAC;CACD,CAAC"}

2
build/Parser/Message/StringTable.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { MessageHandler, StringTablesMessage } from '../../Data/Message';
export declare const StringTableHandler: MessageHandler<StringTablesMessage>;

View file

@ -0,0 +1,94 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Message_1 = require("../../Data/Message");
exports.StringTableHandler = {
parseMessage: (stream) => {
const tick = stream.readInt32();
const length = stream.readInt32();
const messageStream = stream.readBitStream(length * 8);
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs
const tableCount = messageStream.readUint8();
const tables = [];
for (let i = 0; i < tableCount; i++) {
const entries = [];
const tableName = messageStream.readASCIIString();
const entryCount = messageStream.readUint16();
for (let j = 0; j < entryCount; j++) {
const entry = readEntry(messageStream);
entries.push(entry);
}
const table = {
entries,
name: tableName,
maxEntries: entryCount,
clientEntries: [],
compressed: false
};
if (messageStream.readBoolean()) {
const clientEntries = messageStream.readUint16();
for (let j = 0; j < clientEntries; j++) {
const entry = readEntry(messageStream);
table.clientEntries.push(entry);
}
}
tables.push(table);
}
return {
type: Message_1.MessageType.StringTables,
tick,
rawData: messageStream,
tables
};
},
encodeMessage: (message, stream) => {
stream.writeUint32(message.tick);
const lengthStart = stream.index;
stream.index += 32;
const dataStart = stream.index;
stream.writeUint8(message.tables.length);
for (const table of message.tables) {
stream.writeASCIIString(table.name);
stream.writeUint16(table.entries.length);
for (const entry of table.entries) {
writeEntry(entry, stream);
}
if (table.clientEntries && table.clientEntries.length) {
stream.writeBoolean(true);
stream.writeUint16(table.clientEntries.length);
for (const entry of table.clientEntries) {
writeEntry(entry, stream);
}
}
else {
stream.writeBoolean(false);
}
}
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 readEntry(stream) {
const entry = { text: stream.readUTF8String() };
if (stream.readBoolean()) {
const extraDataLength = stream.readUint16();
entry.extraData = stream.readBitStream(extraDataLength * 8);
}
return entry;
}
function writeEntry(entry, stream) {
stream.writeUTF8String(entry.text);
if (entry.extraData) {
stream.writeBoolean(true);
stream.writeUint16(Math.ceil(entry.extraData.length / 8));
entry.extraData.index = 0;
stream.writeBitStream(entry.extraData, entry.extraData.length);
}
else {
stream.writeBoolean(false);
}
}
//# sourceMappingURL=StringTable.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"StringTable.js","sourceRoot":"","sources":["../../../src/Parser/Message/StringTable.ts"],"names":[],"mappings":"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"}

2
build/Parser/Message/SyncTick.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { MessageHandler, SyncTickMessage } from '../../Data/Message';
export declare const SyncTickHandler: MessageHandler<SyncTickMessage>;

View file

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Message_1 = require("../../Data/Message");
exports.SyncTickHandler = {
parseMessage: (stream) => {
const tick = stream.readInt32();
return {
type: Message_1.MessageType.SyncTick,
tick,
rawData: stream.readBitStream(0)
};
},
encodeMessage: (message, stream) => {
stream.writeUint32(message.tick);
}
};
//# sourceMappingURL=SyncTick.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"SyncTick.js","sourceRoot":"","sources":["../../../src/Parser/Message/SyncTick.ts"],"names":[],"mappings":";;AACA,gDAAgF;AAEnE,QAAA,eAAe,GAAoC;IAC/D,YAAY,EAAE,CAAC,MAAiB,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAEhC,OAAO;YACN,IAAI,EAAE,qBAAW,CAAC,QAAQ;YAC1B,IAAI;YACJ,OAAO,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;SAChC,CAAC;IACH,CAAC;IACD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACD,CAAC"}

2
build/Parser/Message/UserCmd.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
import { MessageHandler, UserCmdMessage } from '../../Data/Message';
export declare const UserCmdHandler: MessageHandler<UserCmdMessage>;

View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Message_1 = require("../../Data/Message");
exports.UserCmdHandler = {
parseMessage: (stream) => {
const tick = stream.readInt32();
const sequenceOut = stream.readInt32();
const length = stream.readInt32();
const messageStream = stream.readBitStream(length * 8);
return {
type: Message_1.MessageType.UserCmd,
tick,
rawData: messageStream,
sequenceOut
};
},
encodeMessage: (message, stream) => {
throw new Error('not implemented');
}
};
//# sourceMappingURL=UserCmd.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"UserCmd.js","sourceRoot":"","sources":["../../../src/Parser/Message/UserCmd.ts"],"names":[],"mappings":";;AACA,gDAA+E;AAElE,QAAA,cAAc,GAAmC;IAC7D,YAAY,EAAE,CAAC,MAAiB,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAEhC,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAEvC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEvD,OAAO;YACN,IAAI,EAAE,qBAAW,CAAC,OAAO;YACzB,IAAI;YACJ,OAAO,EAAE,aAAa;YACtB,WAAW;SACX,CAAC;IACH,CAAC;IACD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;CACD,CAAC"}

7
build/Parser/Packet/BSPDecal.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
import { BitStream } from 'bit-buffer';
import { BSPDecalPacket } from '../../Data/Packet';
import { Vector } from '../../Data/Vector';
export declare function getVecCoord(stream: BitStream): Vector;
export declare function encodeVecCoord(vector: Vector, stream: BitStream): void;
export declare function ParseBSPDecal(stream: BitStream): BSPDecalPacket;
export declare function EncodeBSPDecal(packet: BSPDecalPacket, stream: BitStream): void;

View file

@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const SendPropEncoder_1 = require("../SendPropEncoder");
const SendPropParser_1 = require("../SendPropParser");
function getVecCoord(stream) {
const hasX = stream.readBoolean();
const hasY = stream.readBoolean();
const hasZ = stream.readBoolean();
return {
x: hasX ? SendPropParser_1.SendPropParser.readBitCoord(stream) : 0,
y: hasY ? SendPropParser_1.SendPropParser.readBitCoord(stream) : 0,
z: hasZ ? SendPropParser_1.SendPropParser.readBitCoord(stream) : 0
};
}
exports.getVecCoord = getVecCoord;
function encodeVecCoord(vector, stream) {
stream.writeBoolean(vector.x !== 0);
stream.writeBoolean(vector.y !== 0);
stream.writeBoolean(vector.z !== 0);
if (vector.x !== 0) {
SendPropEncoder_1.SendPropEncoder.writeBitCoord(vector.x, stream);
}
if (vector.y !== 0) {
SendPropEncoder_1.SendPropEncoder.writeBitCoord(vector.y, stream);
}
if (vector.z !== 0) {
SendPropEncoder_1.SendPropEncoder.writeBitCoord(vector.z, stream);
}
}
exports.encodeVecCoord = encodeVecCoord;
function ParseBSPDecal(stream) {
let modelIndex = 0;
let entIndex = 0;
const position = getVecCoord(stream);
const textureIndex = stream.readBits(9);
if (stream.readBoolean()) {
entIndex = stream.readBits(11);
modelIndex = stream.readBits(12);
}
const lowPriority = stream.readBoolean();
return {
packetType: 'bspDecal',
position,
textureIndex,
entIndex,
modelIndex,
lowPriority
};
}
exports.ParseBSPDecal = ParseBSPDecal;
function EncodeBSPDecal(packet, stream) {
encodeVecCoord(packet.position, stream);
stream.writeBits(packet.textureIndex, 9);
if (packet.entIndex || packet.modelIndex) {
stream.writeBoolean(true);
stream.writeBits(packet.entIndex, 11);
stream.writeBits(packet.modelIndex, 12);
}
else {
stream.writeBoolean(false);
}
stream.writeBoolean(packet.lowPriority);
}
exports.EncodeBSPDecal = EncodeBSPDecal;
//# sourceMappingURL=BSPDecal.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"BSPDecal.js","sourceRoot":"","sources":["../../../src/Parser/Packet/BSPDecal.ts"],"names":[],"mappings":"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"}

4
build/Parser/Packet/ClassInfo.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { ClassInfoPacket } from '../../Data/Packet';
export declare function ParseClassInfo(stream: BitStream): ClassInfoPacket;
export declare function EncodeClassInfo(packet: ClassInfoPacket, stream: BitStream): void;

View file

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Math_1 = require("../../Math");
function ParseClassInfo(stream) {
const count = stream.readUint16();
const create = stream.readBoolean();
const entries = [];
if (!create) {
const bits = Math_1.logBase2(count) + 1;
for (let i = 0; i < count; i++) {
const entry = {
classId: stream.readBits(bits),
className: stream.readASCIIString(),
dataTableName: stream.readASCIIString()
};
entries.push(entry);
}
}
return {
packetType: 'classInfo',
number: count,
create,
entries
};
}
exports.ParseClassInfo = ParseClassInfo;
function EncodeClassInfo(packet, stream) {
stream.writeUint16(packet.number);
stream.writeBoolean(packet.create);
if (!packet.create) {
const bits = Math_1.logBase2(packet.number) + 1;
for (const entry of packet.entries) {
stream.writeBits(entry.classId, bits);
stream.writeASCIIString(entry.className);
stream.writeASCIIString(entry.dataTableName);
}
}
}
exports.EncodeClassInfo = EncodeClassInfo;
//# sourceMappingURL=ClassInfo.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"ClassInfo.js","sourceRoot":"","sources":["../../../src/Parser/Packet/ClassInfo.ts"],"names":[],"mappings":";;AAEA,qCAAoC;AAEpC,SAAgB,cAAc,CAAC,MAAiB;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,OAAO,GAIR,EAAE,CAAC;IACR,IAAI,CAAC,MAAM,EAAE;QACZ,MAAM,IAAI,GAAG,eAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG;gBACb,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAC9B,SAAS,EAAE,MAAM,CAAC,eAAe,EAAE;gBACnC,aAAa,EAAE,MAAM,CAAC,eAAe,EAAE;aACvC,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACpB;KACD;IACD,OAAO;QACN,UAAU,EAAE,WAAW;QACvB,MAAM,EAAE,KAAK;QACb,MAAM;QACN,OAAO;KACP,CAAC;AACH,CAAC;AAzBD,wCAyBC;AAED,SAAgB,eAAe,CAAC,MAAuB,EAAE,MAAiB;IACzE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;QACnB,MAAM,IAAI,GAAG,eAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE;YACnC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;SAC7C;KACD;AACF,CAAC;AAXD,0CAWC"}

View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { CreateStringTablePacket } from '../../Data/Packet';
export declare function ParseCreateStringTable(stream: BitStream): CreateStringTablePacket;
export declare function EncodeCreateStringTable(packet: CreateStringTablePacket, stream: BitStream): void;

View file

@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bit_buffer_1 = require("bit-buffer");
const Math_1 = require("../../Math");
const readBitVar_1 = require("../readBitVar");
const snappyjs_1 = require("snappyjs");
const StringTableParser_1 = require("../StringTableParser");
function ParseCreateStringTable(stream) {
const tableName = stream.readASCIIString();
const maxEntries = stream.readUint16();
const encodeBits = Math_1.logBase2(maxEntries);
const entityCount = stream.readBits(encodeBits + 1);
const bitCount = readBitVar_1.readVarInt(stream);
let userDataSize = 0;
let userDataSizeBits = 0;
// userdata fixed size
if (stream.readBoolean()) {
userDataSize = stream.readBits(12);
userDataSizeBits = stream.readBits(4);
}
const isCompressed = stream.readBoolean();
let data = stream.readBitStream(bitCount);
if (isCompressed) {
const decompressedByteSize = data.readUint32();
const compressedByteSize = data.readUint32();
const magic = data.readASCIIString(4);
const compressedData = data.readArrayBuffer(compressedByteSize - 4); // 4 magic bytes
if (magic !== 'SNAP') {
throw new Error('Unknown compressed stringtable format');
}
const decompressedData = snappyjs_1.uncompress(compressedData);
if (decompressedData.byteLength !== decompressedByteSize) {
throw new Error('Incorrect length of decompressed stringtable');
}
data = new bit_buffer_1.BitStream(decompressedData.buffer);
}
const table = {
name: tableName,
entries: [],
maxEntries,
fixedUserDataSize: userDataSize,
fixedUserDataSizeBits: userDataSizeBits,
compressed: isCompressed
};
// console.log(`${tableName} ${entityCount} ${bitCount}`);
table.entries = StringTableParser_1.parseStringTableEntries(data, table, entityCount);
return {
packetType: 'createStringTable',
table
};
}
exports.ParseCreateStringTable = ParseCreateStringTable;
function EncodeCreateStringTable(packet, stream) {
stream.writeASCIIString(packet.table.name);
stream.writeUint16(packet.table.maxEntries);
const encodeBits = Math_1.logBase2(packet.table.maxEntries);
const numEntries = packet.table.entries.filter((entry) => entry).length;
stream.writeBits(numEntries, encodeBits + 1);
let entryData = new bit_buffer_1.BitStream(new ArrayBuffer(StringTableParser_1.guessStringTableEntryLength(packet.table, packet.table.entries)));
StringTableParser_1.encodeStringTableEntries(entryData, packet.table, packet.table.entries);
if (packet.table.compressed) {
const decompressedByteLength = Math.ceil(entryData.length / 8);
entryData.index = 0;
const compressedData = snappyjs_1.compress(entryData.readArrayBuffer(decompressedByteLength));
entryData = new bit_buffer_1.BitStream(new ArrayBuffer(decompressedByteLength));
entryData.writeUint32(decompressedByteLength);
entryData.writeUint32(compressedData.byteLength + 4); // 4 magic bytes
entryData.writeASCIIString('SNAP', 4);
const typeForce = compressedData.buffer;
entryData.writeArrayBuffer(typeForce);
}
const entryLength = entryData.index;
entryData.index = 0;
readBitVar_1.writeVarInt(entryLength, stream);
if (packet.table.fixedUserDataSize || packet.table.fixedUserDataSizeBits) {
stream.writeBoolean(true);
stream.writeBits(packet.table.fixedUserDataSize || 0, 12);
stream.writeBits(packet.table.fixedUserDataSizeBits || 0, 4);
}
else {
stream.writeBoolean(false);
}
stream.writeBoolean(packet.table.compressed);
if (entryLength) {
stream.writeBitStream(entryData, entryLength);
}
}
exports.EncodeCreateStringTable = EncodeCreateStringTable;
//# sourceMappingURL=CreateStringTable.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"CreateStringTable.js","sourceRoot":"","sources":["../../../src/Parser/Packet/CreateStringTable.ts"],"names":[],"mappings":"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"}

5
build/Parser/Packet/GameEvent.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { GameEventPacket } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare function ParseGameEvent(stream: BitStream, state: ParserState): GameEventPacket;
export declare function EncodeGameEvent(packet: GameEventPacket, stream: BitStream, state: ParserState): void;

View file

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const GameEvent_1 = require("../../Data/GameEvent");
function parseGameEvent(definition, stream) {
const values = {};
for (const entry of definition.entries) {
const value = getGameEventValue(stream, entry);
if (value !== null) {
values[entry.name] = value;
}
}
const name = definition.name;
return {
name,
values
};
}
function encodeGameEvent(event, definition, stream) {
for (const entry of definition.entries) {
const value = event.values[entry.name];
if (typeof value === 'undefined') {
throw new Error('empty event value');
}
else {
encodeGameEventValue(value, stream, entry);
}
}
}
function getGameEventValue(stream, entry) {
switch (entry.type) {
case GameEvent_1.GameEventValueType.STRING:
return stream.readUTF8String();
case GameEvent_1.GameEventValueType.FLOAT:
return stream.readFloat32();
case GameEvent_1.GameEventValueType.LONG:
return stream.readUint32();
case GameEvent_1.GameEventValueType.SHORT:
return stream.readUint16();
case GameEvent_1.GameEventValueType.BYTE:
return stream.readUint8();
case GameEvent_1.GameEventValueType.BOOLEAN:
return stream.readBoolean();
case GameEvent_1.GameEventValueType.LOCAL:
return null;
}
}
function encodeGameEventValue(value, stream, entry) {
switch (entry.type) {
case GameEvent_1.GameEventValueType.STRING:
if (typeof value !== 'string') {
throw new Error(`Invalid value for game event, expected string got ${typeof value}`);
}
return stream.writeASCIIString(value);
case GameEvent_1.GameEventValueType.FLOAT:
if (typeof value !== 'number') {
throw new Error(`Invalid value for game event, expected number got ${typeof value}`);
}
return stream.writeFloat32(value);
case GameEvent_1.GameEventValueType.LONG:
if (typeof value !== 'number') {
throw new Error(`Invalid value for game event, expected number got ${typeof value}`);
}
return stream.writeUint32(value);
case GameEvent_1.GameEventValueType.SHORT:
if (typeof value !== 'number') {
throw new Error(`Invalid value for game event, expected number got ${typeof value}`);
}
return stream.writeUint16(value);
case GameEvent_1.GameEventValueType.BYTE:
if (typeof value !== 'number') {
throw new Error(`Invalid value for game event, expected number got ${typeof value}`);
}
return stream.writeUint8(value);
case GameEvent_1.GameEventValueType.BOOLEAN:
if (typeof value !== 'boolean') {
throw new Error(`Invalid value for game event, expected boolean got ${typeof value}`);
}
return stream.writeBoolean(value);
}
}
function ParseGameEvent(stream, state) {
const length = stream.readBits(11);
const eventData = stream.readBitStream(length);
const eventType = eventData.readBits(9);
const definition = state.eventDefinitions.get(eventType);
if (!definition) {
throw new Error(`Unknown game event type ${eventType}`);
}
const event = parseGameEvent(definition, eventData);
return {
packetType: 'gameEvent',
event: event
};
}
exports.ParseGameEvent = ParseGameEvent;
function EncodeGameEvent(packet, stream, state) {
const lengthStart = stream.index;
stream.index += 11;
const eventId = state.eventDefinitionTypes.get(packet.event.name);
if (typeof eventId === 'undefined') {
throw new Error(`Unknown game event type ${packet.event.name}`);
}
const eventDataStart = stream.index;
stream.writeBits(eventId, 9);
const definition = state.eventDefinitions.get(eventId);
if (typeof definition === 'undefined') {
throw new Error(`Unknown game event type ${packet.event.name}`);
}
encodeGameEvent(packet.event, definition, stream);
const eventDataEnd = stream.index;
stream.index = lengthStart;
stream.writeBits(eventDataEnd - eventDataStart, 11);
stream.index = eventDataEnd;
}
exports.EncodeGameEvent = EncodeGameEvent;
//# sourceMappingURL=GameEvent.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"GameEvent.js","sourceRoot":"","sources":["../../../src/Parser/Packet/GameEvent.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { GameEventListPacket } from '../../Data/Packet';
export declare function ParseGameEventList(stream: BitStream): GameEventListPacket;
export declare function EncodeGameEventList(packet: GameEventListPacket, stream: BitStream): void;

View file

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseGameEventList(stream) {
// list of game events and parameters
const numEvents = stream.readBits(9);
const length = stream.readBits(20);
const listData = stream.readBitStream(length);
const eventList = new Map();
for (let i = 0; i < numEvents; i++) {
const id = listData.readBits(9);
const name = listData.readASCIIString();
let type = listData.readBits(3);
const entries = [];
while (type !== 0) {
entries.push({
type,
name: listData.readASCIIString()
});
type = listData.readBits(3);
}
eventList.set(id, {
id,
name,
entries
});
}
return {
packetType: 'gameEventList',
eventList
};
}
exports.ParseGameEventList = ParseGameEventList;
function EncodeGameEventList(packet, stream) {
const definitions = Array.from(packet.eventList.values());
stream.writeBits(definitions.length, 9);
const lengthStart = stream.index;
stream.index += 20;
const eventListStart = stream.index;
for (const definition of definitions) {
stream.writeBits(definition.id, 9);
stream.writeASCIIString(definition.name);
for (const entry of definition.entries) {
stream.writeBits(entry.type, 3);
stream.writeASCIIString(entry.name);
}
stream.writeBits(0, 3);
}
const eventListEnd = stream.index;
stream.index = lengthStart;
stream.writeBits(eventListEnd - eventListStart, 20);
stream.index = eventListEnd;
}
exports.EncodeGameEventList = EncodeGameEventList;
//# sourceMappingURL=GameEventList.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"GameEventList.js","sourceRoot":"","sources":["../../../src/Parser/Packet/GameEventList.ts"],"names":[],"mappings":";;AAKA,SAAgB,kBAAkB,CAAC,MAAiB;IACnD,qCAAqC;IACrC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAErC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAoD,IAAI,GAAG,EAAE,CAAC;IAC7E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,EAAuB,CAAC;QAC7D,IAAI,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,OAAO,IAAI,KAAK,CAAC,EAAE;YAClB,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,IAAI,EAAE,QAAQ,CAAC,eAAe,EAAE;aAChC,CAAC,CAAC;YACH,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC5B;QACD,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE;YACjB,EAAE;YACF,IAAI;YACJ,OAAO;SACP,CAAC,CAAC;KACH;IAED,OAAO;QACN,UAAU,EAAE,eAAe;QAC3B,SAAS;KACT,CAAC;AACH,CAAC;AA9BD,gDA8BC;AAED,SAAgB,mBAAmB,CAAC,MAA2B,EAAE,MAAiB;IACjF,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAExC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IACjC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IAEnB,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC;IAEpC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;QACrC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,OAAO,EAAE;YACvC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACpC;QACD,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACvB;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;IAElC,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;IAC3B,MAAM,CAAC,SAAS,CAAC,YAAY,GAAG,cAAc,EAAE,EAAE,CAAC,CAAC;IAEpD,MAAM,CAAC,KAAK,GAAG,YAAY,CAAC;AAC7B,CAAC;AAzBD,kDAyBC"}

View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { PacketEntitiesPacket } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare function ParsePacketEntities(stream: BitStream, state: ParserState, skip?: boolean): PacketEntitiesPacket;
export declare function EncodePacketEntities(packet: PacketEntitiesPacket, stream: BitStream, state: ParserState): void;

View file

@ -0,0 +1,214 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const PacketEntity_1 = require("../../Data/PacketEntity");
const ParserState_1 = require("../../Data/ParserState");
const EntityDecoder_1 = require("../EntityDecoder");
const readBitVar_1 = require("../readBitVar");
const pvsMap = new Map([
[0, PacketEntity_1.PVS.PRESERVE],
[2, PacketEntity_1.PVS.ENTER],
[1, PacketEntity_1.PVS.LEAVE],
[3, PacketEntity_1.PVS.LEAVE + PacketEntity_1.PVS.DELETE]
]);
const pvsReverseMap = new Map([
[PacketEntity_1.PVS.PRESERVE, 0],
[PacketEntity_1.PVS.ENTER, 2],
[PacketEntity_1.PVS.LEAVE, 1],
[PacketEntity_1.PVS.LEAVE + PacketEntity_1.PVS.DELETE, 3]
]);
function readPVSType(stream) {
const pvs = stream.readBits(2);
return pvsMap.get(pvs);
}
function writePVSType(pvs, stream) {
const raw = pvsReverseMap.get(pvs);
if (typeof raw === 'undefined') {
throw new Error(`Unknown pvs ${pvs}`);
}
stream.writeBits(raw, 2);
}
function readEnterPVS(stream, entityId, state, baseLineIndex) {
// https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs#L198
const classBits = ParserState_1.getClassBits(state);
const serverClass = state.serverClasses[stream.readBits(classBits)];
const serial = stream.readBits(10); // unused serial number
const sendTable = ParserState_1.getSendTable(state, serverClass.dataTable);
const instanceBaseline = state.instanceBaselines[baseLineIndex].get(entityId);
const entity = new PacketEntity_1.PacketEntity(serverClass, entityId, PacketEntity_1.PVS.ENTER);
entity.serialNumber = serial;
if (instanceBaseline) {
entity.props = instanceBaseline.map((prop) => prop.clone());
return entity;
}
else {
const staticBaseLine = state.staticBaseLines.get(serverClass.id);
if (staticBaseLine) {
let parsedBaseLine = state.staticBaselineCache.get(serverClass.id);
if (!parsedBaseLine) {
staticBaseLine.index = 0;
parsedBaseLine = EntityDecoder_1.getEntityUpdate(sendTable, staticBaseLine);
state.staticBaselineCache.set(serverClass.id, parsedBaseLine);
}
entity.props = parsedBaseLine.map((prop) => prop.clone());
// entity.applyPropUpdate(parsedBaseLine);
// if (staticBaseLine.bitsLeft > 7) {
// console.log(staticBaseLine.length, staticBaseLine.index);
// throw new Error('Unexpected data left at the end of staticBaseline, ' + staticBaseLine.bitsLeft + ' bits left');
// }
}
return entity;
}
}
function writeEnterPVS(entity, stream, state, baseLineIndex) {
const serverClassId = state.serverClasses.findIndex((existingServerClass) => existingServerClass && entity.serverClass.id === existingServerClass.id);
if (serverClassId === -1) {
throw new Error(`Unknown server class ${entity.serverClass.name}(${entity.serverClass.id})`);
}
// get the instance from the match, not the entity
const serverClass = state.serverClasses[serverClassId];
stream.writeBits(serverClassId, ParserState_1.getClassBits(state));
stream.writeBits(entity.serialNumber || 0, 10);
const sendTable = ParserState_1.getSendTable(state, serverClass.dataTable);
let instanceBaseLine = state.instanceBaselines[baseLineIndex].get(entity.entityIndex);
if (!instanceBaseLine) {
const staticBaseLine = state.staticBaseLines.get(serverClass.id);
if (staticBaseLine) {
instanceBaseLine = state.staticBaselineCache.get(serverClass.id);
if (!instanceBaseLine) {
staticBaseLine.index = 0;
instanceBaseLine = EntityDecoder_1.getEntityUpdate(sendTable, staticBaseLine);
state.staticBaselineCache.set(serverClass.id, instanceBaseLine);
}
}
}
const propsToEncode = instanceBaseLine ? entity.diffFromBaseLine(instanceBaseLine) : entity.props;
EntityDecoder_1.encodeEntityUpdate(propsToEncode, sendTable, stream);
}
function getPacketEntityForExisting(entityId, state, pvs) {
const serverClass = state.entityClasses.get(entityId);
if (!serverClass) {
throw new Error(`"unknown entity ${entityId} for ${PacketEntity_1.PVS[pvs]}(${pvs})`);
}
return new PacketEntity_1.PacketEntity(serverClass, entityId, pvs);
}
function ParsePacketEntities(stream, state, skip = false) {
// https://github.com/skadistats/smoke/blob/master/smoke/replay/handler/svc_packetentities.pyx
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Handler/PacketEntitesHandler.cs
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Entity.cs
// https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs
const maxEntries = stream.readBits(11);
const isDelta = stream.readBoolean();
const delta = (isDelta) ? stream.readInt32() : 0;
const baseLine = stream.readBits(1);
const updatedEntries = stream.readBits(11);
const length = stream.readBits(20);
const updatedBaseLine = stream.readBoolean();
const start = stream.index;
const end = stream.index + length;
let entityId = -1;
const receivedEntities = [];
const removedEntityIds = [];
if (!skip) {
if (updatedBaseLine) {
state.instanceBaselines[1 - baseLine] = new Map(state.instanceBaselines[baseLine]);
// state.instanceBaselines[baseLine] = new Map();
}
for (let i = 0; i < updatedEntries; i++) {
const diff = readBitVar_1.readUBitVar(stream);
entityId += 1 + diff;
const pvs = readPVSType(stream);
if (pvs === PacketEntity_1.PVS.ENTER) {
const packetEntity = readEnterPVS(stream, entityId, state, baseLine);
const sendTable = ParserState_1.getSendTable(state, packetEntity.serverClass.dataTable);
const updatedProps = EntityDecoder_1.getEntityUpdate(sendTable, stream);
packetEntity.applyPropUpdate(updatedProps);
if (updatedBaseLine) {
state.instanceBaselines[1 - baseLine].set(entityId, packetEntity.clone().props);
}
packetEntity.inPVS = true;
receivedEntities.push(packetEntity);
}
else if (pvs === PacketEntity_1.PVS.PRESERVE) {
const packetEntity = getPacketEntityForExisting(entityId, state, pvs);
const sendTable = state.sendTables.get(packetEntity.serverClass.dataTable);
if (!sendTable) {
throw new Error(`Unknown sendTable ${packetEntity.serverClass.dataTable}`);
}
const updatedProps = EntityDecoder_1.getEntityUpdate(sendTable, stream);
packetEntity.applyPropUpdate(updatedProps);
receivedEntities.push(packetEntity);
}
else if (state.entityClasses.has(entityId)) {
const packetEntity = getPacketEntityForExisting(entityId, state, pvs);
receivedEntities.push(packetEntity);
}
else {
// throw new Error(`No existing entity to update with id ${entityId}`);
}
}
if (isDelta) {
while (stream.readBoolean()) {
removedEntityIds.push(stream.readBits(11));
}
}
}
stream.index = end;
return {
packetType: 'packetEntities',
entities: receivedEntities,
removedEntities: removedEntityIds,
maxEntries,
delta,
baseLine,
updatedBaseLine
};
}
exports.ParsePacketEntities = ParsePacketEntities;
function EncodePacketEntities(packet, stream, state) {
stream.writeBits(packet.maxEntries, 11);
const isDelta = packet.delta > 0;
stream.writeBoolean(isDelta);
if (isDelta) {
stream.writeInt32(packet.delta);
}
stream.writeBits(packet.baseLine, 1);
stream.writeBits(packet.entities.length, 11);
const lengthStart = stream.index;
stream.index += 20;
stream.writeBoolean(packet.updatedBaseLine);
const packetDataStart = stream.index;
let lastEntityId = -1;
if (packet.updatedBaseLine) {
state.instanceBaselines[1 - packet.baseLine] = new Map(state.instanceBaselines[packet.baseLine]);
// state.instanceBaselines[baseLine] = new Map();
}
for (const entity of packet.entities) {
const diff = entity.entityIndex - lastEntityId;
lastEntityId = entity.entityIndex;
readBitVar_1.writeBitVar(diff - 1, stream);
writePVSType(entity.pvs, stream);
if (entity.pvs === PacketEntity_1.PVS.ENTER) {
if (packet.updatedBaseLine) {
state.instanceBaselines[1 - packet.baseLine].set(entity.entityIndex, entity.clone().props);
}
writeEnterPVS(entity, stream, state, packet.baseLine);
}
else if (entity.pvs === PacketEntity_1.PVS.PRESERVE) {
const sendTable = ParserState_1.getSendTable(state, entity.serverClass.dataTable);
EntityDecoder_1.encodeEntityUpdate(entity.props, sendTable, stream);
}
}
if (isDelta) {
for (const removedEntity of packet.removedEntities) {
stream.writeBoolean(true);
stream.writeBits(removedEntity, 11);
}
stream.writeBoolean(false);
}
const packetDataEnd = stream.index;
stream.index = lengthStart;
stream.writeBits(packetDataEnd - packetDataStart, 20);
stream.index = packetDataEnd;
}
exports.EncodePacketEntities = EncodePacketEntities;
//# sourceMappingURL=PacketEntities.js.map

File diff suppressed because one or more lines are too long

4
build/Parser/Packet/ParseSounds.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { ParseSoundsPacket } from '../../Data/Packet';
export declare function ParseParseSounds(stream: BitStream): ParseSoundsPacket;
export declare function EncodeParseSounds(packet: ParseSoundsPacket, stream: BitStream): void;

View file

@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseParseSounds(stream) {
const reliable = stream.readBoolean();
const num = (reliable) ? 1 : stream.readUint8();
const length = (reliable) ? stream.readUint8() : stream.readUint16();
const data = stream.readBitStream(length);
return {
packetType: 'parseSounds',
reliable,
num,
length,
data
};
}
exports.ParseParseSounds = ParseParseSounds;
function EncodeParseSounds(packet, stream) {
stream.writeBoolean(packet.reliable);
if (packet.reliable) {
stream.writeUint8(packet.length);
}
else {
stream.writeUint8(packet.num);
stream.writeUint16(packet.length);
}
packet.data.index = 0;
stream.writeBitStream(packet.data, packet.length);
packet.data.index = 0;
}
exports.EncodeParseSounds = EncodeParseSounds;
//# sourceMappingURL=ParseSounds.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"ParseSounds.js","sourceRoot":"","sources":["../../../src/Parser/Packet/ParseSounds.ts"],"names":[],"mappings":";;AAGA,SAAgB,gBAAgB,CAAC,MAAiB;IACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;QACN,UAAU,EAAE,aAAa;QACzB,QAAQ;QACR,GAAG;QACH,MAAM;QACN,IAAI;KACJ,CAAC;AACH,CAAC;AAbD,4CAaC;AAED,SAAgB,iBAAiB,CAAC,MAAyB,EAAE,MAAiB;IAC7E,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,MAAM,CAAC,QAAQ,EAAE;QACpB,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACjC;SAAM;QACN,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KAClC;IAED,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACtB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACvB,CAAC;AAZD,8CAYC"}

10
build/Parser/Packet/Parser.d.ts vendored Normal file
View file

@ -0,0 +1,10 @@
import { BitStream } from 'bit-buffer';
import { Packet, VoidPacket } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare type Parser<P extends Packet> = (stream: BitStream, state?: ParserState, skip?: boolean) => P;
export declare type Encoder<P extends Packet> = (packet: P, stream: BitStream, state?: ParserState) => void;
export interface PacketHandler<P extends Packet> {
parser: Parser<P>;
encoder: Encoder<P>;
}
export declare const voidEncoder: Encoder<VoidPacket>;

View file

@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.voidEncoder = () => {
return {
type: 'void'
};
};
//# sourceMappingURL=Parser.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"Parser.js","sourceRoot":"","sources":["../../../src/Parser/Packet/Parser.ts"],"names":[],"mappings":";;AAYa,QAAA,WAAW,GAAwB,GAAG,EAAE;IACpD,OAAO;QACN,IAAI,EAAE,MAAM;KACZ,CAAC;AACH,CAAC,CAAC"}

View file

@ -0,0 +1,7 @@
import { Packet, PacketMapType, PacketType } from '../../Data/Packet';
import { UserMessagePacketType } from '../../Data/UserMessage';
import { PacketHandler } from './Parser';
export interface NamedPacketHandler<P extends Packet, N extends PacketType | UserMessagePacketType> extends PacketHandler<P> {
name: N;
}
export declare function make<T extends PacketType | UserMessagePacketType>(name: T, definition: string, nameKey?: string, extraData?: any): NamedPacketHandler<PacketMapType[T], T>;

View file

@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function make(name, definition, nameKey = 'packetType', extraData = {}) {
const parts = definition.split('}');
const items = parts.map((part) => {
return part.split('{');
}).filter((part) => part[0]);
const parser = (stream) => {
const result = Object.assign({}, extraData);
result[nameKey] = name;
try {
for (const group of items) {
const value = readItem(stream, group[1], result);
if (group[0] !== '_') {
result[group[0]] = value;
}
}
}
catch (e) {
throw new Error('Failed reading pattern ' + definition + '. ' + e);
}
return result;
};
const encoder = (packet, stream) => {
for (const group of items) {
writeItem(stream, group[1], packet, packet[group[0]]);
}
};
return { parser, encoder, name };
}
exports.make = make;
function readItem(stream, description, data) {
if (description[0] === 'b') {
return stream.readBoolean();
}
else if (description[0] === 's') {
if (description.length === 1) {
return stream.readUTF8String();
}
else {
const length = parseInt(description.substr(1), 10);
return stream.readASCIIString(length);
}
}
else if (description === 'f32') {
return stream.readFloat32();
}
else if (description[0] === 'u') {
const length = parseInt(description.substr(1), 10);
return stream.readBits(length);
}
else if (description[0] === '$' && description.substr(description.length - 2) === '*8') {
const variable = description.substr(1, description.length - 3);
return stream.readBitStream(data[variable] * 8);
}
else if (description[0] === '$') {
const variable = description.substr(1);
return stream.readBitStream(data[variable]);
}
else {
return stream.readBits(parseInt(description, 10), true);
}
}
function writeItem(stream, description, data, value) {
if (description[0] === 'b') {
return stream.writeBoolean(value);
}
else if (description[0] === 's') {
if (description.length === 1) {
return stream.writeUTF8String(value);
}
else {
const length = parseInt(description.substr(1), 10);
return stream.writeUTF8String(value, length);
}
}
else if (description === 'f32') {
return stream.writeFloat32(value);
}
else if (description[0] === 'u') {
const length = parseInt(description.substr(1), 10);
return stream.writeBits(value, length);
}
else if (description[0] === '$' && description.substr(description.length - 2) === '*8') {
const variable = description.substr(1, description.length - 3);
return stream.writeBitStream(value, data[variable] * 8);
}
else if (description[0] === '$') {
const variable = description.substr(1);
return stream.writeBitStream(value, data[variable]);
}
else {
return stream.writeBits(value, parseInt(description, 10));
}
}
//# sourceMappingURL=ParserGenerator.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"ParserGenerator.js","sourceRoot":"","sources":["../../../src/Parser/Packet/ParserGenerator.ts"],"names":[],"mappings":"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"}

4
build/Parser/Packet/SetConVar.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { SetConVarPacket } from '../../Data/Packet';
export declare function ParseSetConVar(stream: BitStream): SetConVarPacket;
export declare function EncodeSetConVar(packet: SetConVarPacket, stream: BitStream): void;

View file

@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseSetConVar(stream) {
const count = stream.readUint8();
const vars = new Map();
for (let i = 0; i < count; i++) {
const key = stream.readUTF8String();
const value = stream.readUTF8String();
vars.set(key, value);
}
return {
packetType: 'setConVar',
vars
};
}
exports.ParseSetConVar = ParseSetConVar;
function EncodeSetConVar(packet, stream) {
stream.writeUint8(packet.vars.size);
for (const [key, value] of packet.vars.entries()) {
stream.writeUTF8String(key);
stream.writeUTF8String(value);
}
}
exports.EncodeSetConVar = EncodeSetConVar;
//# sourceMappingURL=SetConVar.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"SetConVar.js","sourceRoot":"","sources":["../../../src/Parser/Packet/SetConVar.ts"],"names":[],"mappings":";;AAGA,SAAgB,cAAc,CAAC,MAAiB;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,MAAM,IAAI,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;KACrB;IACD,OAAO;QACN,UAAU,EAAE,WAAW;QACvB,IAAI;KACJ,CAAC;AACH,CAAC;AAZD,wCAYC;AAED,SAAgB,eAAe,CAAC,MAAuB,EAAE,MAAiB;IACzE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE;QACjD,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;KAC9B;AACF,CAAC;AAND,0CAMC"}

5
build/Parser/Packet/TempEntities.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { TempEntitiesPacket } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare function ParseTempEntities(stream: BitStream, state: ParserState, skip?: boolean): TempEntitiesPacket;
export declare function EncodeTempEntities(packet: TempEntitiesPacket, stream: BitStream, state: ParserState): void;

View file

@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const PacketEntity_1 = require("../../Data/PacketEntity");
const ParserState_1 = require("../../Data/ParserState");
const DynamicBitStream_1 = require("../../DynamicBitStream");
const EntityDecoder_1 = require("../EntityDecoder");
const readBitVar_1 = require("../readBitVar");
function ParseTempEntities(stream, state, skip = false) {
const entityCount = stream.readUint8();
const length = readBitVar_1.readVarInt(stream);
const entityData = stream.readBitStream(length);
let entity = null;
const entities = [];
if (!skip) {
for (let i = 0; i < entityCount; i++) {
const delay = (entityData.readBoolean()) ? entityData.readUint8() / 100 : 0; // unused it seems
if (entityData.readBoolean()) {
const classId = entityData.readBits(ParserState_1.getClassBits(state));
// no clue why the -1 but it works
const serverClass = state.serverClasses[classId - 1];
if (!serverClass) {
throw new Error(`Unknown serverClass ${classId}`);
}
const sendTable = ParserState_1.getSendTable(state, serverClass.dataTable);
entity = new PacketEntity_1.PacketEntity(serverClass, 0, PacketEntity_1.PVS.ENTER);
entity.delay = delay;
entity.props = EntityDecoder_1.getEntityUpdate(sendTable, entityData);
entities.push(entity);
}
else {
if (entity) {
const sendTable = ParserState_1.getSendTable(state, entity.serverClass.dataTable);
const updatedProps = EntityDecoder_1.getEntityUpdate(sendTable, entityData);
entity = entity.clone();
entity.applyPropUpdate(updatedProps);
entities.push(entity);
}
else {
throw new Error('no entity set to update');
}
}
}
if (entityData.bitsLeft > 8) {
throw new Error(`unexpected content after TempEntities ${entityData.bitsLeft} bits`);
}
}
return {
packetType: 'tempEntities',
entities
};
}
exports.ParseTempEntities = ParseTempEntities;
function EncodeTempEntities(packet, stream, state) {
stream.writeUint8(packet.entities.length);
const entityStream = new DynamicBitStream_1.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 = state.serverClasses.findIndex((serverClass) => serverClass && serverClass.name === entity.serverClass.name) + 1;
entityStream.writeBits(classId, ParserState_1.getClassBits(state));
const sendTable = ParserState_1.getSendTable(state, entity.serverClass.dataTable);
EntityDecoder_1.encodeEntityUpdate(entity.props, sendTable, entityStream);
}
const entityDataLength = entityStream.index;
entityStream.index = 0;
readBitVar_1.writeVarInt(entityDataLength, stream);
if (entityDataLength > 0) {
stream.writeBitStream(entityStream, entityDataLength);
}
}
exports.EncodeTempEntities = EncodeTempEntities;
//# sourceMappingURL=TempEntities.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"TempEntities.js","sourceRoot":"","sources":["../../../src/Parser/Packet/TempEntities.ts"],"names":[],"mappings":"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"}

View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { UpdateStringTablePacket } from '../../Data/Packet';
import { ParserState } from '../../Data/ParserState';
export declare function ParseUpdateStringTable(stream: BitStream, state: ParserState): UpdateStringTablePacket;
export declare function EncodeUpdateStringTable(packet: UpdateStringTablePacket, stream: BitStream, state: ParserState): void;

View file

@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const StringTableParser_1 = require("../StringTableParser");
function ParseUpdateStringTable(stream, state) {
const tableId = stream.readBits(5);
const multipleChanged = stream.readBoolean();
const changedEntries = multipleChanged ? stream.readUint16() : 1;
const bitCount = stream.readBits(20);
const data = stream.readBitStream(bitCount);
data.index = 0;
if (!state.stringTables[tableId]) {
throw new Error(`Table not found for update: ${tableId}`);
}
const table = state.stringTables[tableId];
const updatedEntries = StringTableParser_1.parseStringTableEntries(data, table, changedEntries, table.entries);
return {
packetType: 'updateStringTable',
entries: updatedEntries,
tableId
};
}
exports.ParseUpdateStringTable = ParseUpdateStringTable;
function EncodeUpdateStringTable(packet, stream, state) {
stream.writeBits(packet.tableId, 5);
const changedEntryCount = packet.entries.filter((entry) => entry).length;
const multipleChanged = changedEntryCount > 1;
stream.writeBoolean(multipleChanged);
if (multipleChanged) {
stream.writeUint16(changedEntryCount);
}
if (!state.stringTables[packet.tableId]) {
throw new Error(`Table not found for update: ${packet.tableId}`);
}
const lengthStart = stream.index;
stream.index += 20;
const lengthEnd = stream.index;
const table = state.stringTables[packet.tableId];
StringTableParser_1.encodeStringTableEntries(stream, table, packet.entries, table.entries);
const dataEnd = stream.index;
stream.index = lengthStart;
const entryLength = dataEnd - lengthEnd;
stream.writeBits(entryLength, 20);
stream.index = dataEnd;
}
exports.EncodeUpdateStringTable = EncodeUpdateStringTable;
//# sourceMappingURL=UpdateStringTable.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"UpdateStringTable.js","sourceRoot":"","sources":["../../../src/Parser/Packet/UpdateStringTable.ts"],"names":[],"mappings":";;AAGA,4DAAuF;AAEvF,SAAgB,sBAAsB,CAAC,MAAiB,EAAE,KAAkB;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEnC,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAEf,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,EAAE,CAAC,CAAC;KAC1D;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,2CAAuB,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3F,OAAO;QACN,UAAU,EAAE,mBAAmB;QAC/B,OAAO,EAAE,cAAc;QACvB,OAAO;KACP,CAAC;AACH,CAAC;AAtBD,wDAsBC;AAED,SAAgB,uBAAuB,CAAC,MAA+B,EAAE,MAAiB,EAAE,KAAkB;IAC7G,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAEpC,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACzE,MAAM,eAAe,GAAG,iBAAiB,GAAG,CAAC,CAAC;IAC9C,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAErC,IAAI,eAAe,EAAE;QACpB,MAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;KACtC;IAED,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACxC,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;KACjE;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;IACjC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IACnB,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;IAE/B,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,4CAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;IAC7B,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;IAC3B,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;AACxB,CAAC;AA3BD,0DA2BC"}

4
build/Parser/Packet/UserMessage.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { UserMessagePacket } from '../../Data/UserMessage';
export declare function ParseUserMessage(stream: BitStream): UserMessagePacket;
export declare function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream): void;

View file

@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const UserMessage_1 = require("../../Data/UserMessage");
const SayText2_1 = require("../UserMessage/SayText2");
const ParserGenerator_1 = require("./ParserGenerator");
function unknownPacketHandler(userMessageType) {
return {
parser: (data) => {
return {
packetType: 'userMessage',
userMessageType,
type: UserMessage_1.UserMessagePacketTypeMap.get(userMessageType),
data
};
},
encoder: (packet, data) => {
packet.data.index = 0;
data.writeBitStream(packet.data);
packet.data.index = 0;
},
name: userMessageType
};
}
const userMessageParsers = new Map([
[UserMessage_1.UserMessageType.SayText2, { parser: SayText2_1.ParseSayText2, encoder: SayText2_1.EncodeSayText2, name: 'sayText2' }],
[UserMessage_1.UserMessageType.TextMsg,
ParserGenerator_1.make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessage_1.UserMessageType.ResetHUD,
ParserGenerator_1.make('resetHUD', 'data{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessage_1.UserMessageType.Train,
ParserGenerator_1.make('train', 'data{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessage_1.UserMessageType.VoiceSubtitle,
ParserGenerator_1.make('voiceSubtitle', 'client{8}menu{8}item{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessage_1.UserMessageType.BreakModel_Pumpkin, unknownPacketHandler('breakModelPumpkin')],
[UserMessage_1.UserMessageType.Shake,
ParserGenerator_1.make('shake', 'command{8}amplitude{f32}frequency{f32}duration{f32}', 'userMessageType', {
packetType: 'userMessage'
})]
]);
function ParseUserMessage(stream) {
const type = stream.readUint8();
const length = stream.readBits(11);
const messageData = stream.readBitStream(length);
const handler = userMessageParsers.get(type);
if (!handler) {
return {
packetType: 'userMessage',
userMessageType: 'unknownUserMessage',
type,
data: messageData
};
}
else {
return handler.parser(messageData);
}
}
exports.ParseUserMessage = ParseUserMessage;
function EncodeUserMessage(packet, stream) {
if (packet.userMessageType === 'unknownUserMessage') {
stream.writeUint8(packet.type);
stream.writeBits(packet.data.length, 11);
packet.data.index = 0;
stream.writeBitStream(packet.data);
packet.data.index = 0;
}
else {
const messageType = UserMessage_1.UserMessagePacketTypeMap.get(packet.userMessageType);
if (!messageType) {
throw new Error(`Unknown userMessage type ${messageType}`);
}
stream.writeUint8(messageType);
const lengthStart = stream.index;
stream.index += 11;
const messageDataStart = stream.index;
const handler = userMessageParsers.get(messageType);
if (!handler) {
throw new Error(`No encoder for userMessage ${packet.userMessageType}(${messageType})`);
}
handler.encoder(packet, stream);
const messageDataEnd = stream.index;
stream.index = lengthStart;
stream.writeBits(messageDataEnd - messageDataStart, 11);
stream.index = messageDataEnd;
}
}
exports.EncodeUserMessage = EncodeUserMessage;
//# sourceMappingURL=UserMessage.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"UserMessage.js","sourceRoot":"","sources":["../../../src/Parser/Packet/UserMessage.ts"],"names":[],"mappings":"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"}

4
build/Parser/Packet/VoiceData.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { VoiceDataPacket } from '../../Data/Packet';
export declare function ParseVoiceData(stream: BitStream): VoiceDataPacket;
export declare function EncodeVoiceData(packet: VoiceDataPacket, stream: BitStream): void;

View file

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseVoiceData(stream) {
const client = stream.readUint8();
const proximity = stream.readUint8();
const length = stream.readUint16();
const data = stream.readBitStream(length);
return {
packetType: 'voiceData',
client,
proximity,
length,
data
};
}
exports.ParseVoiceData = ParseVoiceData;
function EncodeVoiceData(packet, stream) {
stream.writeUint8(packet.client);
stream.writeUint8(packet.proximity);
stream.writeUint16(packet.length);
packet.data.index = 0;
stream.writeBitStream(packet.data, packet.length);
packet.data.index = 0;
}
exports.EncodeVoiceData = EncodeVoiceData;
//# sourceMappingURL=VoiceData.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"VoiceData.js","sourceRoot":"","sources":["../../../src/Parser/Packet/VoiceData.ts"],"names":[],"mappings":";;AAGA,SAAgB,cAAc,CAAC,MAAiB;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;QACN,UAAU,EAAE,WAAW;QACvB,MAAM;QACN,SAAS;QACT,MAAM;QACN,IAAI;KACJ,CAAC;AACH,CAAC;AAbD,wCAaC;AAED,SAAgB,eAAe,CAAC,MAAuB,EAAE,MAAiB;IACzE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACtB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACvB,CAAC;AAPD,0CAOC"}

4
build/Parser/Packet/VoiceInit.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { VoiceInitPacket } from '../../Data/Packet';
export declare function ParseVoiceInit(stream: BitStream): VoiceInitPacket;
export declare function EncodeVoiceInit(packet: VoiceInitPacket, stream: BitStream): void;

View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseVoiceInit(stream) {
const codec = stream.readASCIIString();
const quality = stream.readUint8();
// no clue, from 2017-2-14 update
const extraData = readExtraData(stream, codec, quality);
return {
packetType: 'voiceInit',
codec,
quality,
extraData
};
}
exports.ParseVoiceInit = ParseVoiceInit;
function readExtraData(stream, codec, quality) {
if (quality === 255) {
return stream.readUint16();
}
else if (codec === 'vaudio_celt') {
return 11025;
}
else {
return 0;
}
}
function EncodeVoiceInit(packet, stream) {
stream.writeASCIIString(packet.codec);
stream.writeUint8(packet.quality);
if (packet.quality === 255) {
stream.writeUint16(packet.extraData);
}
}
exports.EncodeVoiceInit = EncodeVoiceInit;
//# sourceMappingURL=VoiceInit.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"VoiceInit.js","sourceRoot":"","sources":["../../../src/Parser/Packet/VoiceInit.ts"],"names":[],"mappings":";;AAGA,SAAgB,cAAc,CAAC,MAAiB;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAEnC,iCAAiC;IACjC,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAExD,OAAO;QACN,UAAU,EAAE,WAAW;QACvB,KAAK;QACL,OAAO;QACP,SAAS;KACT,CAAC;AACH,CAAC;AAbD,wCAaC;AAED,SAAS,aAAa,CAAC,MAAiB,EAAE,KAAa,EAAE,OAAe;IACvE,IAAI,OAAO,KAAK,GAAG,EAAE;QACpB,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;KAC3B;SAAM,IAAI,KAAK,KAAK,aAAa,EAAE;QACnC,OAAO,KAAK,CAAC;KACb;SAAM;QACN,OAAO,CAAC,CAAC;KACT;AACF,CAAC;AAED,SAAgB,eAAe,CAAC,MAAuB,EAAE,MAAiB;IACzE,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM,CAAC,OAAO,KAAK,GAAG,EAAE;QAC3B,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KACrC;AACF,CAAC;AAND,0CAMC"}

16
build/Parser/SendPropEncoder.d.ts vendored Normal file
View file

@ -0,0 +1,16 @@
import { BitStream } from 'bit-buffer';
import { SendPropArrayValue, SendPropValue } from '../Data/SendProp';
import { SendPropDefinition } from '../Data/SendPropDefinition';
import { Vector } from '../Data/Vector';
export declare class SendPropEncoder {
static encode(value: SendPropValue, propDefinition: SendPropDefinition, stream: BitStream): any;
static writeInt(value: number, propDefinition: SendPropDefinition, stream: BitStream): any;
static writeArray(value: SendPropArrayValue[], propDefinition: SendPropDefinition, stream: BitStream): void;
static writeString(value: string, stream: BitStream): void;
static writeVector(value: Vector, propDefinition: SendPropDefinition, stream: BitStream): void;
static writeVectorXY(value: Vector, propDefinition: SendPropDefinition, stream: BitStream): void;
static writeFloat(value: number, propDefinition: SendPropDefinition, stream: BitStream): any;
static writeBitNormal(value: number, stream: BitStream): void;
static writeBitCoord(value: number, stream: BitStream): void;
static writeBitCoordMP(value: number, stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): void;
}

View file

@ -0,0 +1,165 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const SendPropDefinition_1 = require("../Data/SendPropDefinition");
const Vector_1 = require("../Data/Vector");
const Math_1 = require("../Math");
const readBitVar_1 = require("./readBitVar");
const SendPropParser_1 = require("./SendPropParser");
class SendPropEncoder {
static encode(value, propDefinition, stream) {
switch (propDefinition.type) {
case SendPropDefinition_1.SendPropType.DPT_Int:
if (typeof value !== 'number') {
throw new Error(`Invalid value for DPT_Int ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeInt(value, propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_Vector:
if (!(value instanceof Vector_1.Vector)) {
throw new Error(`Invalid value for DPT_Vector ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeVector(value, propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_VectorXY:
if (!(value instanceof Vector_1.Vector)) {
throw new Error(`Invalid value for DPT_VectorXY ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeVectorXY(value, propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_Float:
if (typeof value !== 'number') {
throw new Error(`Invalid value for DPT_Float ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeFloat(value, propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_String:
if (typeof value !== 'string') {
throw new Error(`Invalid value for DPT_String ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeString(value, stream);
case SendPropDefinition_1.SendPropType.DPT_Array:
if (!Array.isArray(value)) {
throw new Error(`Invalid value for DPT_Array ${JSON.stringify(value)}`);
}
return SendPropEncoder.writeArray(value, propDefinition, stream);
}
throw new Error('Unknown property type');
}
static writeInt(value, propDefinition, stream) {
if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_VARINT)) {
return readBitVar_1.writeVarInt(value, stream, !propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_UNSIGNED));
}
else {
if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_UNSIGNED)) {
return stream.writeBits(value, propDefinition.bitCount);
}
else {
return stream.writeBits(readBitVar_1.makeUnsigned(value), propDefinition.bitCount);
}
}
}
static writeArray(value, propDefinition, stream) {
const numBits = Math_1.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);
}
}
static writeString(value, stream) {
stream.writeBits(value.length, 9);
if (value) {
// specify the length to exclude the null terminator
stream.writeASCIIString(value, value.length);
}
}
static writeVector(value, propDefinition, stream) {
SendPropEncoder.writeFloat(value.x, propDefinition, stream);
SendPropEncoder.writeFloat(value.y, propDefinition, stream);
SendPropEncoder.writeFloat(value.z, propDefinition, stream);
}
static writeVectorXY(value, propDefinition, stream) {
SendPropEncoder.writeFloat(value.x, propDefinition, stream);
SendPropEncoder.writeFloat(value.y, propDefinition, stream);
}
static writeFloat(value, propDefinition, stream) {
if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD)) {
return SendPropEncoder.writeBitCoord(value, stream);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP)) {
return SendPropEncoder.writeBitCoordMP(value, stream, false, false);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP_LOWPRECISION)) {
return SendPropEncoder.writeBitCoordMP(value, stream, false, true);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP_INTEGRAL)) {
return SendPropEncoder.writeBitCoordMP(value, stream, true, false);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NOSCALE)) {
return stream.writeFloat32(value);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.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);
}
}
static writeBitNormal(value, stream) {
stream.writeBoolean(value < 0);
const abs = Math.abs(value);
const fractPart = abs % 1;
const fractVal = Math.round(fractPart / SendPropParser_1.bitNormalFactor);
stream.writeBits(fractVal, 11);
}
static writeBitCoord(value, stream) {
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);
}
}
}
static writeBitCoordMP(value, stream, isIntegral, isLowPrecision) {
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);
}
}
}
exports.SendPropEncoder = SendPropEncoder;
//# sourceMappingURL=SendPropEncoder.js.map

File diff suppressed because one or more lines are too long

17
build/Parser/SendPropParser.d.ts vendored Normal file
View file

@ -0,0 +1,17 @@
import { BitStream } from 'bit-buffer';
import { SendPropArrayValue, SendPropValue } from '../Data/SendProp';
import { SendPropDefinition } from '../Data/SendPropDefinition';
import { Vector } from '../Data/Vector';
export declare const bitNormalFactor: number;
export declare class SendPropParser {
static decode(propDefinition: SendPropDefinition, stream: BitStream): SendPropValue;
static readInt(propDefinition: SendPropDefinition, stream: BitStream): number;
static readArray(propDefinition: SendPropDefinition, stream: BitStream): SendPropArrayValue[];
static readString(stream: BitStream): string;
static readVector(propDefinition: SendPropDefinition, stream: BitStream): Vector;
static readVectorXY(propDefinition: SendPropDefinition, stream: BitStream): Vector;
static readFloat(propDefinition: SendPropDefinition, stream: BitStream): number;
static readBitNormal(stream: BitStream): number;
static readBitCoord(stream: BitStream): number;
static readBitCoordMP(stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): number;
}

View file

@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const SendPropDefinition_1 = require("../Data/SendPropDefinition");
const Vector_1 = require("../Data/Vector");
const Math_1 = require("../Math");
const readBitVar_1 = require("./readBitVar");
exports.bitNormalFactor = (1 / ((1 << 11) - 1));
class SendPropParser {
static decode(propDefinition, stream) {
switch (propDefinition.type) {
case SendPropDefinition_1.SendPropType.DPT_Int:
return SendPropParser.readInt(propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_Vector:
return SendPropParser.readVector(propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_VectorXY:
return SendPropParser.readVectorXY(propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_Float:
return SendPropParser.readFloat(propDefinition, stream);
case SendPropDefinition_1.SendPropType.DPT_String:
return SendPropParser.readString(stream);
case SendPropDefinition_1.SendPropType.DPT_Array:
return SendPropParser.readArray(propDefinition, stream);
}
throw new Error(`Unknown property type ${propDefinition.type}`);
}
static readInt(propDefinition, stream) {
if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_VARINT)) {
return readBitVar_1.readVarInt(stream, !propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_UNSIGNED));
}
else {
return stream.readBits(propDefinition.bitCount, !propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_UNSIGNED));
}
}
static readArray(propDefinition, stream) {
const numBits = Math_1.logBase2(propDefinition.numElements) + 1;
const count = stream.readBits(numBits);
const values = [];
if (!propDefinition.arrayProperty) {
throw new Error('Array of undefined type');
}
for (let i = 0; i < count; i++) {
const value = SendPropParser.decode(propDefinition.arrayProperty, stream);
if (value instanceof Array) {
throw new Error('Nested arrays not supported');
}
values.push(value);
}
return values;
}
static readString(stream) {
const length = stream.readBits(9);
return stream.readASCIIString(length);
}
static readVector(propDefinition, stream) {
const x = SendPropParser.readFloat(propDefinition, stream);
const y = SendPropParser.readFloat(propDefinition, stream);
const z = SendPropParser.readFloat(propDefinition, stream);
return new Vector_1.Vector(x, y, z);
}
static readVectorXY(propDefinition, stream) {
const x = SendPropParser.readFloat(propDefinition, stream);
const y = SendPropParser.readFloat(propDefinition, stream);
return new Vector_1.Vector(x, y, 0);
}
static readFloat(propDefinition, stream) {
if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD)) {
return SendPropParser.readBitCoord(stream);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP)) {
return SendPropParser.readBitCoordMP(stream, false, false);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP_LOWPRECISION)) {
return SendPropParser.readBitCoordMP(stream, false, true);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_COORD_MP_INTEGRAL)) {
return SendPropParser.readBitCoordMP(stream, true, false);
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NOSCALE)) {
return stream.readFloat32();
}
else if (propDefinition.hasFlag(SendPropDefinition_1.SendPropFlag.SPROP_NORMAL)) {
return SendPropParser.readBitNormal(stream);
}
else {
const raw = stream.readBits(propDefinition.bitCount);
const percentage = raw / ((1 << propDefinition.bitCount) - 1);
return propDefinition.lowValue + (propDefinition.highValue - propDefinition.lowValue) * percentage;
}
}
static readBitNormal(stream) {
const isNegative = stream.readBoolean();
const fractVal = stream.readBits(11);
const value = fractVal * exports.bitNormalFactor;
return (isNegative) ? -value : value;
}
static readBitCoord(stream) {
const hasIntVal = stream.readBoolean();
const hasFractVal = stream.readBoolean();
if (hasIntVal || hasFractVal) {
const isNegative = stream.readBoolean();
const intVal = (hasIntVal) ? stream.readBits(14) + 1 : 0;
const fractVal = (hasFractVal) ? stream.readBits(5) : 0;
const value = intVal + fractVal * (1 / 32);
return (isNegative) ? -value : value;
}
return 0;
}
static readBitCoordMP(stream, isIntegral, isLowPrecision) {
let value = 0;
let isNegative = false;
const inBounds = stream.readBoolean();
const hasIntVal = stream.readBoolean();
if (isIntegral) {
if (hasIntVal) {
isNegative = stream.readBoolean();
if (inBounds) {
value = stream.readBits(11) + 1;
}
else {
value = stream.readBits(14) + 1;
if (value < (1 << 11)) {
throw new Error('Something\'s fishy...');
}
}
}
}
else {
isNegative = stream.readBoolean();
if (hasIntVal) {
if (inBounds) {
value = stream.readBits(11) + 1;
}
else {
value = stream.readBits(14) + 1;
if (value < (1 << 11)) {
// console.log(propDefinition, value);
// throw new Error("Something's fishy...");
}
}
}
const fractalVal = stream.readBits(isLowPrecision ? 3 : 5);
value += fractalVal * (1 / (1 << (isLowPrecision ? 3 : 5)));
}
if (isNegative) {
value = -value;
}
return value;
}
}
exports.SendPropParser = SendPropParser;
//# sourceMappingURL=SendPropParser.js.map

File diff suppressed because one or more lines are too long

5
build/Parser/StringTableParser.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
import { BitStream } from 'bit-buffer';
import { StringTable, StringTableEntry } from '../Data/StringTable';
export declare function parseStringTableEntries(stream: BitStream, table: StringTable, entryCount: number, existingEntries?: StringTableEntry[]): StringTableEntry[];
export declare function guessStringTableEntryLength(table: StringTable, entries: StringTableEntry[]): number;
export declare function encodeStringTableEntries(stream: BitStream, table: StringTable, entries: StringTableEntry[], oldEntries?: StringTableEntry[]): void;

View file

@ -0,0 +1,164 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Math_1 = require("../Math");
function parseStringTableEntries(stream, table, entryCount, existingEntries = []) {
const entryBits = Math_1.logBase2(table.maxEntries);
const entries = [];
let lastEntry = -1;
const history = [];
for (let i = 0; i < entryCount; i++) {
const entryIndex = !stream.readBoolean() ? stream.readBits(entryBits) : lastEntry + 1;
lastEntry = entryIndex;
if (entryIndex < 0 || entryIndex > table.maxEntries) {
throw new Error('Invalid string index for string table');
}
let value;
if (stream.readBoolean()) {
const subStringCheck = stream.readBoolean();
if (subStringCheck) {
const index = stream.readBits(5);
const bytesToCopy = stream.readBits(5);
const restOfString = stream.readASCIIString();
if (!history[index].text) {
value = restOfString; // best guess, happens in some pov demos but only for unimportant tables it seems
}
else {
value = history[index].text.substr(0, bytesToCopy) + restOfString;
}
}
else {
value = stream.readASCIIString();
}
}
let userData;
if (stream.readBoolean()) {
if (table.fixedUserDataSize && table.fixedUserDataSizeBits) {
userData = stream.readBitStream(table.fixedUserDataSizeBits);
}
else {
const userDataBytes = stream.readBits(14);
userData = stream.readBitStream(userDataBytes * 8);
}
}
if (existingEntries[entryIndex]) {
const existingEntry = Object.assign({}, existingEntries[entryIndex]);
if (userData) {
existingEntry.extraData = userData;
}
if (typeof value !== 'undefined') {
existingEntry.text = value;
}
entries[entryIndex] = existingEntry;
history.push(existingEntry);
}
else {
entries[entryIndex] = {
text: value,
extraData: userData
};
history.push(entries[entryIndex]);
}
if (history.length > 32) {
history.shift();
}
}
return entries;
}
exports.parseStringTableEntries = parseStringTableEntries;
function guessStringTableEntryLength(table, entries) {
// a rough guess of how many bytes are needed to encode the table entries
const entryBits = Math.ceil(Math_1.logBase2(table.maxEntries) / 8);
return entries.reduce((length, entry) => {
return length +
entryBits +
1 + // new index bit
1 + // misc boolean
1 + // substring bit
(entry.text ? entry.text.length + 1 : 1) + // +1 for null termination
(entry.extraData ? Math.ceil(entry.extraData.length / 8) : 0);
}, 1);
}
exports.guessStringTableEntryLength = guessStringTableEntryLength;
function encodeStringTableEntries(stream, table, entries, oldEntries = []) {
const entryBits = Math_1.logBase2(table.maxEntries);
let lastIndex = -1;
const history = [];
for (let i = 0; i < entries.length; i++) {
if (entries[i]) {
const entry = entries[i];
if (i !== (lastIndex + 1)) {
stream.writeBoolean(false);
stream.writeBits(i, entryBits);
}
else {
stream.writeBoolean(true);
}
lastIndex = i;
if (typeof entry.text !== 'undefined' && !(oldEntries[i] && entry.text === oldEntries[i].text)) {
stream.writeBoolean(true);
const { index, count } = getBestPreviousString(history, entry.text);
if (index !== -1) {
stream.writeBoolean(true);
stream.writeBits(index, 5);
stream.writeBits(count, 5);
stream.writeASCIIString(entry.text.substr(count));
}
else {
stream.writeBoolean(false);
stream.writeASCIIString(entry.text);
}
}
else {
stream.writeBoolean(false);
}
if (entry.extraData) {
stream.writeBoolean(true);
entry.extraData.index = 0;
if (table.fixedUserDataSize && table.fixedUserDataSizeBits) {
stream.writeBitStream(entry.extraData, table.fixedUserDataSizeBits);
}
else {
const byteLength = Math.ceil(entry.extraData.length / 8);
stream.writeBits(byteLength, 14);
stream.writeBitStream(entry.extraData, byteLength * 8);
}
entry.extraData.index = 0;
}
else {
stream.writeBoolean(false);
}
history.push(entry);
if (history.length > 32) {
history.shift();
}
}
}
}
exports.encodeStringTableEntries = encodeStringTableEntries;
function getBestPreviousString(history, newString) {
let bestIndex = -1;
let bestCount = 0;
for (let i = 0; i < history.length; i++) {
const prev = history[i].text;
const similar = countSimilarCharacters(prev, newString);
if (similar >= 3 && similar > bestCount) {
bestCount = similar;
bestIndex = i;
}
}
return {
index: bestIndex,
count: bestCount
};
}
const maxSimLength = 1 << 5;
function countSimilarCharacters(a, b) {
const length = Math.min(a.length, b.length, maxSimLength);
for (let i = 0; i < length; i++) {
if (a[i] !== b[i]) {
return i;
}
}
return Math.min(length, maxSimLength - 1);
}
//# sourceMappingURL=StringTableParser.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,4 @@
import { BitStream } from 'bit-buffer';
import { SayText2Packet } from '../../Data/UserMessage';
export declare function ParseSayText2(stream: BitStream): SayText2Packet;
export declare function EncodeSayText2(packet: SayText2Packet, stream: BitStream): void;

View file

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ParseSayText2(stream) {
const client = stream.readUint8();
const raw = stream.readUint8();
const pos = stream.index;
let from;
let text;
let kind;
if (stream.readUint8() === 1) {
const first = stream.readUint8();
if (first === 7) {
const color = stream.readUTF8String(6);
}
else {
stream.index = pos + 8;
}
text = stream.readUTF8String();
if (text.substr(0, 6) === '*DEAD*') {
// grave talk is in the format '*DEAD* \u0003$from\u0001: $text'
const start = text.indexOf('\u0003');
const end = text.indexOf('\u0001');
from = text.substr(start + 1, end - start - 1);
text = text.substr(end + 5);
kind = 'TF_Chat_AllDead';
}
}
else {
stream.index = pos;
kind = stream.readUTF8String();
from = stream.readUTF8String();
text = stream.readUTF8String();
// maybe always 2 null bytes?
// stream.readASCIIString();
// stream.readASCIIString();
stream.readUint16();
}
// cleanup color codes
text = text.replace(/\u0001/g, '');
text = text.replace(/\u0003/g, '');
let stringPos = text.indexOf('\u0007');
while (stringPos !== -1) {
text = text.slice(0, stringPos) + text.slice(stringPos + 7);
stringPos = text.indexOf('\u0007');
}
return {
packetType: 'userMessage',
userMessageType: 'sayText2',
client,
raw,
kind,
from,
text
};
}
exports.ParseSayText2 = ParseSayText2;
function EncodeSayText2(packet, stream) {
stream.writeUint8(packet.client);
stream.writeUint8(packet.raw);
if (packet.kind === 'TF_Chat_AllDead') {
const rawText = `*DEAD* \u0003${packet.from}\u0001: ${packet.text}`;
stream.writeUTF8String(rawText);
}
else {
stream.writeUTF8String(packet.kind);
stream.writeUTF8String(packet.from);
stream.writeUTF8String(packet.text);
stream.writeUint16(0);
}
}
exports.EncodeSayText2 = EncodeSayText2;
//# sourceMappingURL=SayText2.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"SayText2.js","sourceRoot":"","sources":["../../../src/Parser/UserMessage/SayText2.ts"],"names":[],"mappings":"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"}

7
build/Parser/readBitVar.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
import { BitStream } from 'bit-buffer';
export declare function makeUnsigned(value: number, signed?: boolean): number;
export declare function readBitVar(stream: BitStream, signed?: boolean): number;
export declare function writeBitVar(value: number, stream: BitStream, signed?: boolean): void;
export declare const readUBitVar: typeof readBitVar;
export declare function readVarInt(stream: BitStream, signed?: boolean): number;
export declare function writeVarInt(value: number, stream: BitStream, signed?: boolean): void;

View file

@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Math_1 = require("../Math");
function makeUnsigned(value, signed) {
if (signed) {
const signBit = value < 0 ? 1 : 0;
return ((value ^ -signBit) << 1) + signBit;
}
else {
return value;
}
}
exports.makeUnsigned = makeUnsigned;
function readBitVar(stream, signed) {
const type = stream.readBits(2);
switch (type) {
case 0:
return stream.readBits(4, signed);
case 1:
return stream.readBits(8, signed);
case 2:
return stream.readBits(12, signed);
case 3:
return stream.readBits(32, signed);
}
throw new Error('Invalid var bit');
}
exports.readBitVar = readBitVar;
function writeBitVar(value, stream, signed) {
const bitsNeeded = (signed) ? Math_1.logBase2(Math.abs(value)) + 2 : Math_1.logBase2(value) + 1;
if (signed) {
const signBit = value < 0 ? 1 : 0;
value = value ^ (-signBit << (bitsNeeded - 1)) + (signBit << (bitsNeeded - 1));
}
if (bitsNeeded > 12) {
stream.writeBits(3, 2);
stream.writeBits(value, 32);
}
else if (bitsNeeded > 8) {
stream.writeBits(2, 2);
stream.writeBits(value, 12);
}
else if (bitsNeeded > 4) {
stream.writeBits(1, 2);
stream.writeBits(value, 8);
}
else {
stream.writeBits(0, 2);
stream.writeBits(value, 4);
}
}
exports.writeBitVar = writeBitVar;
exports.readUBitVar = readBitVar;
function readVarInt(stream, signed = false) {
let result = 0;
for (let i = 0; i < 35; i += 7) {
const byte = stream.readUint8();
result |= ((byte & 0x7F) << i);
if ((byte >> 7) === 0) {
break;
}
}
if (signed) {
return ((result >> 1) ^ -(result & 1));
}
else {
return result;
}
}
exports.readVarInt = readVarInt;
function writeVarInt(value, stream, signed = false) {
value = makeUnsigned(value, signed);
do {
const byte = value & 0x7F;
const resumeBit = (value >= 128) ? 0x80 : 0;
stream.writeUint8(byte | resumeBit);
value = value >> 7;
} while (value > 0);
}
exports.writeVarInt = writeVarInt;
//# sourceMappingURL=readBitVar.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"readBitVar.js","sourceRoot":"","sources":["../../src/Parser/readBitVar.ts"],"names":[],"mappings":"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"}