mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
code style and add tslint
This commit is contained in:
parent
da007aca8c
commit
52a36ed8c8
61 changed files with 1708 additions and 872 deletions
|
|
@ -1,21 +1,22 @@
|
|||
import {PacketEntity} from "../Data/PacketEntity";
|
||||
import {BitStream} from "bit-buffer";
|
||||
import {SendProp} from "../Data/SendProp";
|
||||
import {SendPropParser} from "./SendPropParser";
|
||||
import {readUBitVar} from "./readBitVar";
|
||||
import {SendTable} from "../Data/SendTable";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {PacketEntity} from '../Data/PacketEntity';
|
||||
import {SendProp} from '../Data/SendProp';
|
||||
import {SendTable} from '../Data/SendTable';
|
||||
import {readUBitVar} from './readBitVar';
|
||||
import {SendPropParser} from './SendPropParser';
|
||||
|
||||
export function applyEntityUpdate(entity: PacketEntity, sendTable: SendTable, stream: BitStream): PacketEntity {
|
||||
let index = -1;
|
||||
let index = -1;
|
||||
const allProps = sendTable.flattenedProps;
|
||||
while ((index = readFieldIndex(stream, index)) != -1) {
|
||||
index = readFieldIndex(stream, index);
|
||||
while (index !== -1) {
|
||||
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');
|
||||
}
|
||||
|
||||
const propDefinition = allProps[index];
|
||||
const existingProp = entity.getPropByDefinition(propDefinition);
|
||||
const existingProp = entity.getPropByDefinition(propDefinition);
|
||||
|
||||
const prop = existingProp ? existingProp : new SendProp(propDefinition);
|
||||
prop.value = SendPropParser.decode(propDefinition, stream);
|
||||
|
|
@ -23,14 +24,16 @@ export function applyEntityUpdate(entity: PacketEntity, sendTable: SendTable, st
|
|||
if (!existingProp) {
|
||||
entity.props.push(prop);
|
||||
}
|
||||
|
||||
index = readFieldIndex(stream, index);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
const readFieldIndex = function (stream: BitStream, lastIndex: number): number {
|
||||
function readFieldIndex(stream: BitStream, lastIndex: number): number {
|
||||
if (!stream.readBoolean()) {
|
||||
return -1;
|
||||
}
|
||||
const diff = readUBitVar(stream);
|
||||
return lastIndex + diff + 1;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import {ConsoleCmdPacket} from "../../Data/Packet";
|
||||
import {ConsoleCmdPacket} from '../../Data/Packet';
|
||||
import {Parser} from './Parser';
|
||||
|
||||
export class ConsoleCmd extends Parser {
|
||||
parse(): ConsoleCmdPacket[] {
|
||||
public parse(): ConsoleCmdPacket[] {
|
||||
return [{
|
||||
packetType: 'consoleCmd',
|
||||
command: this.stream.readUTF8String()
|
||||
command: this.stream.readUTF8String(),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import {SendTable} from '../../Data/SendTable';
|
||||
import {DataTablePacket} from '../../Data/Packet';
|
||||
import {SendPropDefinition, SendPropFlag, SendPropType} from '../../Data/SendPropDefinition';
|
||||
import {SendTable} from '../../Data/SendTable';
|
||||
import {ServerClass} from '../../Data/ServerClass';
|
||||
import {Parser} from './Parser';
|
||||
import {DataTablePacket} from "../../Data/Packet";
|
||||
|
||||
export class DataTable extends Parser {
|
||||
parse(): DataTablePacket[] {
|
||||
public parse(): DataTablePacket[] {
|
||||
// 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
|
||||
let tables: SendTable[] = [];
|
||||
let i, j;
|
||||
const tables: SendTable[] = [];
|
||||
const tableMap: {[key: string]: SendTable} = {};
|
||||
while (this.stream.readBoolean()) {
|
||||
const needsDecoder = this.stream.readBoolean();
|
||||
|
|
@ -20,7 +19,7 @@ export class DataTable extends Parser {
|
|||
|
||||
// get props metadata
|
||||
let arrayElementProp;
|
||||
for (i = 0; i < numProps; i++) {
|
||||
for (let i = 0; i < numProps; i++) {
|
||||
const propType = this.stream.readBits(5);
|
||||
const propName = this.stream.readASCIIString();
|
||||
const nFlagsBits = 16; // might be 11 (old?), 13 (new?), 16(networked) or 17(??)
|
||||
|
|
@ -52,7 +51,7 @@ export class DataTable extends Parser {
|
|||
|
||||
if (arrayElementProp) {
|
||||
if (prop.type !== SendPropType.DPT_Array) {
|
||||
throw "expected prop of type array";
|
||||
throw new Error('expected prop of type array');
|
||||
}
|
||||
prop.arrayProperty = arrayElementProp;
|
||||
arrayElementProp = null;
|
||||
|
|
@ -60,10 +59,10 @@ export class DataTable extends Parser {
|
|||
|
||||
if (prop.hasFlag(SendPropFlag.SPROP_INSIDEARRAY)) {
|
||||
if (arrayElementProp) {
|
||||
throw new Error("array element already set");
|
||||
throw new Error('array element already set');
|
||||
}
|
||||
if (prop.hasFlag(SendPropFlag.SPROP_CHANGES_OFTEN)) {
|
||||
throw new Error("unexpected CHANGES_OFTEN prop in array");
|
||||
throw new Error('unexpected CHANGES_OFTEN prop in array');
|
||||
}
|
||||
arrayElementProp = prop;
|
||||
} else {
|
||||
|
|
@ -89,13 +88,13 @@ export class DataTable extends Parser {
|
|||
const numServerClasses = this.stream.readUint16(); // short
|
||||
const serverClasses: ServerClass[] = [];
|
||||
if (numServerClasses <= 0) {
|
||||
throw "expected one or more serverclasses";
|
||||
throw new Error('expected one or more serverclasses');
|
||||
}
|
||||
|
||||
for (i = 0; i < numServerClasses; i++) {
|
||||
for (let i = 0; i < numServerClasses; i++) {
|
||||
const classId = this.stream.readUint16();
|
||||
if (classId > numServerClasses) {
|
||||
throw "invalid class id";
|
||||
throw new Error('invalid class id');
|
||||
}
|
||||
const className = this.stream.readASCIIString();
|
||||
const dataTable = this.stream.readASCIIString();
|
||||
|
|
@ -104,14 +103,13 @@ export class DataTable extends Parser {
|
|||
|
||||
const bitsLeft = (this.length * 8) - this.stream.index;
|
||||
if (bitsLeft > 7 || bitsLeft < 0) {
|
||||
throw "unexpected remaining data in datatable (" + bitsLeft + " bits)";
|
||||
throw new Error('unexpected remaining data in datatable (' + bitsLeft + ' bits)');
|
||||
}
|
||||
|
||||
|
||||
return [{
|
||||
packetType: 'dataTable',
|
||||
tables: tables,
|
||||
serverClasses: serverClasses
|
||||
tables,
|
||||
serverClasses,
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,25 @@
|
|||
import * as ParserGenerator from '../Packet/ParserGenerator';
|
||||
|
||||
import {Parser} from './Parser';
|
||||
import {BSPDecal} from '../Packet/BSPDecal';
|
||||
import {ClassInfo} from '../Packet/ClassInfo';
|
||||
import {CmdKeyValues} from '../Packet/CmdKeyValues';
|
||||
import {CreateStringTable} from '../Packet/CreateStringTable';
|
||||
import {EntityMessage} from '../Packet/EntityMessage';
|
||||
import {GameEvent} from '../Packet/GameEvent';
|
||||
import {GameEventList} from '../Packet/GameEventList';
|
||||
import {Menu} from '../Packet/Menu';
|
||||
import {PacketEntities} from '../Packet/PacketEntities';
|
||||
import {PacketParserMap} from '../Packet/Parser';
|
||||
import {ParseSounds} from '../Packet/ParseSounds';
|
||||
import {SetConVar} from '../Packet/SetConVar';
|
||||
import {TempEntities} from '../Packet/TempEntities';
|
||||
import {UpdateStringTable} from '../Packet/UpdateStringTable';
|
||||
import {UserMessage} from '../Packet/UserMessage';
|
||||
import {PacketParserMap} from '../Packet/Parser';
|
||||
import {TempEntities} from '../Packet/TempEntities';
|
||||
import {VoiceInit} from '../Packet/VoiceInit';
|
||||
import {VoiceData} from '../Packet/VoiceData';
|
||||
import {Menu} from '../Packet/Menu';
|
||||
import {CmdKeyValues} from '../Packet/CmdKeyValues';
|
||||
|
||||
import {GameEventDefinitionMap} from "../../Data/GameEvent";
|
||||
import {VoiceInit} from '../Packet/VoiceInit';
|
||||
import {Parser} from './Parser';
|
||||
|
||||
import {GameEventDefinitionMap} from '../../Data/GameEvent';
|
||||
|
||||
import {Packet as IPacket} from '../../Data/Packet';
|
||||
|
||||
|
|
@ -30,30 +29,7 @@ import {Packet as IPacket} from '../../Data/Packet';
|
|||
// https://github.com/LestaD/SourceEngine2007/blob/master/src_main/common/netmessages.cpp
|
||||
|
||||
export class Packet extends Parser {
|
||||
parse() {
|
||||
let packets: IPacket[] = [];
|
||||
let lastPacketType = 0;
|
||||
while (this.bitsLeft > 6) { // last 6 bits for NOOP
|
||||
const type = this.stream.readBits(6);
|
||||
if (type !== 0) {
|
||||
if (Packet.parsers[type]) {
|
||||
const skip = this.skippedPackets.indexOf(type) !== -1;
|
||||
const packet = Packet.parsers[type].call(this, this.stream, this.match, skip);
|
||||
packets.push(packet);
|
||||
} else {
|
||||
throw new Error('Unknown packet type ' + type + " just parsed a " + PacketType[lastPacketType]);
|
||||
}
|
||||
lastPacketType = type;
|
||||
}
|
||||
}
|
||||
return packets;
|
||||
}
|
||||
|
||||
get bitsLeft() {
|
||||
return (this.length * 8) - this.stream.index;
|
||||
}
|
||||
|
||||
static parsers: PacketParserMap = {
|
||||
private static parsers: PacketParserMap = {
|
||||
2: ParserGenerator.make('file', 'transferId{32}fileName{s}requested{b}'),
|
||||
3: ParserGenerator.make('netTick', 'tick{32}frameTime{16}stdDev{16}'),
|
||||
4: ParserGenerator.make('stringCmd', 'command{s}'),
|
||||
|
|
@ -83,8 +59,31 @@ export class Packet extends Parser {
|
|||
29: Menu,
|
||||
30: GameEventList,
|
||||
31: ParserGenerator.make('getCvarValue', 'cookie{32}value{s}'),
|
||||
32: CmdKeyValues
|
||||
32: CmdKeyValues,
|
||||
};
|
||||
|
||||
public parse() {
|
||||
const packets: IPacket[] = [];
|
||||
let lastPacketType = 0;
|
||||
while (this.bitsLeft > 6) { // last 6 bits for NOOP
|
||||
const type = this.stream.readBits(6);
|
||||
if (type !== 0) {
|
||||
if (Packet.parsers[type]) {
|
||||
const skip = this.skippedPackets.indexOf(type) !== -1;
|
||||
const packet = Packet.parsers[type].call(this, this.stream, this.match, skip);
|
||||
packets.push(packet);
|
||||
} else {
|
||||
throw new Error('Unknown packet type ' + type + ' just parsed a ' + PacketType[lastPacketType]);
|
||||
}
|
||||
lastPacketType = type;
|
||||
}
|
||||
}
|
||||
return packets;
|
||||
}
|
||||
|
||||
get bitsLeft() {
|
||||
return (this.length * 8) - this.stream.index;
|
||||
}
|
||||
}
|
||||
|
||||
export enum PacketType {
|
||||
|
|
@ -114,5 +113,5 @@ export enum PacketType {
|
|||
menu = 29,
|
||||
gameEventList = 30,
|
||||
getCvarValue = 30,
|
||||
cmdKeyValues = 32
|
||||
cmdKeyValues = 32,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from '../../Data/Match';
|
||||
import {Packet} from "../../Data/Packet";
|
||||
import {MessageType} from "../../Parser";
|
||||
import {PacketType} from "./Packet";
|
||||
import {Packet} from '../../Data/Packet';
|
||||
import {MessageType} from '../../Parser';
|
||||
import {PacketType} from './Packet';
|
||||
|
||||
export abstract class Parser {
|
||||
type: any;
|
||||
tick: number;
|
||||
stream: BitStream;
|
||||
length: number;
|
||||
match: Match;
|
||||
skippedPackets: PacketType[];
|
||||
protected type: any;
|
||||
protected tick: number;
|
||||
protected stream: BitStream;
|
||||
protected length: number;
|
||||
protected match: Match;
|
||||
protected skippedPackets: PacketType[];
|
||||
|
||||
constructor(type: MessageType, tick: number, stream: BitStream, length: number, match: Match, skippedPacket: PacketType[] = []) {
|
||||
this.type = type;
|
||||
this.tick = tick;
|
||||
this.stream = stream;
|
||||
this.length = length;//length in bytes
|
||||
this.length = length; // length in bytes
|
||||
this.match = match;
|
||||
this.skippedPackets = skippedPacket;
|
||||
}
|
||||
|
||||
abstract parse(): Packet[];
|
||||
public abstract parse(): Packet[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import {StringTablePacket} from '../../Data/Packet';
|
||||
import {StringTable as StringTableObject, StringTableEntry} from '../../Data/StringTable';
|
||||
import {Parser} from './Parser';
|
||||
import {StringTableEntry, StringTable as StringTableObject} from "../../Data/StringTable";
|
||||
import {StringTablePacket} from "../../Data/Packet";
|
||||
|
||||
export class StringTable extends Parser {
|
||||
parse(): StringTablePacket[] {
|
||||
public parse(): StringTablePacket[] {
|
||||
// we get the tables from the packets
|
||||
// return [{
|
||||
// packetType: 'stringTable',
|
||||
|
|
@ -11,22 +11,22 @@ export class StringTable extends Parser {
|
|||
// }];
|
||||
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs
|
||||
const tableCount = this.stream.readUint8();
|
||||
let tables: StringTableObject[] = [];
|
||||
const tables: StringTableObject[] = [];
|
||||
let extraDataLength;
|
||||
for (let i = 0; i < tableCount; i++) {
|
||||
let entries: StringTableEntry[] = [];
|
||||
const entries: StringTableEntry[] = [];
|
||||
const tableName = this.stream.readASCIIString();
|
||||
const entryCount = this.stream.readUint16();
|
||||
for (let j = 0; j < entryCount; j++) {
|
||||
let entry: StringTableEntry;
|
||||
try {
|
||||
entry = {
|
||||
text: this.stream.readUTF8String()
|
||||
text: this.stream.readUTF8String(),
|
||||
};
|
||||
} catch (e) {
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
tables,
|
||||
}];
|
||||
}
|
||||
if (this.stream.readBoolean()) {
|
||||
|
|
@ -36,7 +36,7 @@ export class StringTable extends Parser {
|
|||
// seems to happen in POV demos after the MyM update
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
tables,
|
||||
}];
|
||||
}
|
||||
entry.extraData = this.stream.readBitStream(extraDataLength * 8);
|
||||
|
|
@ -46,13 +46,13 @@ export class StringTable extends Parser {
|
|||
const table: StringTableObject = {
|
||||
entries,
|
||||
name: tableName,
|
||||
maxEntries: entryCount
|
||||
maxEntries: entryCount,
|
||||
};
|
||||
tables.push(table);
|
||||
if (this.stream.readBits(1)) {
|
||||
this.stream.readASCIIString();
|
||||
if (this.stream.readBits(1)) {
|
||||
//throw 'more extra data not implemented';
|
||||
// throw 'more extra data not implemented';
|
||||
extraDataLength = this.stream.readBits(16);
|
||||
this.stream.readBits(extraDataLength);
|
||||
}
|
||||
|
|
@ -60,26 +60,7 @@ export class StringTable extends Parser {
|
|||
}
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
tables,
|
||||
}];
|
||||
}
|
||||
|
||||
readExtraData(length): string[] {
|
||||
const end = this.stream.index + (length * 8);
|
||||
let data: string[] = [];
|
||||
//console.log(this.stream.readUTF8String());
|
||||
data.push(this.stream.readUTF8String());
|
||||
while (this.stream.index < end && this.stream.index < (this.stream.length - 7)) { // -7 because we need a full byte
|
||||
try {
|
||||
let string = this.stream.readUTF8String();
|
||||
if (string) {
|
||||
data.push(string);
|
||||
}
|
||||
} catch (e) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
this.stream.index = end;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {Parser} from './Parser';
|
||||
|
||||
export class UserCmd extends Parser {
|
||||
parse() {
|
||||
public parse() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import {BSPDecalPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Vector} from "../../Data/Vector";
|
||||
import {BSPDecalPacket} from '../../Data/Packet';
|
||||
import {Vector} from '../../Data/Vector';
|
||||
|
||||
const getCoord = function (stream) {
|
||||
const hasInt = !!stream.readBits(1);
|
||||
function getCoord(stream) {
|
||||
const hasInt = !!stream.readBits(1);
|
||||
const hasFract = !!stream.readBits(1);
|
||||
let value = 0;
|
||||
let value = 0;
|
||||
if (hasInt || hasFract) {
|
||||
const sign = !!stream.readBits(1);
|
||||
if (hasInt) {
|
||||
|
|
@ -19,34 +19,35 @@ const getCoord = function (stream) {
|
|||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
const getVecCoord = function (stream): Vector {
|
||||
function getVecCoord(stream): Vector {
|
||||
const hasX = !!stream.readBits(1);
|
||||
const hasY = !!stream.readBits(1);
|
||||
const hasZ = !!stream.readBits(1);
|
||||
return {
|
||||
x: hasX ? getCoord(stream) : 0,
|
||||
y: hasY ? getCoord(stream) : 0,
|
||||
z: hasZ ? getCoord(stream) : 0
|
||||
}
|
||||
};
|
||||
z: hasZ ? getCoord(stream) : 0,
|
||||
};
|
||||
}
|
||||
|
||||
export function BSPDecal(stream: BitStream): BSPDecalPacket { // 21: BSPDecal
|
||||
let modelIndex, entIndex;
|
||||
const position = getVecCoord(stream);
|
||||
let modelIndex = 0;
|
||||
let entIndex = 0;
|
||||
const position = getVecCoord(stream);
|
||||
const textureIndex = stream.readBits(9);
|
||||
if (stream.readBits(1)) {
|
||||
entIndex = stream.readBits(11);
|
||||
entIndex = stream.readBits(11);
|
||||
modelIndex = stream.readBits(12);
|
||||
}
|
||||
const lowPriority = stream.readBoolean();
|
||||
return {
|
||||
packetType: 'bspDecal',
|
||||
position: position,
|
||||
textureIndex: textureIndex,
|
||||
entIndex: entIndex,
|
||||
modelIndex: modelIndex,
|
||||
lowPriority: lowPriority
|
||||
}
|
||||
packetType: 'bspDecal',
|
||||
position,
|
||||
textureIndex,
|
||||
entIndex,
|
||||
modelIndex,
|
||||
lowPriority,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
import {ClassInfoPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {ClassInfoPacket} from '../../Data/Packet';
|
||||
import {logBase2} from '../../Math';
|
||||
|
||||
export function ClassInfo(stream: BitStream): ClassInfoPacket { // 10: classInfo
|
||||
const number = stream.readBits(16);
|
||||
const count = stream.readBits(16);
|
||||
const create = stream.readBoolean();
|
||||
let entries: any[] = [];
|
||||
const entries: any[] = [];
|
||||
if (!create) {
|
||||
const bits = logBase2(number) + 1;
|
||||
for (let i = 0; i < number; i++) {
|
||||
const bits = logBase2(count) + 1;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const entry = {
|
||||
'classId': stream.readBits(bits),
|
||||
'className': stream.readASCIIString(),
|
||||
'dataTableName': stream.readASCIIString()
|
||||
classId: stream.readBits(bits),
|
||||
className: stream.readASCIIString(),
|
||||
dataTableName: stream.readASCIIString(),
|
||||
};
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
return {
|
||||
'packetType': 'classInfo',
|
||||
number: number,
|
||||
create: create,
|
||||
entries: entries
|
||||
}
|
||||
packetType: 'classInfo',
|
||||
number: count,
|
||||
create,
|
||||
entries,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import {CmdKeyValuesPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {CmdKeyValuesPacket} from '../../Data/Packet';
|
||||
|
||||
export function CmdKeyValues(stream: BitStream): CmdKeyValuesPacket {
|
||||
//'length{32}data{$length}'
|
||||
// 'length{32}data{$length}'
|
||||
const length = stream.readUint32();
|
||||
const data = stream.readBitStream(length);
|
||||
return {
|
||||
packetType: 'cmdKeyValues',
|
||||
length: length,
|
||||
data: data
|
||||
length,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import {StringTablePacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {logBase2} from "../../Math";
|
||||
import {readVarInt} from "../readBitVar";
|
||||
import {StringTablePacket} from '../../Data/Packet';
|
||||
import {logBase2} from '../../Math';
|
||||
import {readVarInt} from '../readBitVar';
|
||||
|
||||
import {uncompress} from "snappyjs";
|
||||
import {StringTable} from "../../Data/StringTable";
|
||||
import {parseStringTable} from "../StringTableParser";
|
||||
import {Match} from "../../Data/Match";
|
||||
import {uncompress} from 'snappyjs';
|
||||
import {Match} from '../../Data/Match';
|
||||
import {StringTable} from '../../Data/StringTable';
|
||||
import {parseStringTable} from '../StringTableParser';
|
||||
|
||||
export function CreateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: createStringTable
|
||||
const tableName = stream.readASCIIString();
|
||||
|
|
@ -38,12 +38,12 @@ export function CreateStringTable(stream: BitStream, match: Match): StringTableP
|
|||
const compressedData = data.readArrayBuffer(compressedByteSize - 4); // 4 magic bytes
|
||||
|
||||
if (magic !== 'SNAP') {
|
||||
throw new Error("Unknown compressed stringtable format");
|
||||
throw new Error('Unknown compressed stringtable format');
|
||||
}
|
||||
|
||||
const decompressedData = uncompress(compressedData);
|
||||
if (decompressedData.byteLength !== decompressedByteSize) {
|
||||
throw new Error("Incorrect length of decompressed stringtable");
|
||||
throw new Error('Incorrect length of decompressed stringtable');
|
||||
}
|
||||
|
||||
data = new BitStream(decompressedData.buffer);
|
||||
|
|
@ -52,15 +52,15 @@ export function CreateStringTable(stream: BitStream, match: Match): StringTableP
|
|||
const table: StringTable = {
|
||||
name: tableName,
|
||||
entries: [],
|
||||
maxEntries: maxEntries,
|
||||
maxEntries,
|
||||
fixedUserDataSize: userDataSize,
|
||||
fixedUserDataSizeBits: userDataSizeBits
|
||||
fixedUserDataSizeBits: userDataSizeBits,
|
||||
};
|
||||
|
||||
parseStringTable(data, table, entityCount, match);
|
||||
|
||||
return {
|
||||
packetType: 'stringTable',
|
||||
tables: [table]
|
||||
tables: [table],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import {make} from './ParserGenerator';
|
||||
|
||||
import {EntityMessagePacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from "../../Data/Match";
|
||||
import {Match} from '../../Data/Match';
|
||||
import {EntityMessagePacket} from '../../Data/Packet';
|
||||
|
||||
const baseParser = make('entityMessage', 'index{11}classId{9}length{11}data{$length}');
|
||||
|
||||
export function EntityMessage(stream: BitStream, match: Match): EntityMessagePacket { // 24: entityMessage
|
||||
const result = <EntityMessagePacket>baseParser(stream); //todo parse data further?
|
||||
return result;
|
||||
};
|
||||
return baseParser(stream) as EntityMessagePacket; // todo parse data further?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
import {GameEventPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {
|
||||
GameEventType, GameEventValue, GameEventEntry, GameEventDefinition, GameEvent as IGameEvent,
|
||||
GameEventValueMap, GameEventDefinitionMap
|
||||
} from "../../Data/GameEvent";
|
||||
import {Match} from "../../Data/Match";
|
||||
GameEvent as IGameEvent, GameEventDefinition, GameEventDefinitionMap, GameEventEntry, GameEventType,
|
||||
GameEventValue, GameEventValueMap,
|
||||
} from '../../Data/GameEvent';
|
||||
import {Match} from '../../Data/Match';
|
||||
import {GameEventPacket} from '../../Data/Packet';
|
||||
|
||||
const parseGameEvent = function (eventId: number, stream: BitStream, events: GameEventDefinitionMap): IGameEvent {
|
||||
function parseGameEvent(eventId: number, stream: BitStream, events: GameEventDefinitionMap): IGameEvent {
|
||||
if (!events[eventId]) {
|
||||
throw new Error('unknown event type')
|
||||
throw new Error('unknown event type');
|
||||
}
|
||||
const eventDescription: GameEventDefinition = events[eventId];
|
||||
const values: GameEventValueMap = {};
|
||||
for (let i = 0; i < eventDescription.entries.length; i++) {
|
||||
const entry: GameEventEntry = eventDescription.entries[i];
|
||||
const value = getGameEventValue(stream, entry);
|
||||
const values: GameEventValueMap = {};
|
||||
for (const entry of eventDescription.entries) {
|
||||
const value = getGameEventValue(stream, entry);
|
||||
if (value) {
|
||||
values[entry.name] = value;
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: eventDescription.name,
|
||||
values: values
|
||||
name: eventDescription.name,
|
||||
values,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const getGameEventValue = function (stream: BitStream, entry: GameEventEntry): GameEventValue|null {
|
||||
function getGameEventValue(stream: BitStream, entry: GameEventEntry): GameEventValue | null {
|
||||
switch (entry.type) {
|
||||
case GameEventType.STRING:
|
||||
return stream.readUTF8String();
|
||||
|
|
@ -44,17 +43,16 @@ const getGameEventValue = function (stream: BitStream, entry: GameEventEntry): G
|
|||
default:
|
||||
throw new Error('invalid game event type');
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export function GameEvent(stream: BitStream, match: Match): GameEventPacket { // 25: game event
|
||||
const length = stream.readBits(11);
|
||||
const end = stream.index + length;
|
||||
const length = stream.readBits(11);
|
||||
const end = stream.index + length;
|
||||
const eventId = stream.readBits(9);
|
||||
const event = parseGameEvent(eventId, stream, match.eventDefinitions);
|
||||
const event = parseGameEvent(eventId, stream, match.eventDefinitions);
|
||||
stream.index = end;
|
||||
return {
|
||||
packetType: 'gameEvent',
|
||||
event: event
|
||||
}
|
||||
event,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {GameEventListPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {GameEventEntry, GameEventDefinitionMap} from "../../Data/GameEvent";
|
||||
import {Match} from "../../Data/Match";
|
||||
import {GameEventDefinitionMap, GameEventEntry} from '../../Data/GameEvent';
|
||||
import {Match} from '../../Data/Match';
|
||||
import {GameEventListPacket} from '../../Data/Packet';
|
||||
|
||||
export function GameEventList(stream: BitStream, match: Match): GameEventListPacket { // 30: gameEventList
|
||||
// list of game events and parameters
|
||||
|
|
@ -15,19 +15,19 @@ export function GameEventList(stream: BitStream, match: Match): GameEventListPac
|
|||
const entries: GameEventEntry[] = [];
|
||||
while (type !== 0) {
|
||||
entries.push({
|
||||
type: type,
|
||||
name: stream.readASCIIString()
|
||||
type,
|
||||
name: stream.readASCIIString(),
|
||||
});
|
||||
type = stream.readBits(3);
|
||||
}
|
||||
eventList[id] = {
|
||||
id: id,
|
||||
name: name,
|
||||
entries: entries
|
||||
id,
|
||||
name,
|
||||
entries,
|
||||
};
|
||||
}
|
||||
return {
|
||||
packetType: 'gameEventList',
|
||||
eventList: eventList
|
||||
}
|
||||
eventList,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import {MenuPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {MenuPacket} from '../../Data/Packet';
|
||||
|
||||
export function Menu(stream: BitStream): MenuPacket {
|
||||
//'type{16}length{16}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}'
|
||||
const type = stream.readUint16();
|
||||
const length = stream.readUint16();
|
||||
const data = stream.readBitStream(length * 8); //length is in bytes
|
||||
const data = stream.readBitStream(length * 8); // length is in bytes
|
||||
return {
|
||||
packetType: 'menu',
|
||||
type: type,
|
||||
length: length,
|
||||
data: data
|
||||
type,
|
||||
length,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from '../../Data/Match';
|
||||
import {PacketEntitiesPacket} from '../../Data/Packet';
|
||||
import {PacketEntity, PVS} from '../../Data/PacketEntity';
|
||||
import {SendProp} from '../../Data/SendProp';
|
||||
import {PacketEntitiesPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from "../../Data/Match";
|
||||
import {readUBitVar} from "../readBitVar";
|
||||
import {applyEntityUpdate} from "../EntityDecoder";
|
||||
import {applyEntityUpdate} from '../EntityDecoder';
|
||||
import {readUBitVar} from '../readBitVar';
|
||||
|
||||
const pvsMap = {
|
||||
0: PVS.PRESERVE,
|
||||
2: PVS.ENTER,
|
||||
1: PVS.LEAVE,
|
||||
3: PVS.LEAVE + PVS.DELETE
|
||||
3: PVS.LEAVE + PVS.DELETE,
|
||||
};
|
||||
|
||||
function readPVSType(stream: BitStream): PVS {
|
||||
|
|
@ -58,7 +58,7 @@ function getPacketEntityForExisting(entityId: number, match: Match, pvs: PVS) {
|
|||
return new PacketEntity(serverClass, entityId, pvs);
|
||||
}
|
||||
|
||||
export function PacketEntities(stream: BitStream, match: Match, skip: boolean = false): PacketEntitiesPacket { //26: packetEntities
|
||||
export function PacketEntities(stream: BitStream, match: Match, skip: boolean = false): PacketEntitiesPacket { // 26: packetEntities
|
||||
// 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
|
||||
|
|
@ -106,8 +106,7 @@ export function PacketEntities(stream: BitStream, match: Match, skip: boolean =
|
|||
|
||||
if (isDelta) {
|
||||
while (stream.readBoolean()) {
|
||||
const entityId = stream.readBits(11);
|
||||
removedEntityIds.push(entityId);
|
||||
removedEntityIds.push(stream.readBits(11));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,12 +116,12 @@ export function PacketEntities(stream: BitStream, match: Match, skip: boolean =
|
|||
packetType: 'packetEntities',
|
||||
entities: receivedEntities,
|
||||
removedEntities: removedEntityIds,
|
||||
maxEntries: maxEntries,
|
||||
isDelta: isDelta,
|
||||
delta: delta,
|
||||
baseLine: baseLine,
|
||||
updatedEntries: updatedEntries,
|
||||
length: length,
|
||||
updatedBaseLine: updatedBaseLine
|
||||
maxEntries,
|
||||
isDelta,
|
||||
delta,
|
||||
baseLine,
|
||||
updatedEntries,
|
||||
length,
|
||||
updatedBaseLine,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {ParseSoundsPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {ParseSoundsPacket} from '../../Data/Packet';
|
||||
|
||||
export function ParseSounds(stream: BitStream): ParseSoundsPacket { // 17: parseSounds
|
||||
const reliable = stream.readBoolean();
|
||||
|
|
@ -8,8 +8,8 @@ export function ParseSounds(stream: BitStream): ParseSoundsPacket { // 17: parse
|
|||
stream.index += length;
|
||||
return {
|
||||
packetType: 'parseSounds',
|
||||
reliable: reliable,
|
||||
num: num,
|
||||
length: length
|
||||
}
|
||||
reliable,
|
||||
num,
|
||||
length,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import {Packet} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from "../../Data/Match";
|
||||
import {Match} from '../../Data/Match';
|
||||
import {Packet} from '../../Data/Packet';
|
||||
|
||||
export type Parser = (stream: BitStream, match?: Match, skip?: boolean) => Packet;
|
||||
export type PacketParserMap = {[id: number]: Parser};
|
||||
|
||||
export interface PacketParserMap {
|
||||
[id: number]: Parser;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
import {Packet} from '../../Data/Packet';
|
||||
import {Parser} from './Parser';
|
||||
import {Packet} from "../../Data/Packet";
|
||||
|
||||
export function make(name: string, definition: string): Parser {
|
||||
const parts = definition.substr(0, definition.length - 1).split('}');//remove leading } to prevent empty part
|
||||
const items = parts.map(function (part) {
|
||||
const parts = definition.substr(0, definition.length - 1).split('}'); // remove leading } to prevent empty part
|
||||
const items = parts.map((part) => {
|
||||
return part.split('{');
|
||||
});
|
||||
return function (stream):Packet {
|
||||
let result = {
|
||||
'packetType': name
|
||||
return (stream) => {
|
||||
const result = {
|
||||
packetType: name,
|
||||
};
|
||||
try {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const value = readItem(stream, items[i][1], result);
|
||||
if (items[i][0] !== '_') {
|
||||
result[items[i][0]] = value;
|
||||
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 <Packet>result;
|
||||
}
|
||||
return result as Packet;
|
||||
};
|
||||
}
|
||||
|
||||
const readItem = function (stream, description, data) {
|
||||
function readItem(stream, description, data) {
|
||||
let length;
|
||||
if (description[0] === 'b') {
|
||||
return stream.readBoolean();
|
||||
|
|
@ -46,4 +46,4 @@ const readItem = function (stream, description, data) {
|
|||
} else {
|
||||
return stream.readBits(parseInt(description, 10), true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import {SetConVarPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {SetConVarPacket} from '../../Data/Packet';
|
||||
|
||||
export function SetConVar(stream: BitStream): SetConVarPacket { // 5: setconvar
|
||||
const count = stream.readBits(8);
|
||||
let vars: {[key: string]: string} = {};
|
||||
const vars: {[key: string]: string} = {};
|
||||
for (let i = 0; i < count; i++) {
|
||||
vars[stream.readUTF8String()] = stream.readUTF8String();
|
||||
}
|
||||
return {
|
||||
packetType: 'setConVar',
|
||||
vars: vars
|
||||
}
|
||||
vars,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import {TempEntitiesPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from "../../Data/Match";
|
||||
import {PacketEntity, PVS} from "../../Data/PacketEntity";
|
||||
import {applyEntityUpdate} from "../EntityDecoder";
|
||||
import {Match} from '../../Data/Match';
|
||||
import {TempEntitiesPacket} from '../../Data/Packet';
|
||||
import {PacketEntity, PVS} from '../../Data/PacketEntity';
|
||||
import {applyEntityUpdate} from '../EntityDecoder';
|
||||
|
||||
export function TempEntities(stream: BitStream, match: Match, skip: boolean = false): TempEntitiesPacket { // 10: classInfo
|
||||
const entityCount = stream.readBits(8);
|
||||
|
|
@ -10,10 +10,10 @@ export function TempEntities(stream: BitStream, match: Match, skip: boolean = fa
|
|||
const end = stream.index + length;
|
||||
|
||||
let entity: PacketEntity|null = null;
|
||||
let entities: PacketEntity[] = [];
|
||||
const entities: PacketEntity[] = [];
|
||||
if (!skip) {
|
||||
for (let i = 0; i < entityCount; i++) {
|
||||
const delay = (stream.readBoolean()) ? stream.readUint8() / 100 : 0; //unused it seems
|
||||
const delay = (stream.readBoolean()) ? stream.readUint8() / 100 : 0; // unused it seems
|
||||
if (stream.readBoolean()) {
|
||||
const classId = stream.readBits(match.classBits);
|
||||
const serverClass = match.serverClasses[classId - 1];
|
||||
|
|
@ -28,20 +28,20 @@ export function TempEntities(stream: BitStream, match: Match, skip: boolean = fa
|
|||
if (entity) {
|
||||
applyEntityUpdate(entity, match.getSendTable(entity.serverClass.dataTable), stream);
|
||||
} else {
|
||||
throw new Error("no entity set to update");
|
||||
throw new Error('no entity set to update');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end - stream.index > 8) {
|
||||
throw new Error("unexpected content after TempEntities");
|
||||
throw new Error('unexpected content after TempEntities');
|
||||
}
|
||||
}
|
||||
|
||||
stream.index = end;
|
||||
return {
|
||||
packetType: 'tempEntities',
|
||||
entities: entities
|
||||
}
|
||||
entities,
|
||||
};
|
||||
}
|
||||
|
||||
function readVarInt(stream: BitStream) {
|
||||
|
|
@ -50,7 +50,7 @@ function readVarInt(stream: BitStream) {
|
|||
const byte = stream.readUint8();
|
||||
result |= ((byte & 0x7F) << run);
|
||||
|
||||
if ((byte >> 7) == 0) {
|
||||
if ((byte >> 7) === 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {StringTablePacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {Match} from "../../Data/Match";
|
||||
import {parseStringTable} from "../StringTableParser";
|
||||
import {Match} from '../../Data/Match';
|
||||
import {StringTablePacket} from '../../Data/Packet';
|
||||
import {parseStringTable} from '../StringTableParser';
|
||||
|
||||
export function UpdateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: updateStringTable
|
||||
const tableId = stream.readBits(5);
|
||||
|
|
@ -21,6 +21,6 @@ export function UpdateStringTable(stream: BitStream, match: Match): StringTableP
|
|||
|
||||
return {
|
||||
packetType: 'stringTable',
|
||||
tables: [table]
|
||||
tables: [table],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import {UserMessagePacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {make} from './ParserGenerator';
|
||||
import {UserMessagePacket} from '../../Data/Packet';
|
||||
import {SayText2} from '../UserMessage/SayText2';
|
||||
import {make} from './ParserGenerator';
|
||||
|
||||
enum UserMessageType{
|
||||
enum UserMessageType {
|
||||
Geiger = 0,
|
||||
Train = 1,
|
||||
HudText = 2,
|
||||
|
|
@ -61,12 +61,12 @@ enum UserMessageType{
|
|||
HapPunch = 54,
|
||||
HapSetDrag = 55,
|
||||
HapSet = 56,
|
||||
HapMeleeContact = 57
|
||||
HapMeleeContact = 57,
|
||||
}
|
||||
|
||||
const userMessageParsers = {
|
||||
4: SayText2,
|
||||
5: make('textMsg', 'destType{8}text{s}')
|
||||
5: make('textMsg', 'destType{8}text{s}'),
|
||||
};
|
||||
|
||||
export function UserMessage(stream: BitStream): UserMessagePacket { // 23: user message
|
||||
|
|
@ -79,7 +79,7 @@ export function UserMessage(stream: BitStream): UserMessagePacket { // 23: user
|
|||
} else {
|
||||
result = {
|
||||
packetType: 'unknownUserMessage',
|
||||
type: type
|
||||
type,
|
||||
};
|
||||
}
|
||||
stream.index = pos + length;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {VoiceDataPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {VoiceDataPacket} from '../../Data/Packet';
|
||||
|
||||
export function VoiceData(stream: BitStream): VoiceDataPacket {
|
||||
// 'client{8}proximity{8}length{16}_{$length}'
|
||||
|
|
@ -9,9 +9,9 @@ export function VoiceData(stream: BitStream): VoiceDataPacket {
|
|||
const data = stream.readBitStream(length);
|
||||
return {
|
||||
packetType: 'voiceData',
|
||||
client: client,
|
||||
proximity: proximity,
|
||||
length: length,
|
||||
data: data
|
||||
client,
|
||||
proximity,
|
||||
length,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {VoiceInitPacket} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {VoiceInitPacket} from '../../Data/Packet';
|
||||
|
||||
export function VoiceInit(stream: BitStream): VoiceInitPacket {
|
||||
const codec = stream.readASCIIString();
|
||||
|
|
@ -8,8 +8,8 @@ export function VoiceInit(stream: BitStream): VoiceInitPacket {
|
|||
const extraData = (codec === 'vaudio_celt' && quality === 255) ? stream.readUint16() : 0;
|
||||
return {
|
||||
packetType: 'voiceInit',
|
||||
codec: codec,
|
||||
quality: quality,
|
||||
extraData: extraData
|
||||
codec,
|
||||
quality,
|
||||
extraData,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import {SendPropDefinition, SendPropType, SendPropFlag} from '../Data/SendPropDefinition';
|
||||
import {Vector} from "../Data/Vector";
|
||||
import {BitStream} from "bit-buffer";
|
||||
import {SendPropValue, SendPropArrayValue} from "../Data/SendProp";
|
||||
import {readVarInt} from "./readBitVar";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {SendPropArrayValue, SendPropValue} from '../Data/SendProp';
|
||||
import {SendPropDefinition, SendPropFlag, SendPropType} from '../Data/SendPropDefinition';
|
||||
import {Vector} from '../Data/Vector';
|
||||
import {logBase2} from '../Math';
|
||||
import {readVarInt} from './readBitVar';
|
||||
|
||||
export class SendPropParser {
|
||||
static decode(propDefinition: SendPropDefinition, stream: BitStream): SendPropValue {
|
||||
public static decode(propDefinition: SendPropDefinition, stream: BitStream): SendPropValue {
|
||||
switch (propDefinition.type) {
|
||||
case SendPropType.DPT_Int:
|
||||
return SendPropParser.readInt(propDefinition, stream);
|
||||
|
|
@ -23,7 +24,7 @@ export class SendPropParser {
|
|||
throw new Error('Unknown property type');
|
||||
}
|
||||
|
||||
static readInt(propDefinition: SendPropDefinition, stream: BitStream) {
|
||||
public static readInt(propDefinition: SendPropDefinition, stream: BitStream) {
|
||||
if (propDefinition.hasFlag(SendPropFlag.SPROP_VARINT)) {
|
||||
return readVarInt(stream, !propDefinition.hasFlag(SendPropFlag.SPROP_UNSIGNED));
|
||||
} else {
|
||||
|
|
@ -31,13 +32,10 @@ export class SendPropParser {
|
|||
}
|
||||
}
|
||||
|
||||
static readArray(propDefinition: SendPropDefinition, stream: BitStream): SendPropArrayValue[] {
|
||||
let maxElements = propDefinition.numElements;
|
||||
let numBits = 1;
|
||||
while ((maxElements >>= 1) != 0)
|
||||
numBits++;
|
||||
public static readArray(propDefinition: SendPropDefinition, stream: BitStream): SendPropArrayValue[] {
|
||||
const numBits = logBase2(propDefinition.numElements) + 1;
|
||||
|
||||
const count = stream.readBits(numBits);
|
||||
const count = stream.readBits(numBits);
|
||||
const values: SendPropArrayValue[] = [];
|
||||
if (!propDefinition.arrayProperty) {
|
||||
throw new Error('Array of undefined type');
|
||||
|
|
@ -52,25 +50,25 @@ export class SendPropParser {
|
|||
return values;
|
||||
}
|
||||
|
||||
static readString(stream: BitStream): string {
|
||||
public static readString(stream: BitStream): string {
|
||||
const length = stream.readBits(9);
|
||||
return stream.readASCIIString(length);
|
||||
}
|
||||
|
||||
static readVector(propDefinition: SendPropDefinition, stream: BitStream): Vector {
|
||||
public static readVector(propDefinition: SendPropDefinition, stream: BitStream): Vector {
|
||||
const x = SendPropParser.readFloat(propDefinition, stream);
|
||||
const y = SendPropParser.readFloat(propDefinition, stream);
|
||||
const z = SendPropParser.readFloat(propDefinition, stream);
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
static readVectorXY(propDefinition: SendPropDefinition, stream: BitStream): Vector {
|
||||
public static readVectorXY(propDefinition: SendPropDefinition, stream: BitStream): Vector {
|
||||
const x = SendPropParser.readFloat(propDefinition, stream);
|
||||
const y = SendPropParser.readFloat(propDefinition, stream);
|
||||
return new Vector(x, y, 0);
|
||||
}
|
||||
|
||||
static readFloat(propDefinition: SendPropDefinition, stream: BitStream): number {
|
||||
public static readFloat(propDefinition: SendPropDefinition, stream: BitStream): number {
|
||||
if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD)) {
|
||||
return SendPropParser.readBitCoord(stream);
|
||||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_COORD_MP)) {
|
||||
|
|
@ -84,36 +82,36 @@ export class SendPropParser {
|
|||
} else if (propDefinition.hasFlag(SendPropFlag.SPROP_NORMAL)) {
|
||||
return SendPropParser.readBitNormal(stream);
|
||||
} else {
|
||||
const raw = stream.readBits(propDefinition.bitCount);
|
||||
const raw = stream.readBits(propDefinition.bitCount);
|
||||
const percentage = raw / ((1 << propDefinition.bitCount) - 1);
|
||||
return propDefinition.lowValue + (propDefinition.highValue - propDefinition.lowValue) * percentage;
|
||||
}
|
||||
}
|
||||
|
||||
static readBitNormal(stream: BitStream) {
|
||||
public static readBitNormal(stream: BitStream) {
|
||||
const isNegative = stream.readBoolean();
|
||||
const fractVal = stream.readBits(11);
|
||||
const value = fractVal * (1 / ((1 << 11) - 1));
|
||||
const fractVal = stream.readBits(11);
|
||||
const value = fractVal * (1 / ((1 << 11) - 1));
|
||||
return (isNegative) ? -value : value;
|
||||
}
|
||||
|
||||
static readBitCoord(stream: BitStream) {
|
||||
const hasIntVal = stream.readBoolean();
|
||||
public static readBitCoord(stream: BitStream) {
|
||||
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 / (1 << 5));
|
||||
const intVal = (hasIntVal) ? stream.readBits(14) + 1 : 0;
|
||||
const fractVal = (hasFractVal) ? stream.readBits(5) : 0;
|
||||
const value = intVal + fractVal * (1 / (1 << 5));
|
||||
return (isNegative) ? -value : value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static readBitCoordMP(propDefinition: SendPropDefinition, stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): number {
|
||||
let value = 0;
|
||||
public static readBitCoordMP(propDefinition: SendPropDefinition, stream: BitStream, isIntegral: boolean, isLowPrecision: boolean): number {
|
||||
let value = 0;
|
||||
let isNegative = false;
|
||||
const inBounds = stream.readBoolean();
|
||||
|
||||
|
|
@ -127,7 +125,7 @@ export class SendPropParser {
|
|||
} else {
|
||||
value = stream.readBits(14) + 1;
|
||||
if (value < (1 << 11)) {
|
||||
throw new Error("Something's fishy...");
|
||||
throw new Error('Something\'s fishy...');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {BitStream} from 'bit-buffer';
|
||||
import {StringTable, StringTableEntry} from "../Data/StringTable";
|
||||
import {logBase2} from "../Math";
|
||||
import {Match} from "../Data/Match";
|
||||
import {Match} from '../Data/Match';
|
||||
import {StringTable, StringTableEntry} from '../Data/StringTable';
|
||||
import {logBase2} from '../Math';
|
||||
|
||||
export function parseStringTable(stream: BitStream, table: StringTable, entries: number, match: Match) {
|
||||
const entryBits = logBase2(table.maxEntries);
|
||||
|
|
@ -19,7 +19,7 @@ export function parseStringTable(stream: BitStream, table: StringTable, entries:
|
|||
lastEntry = entryIndex;
|
||||
|
||||
if (entryIndex < 0 || entryIndex > table.maxEntries) {
|
||||
throw new Error("Invalid string index for stringtable");
|
||||
throw new Error('Invalid string index for stringtable');
|
||||
}
|
||||
|
||||
let value;
|
||||
|
|
@ -67,7 +67,7 @@ export function parseStringTable(stream: BitStream, table: StringTable, entries:
|
|||
} else {
|
||||
table.entries[entryIndex] = {
|
||||
text: value,
|
||||
extraData: userData
|
||||
extraData: userData,
|
||||
};
|
||||
history.push(table.entries[entryIndex]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,51 @@
|
|||
import {SayText2Packet} from "../../Data/Packet";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
import {SayText2Packet} from '../../Data/Packet';
|
||||
|
||||
export function SayText2(stream: BitStream): SayText2Packet { // 4: SayText2
|
||||
var client = stream.readBits(8);
|
||||
var raw = stream.readBits(8);
|
||||
var pos = stream.index;
|
||||
var from, text, kind, arg1, arg2;
|
||||
const client = stream.readBits(8);
|
||||
const raw = stream.readBits(8);
|
||||
const pos = stream.index;
|
||||
let from;
|
||||
let text;
|
||||
let kind;
|
||||
if (stream.readBits(8) === 1) {
|
||||
var first = stream.readBits(8);
|
||||
const first = stream.readBits(8);
|
||||
if (first === 7) {
|
||||
var color = stream.readUTF8String(6);
|
||||
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'
|
||||
var start = text.indexOf('\u0003');
|
||||
var end = text.indexOf('\u0001');
|
||||
from = text.substr(start + 1, end - start - 1);
|
||||
text = text.substr(end + 5);
|
||||
kind = 'TF_Chat_AllDead';
|
||||
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();
|
||||
kind = stream.readUTF8String();
|
||||
from = stream.readUTF8String();
|
||||
text = stream.readUTF8String();
|
||||
stream.readASCIIString();
|
||||
stream.readASCIIString();
|
||||
}
|
||||
// cleanup color codes
|
||||
text = text.replace(/\u0001/g, '');
|
||||
text = text.replace(/\u0003/g, '');
|
||||
while ((pos = text.indexOf('\u0007')) !== -1) {
|
||||
text = text.slice(0, pos) + text.slice(pos + 7);
|
||||
let stringPos = text.indexOf('\u0007');
|
||||
while (stringPos !== -1) {
|
||||
text = text.slice(0, stringPos) + text.slice(stringPos + 7);
|
||||
stringPos = text.indexOf('\u0007');
|
||||
}
|
||||
return {
|
||||
packetType: 'sayText2',
|
||||
client: client,
|
||||
raw: raw,
|
||||
kind: kind,
|
||||
from: from,
|
||||
text: text
|
||||
}
|
||||
};
|
||||
client,
|
||||
raw,
|
||||
kind,
|
||||
from,
|
||||
text,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {BitStream} from "bit-buffer";
|
||||
import {BitStream} from 'bit-buffer';
|
||||
export function readBitVar(stream: BitStream, signed?: boolean): number {
|
||||
const type = stream.readBits(2);
|
||||
switch (type) {
|
||||
|
|
@ -16,8 +16,7 @@ export function readBitVar(stream: BitStream, signed?: boolean): number {
|
|||
|
||||
export const readUBitVar = readBitVar;
|
||||
|
||||
|
||||
export function readVarInt(stream: BitStream, signed:boolean = false) {
|
||||
export function readVarInt(stream: BitStream, signed: boolean = false) {
|
||||
let result = 0;
|
||||
for (let i = 0; i < 35; i += 7) {
|
||||
const byte = stream.readBits(8);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue