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

lint fixes

This commit is contained in:
Robin Appelman 2017-09-26 02:29:45 +02:00
commit 0aad1e874b
78 changed files with 879 additions and 851 deletions

102
package-lock.json generated
View file

@ -484,14 +484,6 @@
"requires": { "requires": {
"balanced-match": "1.0.0", "balanced-match": "1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
},
"dependencies": {
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
}
} }
}, },
"clone": { "clone": {
@ -520,6 +512,12 @@
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
"dev": true "dev": true
}, },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@ -532,6 +530,12 @@
"integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
"dev": true "dev": true
}, },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"glob": { "glob": {
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -544,51 +548,6 @@
"minimatch": "3.0.4", "minimatch": "3.0.4",
"once": "1.4.0", "once": "1.4.0",
"path-is-absolute": "1.0.1" "path-is-absolute": "1.0.1"
},
"dependencies": {
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
} }
}, },
"has-flag": { "has-flag": {
@ -612,6 +571,22 @@
"parse-passwd": "1.0.0" "parse-passwd": "1.0.0"
} }
}, },
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
},
"isarray": { "isarray": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -929,12 +904,27 @@
} }
} }
}, },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
}
},
"parse-passwd": { "parse-passwd": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true "dev": true
}, },
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-parse": { "path-parse": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
@ -1209,6 +1199,12 @@
"homedir-polyfill": "1.0.1" "homedir-polyfill": "1.0.1"
} }
}, },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"yn": { "yn": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",

View file

@ -1,7 +1,7 @@
import {Parser} from './Parser';
import {Match} from './Data/Match';
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import {Header} from './Data/Header'; import {Header} from './Data/Header';
import {Match} from './Data/Match';
import {Parser} from './Parser';
export class Analyser extends EventEmitter { export class Analyser extends EventEmitter {
private parser: Parser; private parser: Parser;

View file

@ -1,6 +1,6 @@
export interface Chat { export interface Chat {
kind: string, kind: string;
from: string, from: string;
text: string, text: string;
tick: number, tick: number;
} }

View file

@ -18,7 +18,7 @@ export enum GameEventValueType {
SHORT = 4, SHORT = 4,
BYTE = 5, BYTE = 5,
BOOLEAN = 6, BOOLEAN = 6,
LOCAL = 7, LOCAL = 7
} }
export type GameEventValue = string | number | boolean; export type GameEventValue = string | number | boolean;

View file

@ -3528,7 +3528,7 @@ export type GameEvent = ServerSpawnEvent |
export type GameEventType = GameEvent['name']; export type GameEventType = GameEvent['name'];
export type GameEventTypeMap = { export interface GameEventTypeMap {
server_spawn: ServerSpawnEvent; server_spawn: ServerSpawnEvent;
server_changelevel_failed: ServerChangelevelFailedEvent; server_changelevel_failed: ServerChangelevelFailedEvent;
server_shutdown: ServerShutdownEvent; server_shutdown: ServerShutdownEvent;
@ -3905,7 +3905,7 @@ export type GameEventTypeMap = {
replay_endrecord: ReplayEndRecordEvent; replay_endrecord: ReplayEndRecordEvent;
replay_replaysavailable: ReplayReplaysAvailableEvent; replay_replaysavailable: ReplayReplaysAvailableEvent;
replay_servererror: ReplayServerErrorEvent; replay_servererror: ReplayServerErrorEvent;
}; }
export type GameEventTypeId = number; export type GameEventTypeId = number;
@ -4285,6 +4285,5 @@ export const GameEventTypeIdMap: Map<GameEventType, GameEventTypeId> = new Map<G
['replay_sessioninfo', 372], ['replay_sessioninfo', 372],
['replay_endrecord', 373], ['replay_endrecord', 373],
['replay_replaysavailable', 374], ['replay_replaysavailable', 374],
['replay_servererror', 375], ['replay_servererror', 375]
]); ]);

View file

@ -3,19 +3,19 @@ import {handleGameEvent} from '../PacketHandler/GameEvent';
import {handlePacketEntities} from '../PacketHandler/PacketEntities'; import {handlePacketEntities} from '../PacketHandler/PacketEntities';
import {handleSayText2} from '../PacketHandler/SayText2'; import {handleSayText2} from '../PacketHandler/SayText2';
import {Building} from './Building'; import {Building} from './Building';
import {Chat} from './Chat';
import {Death} from './Death'; import {Death} from './Death';
import {Packet} from './Packet';
import {EntityId, PacketEntity} from './PacketEntity'; import {EntityId, PacketEntity} from './PacketEntity';
import {ParserState} from './ParserState';
import {Player} from './Player'; import {Player} from './Player';
import {PlayerResource} from './PlayerResource'; import {PlayerResource} from './PlayerResource';
import {Round} from './Round';
import {StringTableEntry} from './StringTable';
import {Team, TeamNumber} from './Team'; import {Team, TeamNumber} from './Team';
import {UserInfo} from './UserInfo'; import {UserInfo} from './UserInfo';
import {Weapon} from './Weapon'; import {Weapon} from './Weapon';
import {World} from './World'; import {World} from './World';
import {Round} from './Round';
import {Chat} from './Chat';
import {Packet} from './Packet';
import {ParserState} from './ParserState';
import {StringTableEntry} from './StringTable';
export class Match { export class Match {
public tick: number = 0; public tick: number = 0;
@ -27,7 +27,7 @@ export class Match {
public intervalPerTick: number = 0; public intervalPerTick: number = 0;
public world: World = { public world: World = {
boundaryMin: {x: 0, y: 0, z: 0}, boundaryMin: {x: 0, y: 0, z: 0},
boundaryMax: {x: 0, y: 0, z: 0}, boundaryMax: {x: 0, y: 0, z: 0}
}; };
public playerEntityMap: Map<EntityId, Player> = new Map(); public playerEntityMap: Map<EntityId, Player> = new Map();
public weaponMap: Map<EntityId, Weapon> = new Map(); public weaponMap: Map<EntityId, Weapon> = new Map();
@ -49,7 +49,7 @@ export class Match {
classes: user.classes, classes: user.classes,
name: user.name, name: user.name,
steamId: user.steamId, steamId: user.steamId,
userId: user.userId, userId: user.userId
}; };
if (user.team) { if (user.team) {
users[key].team = user.team; users[key].team = user.team;
@ -62,7 +62,7 @@ export class Match {
deaths: this.deaths, deaths: this.deaths,
rounds: this.rounds, rounds: this.rounds,
startTick: this.startTick, startTick: this.startTick,
intervalPerTick: this.intervalPerTick, intervalPerTick: this.intervalPerTick
}; };
} }
@ -94,6 +94,38 @@ export class Match {
} }
} }
public getUserInfo(userId: number): UserInfo {
// no clue why it does this
// only seems to be the case with per user ready
while (userId > 256) {
userId -= 256;
}
const user = this.users.get(userId);
if (!user) {
const newUser = {
name: '',
userId,
steamId: '',
classes: {},
entityId: 0,
team: ''
};
this.users.set(userId, newUser);
return newUser;
}
return user;
}
public getUserInfoForEntity(entity: PacketEntity): UserInfo | null {
for (const user of this.users.values()) {
if (user && user.entityId === entity.entityIndex) {
return user;
}
}
return this.calculateUserInfoByEntityId(entity.entityIndex);
}
private calculateUserInfo() { private calculateUserInfo() {
for (const [text, extraData] of this.parserState.userInfoEntries.entries()) { for (const [text, extraData] of this.parserState.userInfoEntries.entries()) {
this.calculateUserInfoFromEntry(text, extraData); this.calculateUserInfoFromEntry(text, extraData);
@ -127,36 +159,4 @@ export class Match {
throw new Error(); throw new Error();
} }
} }
public getUserInfo(userId: number): UserInfo {
// no clue why it does this
// only seems to be the case with per user ready
while (userId > 256) {
userId -= 256;
}
const user = this.users.get(userId);
if (!user) {
const newUser = {
name: '',
userId,
steamId: '',
classes: {},
entityId: 0,
team: '',
};
this.users.set(userId, newUser);
return newUser;
}
return user;
}
public getUserInfoForEntity(entity: PacketEntity): UserInfo | null {
for (const user of this.users.values()) {
if (user && user.entityId === entity.entityIndex) {
return user;
}
}
return this.calculateUserInfoByEntityId(entity.entityIndex);
}
} }

View file

@ -1,9 +1,9 @@
import {Packet} from './Packet';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {ServerClass} from './ServerClass'; import {Packet} from './Packet';
import {SendTable} from './SendTable';
import {StringTable} from './StringTable';
import {ParserState} from './ParserState'; import {ParserState} from './ParserState';
import {SendTable} from './SendTable';
import {ServerClass} from './ServerClass';
import {StringTable} from './StringTable';
import {Vector} from './Vector'; import {Vector} from './Vector';
export enum MessageType { export enum MessageType {
@ -14,7 +14,7 @@ export enum MessageType {
UserCmd = 5, UserCmd = 5,
DataTables = 6, DataTables = 6,
Stop = 7, Stop = 7,
StringTables = 8, StringTables = 8
} }
export interface BaseMessage { export interface BaseMessage {
@ -33,8 +33,7 @@ export interface PacketMessage extends BaseMessage {
flags: number; flags: number;
} }
export interface SigonMessage extends PacketMessage { export type SigonMessage = PacketMessage;
}
export interface SyncTickMessage extends BaseMessage { export interface SyncTickMessage extends BaseMessage {
type: MessageType.SyncTick; type: MessageType.SyncTick;
@ -53,7 +52,7 @@ export interface UserCmdMessage extends BaseMessage {
export interface DataTablesMessage extends BaseMessage { export interface DataTablesMessage extends BaseMessage {
type: MessageType.DataTables; type: MessageType.DataTables;
tables: SendTable[]; tables: SendTable[];
serverClasses: ServerClass[] serverClasses: ServerClass[];
} }
export interface StopMessage extends BaseMessage { export interface StopMessage extends BaseMessage {
@ -62,7 +61,7 @@ export interface StopMessage extends BaseMessage {
export interface StringTablesMessage extends BaseMessage { export interface StringTablesMessage extends BaseMessage {
type: MessageType.StringTables; type: MessageType.StringTables;
tables: StringTable[] tables: StringTable[];
} }
export type Message = SigonMessage | export type Message = SigonMessage |

View file

@ -1,48 +1,45 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {GameEventDefinition} from './GameEvent'; import {GameEventDefinition} from './GameEvent';
import {GameEvent, GameEventType} from './GameEventTypes';
import {EntityId, PacketEntity} from './PacketEntity'; import {EntityId, PacketEntity} from './PacketEntity';
import {SendTable} from './SendTable'; import {SendTable} from './SendTable';
import {ServerClass} from './ServerClass'; import {ServerClass} from './ServerClass';
import {StringTable, StringTableEntry} from './StringTable'; import {StringTable, StringTableEntry} from './StringTable';
import {Vector} from './Vector';
import {GameEvent, GameEventType} from './GameEventTypes';
import { import {
BreakModelPumpkinPacket, ResetHUDPacket, TextMessagePacket, TrainPacket, UnknownUserMessagePacket, BreakModelPumpkinPacket, ResetHUDPacket, SayText2Packet, TextMessagePacket, TrainPacket,
UserMessagePacket, UserMessageType, UnknownUserMessagePacket, UserMessagePacket,
UserMessageTypeMap, VoiceSubtitlePacket, SayText2Packet UserMessageType, UserMessageTypeMap, VoiceSubtitlePacket
} from './UserMessage'; } from './UserMessage';
import {Vector} from './Vector';
export interface BasePacket { export interface StringTablePacket {
}
export interface StringTablePacket extends BasePacket {
packetType: 'stringTable'; packetType: 'stringTable';
tables: StringTable[]; tables: StringTable[];
} }
export interface CreateStringTablePacket extends BasePacket { export interface CreateStringTablePacket {
packetType: 'createStringTable'; packetType: 'createStringTable';
table: StringTable; table: StringTable;
} }
export interface UpdateStringTablePacket extends BasePacket { export interface UpdateStringTablePacket {
packetType: 'updateStringTable'; packetType: 'updateStringTable';
entries: StringTableEntry[]; entries: StringTableEntry[];
tableId: number; tableId: number;
} }
export interface ConsoleCmdPacket extends BasePacket { export interface ConsoleCmdPacket {
packetType: 'consoleCmd'; packetType: 'consoleCmd';
command: string; command: string;
} }
export interface DataTablePacket extends BasePacket { export interface DataTablePacket {
packetType: 'dataTable'; packetType: 'dataTable';
tables: SendTable[]; tables: SendTable[];
serverClasses: ServerClass[]; serverClasses: ServerClass[];
} }
export interface BSPDecalPacket extends BasePacket { export interface BSPDecalPacket {
packetType: 'bspDecal'; packetType: 'bspDecal';
position: Vector; position: Vector;
textureIndex: number; textureIndex: number;
@ -51,35 +48,35 @@ export interface BSPDecalPacket extends BasePacket {
lowPriority: boolean; lowPriority: boolean;
} }
export interface ClassInfoPacket extends BasePacket { export interface ClassInfoPacket {
packetType: 'classInfo'; packetType: 'classInfo';
number: number; number: number;
create: boolean; create: boolean;
entries: { entries: Array<{
classId: number; classId: number;
className: string; className: string;
dataTableName: string; dataTableName: string;
}[]; }>;
} }
export interface EntityMessagePacket extends BasePacket { export interface EntityMessagePacket {
packetType: 'entityMessage'; packetType: 'entityMessage';
classId: number; classId: number;
length: number; length: number;
data: string; data: string;
} }
export interface GameEventPacket extends BasePacket { export interface GameEventPacket {
packetType: 'gameEvent'; packetType: 'gameEvent';
event: GameEvent; event: GameEvent;
} }
export interface GameEventListPacket extends BasePacket { export interface GameEventListPacket {
packetType: 'gameEventList'; packetType: 'gameEventList';
eventList: Map<number, GameEventDefinition<GameEvent['name']>>; eventList: Map<number, GameEventDefinition<GameEvent['name']>>;
} }
export interface PacketEntitiesPacket extends BasePacket { export interface PacketEntitiesPacket {
packetType: 'packetEntities'; packetType: 'packetEntities';
entities: PacketEntity[]; entities: PacketEntity[];
removedEntities: EntityId[]; removedEntities: EntityId[];
@ -89,7 +86,7 @@ export interface PacketEntitiesPacket extends BasePacket {
updatedBaseLine: boolean; updatedBaseLine: boolean;
} }
export interface ParseSoundsPacket extends BasePacket { export interface ParseSoundsPacket {
packetType: 'parseSounds'; packetType: 'parseSounds';
reliable: boolean; reliable: boolean;
num: number; num: number;
@ -97,24 +94,24 @@ export interface ParseSoundsPacket extends BasePacket {
data: BitStream; data: BitStream;
} }
export interface SetConVarPacket extends BasePacket { export interface SetConVarPacket {
packetType: 'setConVar'; packetType: 'setConVar';
vars: Map<string, string>; vars: Map<string, string>;
} }
export interface TempEntitiesPacket extends BasePacket { export interface TempEntitiesPacket {
packetType: 'tempEntities'; packetType: 'tempEntities';
entities: PacketEntity[]; entities: PacketEntity[];
} }
export interface VoiceInitPacket extends BasePacket { export interface VoiceInitPacket {
packetType: 'voiceInit'; packetType: 'voiceInit';
codec: string; codec: string;
quality: number; quality: number;
extraData: number; extraData: number;
} }
export interface VoiceDataPacket extends BasePacket { export interface VoiceDataPacket {
packetType: 'voiceData'; packetType: 'voiceData';
client: number; client: number;
proximity: number; proximity: number;
@ -122,54 +119,54 @@ export interface VoiceDataPacket extends BasePacket {
data: BitStream; data: BitStream;
} }
export interface MenuPacket extends BasePacket { export interface MenuPacket {
packetType: 'menu'; packetType: 'menu';
type: number; type: number;
length: number; length: number;
data: BitStream; data: BitStream;
} }
export interface CmdKeyValuesPacket extends BasePacket { export interface CmdKeyValuesPacket {
packetType: 'cmdKeyValues'; packetType: 'cmdKeyValues';
length: number; length: number;
data: BitStream; data: BitStream;
} }
export interface VoidPacket extends BasePacket { export interface VoidPacket {
packetType: 'void'; packetType: 'void';
} }
export interface FilePacket extends BasePacket { export interface FilePacket {
packetType: 'file'; packetType: 'file';
transferId: number; transferId: number;
fileName: string; fileName: string;
requested: boolean; requested: boolean;
} }
export interface NetTickPacket extends BasePacket { export interface NetTickPacket {
packetType: 'netTick'; packetType: 'netTick';
tick: number; tick: number;
frameTime: number; frameTime: number;
stdDev: number; stdDev: number;
} }
export interface StringCmdPacket extends BasePacket { export interface StringCmdPacket {
packetType: 'stringCmd'; packetType: 'stringCmd';
command: string; command: string;
} }
export interface SigOnStatePacket extends BasePacket { export interface SigOnStatePacket {
packetType: 'sigOnState'; packetType: 'sigOnState';
state: number; state: number;
count: number; count: number;
} }
export interface PrintPacket extends BasePacket { export interface PrintPacket {
packetType: 'print'; packetType: 'print';
value: string; value: string;
} }
export interface ServerInfoPacket extends BasePacket { export interface ServerInfoPacket {
packetType: 'serverInfo'; packetType: 'serverInfo';
version: number; version: number;
serverCount: number; serverCount: number;
@ -188,17 +185,17 @@ export interface ServerInfoPacket extends BasePacket {
replay: boolean; replay: boolean;
} }
export interface SetPausePacket extends BasePacket { export interface SetPausePacket {
packetType: 'setPause'; packetType: 'setPause';
paused: boolean; paused: boolean;
} }
export interface SetViewPacket extends BasePacket { export interface SetViewPacket {
packetType: 'setView'; packetType: 'setView';
index: number; index: number;
} }
export interface FixAnglePacket extends BasePacket { export interface FixAnglePacket {
packetType: 'fixAngle'; packetType: 'fixAngle';
relative: boolean; relative: boolean;
x: number; x: number;
@ -206,12 +203,12 @@ export interface FixAnglePacket extends BasePacket {
z: number; z: number;
} }
export interface PreFetchPacket extends BasePacket { export interface PreFetchPacket {
packetType: 'preFetch'; packetType: 'preFetch';
index: number; index: number;
} }
export interface GetCvarValuePacket extends BasePacket { export interface GetCvarValuePacket {
packetType: 'getCvarValue'; packetType: 'getCvarValue';
cookie: number; cookie: number;
value: string; value: string;
@ -312,5 +309,5 @@ export enum PacketTypeId {
menu = 29, menu = 29,
gameEventList = 30, gameEventList = 30,
getCvarValue = 31, getCvarValue = 31,
cmdKeyValues = 32, cmdKeyValues = 32
} }

View file

@ -6,12 +6,21 @@ export enum PVS {
PRESERVE = 0, PRESERVE = 0,
ENTER = 1, ENTER = 1,
LEAVE = 2, LEAVE = 2,
DELETE = 4, DELETE = 4
} }
export type EntityId = number; export type EntityId = number;
export class PacketEntity { export class PacketEntity {
public static getPropByFullName(props: SendProp[], fullName: string): SendProp | null {
for (const prop of props) {
if (prop.definition.fullName === fullName) {
return prop;
}
}
return null;
}
public serverClass: ServerClass; public serverClass: ServerClass;
public entityIndex: EntityId; public entityIndex: EntityId;
public props: SendProp[]; public props: SendProp[];
@ -28,15 +37,6 @@ export class PacketEntity {
this.pvs = pvs; this.pvs = pvs;
} }
public static getPropByFullName(props: SendProp[], fullName: string): SendProp | null {
for (const prop of props) {
if (prop.definition.fullName === fullName) {
return prop;
}
}
return null;
}
public getPropByDefinition(definition: SendPropDefinition) { public getPropByDefinition(definition: SendPropDefinition) {
return PacketEntity.getPropByFullName(this.props, definition.fullName); return PacketEntity.getPropByFullName(this.props, definition.fullName);
} }
@ -75,7 +75,7 @@ export class PacketEntity {
} }
public diffFromBaseLine(baselineProps: SendProp[]): SendProp[] { public diffFromBaseLine(baselineProps: SendProp[]): SendProp[] {
return this.props.filter(prop => { return this.props.filter((prop) => {
const baseProp = PacketEntity.getPropByFullName(baselineProps, prop.definition.fullName); const baseProp = PacketEntity.getPropByFullName(baselineProps, prop.definition.fullName);
return (!baseProp || prop.value !== baseProp.value); return (!baseProp || prop.value !== baseProp.value);
}); });

View file

@ -1,19 +1,19 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {GameEventDefinition} from './GameEvent'; import {handleGameEventList} from '../PacketHandler/GameEventList';
import {EntityId} from './PacketEntity'; import {handlePacketEntitiesForState} from '../PacketHandler/PacketEntities';
import {SendTable, SendTableName} from './SendTable';
import {ServerClass, ServerClassId} from './ServerClass';
import {StringTable} from './StringTable';
import {GameEventType} from './GameEventTypes';
import {SendProp} from './SendProp';
import {Packet, PacketTypeId} from './Packet';
import { import {
handleStringTable, handleStringTables, handleStringTableUpdate, handleStringTable, handleStringTables, handleStringTableUpdate,
handleTable handleTable
} from '../PacketHandler/StringTable'; } from '../PacketHandler/StringTable';
import {handleGameEventList} from '../PacketHandler/GameEventList'; import {GameEventDefinition} from './GameEvent';
import {GameEventType} from './GameEventTypes';
import {DataTablesMessage, Message, MessageType, StringTablesMessage} from './Message'; import {DataTablesMessage, Message, MessageType, StringTablesMessage} from './Message';
import {handlePacketEntitiesForState} from '../PacketHandler/PacketEntities'; import {Packet, PacketTypeId} from './Packet';
import {EntityId} from './PacketEntity';
import {SendProp} from './SendProp';
import {SendTable, SendTableName} from './SendTable';
import {ServerClass, ServerClassId} from './ServerClass';
import {StringTable} from './StringTable';
export class ParserState { export class ParserState {
public version: number = 0; public version: number = 0;
@ -62,6 +62,14 @@ export class ParserState {
} }
} }
public getStringTable(name: string): StringTable | null {
const table = this.stringTables.find((stringTable) => stringTable.name === name);
if (!table) {
return null;
}
return table;
}
private handleDataTableMessage(message: DataTablesMessage) { private handleDataTableMessage(message: DataTablesMessage) {
for (const table of message.tables) { for (const table of message.tables) {
this.sendTables.set(table.name, table); this.sendTables.set(table.name, table);
@ -74,14 +82,6 @@ export class ParserState {
handleTable(table, this); handleTable(table, this);
} }
} }
public getStringTable(name: string): StringTable | null {
const table = this.stringTables.find(table => table.name === name);
if (!table) {
return null;
}
return table;
}
} }
export function getClassBits(state: ParserState) { export function getClassBits(state: ParserState) {

View file

@ -1,15 +1,15 @@
import {Match} from './Match'; import {Match} from './Match';
import {EntityId} from './PacketEntity';
import {PlayerCondition} from './PlayerCondition'; import {PlayerCondition} from './PlayerCondition';
import {UserInfo} from './UserInfo'; import {UserInfo} from './UserInfo';
import {Vector} from './Vector'; import {Vector} from './Vector';
import {Weapon} from './Weapon'; import {Weapon} from './Weapon';
import {EntityId} from './PacketEntity';
export enum LifeState { export enum LifeState {
ALIVE = 0, ALIVE = 0,
DYING = 1, DYING = 1,
DEATH = 2, DEATH = 2,
RESPAWNABLE = 3, RESPAWNABLE = 3
} }
export class Player { export class Player {
@ -33,8 +33,8 @@ export class Player {
get weapons(): Weapon[] { get weapons(): Weapon[] {
return this.weaponIds return this.weaponIds
.map(id => this.match.outerMap.get(id) as EntityId) .map((id) => this.match.outerMap.get(id) as EntityId)
.filter(entityId => entityId > 0) .filter((entityId) => entityId > 0)
.map(entityId => this.match.weaponMap.get(entityId) as Weapon); .map((entityId) => this.match.weaponMap.get(entityId) as Weapon);
} }
} }

View file

@ -77,5 +77,5 @@ export enum PlayerCondition {
TF_COND_HALLOWEEN_TINY = (1 << 75), TF_COND_HALLOWEEN_TINY = (1 << 75),
TF_COND_HALLOWEEN_IN_HELL = (1 << 76), TF_COND_HALLOWEEN_IN_HELL = (1 << 76),
TF_COND_HALLOWEEN_GHOST_MODE = (1 << 77), TF_COND_HALLOWEEN_GHOST_MODE = (1 << 77),
TF_COND_MINICRITBOOSTED_ON_KILL = (1 << 78), TF_COND_MINICRITBOOSTED_ON_KILL = (1 << 78)
} }

View file

@ -1,5 +1,5 @@
export interface Round { export interface Round {
winner: 'red' | 'blue', winner: 'red' | 'blue';
length: number; length: number;
end_tick: number; end_tick: number;
} }

View file

@ -1,6 +1,21 @@
import {SendTable} from './SendTable'; import {SendTable} from './SendTable';
export class SendPropDefinition { export class SendPropDefinition {
public static formatFlags(flags: number) {
const names: string[] = [];
for (const name in SendPropFlag) {
if ((SendPropFlag as object).hasOwnProperty(name)) {
const flagValue = SendPropFlag[name] as SendPropFlag | string;
if (typeof flagValue === 'number') {
if (flags & flagValue) {
names.push(name);
}
}
}
}
return names;
}
public type: SendPropType; public type: SendPropType;
public name: string; public name: string;
public flags: number; public flags: number;
@ -41,7 +56,7 @@ export class SendPropDefinition {
name: this.name, name: this.name,
type: SendPropType[this.type], type: SendPropType[this.type],
flags: this.flags, flags: this.flags,
bitCount: this.bitCount, bitCount: this.bitCount
}; };
if (this.type === SendPropType.DPT_Float) { if (this.type === SendPropType.DPT_Float) {
data.lowValue = this.lowValue; data.lowValue = this.lowValue;
@ -61,19 +76,6 @@ export class SendPropDefinition {
get allFlags() { get allFlags() {
return SendPropDefinition.formatFlags(this.flags); return SendPropDefinition.formatFlags(this.flags);
} }
static formatFlags(flags: number) {
let names: string[] = [];
for (const name in SendPropFlag) {
const flagValue = <SendPropFlag | string>SendPropFlag[name];
if (typeof flagValue === 'number') {
if (flags & flagValue) {
names.push(name);
}
}
}
return names;
}
} }
export enum SendPropType { export enum SendPropType {
@ -84,7 +86,7 @@ export enum SendPropType {
DPT_String, DPT_String,
DPT_Array, DPT_Array,
DPT_DataTable, DPT_DataTable,
DPT_NUMSendPropTypes, DPT_NUMSendPropTypes
} }
export enum SendPropFlag { export enum SendPropFlag {
@ -111,5 +113,5 @@ export enum SendPropFlag {
SPROP_COORD_MP_LOWPRECISION = (1 << 14), // Like SPROP_COORD, but special handling for multiplayer games SPROP_COORD_MP_LOWPRECISION = (1 << 14), // Like SPROP_COORD, but special handling for multiplayer games
// where the fractional component only gets a 3 bits instead of 5 // where the fractional component only gets a 3 bits instead of 5
SPROP_COORD_MP_INTEGRAL = (1 << 15), // SPROP_COORD_MP, but coordinates are rounded to integral boundaries SPROP_COORD_MP_INTEGRAL = (1 << 15), // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
SPROP_VARINT = (1 << 5), SPROP_VARINT = (1 << 5)
} }

View file

@ -2,7 +2,7 @@ export enum TeamNumber {
UNASGINED = 0, UNASGINED = 0,
SPECTATOR = 1, SPECTATOR = 1,
RED = 2, RED = 2,
BLU = 3, BLU = 3
} }
export interface Team { export interface Team {

View file

@ -1,4 +1,3 @@
import {BasePacket} from './Packet';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
export enum UserMessageType { export enum UserMessageType {
@ -59,14 +58,14 @@ export enum UserMessageType {
HapPunch = 54, HapPunch = 54,
HapSetDrag = 55, HapSetDrag = 55,
HapSet = 56, HapSet = 56,
HapMeleeContact = 57, HapMeleeContact = 57
} }
export interface BaseDataUserPacket extends BasePacket { export interface BaseDataUserPacket {
data: number; data: number;
} }
export interface SayText2Packet extends BasePacket { export interface SayText2Packet {
packetType: 'sayText2'; packetType: 'sayText2';
client: number; client: number;
raw: number; raw: number;
@ -82,7 +81,7 @@ export enum HudTextLocation {
HUD_PRINTCENTER = 4 HUD_PRINTCENTER = 4
} }
export interface TextMessagePacket extends BasePacket { export interface TextMessagePacket {
packetType: 'textMsg'; packetType: 'textMsg';
destType: HudTextLocation; destType: HudTextLocation;
text: string; text: string;
@ -96,14 +95,14 @@ export interface TrainPacket extends BaseDataUserPacket {
packetType: 'train'; packetType: 'train';
} }
export interface VoiceSubtitlePacket extends BasePacket { export interface VoiceSubtitlePacket {
packetType: 'voiceSubtitle'; packetType: 'voiceSubtitle';
client: number; client: number;
menu: number; menu: number;
item: number; item: number;
} }
export interface ShakePacket extends BasePacket { export interface ShakePacket {
packetType: 'shake'; packetType: 'shake';
command: number; command: number;
amplitude: number; amplitude: number;
@ -111,7 +110,7 @@ export interface ShakePacket extends BasePacket {
duration: number; duration: number;
} }
export interface UnknownUserMessageBasePacket extends BasePacket { export interface UnknownUserMessageBasePacket {
data: BitStream; data: BitStream;
type: number; type: number;
} }
@ -136,7 +135,7 @@ export type UserMessagePacket = SayText2Packet
| BreakModelPumpkinPacket | BreakModelPumpkinPacket
| ShakePacket; | ShakePacket;
export type UserMessageTypeMap = { export interface UserMessageTypeMap {
sayText2: SayText2Packet; sayText2: SayText2Packet;
textMsg: TextMessagePacket; textMsg: TextMessagePacket;
unknownUserMessage: GenericUnknownUserMessagePacket; unknownUserMessage: GenericUnknownUserMessagePacket;
@ -147,7 +146,8 @@ export type UserMessageTypeMap = {
shake: ShakePacket; shake: ShakePacket;
} }
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> = new Map<UserMessagePacket['packetType'], UserMessageType>([ export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> =
new Map<UserMessagePacket['packetType'], UserMessageType>([
['sayText2', UserMessageType.SayText2], ['sayText2', UserMessageType.SayText2],
['textMsg', UserMessageType.TextMsg], ['textMsg', UserMessageType.TextMsg],
['train', UserMessageType.Train], ['train', UserMessageType.Train],

View file

@ -1,7 +1,7 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {Parser} from './Parser';
import {PacketTypeId} from './Data/Packet';
import {Analyser} from './Analyser'; import {Analyser} from './Analyser';
import {PacketTypeId} from './Data/Packet';
import {Parser} from './Parser';
export class Demo { export class Demo {
public static fromNodeBuffer(nodeBuffer) { public static fromNodeBuffer(nodeBuffer) {
@ -26,7 +26,7 @@ export class Demo {
const skippedPackets = fastMode ? [ const skippedPackets = fastMode ? [
PacketTypeId.packetEntities, PacketTypeId.packetEntities,
PacketTypeId.tempEntities, PacketTypeId.tempEntities,
PacketTypeId.entityMessage, PacketTypeId.entityMessage
] : []; ] : [];
this.parser = new Parser(this.stream, skippedPackets); this.parser = new Parser(this.stream, skippedPackets);
} }

View file

@ -1,23 +1,5 @@
import {BitStream, BitView} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {DynamicBitView} from './DynamicBitView';
class DynamicBitView extends BitView {
protected _view: Uint8Array;
setBits(offset: number, value: number, bits: number) {
const available = (this.byteLength * 8 - offset);
if (bits > available) {
this.grow();
}
return super.setBits(offset, value, bits);
}
grow() {
const newView = new Uint8Array(this.byteLength * 2);
newView.set(this._view);
this._view = newView;
}
}
export class DynamicBitStream extends BitStream { export class DynamicBitStream extends BitStream {
constructor(initialByteSize: number = 16 * 1024) { constructor(initialByteSize: number = 16 * 1024) {

21
src/DynamicBitView.ts Normal file
View file

@ -0,0 +1,21 @@
import {BitView} from 'bit-buffer';
export class DynamicBitView extends BitView {
// tslint:disable-next-line
protected _view: Uint8Array;
public setBits(offset: number, value: number, bits: number) {
const available = (this.byteLength * 8 - offset);
if (bits > available) {
this.grow();
}
return super.setBits(offset, value, bits);
}
public grow() {
const newView = new Uint8Array(this.byteLength * 2);
newView.set(this._view);
this._view = newView;
}
}

View file

@ -1,8 +1,8 @@
import {Match} from '../Data/Match';
import {GameEventPacket} from '../Data/Packet';
import { import {
ObjectDestroyedEvent, PlayerDeathEvent, PlayerSpawnEvent, TeamPlayRoundStartEvent, TeamPlayRoundWinEvent ObjectDestroyedEvent, PlayerDeathEvent, PlayerSpawnEvent, TeamPlayRoundStartEvent, TeamPlayRoundWinEvent
} from '../Data/GameEventTypes'; } from '../Data/GameEventTypes';
import {Match} from '../Data/Match';
import {GameEventPacket} from '../Data/Packet';
export function handleGameEvent(packet: GameEventPacket, match: Match) { export function handleGameEvent(packet: GameEventPacket, match: Match) {
switch (packet.event.name) { switch (packet.event.name) {
@ -42,7 +42,7 @@ function handlePlayerDeath(event: PlayerDeathEvent, match: Match) {
assister, assister,
victim: values.userid, victim: values.userid,
weapon: values.weapon, weapon: values.weapon,
tick: match.tick, tick: match.tick
}); });
} }
@ -52,7 +52,7 @@ function handleRoundWin(event: TeamPlayRoundWinEvent, match: Match) {
match.rounds.push({ match.rounds.push({
winner: values.team === 2 ? 'red' : 'blue', winner: values.team === 2 ? 'red' : 'blue',
length: values.round_time, length: values.round_time,
end_tick: match.tick, end_tick: match.tick
}); });
} }
} }

View file

@ -2,12 +2,12 @@ import {Building, Dispenser, Sentry, Teleporter} from '../Data/Building';
import {Match} from '../Data/Match'; import {Match} from '../Data/Match';
import {PacketEntitiesPacket} from '../Data/Packet'; import {PacketEntitiesPacket} from '../Data/Packet';
import {PacketEntity, PVS} from '../Data/PacketEntity'; import {PacketEntity, PVS} from '../Data/PacketEntity';
import {ParserState} from '../Data/ParserState';
import {LifeState, Player} from '../Data/Player'; import {LifeState, Player} from '../Data/Player';
import {SendProp} from '../Data/SendProp'; import {SendProp} from '../Data/SendProp';
import {TeamNumber} from '../Data/Team';
import {Vector} from '../Data/Vector'; import {Vector} from '../Data/Vector';
import {CWeaponMedigun, Weapon} from '../Data/Weapon'; import {CWeaponMedigun, Weapon} from '../Data/Weapon';
import {TeamNumber} from '../Data/Team';
import {ParserState} from '../Data/ParserState';
export function handlePacketEntities(packet: PacketEntitiesPacket, match: Match) { export function handlePacketEntities(packet: PacketEntitiesPacket, match: Match) {
for (const entity of packet.entities) { for (const entity of packet.entities) {
@ -47,7 +47,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
if (!match.weaponMap.has(entity.entityIndex)) { if (!match.weaponMap.has(entity.entityIndex)) {
match.weaponMap.set(entity.entityIndex, { match.weaponMap.set(entity.entityIndex, {
className: entity.serverClass.name, className: entity.serverClass.name,
owner: prop.value as number, owner: prop.value as number
}); });
} }
} }
@ -176,7 +176,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
score: entity.getProperty('DT_Team', 'm_iScore').value as number, score: entity.getProperty('DT_Team', 'm_iScore').value as number,
roundsWon: entity.getProperty('DT_Team', 'm_iRoundsWon').value as number, roundsWon: entity.getProperty('DT_Team', 'm_iRoundsWon').value as number,
players: entity.getProperty('DT_Team', '"player_array"').value as number[], players: entity.getProperty('DT_Team', '"player_array"').value as number[],
teamNumber: teamId, teamNumber: teamId
}; };
match.teams.set(teamId, team); match.teams.set(teamId, team);
match.teamEntityMap.set(entity.entityIndex, team); match.teamEntityMap.set(entity.entityIndex, team);
@ -225,7 +225,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
shieldLevel: 0, shieldLevel: 0,
isMini: false, isMini: false,
team: 0, team: 0,
angle: 0, angle: 0
}); });
} }
const sentry = match.buildings.get(entity.entityIndex) as Sentry; const sentry = match.buildings.get(entity.entityIndex) as Sentry;
@ -274,7 +274,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
team: 0, team: 0,
healing: [], healing: [],
metal: 0, metal: 0,
angle: 0, angle: 0
}); });
} }
const dispenser = match.buildings.get(entity.entityIndex) as Dispenser; const dispenser = match.buildings.get(entity.entityIndex) as Dispenser;
@ -312,7 +312,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
rechargeDuration: 0, rechargeDuration: 0,
timesUsed: 0, timesUsed: 0,
angle: 0, angle: 0,
yawToExit: 0, yawToExit: 0
}); });
} }
const teleporter = match.buildings.get(entity.entityIndex) as Teleporter; const teleporter = match.buildings.get(entity.entityIndex) as Teleporter;
@ -372,7 +372,7 @@ function handleEntity(entity: PacketEntity, match: Match) {
score: 0, score: 0,
team: 0, team: 0,
totalScore: 0, totalScore: 0,
damage: 0, damage: 0
}; };
} }
const playerResource = match.playerResources[playerId]; const playerResource = match.playerResources[playerId];

View file

@ -6,6 +6,6 @@ export function handleSayText2(packet: SayText2Packet, match: Match) {
kind: packet.kind, kind: packet.kind,
from: packet.from, from: packet.from,
text: packet.text, text: packet.text,
tick: match.tick, tick: match.tick
}); });
} }

View file

@ -1,6 +1,6 @@
import {CreateStringTablePacket, StringTablePacket, UpdateStringTablePacket} from '../Data/Packet'; import {CreateStringTablePacket, StringTablePacket, UpdateStringTablePacket} from '../Data/Packet';
import {StringTable, StringTableEntry} from '../Data/StringTable';
import {ParserState} from '../Data/ParserState'; import {ParserState} from '../Data/ParserState';
import {StringTable, StringTableEntry} from '../Data/StringTable';
export function handleStringTable(packet: CreateStringTablePacket, state: ParserState) { export function handleStringTable(packet: CreateStringTablePacket, state: ParserState) {
handleTable(packet.table, state); handleTable(packet.table, state);
@ -17,7 +17,6 @@ export function handleStringTableUpdate(packet: UpdateStringTablePacket, state:
handleStringTableEntries(updatedTable.name, packet.entries, state); handleStringTableEntries(updatedTable.name, packet.entries, state);
} }
export function handleTable(table: StringTable, state: ParserState) { export function handleTable(table: StringTable, state: ParserState) {
if (!state.getStringTable(table.name)) { if (!state.getStringTable(table.name)) {
state.stringTables.push(table); state.stringTables.push(table);

View file

@ -1,14 +1,14 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {Header} from './Data/Header'; import {Header} from './Data/Header';
import {Message, MessageHandler, MessageType, PacketMessage} from './Data/Message';
import {Packet, PacketTypeId} from './Data/Packet';
import {ParserState} from './Data/ParserState';
import {ConsoleCmdHandler} from './Parser/Message/ConsoleCmd'; import {ConsoleCmdHandler} from './Parser/Message/ConsoleCmd';
import {DataTableHandler} from './Parser/Message/DataTable'; import {DataTableHandler} from './Parser/Message/DataTable';
import {PacketMessageHandler} from './Parser/Message/Packet'; import {PacketMessageHandler} from './Parser/Message/Packet';
import {StringTableHandler} from './Parser/Message/StringTable'; import {StringTableHandler} from './Parser/Message/StringTable';
import {UserCmdHandler} from './Parser/Message/UserCmd';
import {Packet, PacketTypeId} from './Data/Packet';
import {Message, MessageHandler, MessageType, PacketMessage} from './Data/Message';
import {ParserState} from './Data/ParserState';
import {SyncTickHandler} from './Parser/Message/SyncTick'; import {SyncTickHandler} from './Parser/Message/SyncTick';
import {UserCmdHandler} from './Parser/Message/UserCmd';
const messageHandlers: Map<MessageType, MessageHandler<Message>> = new Map<MessageType, MessageHandler<Message>>([ const messageHandlers: Map<MessageType, MessageHandler<Message>> = new Map<MessageType, MessageHandler<Message>>([
[MessageType.Sigon, PacketMessageHandler], [MessageType.Sigon, PacketMessageHandler],
@ -47,7 +47,7 @@ export class Parser {
} }
} }
private * getMessages(): Iterable<Message> { protected * getMessages(): Iterable<Message> {
while (true) { while (true) {
const message = this.readMessage(this.stream, this.parserState); const message = this.readMessage(this.stream, this.parserState);
if (message) { if (message) {
@ -78,7 +78,7 @@ export class Parser {
duration: stream.readFloat32(), duration: stream.readFloat32(),
ticks: stream.readInt32(), ticks: stream.readInt32(),
frames: stream.readInt32(), frames: stream.readInt32(),
sigon: stream.readInt32(), sigon: stream.readInt32()
}; };
} }

View file

@ -2,8 +2,8 @@ import {BitStream} from 'bit-buffer';
import {SendProp} from '../Data/SendProp'; import {SendProp} from '../Data/SendProp';
import {SendTable} from '../Data/SendTable'; import {SendTable} from '../Data/SendTable';
import {readBitVar, writeBitVar} from './readBitVar'; import {readBitVar, writeBitVar} from './readBitVar';
import {SendPropParser} from './SendPropParser';
import {SendPropEncoder} from './SendPropEncoder'; import {SendPropEncoder} from './SendPropEncoder';
import {SendPropParser} from './SendPropParser';
export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[] { export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[] {
let index = -1; let index = -1;
@ -29,13 +29,15 @@ export function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stre
let lastIndex = -1; let lastIndex = -1;
for (const prop of props) { for (const prop of props) {
stream.writeBoolean(true); stream.writeBoolean(true);
const index = allProps.findIndex(propDef => propDef.fullName === prop.definition.fullName); const index = allProps.findIndex((propDef) => propDef.fullName === prop.definition.fullName);
if (index === -1) { if (index === -1) {
throw new Error(`Unknown definition for property ${prop.definition.fullName} in ${sendTable.name}`); throw new Error(`Unknown definition for property ${prop.definition.fullName} in ${sendTable.name}`);
} }
if (index < lastIndex) { 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})`); 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); writeFieldIndex(index, stream, lastIndex);
lastIndex = index; lastIndex = index;

View file

@ -1,14 +1,14 @@
import {BitStream} from 'bit-buffer';
import {TextEncoder} from 'text-encoding-shim';
import {ConsoleCmdMessage, MessageHandler, MessageType} from '../../Data/Message';
import {ConsoleCmdPacket} from '../../Data/Packet'; import {ConsoleCmdPacket} from '../../Data/Packet';
import {Parser} from './Parser'; import {Parser} from './Parser';
import {BitStream} from 'bit-buffer';
import {ConsoleCmdMessage, MessageHandler, MessageType} from '../../Data/Message';
import {TextEncoder} from 'text-encoding-shim';
export class ConsoleCmd extends Parser { export class ConsoleCmd extends Parser {
public parse(): ConsoleCmdPacket[] { public parse(): ConsoleCmdPacket[] {
return [{ return [{
packetType: 'consoleCmd', packetType: 'consoleCmd',
command: this.stream.readUTF8String(), command: this.stream.readUTF8String()
}]; }];
} }
} }

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer';
import {DataTablesMessage, MessageHandler, MessageType} from '../../Data/Message';
import {SendPropDefinition, SendPropFlag, SendPropType} from '../../Data/SendPropDefinition'; import {SendPropDefinition, SendPropFlag, SendPropType} from '../../Data/SendPropDefinition';
import {SendTable} from '../../Data/SendTable'; import {SendTable} from '../../Data/SendTable';
import {ServerClass} from '../../Data/ServerClass'; import {ServerClass} from '../../Data/ServerClass';
import {DataTablesMessage, MessageHandler, MessageType} from '../../Data/Message';
import {BitStream} from 'bit-buffer';
export const DataTableHandler: MessageHandler<DataTablesMessage> = { export const DataTableHandler: MessageHandler<DataTablesMessage> = {
parseMessage: (stream: BitStream) => { parseMessage: (stream: BitStream) => {
@ -129,7 +129,7 @@ export const DataTableHandler: MessageHandler<DataTablesMessage> = {
tick, tick,
rawData: messageStream, rawData: messageStream,
tables, tables,
serverClasses, serverClasses
}; };
}, },
encodeMessage: (message, stream) => { encodeMessage: (message, stream) => {

View file

@ -1,4 +1,3 @@
import {make} from '../Packet/ParserGenerator';
import {EncodeBSPDecal, ParseBSPDecal} from '../Packet/BSPDecal'; import {EncodeBSPDecal, ParseBSPDecal} from '../Packet/BSPDecal';
import {EncodeClassInfo, ParseClassInfo} from '../Packet/ClassInfo'; import {EncodeClassInfo, ParseClassInfo} from '../Packet/ClassInfo';
import {EncodeCreateStringTable, ParseCreateStringTable} from '../Packet/CreateStringTable'; import {EncodeCreateStringTable, ParseCreateStringTable} from '../Packet/CreateStringTable';
@ -6,6 +5,7 @@ import {EncodeGameEvent, ParseGameEvent} from '../Packet/GameEvent';
import {EncodeGameEventList, ParseGameEventList} from '../Packet/GameEventList'; import {EncodeGameEventList, ParseGameEventList} from '../Packet/GameEventList';
import {EncodePacketEntities, ParsePacketEntities} from '../Packet/PacketEntities'; import {EncodePacketEntities, ParsePacketEntities} from '../Packet/PacketEntities';
import {PacketHandler} from '../Packet/Parser'; import {PacketHandler} from '../Packet/Parser';
import {make} from '../Packet/ParserGenerator';
import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds'; import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds';
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar'; import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
import {EncodeTempEntities, ParseTempEntities} from '../Packet/TempEntities'; import {EncodeTempEntities, ParseTempEntities} from '../Packet/TempEntities';
@ -14,9 +14,9 @@ import {EncodeUserMessage, ParseUserMessage} from '../Packet/UserMessage';
import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData'; import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData';
import {EncodeVoiceInit, ParseVoiceInit} from '../Packet/VoiceInit'; import {EncodeVoiceInit, ParseVoiceInit} from '../Packet/VoiceInit';
import {Packet as IPacket, PacketTypeId} from '../../Data/Packet';
import {MessageHandler, MessageType, PacketMessage} from '../../Data/Message';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {MessageHandler, MessageType, PacketMessage} from '../../Data/Message';
import {Packet as IPacket, PacketTypeId} from '../../Data/Packet';
import {ParserState} from '../../Data/ParserState'; import {ParserState} from '../../Data/ParserState';
import {Vector} from '../../Data/Vector'; import {Vector} from '../../Data/Vector';
@ -79,7 +79,7 @@ const handlers: PacketHandlerMap = new Map<PacketTypeId, PacketHandler<IPacket>>
[PacketTypeId.getCvarValue, [PacketTypeId.getCvarValue,
make('getCvarValue', 'cookie{32}value{s}')], make('getCvarValue', 'cookie{32}value{s}')],
[PacketTypeId.cmdKeyValues, [PacketTypeId.cmdKeyValues,
make('cmdKeyValues', 'length{32}data{$length}')], make('cmdKeyValues', 'length{32}data{$length}')]
]); ]);
export const PacketMessageHandler: MessageHandler<PacketMessage> = { export const PacketMessageHandler: MessageHandler<PacketMessage> = {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {Packet, PacketTypeId} from '../../Data/Packet';
import {MessageType} from '../../Data/Message'; import {MessageType} from '../../Data/Message';
import {Packet, PacketTypeId} from '../../Data/Packet';
import {ParserState} from '../../Data/ParserState'; import {ParserState} from '../../Data/ParserState';
export abstract class Parser { export abstract class Parser {

View file

@ -1,6 +1,6 @@
import {StringTable as StringTableObject, StringTableEntry} from '../../Data/StringTable';
import {MessageHandler, MessageType, StringTablesMessage} from '../../Data/Message';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {MessageHandler, MessageType, StringTablesMessage} from '../../Data/Message';
import {StringTable as StringTableObject, StringTableEntry} from '../../Data/StringTable';
export const StringTableHandler: MessageHandler<StringTablesMessage> = { export const StringTableHandler: MessageHandler<StringTablesMessage> = {
parseMessage: (stream: BitStream) => { parseMessage: (stream: BitStream) => {
@ -18,7 +18,7 @@ export const StringTableHandler: MessageHandler<StringTablesMessage> = {
const entryCount = messageStream.readUint16(); const entryCount = messageStream.readUint16();
for (let j = 0; j < entryCount; j++) { for (let j = 0; j < entryCount; j++) {
const entry: StringTableEntry = { const entry: StringTableEntry = {
text: messageStream.readUTF8String(), text: messageStream.readUTF8String()
}; };
if (messageStream.readBoolean()) { if (messageStream.readBoolean()) {
const extraDataLength = messageStream.readUint16(); const extraDataLength = messageStream.readUint16();
@ -40,7 +40,7 @@ export const StringTableHandler: MessageHandler<StringTablesMessage> = {
const table: StringTableObject = { const table: StringTableObject = {
entries, entries,
name: tableName, name: tableName,
maxEntries: entryCount, maxEntries: entryCount
}; };
if (messageStream.readBoolean()) { if (messageStream.readBoolean()) {
@ -57,7 +57,7 @@ export const StringTableHandler: MessageHandler<StringTablesMessage> = {
type: MessageType.StringTables, type: MessageType.StringTables,
tick, tick,
rawData: messageStream, rawData: messageStream,
tables, tables
}; };
}, },
encodeMessage: (message, stream) => { encodeMessage: (message, stream) => {

View file

@ -1,5 +1,5 @@
import {MessageHandler, MessageType, SyncTickMessage} from '../../Data/Message';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {MessageHandler, MessageType, SyncTickMessage} from '../../Data/Message';
export const SyncTickHandler: MessageHandler<SyncTickMessage> = { export const SyncTickHandler: MessageHandler<SyncTickMessage> = {
parseMessage: (stream: BitStream) => { parseMessage: (stream: BitStream) => {

View file

@ -1,5 +1,5 @@
import {MessageHandler, MessageType, UserCmdMessage} from '../../Data/Message';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {MessageHandler, MessageType, UserCmdMessage} from '../../Data/Message';
export const UserCmdHandler: MessageHandler<UserCmdMessage> = { export const UserCmdHandler: MessageHandler<UserCmdMessage> = {
parseMessage: (stream: BitStream) => { parseMessage: (stream: BitStream) => {

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {BSPDecalPacket} from '../../Data/Packet'; import {BSPDecalPacket} from '../../Data/Packet';
import {Vector} from '../../Data/Vector'; import {Vector} from '../../Data/Vector';
import {SendPropParser} from '../SendPropParser';
import {SendPropEncoder} from '../SendPropEncoder'; import {SendPropEncoder} from '../SendPropEncoder';
import {SendPropParser} from '../SendPropParser';
export function getVecCoord(stream: BitStream): Vector { export function getVecCoord(stream: BitStream): Vector {
const hasX = stream.readBoolean(); const hasX = stream.readBoolean();
@ -12,7 +12,7 @@ export function getVecCoord(stream: BitStream): Vector {
return { return {
x: hasX ? SendPropParser.readBitCoord(stream) : 0, x: hasX ? SendPropParser.readBitCoord(stream) : 0,
y: hasY ? SendPropParser.readBitCoord(stream) : 0, y: hasY ? SendPropParser.readBitCoord(stream) : 0,
z: hasZ ? SendPropParser.readBitCoord(stream) : 0, z: hasZ ? SendPropParser.readBitCoord(stream) : 0
}; };
} }
@ -49,7 +49,7 @@ export function ParseBSPDecal(stream: BitStream): BSPDecalPacket { // 21: ParseB
textureIndex, textureIndex,
entIndex, entIndex,
modelIndex, modelIndex,
lowPriority, lowPriority
}; };
} }

View file

@ -2,22 +2,21 @@ import {BitStream} from 'bit-buffer';
import {ClassInfoPacket} from '../../Data/Packet'; import {ClassInfoPacket} from '../../Data/Packet';
import {logBase2} from '../../Math'; import {logBase2} from '../../Math';
export function ParseClassInfo(stream: BitStream): ClassInfoPacket { // 10: classInfo export function ParseClassInfo(stream: BitStream): ClassInfoPacket { // 10: classInfo
const count = stream.readUint16(); const count = stream.readUint16();
const create = stream.readBoolean(); const create = stream.readBoolean();
const entries: { const entries: Array<{
classId: number; classId: number;
className: string; className: string;
dataTableName: string; dataTableName: string;
}[] = []; }> = [];
if (!create) { if (!create) {
const bits = logBase2(count) + 1; const bits = logBase2(count) + 1;
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const entry = { const entry = {
classId: stream.readBits(bits), classId: stream.readBits(bits),
className: stream.readASCIIString(), className: stream.readASCIIString(),
dataTableName: stream.readASCIIString(), dataTableName: stream.readASCIIString()
}; };
entries.push(entry); entries.push(entry);
} }
@ -26,7 +25,7 @@ export function ParseClassInfo(stream: BitStream): ClassInfoPacket { // 10: clas
packetType: 'classInfo', packetType: 'classInfo',
number: count, number: count,
create, create,
entries, entries
}; };
} }

View file

@ -53,14 +53,14 @@ export function ParseCreateStringTable(stream: BitStream): CreateStringTablePack
entries: [], entries: [],
maxEntries, maxEntries,
fixedUserDataSize: userDataSize, fixedUserDataSize: userDataSize,
fixedUserDataSizeBits: userDataSizeBits, fixedUserDataSizeBits: userDataSizeBits
}; };
table.entries = parseStringTableEntries(data, table, entityCount); table.entries = parseStringTableEntries(data, table, entityCount);
return { return {
packetType: 'createStringTable', packetType: 'createStringTable',
table: table, table
}; };
} }

View file

@ -1,7 +1,7 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import { import {
GameEventDefinition, GameEventEntry, GameEventDefinition, GameEventEntry,
GameEventValue, GameEventValueType, GameEventValue, GameEventValueType
} from '../../Data/GameEvent'; } from '../../Data/GameEvent';
import {GameEvent, GameEventType, GameEventTypeIdMap, GameEventTypeMap} from '../../Data/GameEventTypes'; import {GameEvent, GameEventType, GameEventTypeIdMap, GameEventTypeMap} from '../../Data/GameEventTypes';
import {GameEventPacket} from '../../Data/Packet'; import {GameEventPacket} from '../../Data/Packet';
@ -19,7 +19,7 @@ function parseGameEvent<T extends GameEventType>(definition: GameEventDefinition
return { return {
name, name,
values, values
}; };
} }
@ -98,7 +98,7 @@ export function ParseGameEvent(stream: BitStream, state: ParserState): GameEvent
return { return {
packetType: 'gameEvent', packetType: 'gameEvent',
event: event as GameEvent, event: event as GameEvent
}; };
} }

View file

@ -1,7 +1,7 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {GameEventDefinition, GameEventEntry} from '../../Data/GameEvent'; import {GameEventDefinition, GameEventEntry} from '../../Data/GameEvent';
import {GameEventListPacket} from '../../Data/Packet';
import {GameEvent, GameEventType} from '../../Data/GameEventTypes'; import {GameEvent, GameEventType} from '../../Data/GameEventTypes';
import {GameEventListPacket} from '../../Data/Packet';
export function ParseGameEventList(stream: BitStream): GameEventListPacket { // 30: gameEventList export function ParseGameEventList(stream: BitStream): GameEventListPacket { // 30: gameEventList
const s = stream.index; const s = stream.index;
@ -18,19 +18,19 @@ export function ParseGameEventList(stream: BitStream): GameEventListPacket { //
while (type !== 0) { while (type !== 0) {
entries.push({ entries.push({
type, type,
name: stream.readASCIIString(), name: stream.readASCIIString()
}); });
type = stream.readBits(3); type = stream.readBits(3);
} }
eventList.set(id, { eventList.set(id, {
id, id,
name, name,
entries, entries
}); });
} }
return { return {
packetType: 'gameEventList', packetType: 'gameEventList',
eventList, eventList
}; };
} }

View file

@ -1,23 +1,23 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {PacketEntitiesPacket} from '../../Data/Packet'; import {PacketEntitiesPacket} from '../../Data/Packet';
import {EntityId, PacketEntity, PVS} from '../../Data/PacketEntity'; import {EntityId, PacketEntity, PVS} from '../../Data/PacketEntity';
import {getClassBits, getSendTable, ParserState} from '../../Data/ParserState';
import {SendProp} from '../../Data/SendProp'; import {SendProp} from '../../Data/SendProp';
import {encodeEntityUpdate, getEntityUpdate} from '../EntityDecoder'; import {encodeEntityUpdate, getEntityUpdate} from '../EntityDecoder';
import {readUBitVar, writeBitVar} from '../readBitVar'; import {readUBitVar, writeBitVar} from '../readBitVar';
import {getClassBits, getSendTable, ParserState} from '../../Data/ParserState';
const pvsMap = new Map([ const pvsMap = new Map([
[0, PVS.PRESERVE], [0, PVS.PRESERVE],
[2, PVS.ENTER], [2, PVS.ENTER],
[1, PVS.LEAVE], [1, PVS.LEAVE],
[3, PVS.LEAVE + PVS.DELETE], [3, PVS.LEAVE + PVS.DELETE]
]); ]);
const pvsReverseMap = new Map([ const pvsReverseMap = new Map([
[PVS.PRESERVE, 0], [PVS.PRESERVE, 0],
[PVS.ENTER, 2], [PVS.ENTER, 2],
[PVS.LEAVE, 1], [PVS.LEAVE, 1],
[PVS.LEAVE + PVS.DELETE, 3], [PVS.LEAVE + PVS.DELETE, 3]
]); ]);
function readPVSType(stream: BitStream): PVS { function readPVSType(stream: BitStream): PVS {
@ -70,7 +70,9 @@ function readEnterPVS(stream: BitStream, entityId: EntityId, state: ParserState,
} }
function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserState, baseLineIndex: number) { function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserState, baseLineIndex: number) {
const serverClassId = state.serverClasses.findIndex(serverClass => serverClass && entity.serverClass.id === serverClass.id); const serverClassId = state.serverClasses.findIndex(
(existingServerClass) => existingServerClass && entity.serverClass.id === existingServerClass.id
);
if (serverClassId === -1) { if (serverClassId === -1) {
throw new Error(`Unknown server class ${entity.serverClass.name}(${entity.serverClass.id})`); throw new Error(`Unknown server class ${entity.serverClass.name}(${entity.serverClass.id})`);
} }
@ -100,8 +102,8 @@ function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserSta
// console.log(propsToEncode.map(prop => `${prop.definition.name}: ${prop.value}`)); // console.log(propsToEncode.map(prop => `${prop.definition.name}: ${prop.value}`));
const allProps = sendTable.flattenedProps; const allProps = sendTable.flattenedProps;
propsToEncode.sort((a, b) => allProps.findIndex(propDef => propDef.fullName === a.definition.fullName) - propsToEncode.sort((a, b) => allProps.findIndex((propDef) => propDef.fullName === a.definition.fullName) -
allProps.findIndex(propDef => propDef.fullName === b.definition.fullName)); allProps.findIndex((propDef) => propDef.fullName === b.definition.fullName));
encodeEntityUpdate(propsToEncode, sendTable, stream); encodeEntityUpdate(propsToEncode, sendTable, stream);
} }
@ -115,7 +117,11 @@ function getPacketEntityForExisting(entityId: EntityId, state: ParserState, pvs:
return new PacketEntity(serverClass, entityId, pvs); return new PacketEntity(serverClass, entityId, pvs);
} }
export function ParsePacketEntities(stream: BitStream, state: ParserState, skip: boolean = false): PacketEntitiesPacket { // 26: packetEntities export function ParsePacketEntities(
stream: BitStream,
state: ParserState,
skip: boolean = false
): PacketEntitiesPacket { // 26: packetEntities
// https://github.com/skadistats/smoke/blob/master/smoke/replay/handler/svc_packetentities.pyx // 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/Handler/PacketEntitesHandler.cs
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Entity.cs // https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Entity.cs
@ -186,7 +192,7 @@ export function ParsePacketEntities(stream: BitStream, state: ParserState, skip:
maxEntries, maxEntries,
delta, delta,
baseLine, baseLine,
updatedBaseLine, updatedBaseLine
}; };
} }

View file

@ -6,8 +6,8 @@ export type Parser<P extends Packet> = (stream: BitStream, state?: ParserState,
export type Encoder<P extends Packet> = (packet: P, stream: BitStream, state?: ParserState) => void; export type Encoder<P extends Packet> = (packet: P, stream: BitStream, state?: ParserState) => void;
export interface PacketHandler<P extends Packet> { export interface PacketHandler<P extends Packet> {
parser: Parser<P>, parser: Parser<P>;
encoder: Encoder<P> encoder: Encoder<P>;
} }
export const voidEncoder: Encoder<VoidPacket> = () => { export const voidEncoder: Encoder<VoidPacket> = () => {

View file

@ -1,15 +1,15 @@
import {BitStream} from 'bit-buffer';
import {PacketMapType, PacketType} from '../../Data/Packet'; import {PacketMapType, PacketType} from '../../Data/Packet';
import {Encoder, PacketHandler, Parser} from './Parser'; import {Encoder, PacketHandler, Parser} from './Parser';
import {BitStream} from 'bit-buffer';
export function make<T extends PacketType>(name: T, definition: string): PacketHandler<PacketMapType[T]> { export function make<T extends PacketType>(name: T, definition: string): PacketHandler<PacketMapType[T]> {
const parts = definition.split('}'); const parts = definition.split('}');
const items = parts.map((part) => { const items = parts.map((part) => {
return part.split('{'); return part.split('{');
}).filter(part => part[0]); }).filter((part) => part[0]);
const parser: Parser<PacketMapType[T]> = (stream: BitStream) => { const parser: Parser<PacketMapType[T]> = (stream: BitStream) => {
const result = { const result = {
packetType: name, packetType: name
}; };
try { try {
for (const group of items) { for (const group of items) {

View file

@ -11,7 +11,7 @@ export function ParseSetConVar(stream: BitStream): SetConVarPacket { // 5: setco
} }
return { return {
packetType: 'setConVar', packetType: 'setConVar',
vars, vars
}; };
} }

View file

@ -1,10 +1,10 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {TempEntitiesPacket} from '../../Data/Packet'; import {TempEntitiesPacket} from '../../Data/Packet';
import {PacketEntity, PVS} from '../../Data/PacketEntity'; import {PacketEntity, PVS} from '../../Data/PacketEntity';
import {getClassBits, getSendTable, ParserState} from '../../Data/ParserState';
import {DynamicBitStream} from '../../DynamicBitStream';
import {encodeEntityUpdate, getEntityUpdate} from '../EntityDecoder'; import {encodeEntityUpdate, getEntityUpdate} from '../EntityDecoder';
import {readVarInt, writeVarInt} from '../readBitVar'; import {readVarInt, writeVarInt} from '../readBitVar';
import {DynamicBitStream} from '../../DynamicBitStream';
import {getClassBits, getSendTable, ParserState} from '../../Data/ParserState';
export function ParseTempEntities(stream: BitStream, state: ParserState, skip: boolean = false): TempEntitiesPacket { // 10: classInfo export function ParseTempEntities(stream: BitStream, state: ParserState, skip: boolean = false): TempEntitiesPacket { // 10: classInfo
const entityCount = stream.readUint8(); const entityCount = stream.readUint8();
@ -45,7 +45,7 @@ export function ParseTempEntities(stream: BitStream, state: ParserState, skip: b
return { return {
packetType: 'tempEntities', packetType: 'tempEntities',
entities, entities
}; };
} }
@ -63,7 +63,7 @@ export function EncodeTempEntities(packet: TempEntitiesPacket, stream: BitStream
entityStream.writeBoolean(true); entityStream.writeBoolean(true);
const classId = state.serverClasses.findIndex(serverClass => serverClass && serverClass.name === entity.serverClass.name) + 1; const classId = state.serverClasses.findIndex((serverClass) => serverClass && serverClass.name === entity.serverClass.name) + 1;
entityStream.writeBits(classId, getClassBits(state)); entityStream.writeBits(classId, getClassBits(state));
const sendTable = getSendTable(state, entity.serverClass.dataTable); const sendTable = getSendTable(state, entity.serverClass.dataTable);

View file

@ -1,7 +1,7 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {UpdateStringTablePacket} from '../../Data/Packet'; import {UpdateStringTablePacket} from '../../Data/Packet';
import {encodeStringTableEntries, guessStringTableEntryLength, parseStringTableEntries} from '../StringTableParser';
import {ParserState} from '../../Data/ParserState'; import {ParserState} from '../../Data/ParserState';
import {encodeStringTableEntries, guessStringTableEntryLength, parseStringTableEntries} from '../StringTableParser';
export function ParseUpdateStringTable(stream: BitStream, state: ParserState): UpdateStringTablePacket { // 12: updateStringTable export function ParseUpdateStringTable(stream: BitStream, state: ParserState): UpdateStringTablePacket { // 12: updateStringTable
const tableId = stream.readBits(5); const tableId = stream.readBits(5);
@ -30,7 +30,7 @@ export function ParseUpdateStringTable(stream: BitStream, state: ParserState): U
export function EncodeUpdateStringTable(packet: UpdateStringTablePacket, stream: BitStream, state: ParserState) { export function EncodeUpdateStringTable(packet: UpdateStringTablePacket, stream: BitStream, state: ParserState) {
stream.writeBits(packet.tableId, 5); stream.writeBits(packet.tableId, 5);
const changedEntryCount = packet.entries.filter(entry => entry).length; const changedEntryCount = packet.entries.filter((entry) => entry).length;
const multipleChanged = changedEntryCount > 1; const multipleChanged = changedEntryCount > 1;
stream.writeBoolean(multipleChanged); stream.writeBoolean(multipleChanged);

View file

@ -1,15 +1,15 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
import {make} from './ParserGenerator';
import {PacketHandler} from './Parser';
import { import {
UserMessageType,
UserMessagePacket,
UnknownUserMessagePacket,
UnknownUserMessageBasePacket, UnknownUserMessageBasePacket,
UserMessageTypeMap, UnknownUserMessagePacket,
UserMessagePacketTypeMap UserMessagePacket,
UserMessagePacketTypeMap,
UserMessageType,
UserMessageTypeMap
} from '../../Data/UserMessage'; } from '../../Data/UserMessage';
import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
import {PacketHandler} from './Parser';
import {make} from './ParserGenerator';
function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(packetType: T): PacketHandler<UserMessageTypeMap[T]> { function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(packetType: T): PacketHandler<UserMessageTypeMap[T]> {
return { return {
@ -28,7 +28,8 @@ function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(
}; };
} }
const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> = new Map<UserMessageType, PacketHandler<UserMessagePacket>>([ const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> =
new Map<UserMessageType, PacketHandler<UserMessagePacket>>([
[UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}], [UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}],
[UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}')], [UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}')],
[UserMessageType.ResetHUD, make('resetHUD', 'data{8}')], [UserMessageType.ResetHUD, make('resetHUD', 'data{8}')],
@ -50,7 +51,7 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
return { return {
packetType: 'unknownUserMessage', packetType: 'unknownUserMessage',
type, type,
data: messageData, data: messageData
}; };
} else { } else {
return handler.parser(messageData); return handler.parser(messageData);

View file

@ -12,7 +12,7 @@ export function ParseVoiceData(stream: BitStream): VoiceDataPacket {
client, client,
proximity, proximity,
length, length,
data, data
}; };
} }

View file

@ -12,7 +12,7 @@ export function ParseVoiceInit(stream: BitStream): VoiceInitPacket {
packetType: 'voiceInit', packetType: 'voiceInit',
codec, codec,
quality, quality,
extraData, extraData
}; };
} }

View file

@ -27,9 +27,6 @@ export class SendPropParser {
} }
public static readInt(propDefinition: SendPropDefinition, stream: BitStream) { public static readInt(propDefinition: SendPropDefinition, stream: BitStream) {
if (!propDefinition.hasFlag) {
console.log(propDefinition, propDefinition.hasFlag);
}
if (propDefinition.hasFlag(SendPropFlag.SPROP_VARINT)) { if (propDefinition.hasFlag(SendPropFlag.SPROP_VARINT)) {
return readVarInt(stream, !propDefinition.hasFlag(SendPropFlag.SPROP_UNSIGNED)); return readVarInt(stream, !propDefinition.hasFlag(SendPropFlag.SPROP_UNSIGNED));
} else { } else {

View file

@ -2,7 +2,12 @@ import {BitStream} from 'bit-buffer';
import {StringTable, StringTableEntry} from '../Data/StringTable'; import {StringTable, StringTableEntry} from '../Data/StringTable';
import {logBase2} from '../Math'; import {logBase2} from '../Math';
export function parseStringTableEntries(stream: BitStream, table: StringTable, entryCount: number, existingEntries: StringTableEntry[] = []): StringTableEntry[] { export function parseStringTableEntries(
stream: BitStream,
table: StringTable,
entryCount: number,
existingEntries: StringTableEntry[] = []
): StringTableEntry[] {
const entryBits = logBase2(table.maxEntries); const entryBits = logBase2(table.maxEntries);
const entries: StringTableEntry[] = []; const entries: StringTableEntry[] = [];
let lastEntry = -1; let lastEntry = -1;
@ -64,7 +69,7 @@ export function parseStringTableEntries(stream: BitStream, table: StringTable, e
} else { } else {
entries[entryIndex] = { entries[entryIndex] = {
text: value, text: value,
extraData: userData, extraData: userData
}; };
history.push(entries[entryIndex]); history.push(entries[entryIndex]);
} }
@ -90,7 +95,7 @@ export function guessStringTableEntryLength(table: StringTable, entries: StringT
export function encodeStringTableEntries(stream: BitStream, table: StringTable, entries: StringTableEntry[]) { export function encodeStringTableEntries(stream: BitStream, table: StringTable, entries: StringTableEntry[]) {
const entryBits = logBase2(table.maxEntries); const entryBits = logBase2(table.maxEntries);
let lastIndex = -1; const lastIndex = -1;
for (let i = 0; i < entries.length; i++) { for (let i = 0; i < entries.length; i++) {
if (entries[i]) { if (entries[i]) {
const entry = entries[i]; const entry = entries[i];

View file

@ -49,7 +49,7 @@ export function ParseSayText2(stream: BitStream): SayText2Packet { // 4: ParseSa
raw, raw,
kind, kind,
from, from,
text, text
}; };
} }

View file

@ -1,20 +1,20 @@
import * as assert from 'assert'; import * as assert from 'assert';
import {readFileSync, createWriteStream, createReadStream} from 'fs';
import {Demo} from '../../Demo';
import {Packet} from '../../Data/Packet';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {createReadStream, createWriteStream, readFileSync} from 'fs';
import * as split2 from 'split2'; import * as split2 from 'split2';
import {createUnzip, createGunzip} from 'zlib';
import {PassThrough} from 'stream'; import {PassThrough} from 'stream';
import {createGunzip, createUnzip} from 'zlib';
import {Packet} from '../../Data/Packet';
import {EntityId, PVS} from '../../Data/PacketEntity'; import {EntityId, PVS} from '../../Data/PacketEntity';
import {SendPropValue} from '../../Data/SendProp'; import {SendPropValue} from '../../Data/SendProp';
import {Demo} from '../../Demo';
interface ResultData { interface ResultData {
tick: number, tick: number;
serverClass: string, serverClass: string;
id: EntityId, id: EntityId;
props: {[propName: string]: SendPropValue}, props: {[propName: string]: SendPropValue};
pvs: PVS pvs: PVS;
} }
function writeEntities(name: string) { function writeEntities(name: string) {
@ -48,7 +48,7 @@ function* getResultData(packets: Iterable<Packet>): IterableIterator<ResultData>
entityProps[`${prop.definition.name}`] = prop.value; entityProps[`${prop.definition.name}`] = prop.value;
} }
yield { yield {
tick: tick, tick,
serverClass: entity.serverClass.name, serverClass: entity.serverClass.name,
id: entity.entityIndex, id: entity.entityIndex,
props: entityProps, props: entityProps,
@ -82,7 +82,7 @@ function testEntities(name: string, entityCount: number) {
assert.equal(parsed, entityCount, 'unexpected number of entities'); assert.equal(parsed, entityCount, 'unexpected number of entities');
resolve(); resolve();
}).on('error', err => { }).on('error', (err) => {
reject(err); reject(err);
}); });
}); });

View file

@ -1,7 +1,7 @@
import * as assert from 'assert'; import * as assert from 'assert';
import {BitStream} from 'bit-buffer';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {Demo} from '../../Demo'; import {Demo} from '../../Demo';
import {BitStream} from 'bit-buffer';
function testDemo(name: string, fastMode: boolean = false) { function testDemo(name: string, fastMode: boolean = false) {
const target = JSON.parse(readFileSync(`${__dirname}/../data/${name}.json`, 'utf8')); const target = JSON.parse(readFileSync(`${__dirname}/../data/${name}.json`, 'utf8'));

View file

@ -1,39 +1,39 @@
import {PacketEntity, PVS} from '../../../Data/PacketEntity';
import {ServerClass} from '../../../Data/ServerClass';
import {hydrateEntity, propDataDefinition} from '../Parser/Packet/hydrate';
import {SendProp} from '../../../Data/SendProp';
import * as assert from 'assert'; import * as assert from 'assert';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {PacketEntity, PVS} from '../../../Data/PacketEntity';
import {SendProp} from '../../../Data/SendProp';
import {ServerClass} from '../../../Data/ServerClass';
import {hydrateEntity, propDataDefinition} from '../Parser/Packet/hydrate';
const serverClass = new ServerClass(241, 'CTFPlayer', 'DT_TFPlayer'); const serverClass = new ServerClass(241, 'CTFPlayer', 'DT_TFPlayer');
const playerBaseLineData = JSON.parse(readFileSync(__dirname + '/../../data/packetEntitiesPlayerBaseline.json', 'utf8')); const playerBaseLineData = JSON.parse(readFileSync(__dirname + '/../../data/packetEntitiesPlayerBaseline.json', 'utf8'));
const playerEntityData = JSON.parse(readFileSync(__dirname + '/../../data/packetEntitiesPlayerEntity.json', 'utf8')); const playerEntityData = JSON.parse(readFileSync(__dirname + '/../../data/packetEntitiesPlayerEntity.json', 'utf8'));
const definition1 = propDataDefinition({ const definition1 = propDataDefinition({
'type': 1, type: 1,
'name': 'm_flDucktime', name: 'm_flDucktime',
'flags': 1032, flags: 1032,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 2047.5, highValue: 2047.5,
'bitCount': 12, bitCount: 12,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_Local' ownerTableName: 'DT_Local'
}); });
const definition2 = propDataDefinition({ const definition2 = propDataDefinition({
'type': 1, type: 1,
'name': 'm_flFallVelocity', name: 'm_flFallVelocity',
'flags': 1024, flags: 1024,
'excludeDTName': null, excludeDTName: null,
'lowValue': -4096, lowValue: -4096,
'highValue': 4096, highValue: 4096,
'bitCount': 17, bitCount: 17,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_Local' ownerTableName: 'DT_Local'
}); });
suite('PacketEntity', () => { suite('PacketEntity', () => {

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder} from '../Packet/PacketTest';
import {ConsoleCmdHandler} from '../../../../Parser/Message/ConsoleCmd';
import {ParserState} from '../../../../Data/ParserState';
import {MessageType} from '../../../../Data/Message'; import {MessageType} from '../../../../Data/Message';
import {ParserState} from '../../../../Data/ParserState';
import {ConsoleCmdHandler} from '../../../../Parser/Message/ConsoleCmd';
import {assertEncoder} from '../Packet/PacketTest';
function parse(stream) { function parse(stream) {
const result = ConsoleCmdHandler.parseMessage(stream, new ParserState()); const result = ConsoleCmdHandler.parseMessage(stream, new ParserState());

View file

@ -1,21 +1,26 @@
import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
import {readFileSync} from 'fs';
import {ParserState} from '../../../../Data/ParserState';
import {gunzipSync} from 'zlib';
import {DataTableHandler} from '../../../../Parser/Message/DataTable';
import {DataTablesMessage} from '../../../../Data/Message';
import {hydrateTable} from '../Packet/hydrate';
import {ServerClass} from '../../../../Data/ServerClass';
import * as assert from 'assert'; import * as assert from 'assert';
import {BitStream} from 'bit-buffer';
import {readFileSync} from 'fs';
import {gunzipSync} from 'zlib';
import {DataTablesMessage} from '../../../../Data/Message';
import {ParserState} from '../../../../Data/ParserState';
import {ServerClass} from '../../../../Data/ServerClass';
import {DataTableHandler} from '../../../../Parser/Message/DataTable';
import {hydrateTable} from '../Packet/hydrate';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
const data = Array.from(readFileSync(__dirname + '/../../../data/dataTableData.bin').values()); const data = Array.from(readFileSync(__dirname + '/../../../data/dataTableData.bin').values());
const expectedRaw = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/dataTableResult.json.gz')).toString('utf8')) as DataTablesMessage; const expectedRaw = JSON.parse(
gunzipSync(
readFileSync(__dirname + '/../../../data/dataTableResult.json.gz'
)
).toString('utf8')
) as DataTablesMessage;
const expected = { const expected = {
type: expectedRaw.type, type: expectedRaw.type,
tick: expectedRaw.tick, tick: expectedRaw.tick,
serverClasses: expectedRaw.serverClasses.map(serverClass => new ServerClass(serverClass.id, serverClass.name, serverClass.dataTable)), serverClasses: expectedRaw.serverClasses.map((serverClass) => new ServerClass(serverClass.id, serverClass.name, serverClass.dataTable)),
tables: expectedRaw.tables.map(hydrateTable) tables: expectedRaw.tables.map(hydrateTable)
}; };

View file

@ -1,9 +1,9 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {PacketMessageHandler} from '../../../../Parser/Message/Packet';
import {ParserState} from '../../../../Data/ParserState';
import {PacketTypeId} from '../../../../Data/Packet'; import {PacketTypeId} from '../../../../Data/Packet';
import {ParserState} from '../../../../Data/ParserState';
import {PacketMessageHandler} from '../../../../Parser/Message/Packet';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
const data = Object.values(JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageData.json', 'utf8'))); const data = Object.values(JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageData.json', 'utf8')));
const expected = JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageResult.json', 'utf8')); const expected = JSON.parse(readFileSync(__dirname + '/../../../data/packetMessageResult.json', 'utf8'));
@ -14,7 +14,7 @@ const getParserState = (fastMode) => {
state.skippedPackets = fastMode ? [ state.skippedPackets = fastMode ? [
PacketTypeId.packetEntities, PacketTypeId.packetEntities,
PacketTypeId.tempEntities, PacketTypeId.tempEntities,
PacketTypeId.entityMessage, PacketTypeId.entityMessage
] : []; ] : [];
return state; return state;
}; };

View file

@ -1,18 +1,18 @@
import {StringTable, StringTableEntry} from '../../../../Data/StringTable'; import {BitStream} from 'bit-buffer';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {ParserState} from '../../../../Data/ParserState'; import {ParserState} from '../../../../Data/ParserState';
import {StringTable, StringTableEntry} from '../../../../Data/StringTable';
import {StringTableHandler} from '../../../../Parser/Message/StringTable'; import {StringTableHandler} from '../../../../Parser/Message/StringTable';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest'; import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
import {BitStream} from 'bit-buffer';
const encodeEntry = (entry: StringTableEntry) => { const encodeEntry = (entry: StringTableEntry) => {
const encodeEntry: any = { const result: any = {
text: entry.text, text: entry.text
}; };
if (entry.extraData) { if (entry.extraData) {
encodeEntry.extraData = Array.from(entry.extraData.readArrayBuffer(Math.ceil(entry.extraData.length / 8)).values()); result.extraData = Array.from(entry.extraData.readArrayBuffer(Math.ceil(entry.extraData.length / 8)).values());
} }
return encodeEntry; return result;
}; };
const encodeTables = (tables) => { const encodeTables = (tables) => {
return tables.map((table) => { return tables.map((table) => {
@ -27,13 +27,13 @@ const encodeTables = (tables) => {
}); });
}; };
const decodeEntry = (entry) => { const decodeEntry = (entry) => {
const decodeEntry: any = { const result: any = {
text: entry.text, text: entry.text
}; };
if (entry.extraData) { if (entry.extraData) {
decodeEntry.extraData = getStream(entry.extraData); result.extraData = getStream(entry.extraData);
} }
return decodeEntry; return result;
}; };
const decodeTables = (tables) => { const decodeTables = (tables) => {
return tables.map((table) => { return tables.map((table) => {
@ -62,7 +62,6 @@ const expected = {
rawData: getStream('') rawData: getStream('')
}; };
const getParserState = () => { const getParserState = () => {
return new ParserState(); return new ParserState();
}; };

View file

@ -1,11 +1,11 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import { import {
EncodeBSPDecal, encodeVecCoord, getVecCoord, EncodeBSPDecal, encodeVecCoord, getVecCoord,
ParseBSPDecal ParseBSPDecal
} from '../../../../Parser/Packet/BSPDecal'; } from '../../../../Parser/Packet/BSPDecal';
import {SendPropParser} from '../../../../Parser/SendPropParser';
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder'; import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
import {SendPropParser} from '../../../../Parser/SendPropParser';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [239, 236, 208, 85, 33, 127, 128, 9, 8]; const data = [239, 236, 208, 85, 33, 127, 128, 9, 8];

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeClassInfo, ParseClassInfo} from '../../../../Parser/Packet/ClassInfo'; import {EncodeClassInfo, ParseClassInfo} from '../../../../Parser/Packet/ClassInfo';
import {assertEncoder, assertParser, getStream} from './PacketTest';
suite('ClassInfo', () => { suite('ClassInfo', () => {
test('Parse classInfo', () => { test('Parse classInfo', () => {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeCreateStringTable, ParseCreateStringTable} from '../../../../Parser/Packet/CreateStringTable'; import {EncodeCreateStringTable, ParseCreateStringTable} from '../../../../Parser/Packet/CreateStringTable';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const exampleData = [ const exampleData = [
100, 100,
@ -80,7 +80,6 @@ const examplePacket2 = {
} }
}; };
suite('CreateStringTable', () => { suite('CreateStringTable', () => {
test('Parse createStringTable', () => { test('Parse createStringTable', () => {
assertParser(ParseCreateStringTable, getStream(exampleData), examplePacket, 388); assertParser(ParseCreateStringTable, getStream(exampleData), examplePacket, 388);

View file

@ -1,15 +1,15 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {encodeEntityUpdate, getEntityUpdate} from '../../../../Parser/EntityDecoder';
import {SendProp, SendPropValue} from '../../../../Data/SendProp'; import {SendProp, SendPropValue} from '../../../../Data/SendProp';
import {SendPropType} from '../../../../Data/SendPropDefinition'; import {SendPropType} from '../../../../Data/SendPropDefinition';
import {encodeEntityUpdate, getEntityUpdate} from '../../../../Parser/EntityDecoder';
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder'; import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
import {SendPropParser} from '../../../../Parser/SendPropParser'; import {SendPropParser} from '../../../../Parser/SendPropParser';
import {hydrateEntity, hydrateTable} from './hydrate'; import {hydrateEntity, hydrateTable} from './hydrate';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [ // tslint:disable-next-line
9, 128, 64, 64, 64, 64, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 36, 0, 64, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 128, 0, 0, 8, 0, 128, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 64, 0, 32, 0, 16, 0, 32, 240, 255, 255, 255, 31, 0, 2, 32, 48, 0, 128, 0, 0, 4, 254, 255, 127, 224, 255, 255, 7, 254, 255, 127, 0, 8, 64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 64, 64, 64, 64, 0, 32, 224, 136, 10, 248, 91, 2, 63, 18, 8, 40, 38, 3, 250, 163, 192, 126, 7, 2, 2, 0, 0, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 224, 111, 0, 0, 0, 0, 32, 192, 129, 172, 140, 46, 44, 141, 237, 133, 172, 140, 46, 44, 141, 109, 14, 78, 46, 141, 174, 108, 238, 107, 46, 236, 174, 45, 141, 141, 45, 0]; const data = [9, 128, 64, 64, 64, 64, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 36, 0, 64, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 128, 0, 0, 8, 0, 128, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 64, 0, 32, 0, 16, 0, 32, 240, 255, 255, 255, 31, 0, 2, 32, 48, 0, 128, 0, 0, 4, 254, 255, 127, 224, 255, 255, 7, 254, 255, 127, 0, 8, 64, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 64, 64, 64, 64, 0, 32, 224, 136, 10, 248, 91, 2, 63, 18, 8, 40, 38, 3, 250, 163, 192, 126, 7, 2, 2, 0, 0, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 224, 111, 0, 0, 0, 0, 32, 192, 129, 172, 140, 46, 44, 141, 237, 133, 172, 140, 46, 44, 141, 109, 14, 78, 46, 141, 174, 108, 238, 107, 46, 236, 174, 45, 141, 141, 45, 0];
const entityData = JSON.parse(readFileSync(__dirname + '/../../../data/worldEntity.json', 'utf8')); const entityData = JSON.parse(readFileSync(__dirname + '/../../../data/worldEntity.json', 'utf8'));
const sendTableData = JSON.parse(readFileSync(__dirname + '/../../../data/sendTableDTWorld.json', 'utf8')); const sendTableData = JSON.parse(readFileSync(__dirname + '/../../../data/sendTableDTWorld.json', 'utf8'));
@ -24,15 +24,14 @@ export function encodeUpdate(props: SendProp[], stream: BitStream) {
encodeEntityUpdate(props, sendTable, stream); encodeEntityUpdate(props, sendTable, stream);
} }
function encodeProp(prop: SendProp) { function encodeProp(prop: SendProp) {
return function (value: SendPropValue, stream: BitStream) { return (value: SendPropValue, stream: BitStream) => {
return SendPropEncoder.encode(value, prop.definition, stream); return SendPropEncoder.encode(value, prop.definition, stream);
}; };
} }
function decodeProp(prop: SendProp) { function decodeProp(prop: SendProp) {
return function (stream: BitStream) { return (stream: BitStream) => {
return SendPropParser.decode(prop.definition, stream); return SendPropParser.decode(prop.definition, stream);
}; };
} }
@ -41,7 +40,7 @@ suite('Entity Decoder', () => {
test('Encode sendProps', () => { test('Encode sendProps', () => {
for (const prop of entity.props) { for (const prop of entity.props) {
if (prop.value !== null) { if (prop.value !== null) {
assertEncoder(decodeProp(prop), encodeProp(prop), prop.value, 0, ` for ${SendPropType[prop.definition.type]} with flags ${prop.definition.allFlags}`); assertEncoder(decodeProp(prop), encodeProp(prop), prop.value, 0);
} }
} }
}); });

View file

@ -1,9 +1,9 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {EncodeGameEventList, ParseGameEventList} from '../../../../Parser/Packet/GameEventList';
import {GameEventListPacket} from '../../../../Data/Packet';
import {GameEvent} from '../../../../Data/GameEventTypes'; import {GameEvent} from '../../../../Data/GameEventTypes';
import {GameEventListPacket} from '../../../../Data/Packet';
import {EncodeGameEventList, ParseGameEventList} from '../../../../Parser/Packet/GameEventList';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = JSON.parse(readFileSync(__dirname + '/../../../data/gameEventListData.json', 'utf8')); const data = JSON.parse(readFileSync(__dirname + '/../../../data/gameEventListData.json', 'utf8'));
const expectedSource = JSON.parse(readFileSync(__dirname + '/../../../data/gameEventList.json', 'utf8')); const expectedSource = JSON.parse(readFileSync(__dirname + '/../../../data/gameEventList.json', 'utf8'));
@ -14,71 +14,71 @@ const expected = {
}; };
const eventList: GameEventListPacket = { const eventList: GameEventListPacket = {
'packetType': 'gameEventList', packetType: 'gameEventList',
'eventList': new Map([ eventList: new Map([
[0, { [0, {
'id': 0, id: 0,
'name': 'server_spawn' as GameEvent['name'], name: 'server_spawn' as GameEvent['name'],
'entries': [ entries: [
{ {
'type': 1, type: 1,
'name': 'hostname' name: 'hostname'
}, },
{ {
'type': 1, type: 1,
'name': 'address' name: 'address'
}, },
{ {
'type': 3, type: 3,
'name': 'ip' name: 'ip'
}, },
{ {
'type': 4, type: 4,
'name': 'port' name: 'port'
}, },
{ {
'type': 1, type: 1,
'name': 'game' name: 'game'
}, },
{ {
'type': 1, type: 1,
'name': 'mapname' name: 'mapname'
}, },
{ {
'type': 3, type: 3,
'name': 'maxplayers' name: 'maxplayers'
}, },
{ {
'type': 1, type: 1,
'name': 'os' name: 'os'
}, },
{ {
'type': 6, type: 6,
'name': 'dedicated' name: 'dedicated'
}, },
{ {
'type': 6, type: 6,
'name': 'password' name: 'password'
} }
] ]
}], }],
[1, { [1, {
'id': 1, id: 1,
'name': 'server_changelevel_failed' as GameEvent['name'], name: 'server_changelevel_failed' as GameEvent['name'],
'entries': [ entries: [
{ {
'type': 1, type: 1,
'name': 'levelname' name: 'levelname'
} }
] ]
}], }],
[2, { [2, {
'id': 2, id: 2,
'name': 'server_shutdown' as GameEvent['name'], name: 'server_shutdown' as GameEvent['name'],
'entries': [ entries: [
{ {
'type': 1, type: 1,
'name': 'reason' name: 'reason'
} }
] ]
}] }]

View file

@ -1,9 +1,9 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeGameEvent, ParseGameEvent} from '../../../../Parser/Packet/GameEvent';
import {GameEventPacket} from '../../../../Data/Packet';
import {GameEventValueType} from '../../../../Data/GameEvent'; import {GameEventValueType} from '../../../../Data/GameEvent';
import {GameEventPacket} from '../../../../Data/Packet';
import {createParserState} from '../../../../Data/ParserState'; import {createParserState} from '../../../../Data/ParserState';
import {EncodeGameEvent, ParseGameEvent} from '../../../../Parser/Packet/GameEvent';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [25, 240, 149, 0, 0]; const data = [25, 240, 149, 0, 0];
const expected = { const expected = {

View file

@ -1,20 +1,20 @@
import * as assert from 'assert';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {hydrateEntity, hydrateTable} from './hydrate';
import {ServerClass} from '../../../../Data/ServerClass';
import {PacketEntitiesPacket} from '../../../../Data/Packet';
import {readFileSync} from 'fs'; import {readFileSync} from 'fs';
import {gunzipSync} from 'zlib'; import {gunzipSync} from 'zlib';
import {EncodePacketEntities, ParsePacketEntities} from '../../../../Parser/Packet/PacketEntities'; import {PacketEntitiesPacket} from '../../../../Data/Packet';
import * as assert from 'assert';
import {deepEqual} from '../../deepEqual';
import {createParserState} from '../../../../Data/ParserState'; import {createParserState} from '../../../../Data/ParserState';
import {ServerClass} from '../../../../Data/ServerClass';
import {EncodePacketEntities, ParsePacketEntities} from '../../../../Parser/Packet/PacketEntities';
import {deepEqual} from '../../deepEqual';
import {hydrateEntity, hydrateTable} from './hydrate';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesData.json', 'utf8')); const data = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesData.json', 'utf8'));
const packetData = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/packetEntitiesResult.json.gz')).toString('utf8')); const packetData = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/packetEntitiesResult.json.gz')).toString('utf8'));
const sendTableData = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/packetEntitiesSendTables.json.gz')).toString('utf8')); const sendTableData = JSON.parse(gunzipSync(readFileSync(__dirname + '/../../../data/packetEntitiesSendTables.json.gz')).toString('utf8'));
const serverClassesData = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesServerClasses.json', 'utf8')); const serverClassesData = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesServerClasses.json', 'utf8'));
const baselineData: [number, number[]][] = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntityBaseLines.json', 'utf8')); const baselineData: Array<[number, number[]]> = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntityBaseLines.json', 'utf8'));
const playerEntityData = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesPlayerEntity.json', 'utf8')); const playerEntityData = JSON.parse(readFileSync(__dirname + '/../../../data/packetEntitiesPlayerEntity.json', 'utf8'));
const expected: PacketEntitiesPacket = { const expected: PacketEntitiesPacket = {
@ -58,69 +58,69 @@ function encode(value: PacketEntitiesPacket, stream: BitStream) {
} }
const sunEntityData = { const sunEntityData = {
'serverClass': { serverClass: {
'id': 123, id: 123,
'name': 'CSun', name: 'CSun',
'dataTable': 'DT_Sun' dataTable: 'DT_Sun'
}, },
'entityIndex': 403, entityIndex: 403,
'props': [ props: [
{ {
'definition': { definition: {
'type': 0, type: 0,
'name': 'm_clrRender', name: 'm_clrRender',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_Sun' ownerTableName: 'DT_Sun'
}, },
'value': 4276271871 value: 4276271871
}, },
{ {
'definition': { definition: {
'type': 0, type: 0,
'name': 'm_clrOverlay', name: 'm_clrOverlay',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_Sun' ownerTableName: 'DT_Sun'
}, },
'value': 0 value: 0
}, },
{ {
'definition': { definition: {
'type': 2, type: 2,
'name': 'm_vDirection', name: 'm_vDirection',
'flags': 32, flags: 32,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': -121121.125, highValue: -121121.125,
'bitCount': 0, bitCount: 0,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_Sun' ownerTableName: 'DT_Sun'
}, },
'value': { value: {
'x': -0.6453346360527601, x: -0.6453346360527601,
'y': -0.504152418172936, y: -0.504152418172936,
'z': 0.1880801172447484 z: 0.1880801172447484
} }
} }
], ],
'inPVS': true, inPVS: true,
'pvs': 1, pvs: 1,
'serialNumber': 664 serialNumber: 664
}; };
suite('PacketEntities', () => { suite('PacketEntities', () => {
@ -129,7 +129,11 @@ suite('PacketEntities', () => {
const stream = getStream(data); const stream = getStream(data);
const start = stream.index; const start = stream.index;
const resultPacket = parse(stream); const resultPacket = parse(stream);
assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream'); assert.equal(
stream.index - start,
length,
'Unexpected number of bits consumed from stream'
);
for (let i = 0; i < resultPacket.entities.length; i++) { for (let i = 0; i < resultPacket.entities.length; i++) {
const resultEntity = resultPacket.entities[i]; const resultEntity = resultPacket.entities[i];
@ -138,9 +142,12 @@ suite('PacketEntities', () => {
assert.equal(expectedEntity.serialNumber, resultEntity.serialNumber); assert.equal(expectedEntity.serialNumber, resultEntity.serialNumber);
assert.equal(expectedEntity.entityIndex, resultEntity.entityIndex); assert.equal(expectedEntity.entityIndex, resultEntity.entityIndex);
if (!deepEqual(resultEntity, expectedEntity)) { if (!deepEqual(resultEntity, expectedEntity)) {
for (let i = 0; i < expectedEntity.props.length; i++) { for (let j = 0; j < expectedEntity.props.length; j++) {
console.log(resultEntity.getPropByDefinition(expectedEntity.props[i].definition),expectedEntity.props[i].definition); assert.deepEqual(
assert.deepEqual(resultEntity.getPropByDefinition(expectedEntity.props[i].definition), expectedEntity.props[i], `invalid property #${i} for ${resultEntity.serverClass.name}`); resultEntity.getPropByDefinition(expectedEntity.props[j].definition),
expectedEntity.props[j],
`invalid property #${j} for ${resultEntity.serverClass.name}`
);
} }
assert.equal(resultEntity.props.length, expectedEntity.props.length, `Unexpected number of props for ${resultEntity.serverClass.name}`); assert.equal(resultEntity.props.length, expectedEntity.props.length, `Unexpected number of props for ${resultEntity.serverClass.name}`);
assert(false, 'Invalid entity ' + resultEntity.serverClass.name); assert(false, 'Invalid entity ' + resultEntity.serverClass.name);
@ -153,7 +160,6 @@ suite('PacketEntities', () => {
assertEncoder(parse, encode, toEncode, 0); assertEncoder(parse, encode, toEncode, 0);
}); });
test('Encode small packetEntities', () => { test('Encode small packetEntities', () => {
assertEncoder(parse, encode, { assertEncoder(parse, encode, {
packetType: 'packetEntities', packetType: 'packetEntities',
@ -172,7 +178,7 @@ suite('PacketEntities', () => {
removedEntities: [10, 11], removedEntities: [10, 11],
updatedBaseLine: false, updatedBaseLine: false,
baseLine: 0, baseLine: 0,
delta: 0, delta: 1,
maxEntries: 16, maxEntries: 16,
entities: [hydrateEntity(sunEntityData)] entities: [hydrateEntity(sunEntityData)]
}, 181); }, 181);
@ -184,7 +190,7 @@ suite('PacketEntities', () => {
removedEntities: [10, 11], removedEntities: [10, 11],
updatedBaseLine: false, updatedBaseLine: false,
baseLine: 0, baseLine: 0,
delta: 0, delta: 1,
maxEntries: 16, maxEntries: 16,
entities: [] entities: []
}, 102); }, 102);

View file

@ -1,9 +1,9 @@
import * as assert from 'assert'; import * as assert from 'assert';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {Packet} from '../../../../Data/Packet';
import {deepEqual} from '../../deepEqual';
import {isObject} from 'util'; import {isObject} from 'util';
import {Packet} from '../../../../Data/Packet';
import {ParserState} from '../../../../Data/ParserState'; import {ParserState} from '../../../../Data/ParserState';
import {deepEqual} from '../../deepEqual';
export function getStream(data: string | number[]) { export function getStream(data: string | number[]) {
if (typeof data === 'string') { if (typeof data === 'string') {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeParseSounds, ParseParseSounds} from '../../../../Parser/Packet/ParseSounds'; import {EncodeParseSounds, ParseParseSounds} from '../../../../Parser/Packet/ParseSounds';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [ const data = [
18, 18,

View file

@ -1,5 +1,5 @@
import {make} from '../../../../Parser/Packet/ParserGenerator';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {make} from '../../../../Parser/Packet/ParserGenerator';
import {assertEncoder, assertParser, getStream} from './PacketTest'; import {assertEncoder, assertParser, getStream} from './PacketTest';
function assertGeneratedParser(definition: string, stream: BitStream, expected: any, length: number) { function assertGeneratedParser(definition: string, stream: BitStream, expected: any, length: number) {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeSetConVar, ParseSetConVar} from '../../../../Parser/Packet/SetConVar'; import {EncodeSetConVar, ParseSetConVar} from '../../../../Parser/Packet/SetConVar';
import {assertEncoder, assertParser, getStream} from './PacketTest';
suite('SetConVar', () => { suite('SetConVar', () => {
test('Parse setConVar', () => { test('Parse setConVar', () => {

View file

@ -1,11 +1,11 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest'; import {readFileSync} from 'fs';
import {TempEntitiesPacket} from '../../../../Data/Packet';
import {createParserState} from '../../../../Data/ParserState';
import {ServerClass} from '../../../../Data/ServerClass';
import {EncodeTempEntities, ParseTempEntities} from '../../../../Parser/Packet/TempEntities'; import {EncodeTempEntities, ParseTempEntities} from '../../../../Parser/Packet/TempEntities';
import {hydrateEntity, hydrateTable} from './hydrate'; import {hydrateEntity, hydrateTable} from './hydrate';
import {ServerClass} from '../../../../Data/ServerClass'; import {assertEncoder, assertParser, getStream} from './PacketTest';
import {TempEntitiesPacket} from '../../../../Data/Packet';
import {readFileSync} from 'fs';
import {createParserState} from '../../../../Data/ParserState';
const data = [ const data = [
2, 2,
@ -32,332 +32,332 @@ const data = [
const entityData = JSON.parse(readFileSync(__dirname + '/../../../data/tempEntitiesResult.json', 'utf8')); const entityData = JSON.parse(readFileSync(__dirname + '/../../../data/tempEntitiesResult.json', 'utf8'));
const sendTableData = { const sendTableData = {
'name': 'DT_TEPlayerAnimEvent', name: 'DT_TEPlayerAnimEvent',
'props': [ props: [
{ {
'type': 0, type: 0,
'name': 'm_iPlayerIndex', name: 'm_iPlayerIndex',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 7, bitCount: 7,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TEPlayerAnimEvent' ownerTableName: 'DT_TEPlayerAnimEvent'
}, },
{ {
'type': 0, type: 0,
'name': 'm_iEvent', name: 'm_iEvent',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 6, bitCount: 6,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TEPlayerAnimEvent' ownerTableName: 'DT_TEPlayerAnimEvent'
}, },
{ {
'type': 0, type: 0,
'name': 'm_nData', name: 'm_nData',
'flags': 0, flags: 0,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 12, bitCount: 12,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TEPlayerAnimEvent' ownerTableName: 'DT_TEPlayerAnimEvent'
} }
], ],
'cachedFlattenedProps': [] cachedFlattenedProps: []
}; };
const sendTableData2 = { const sendTableData2 = {
'name': 'DT_TETFParticleEffect', name: 'DT_TETFParticleEffect',
'props': [ props: [
{ {
'type': 6, type: 6,
'name': 'baseclass', name: 'baseclass',
'flags': 4096, flags: 4096,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 0, bitCount: 0,
'table': { table: {
'name': 'DT_BaseTempEntity', name: 'DT_BaseTempEntity',
'props': [], props: [],
'cachedFlattenedProps': [] cachedFlattenedProps: []
}, },
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecOrigin[0]', name: 'm_vecOrigin[0]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecOrigin[1]', name: 'm_vecOrigin[1]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecOrigin[2]', name: 'm_vecOrigin[2]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecStart[0]', name: 'm_vecStart[0]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecStart[1]', name: 'm_vecStart[1]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_vecStart[2]', name: 'm_vecStart[2]',
'flags': 32772, flags: 32772,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 2, type: 2,
'name': 'm_vecAngles', name: 'm_vecAngles',
'flags': 0, flags: 0,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 360, highValue: 360,
'bitCount': 7, bitCount: 7,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_iParticleSystemIndex', name: 'm_iParticleSystemIndex',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 16, bitCount: 16,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'entindex', name: 'entindex',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 11, bitCount: 11,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_iAttachType', name: 'm_iAttachType',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 5, bitCount: 5,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_iAttachmentPointIndex', name: 'm_iAttachmentPointIndex',
'flags': 0, flags: 0,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_bResetParticles', name: 'm_bResetParticles',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 1, bitCount: 1,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_bCustomColors', name: 'm_bCustomColors',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 1, bitCount: 1,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 2, type: 2,
'name': 'm_CustomColors.m_vecColor1', name: 'm_CustomColors.m_vecColor1',
'flags': 0, flags: 0,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 1, highValue: 1,
'bitCount': 8, bitCount: 8,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 2, type: 2,
'name': 'm_CustomColors.m_vecColor2', name: 'm_CustomColors.m_vecColor2',
'flags': 0, flags: 0,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 1, highValue: 1,
'bitCount': 8, bitCount: 8,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_bControlPoint1', name: 'm_bControlPoint1',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 1, bitCount: 1,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 0, type: 0,
'name': 'm_ControlPoint1.m_eParticleAttachment', name: 'm_ControlPoint1.m_eParticleAttachment',
'flags': 1, flags: 1,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 5, bitCount: 5,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_ControlPoint1.m_vecOffset[0]', name: 'm_ControlPoint1.m_vecOffset[0]',
'flags': 8196, flags: 8196,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_ControlPoint1.m_vecOffset[1]', name: 'm_ControlPoint1.m_vecOffset[1]',
'flags': 8196, flags: 8196,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
}, },
{ {
'type': 1, type: 1,
'name': 'm_ControlPoint1.m_vecOffset[2]', name: 'm_ControlPoint1.m_vecOffset[2]',
'flags': 8196, flags: 8196,
'excludeDTName': null, excludeDTName: null,
'lowValue': 0, lowValue: 0,
'highValue': 0, highValue: 0,
'bitCount': 32, bitCount: 32,
'table': null, table: null,
'numElements': 0, numElements: 0,
'arrayProperty': null, arrayProperty: null,
'ownerTableName': 'DT_TETFParticleEffect' ownerTableName: 'DT_TETFParticleEffect'
} }
], ],
'cachedFlattenedProps': [] cachedFlattenedProps: []
}; };
const sendTable = hydrateTable(sendTableData); const sendTable = hydrateTable(sendTableData);
const sendTable2 = hydrateTable(sendTableData2); const sendTable2 = hydrateTable(sendTableData2);

View file

@ -1,9 +1,9 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../../../../Parser/Packet/UpdateStringTable';
import {StringTable} from '../../../../Data/StringTable';
import {UpdateStringTablePacket} from '../../../../Data/Packet'; import {UpdateStringTablePacket} from '../../../../Data/Packet';
import {createParserState} from '../../../../Data/ParserState'; import {createParserState} from '../../../../Data/ParserState';
import {StringTable} from '../../../../Data/StringTable';
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../../../../Parser/Packet/UpdateStringTable';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const exampleData = [200, 3, 0, 48, 130, 53]; const exampleData = [200, 3, 0, 48, 130, 53];
@ -36,7 +36,6 @@ examplePacket.entries[70] = {
) )
}; };
const examplePacket2: UpdateStringTablePacket = { const examplePacket2: UpdateStringTablePacket = {
packetType: 'updateStringTable', packetType: 'updateStringTable',
entries: [ entries: [

View file

@ -1,7 +1,7 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeUserMessage, ParseUserMessage} from '../../../../Parser/Packet/UserMessage';
import {HudTextLocation} from '../../../../Data/UserMessage'; import {HudTextLocation} from '../../../../Data/UserMessage';
import {EncodeUserMessage, ParseUserMessage} from '../../../../Parser/Packet/UserMessage';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [ const data = [
5, 5,
@ -40,7 +40,7 @@ const expected = {
substitute1: 'sekr', substitute1: 'sekr',
substitute2: '', substitute2: '',
substitute3: '', substitute3: '',
substitute4: '', substitute4: ''
}; };
suite('UserMessage', () => { suite('UserMessage', () => {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeVoiceData, ParseVoiceData} from '../../../../Parser/Packet/VoiceData'; import {EncodeVoiceData, ParseVoiceData} from '../../../../Parser/Packet/VoiceData';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [5, 18, 24, 0, 123, 219, 1]; const data = [5, 18, 24, 0, 123, 219, 1];

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './PacketTest';
import {EncodeVoiceInit, ParseVoiceInit} from '../../../../Parser/Packet/VoiceInit'; import {EncodeVoiceInit, ParseVoiceInit} from '../../../../Parser/Packet/VoiceInit';
import {assertEncoder, assertParser, getStream} from './PacketTest';
const data = [118, 97, 117, 100, 105, 111, 95, 99, 101, 108, 116, 0, 255, 34, 86]; const data = [118, 97, 117, 100, 105, 111, 95, 99, 101, 108, 116, 0, 255, 34, 86];

View file

@ -1,12 +1,12 @@
import {SendProp, SendPropValue} from '../../../../Data/SendProp';
import {PacketEntity} from '../../../../Data/PacketEntity'; import {PacketEntity} from '../../../../Data/PacketEntity';
import {SendProp, SendPropValue} from '../../../../Data/SendProp';
import {SendPropDefinition, SendPropType} from '../../../../Data/SendPropDefinition'; import {SendPropDefinition, SendPropType} from '../../../../Data/SendPropDefinition';
import {Vector} from '../../../../Data/Vector';
import {SendTable} from '../../../../Data/SendTable'; import {SendTable} from '../../../../Data/SendTable';
import {Vector} from '../../../../Data/Vector';
export function hydrateEntity(entityData): PacketEntity { export function hydrateEntity(entityData): PacketEntity {
const entity = new PacketEntity(entityData.serverClass, entityData.entityIndex, entityData.pvs); const entity = new PacketEntity(entityData.serverClass, entityData.entityIndex, entityData.pvs);
entity.props = entityData.props.map(propData => { entity.props = entityData.props.map((propData) => {
const prop = new SendProp(propDataDefinition(propData.definition)); const prop = new SendProp(propDataDefinition(propData.definition));
prop.value = hydrateProp(propData.value, prop.definition); prop.value = hydrateProp(propData.value, prop.definition);
return prop; return prop;
@ -27,7 +27,7 @@ function hydrateProp(value: any, definition: SendPropDefinition): SendPropValue
if (arrayProp === null) { if (arrayProp === null) {
throw new Error('arrayProperty not set for array property'); throw new Error('arrayProperty not set for array property');
} }
return value.map(arrayValue => hydrateProp(arrayValue, arrayProp)) as SendPropValue; return value.map((arrayValue) => hydrateProp(arrayValue, arrayProp)) as SendPropValue;
} else if (definition.type === SendPropType.DPT_Vector || definition.type === SendPropType.DPT_VectorXY) { } else if (definition.type === SendPropType.DPT_Vector || definition.type === SendPropType.DPT_VectorXY) {
return new Vector(value.x, value.y, value.z); return new Vector(value.x, value.y, value.z);
} else { } else {

View file

@ -1,9 +1,9 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './Packet/PacketTest';
import {readBitVar, readVarInt, writeBitVar, writeVarInt} from '../../../Parser/readBitVar';
import {SendPropParser} from '../../../Parser/SendPropParser';
import {SendPropDefinition, SendPropFlag, SendPropType} from '../../../Data/SendPropDefinition'; import {SendPropDefinition, SendPropFlag, SendPropType} from '../../../Data/SendPropDefinition';
import {readBitVar, readVarInt, writeBitVar, writeVarInt} from '../../../Parser/readBitVar';
import {SendPropEncoder} from '../../../Parser/SendPropEncoder'; import {SendPropEncoder} from '../../../Parser/SendPropEncoder';
import {SendPropParser} from '../../../Parser/SendPropParser';
import {assertEncoder, assertParser, getStream} from './Packet/PacketTest';
function basicIntReader(bitCount: number, signed: boolean) { function basicIntReader(bitCount: number, signed: boolean) {
return (stream: BitStream) => { return (stream: BitStream) => {

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
import {EncodeSayText2, ParseSayText2} from '../../../../Parser/UserMessage/SayText2'; import {EncodeSayText2, ParseSayText2} from '../../../../Parser/UserMessage/SayText2';
import {assertEncoder, assertParser, getStream} from '../Packet/PacketTest';
const data = [ const data = [
3, 3,

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, getStream} from './Packet/PacketTest';
import {readBitVar, readVarInt, writeBitVar, writeVarInt} from '../../../Parser/readBitVar'; import {readBitVar, readVarInt, writeBitVar, writeVarInt} from '../../../Parser/readBitVar';
import {assertEncoder, assertParser, getStream} from './Packet/PacketTest';
function readVarIntSigned(stream: BitStream) { function readVarIntSigned(stream: BitStream) {
return readVarInt(stream, true); return readVarInt(stream, true);

View file

@ -1,5 +1,5 @@
import {BitStream} from 'bit-buffer';
import * as assert from 'assert'; import * as assert from 'assert';
import {BitStream} from 'bit-buffer';
export interface EqualOpts { export interface EqualOpts {
strict?: boolean; strict?: boolean;
@ -15,7 +15,8 @@ export function deepEqual(actual, expected, opts: EqualOpts = {}) {
// 7.3. Other pairs that do not both pass typeof value == 'object', // 7.3. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==. // equivalence is determined by ==.
} else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') { } else if (!actual || !expected || typeof actual !== 'object' && typeof expected !== 'object') {
// tslint:disable-next-line
return opts.strict ? actual === expected : actual == expected; return opts.strict ? actual === expected : actual == expected;
// 7.4. For all other Object pairs, including Array objects, equivalence is // 7.4. For all other Object pairs, including Array objects, equivalence is
@ -34,7 +35,9 @@ function isUndefinedOrNull(value) {
} }
function isBuffer(x): x is Buffer { function isBuffer(x): x is Buffer {
if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false; if (!x || typeof x !== 'object' || typeof x.length !== 'number') {
return false;
}
if (typeof x.copy !== 'function' || typeof x.slice !== 'function') { if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
return false; return false;
} }
@ -46,9 +49,11 @@ function isStream(stream): stream is BitStream {
} }
function objEquiv(a, b, opts) { function objEquiv(a, b, opts) {
let i, key; let i;
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) let key;
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) {
return false; return false;
}
// an identical 'prototype' property. // an identical 'prototype' property.
if (a.prototype !== b.prototype) { if (a.prototype !== b.prototype) {
return false; return false;
@ -95,21 +100,25 @@ function objEquiv(a, b, opts) {
// having the same number of owned properties (keys incorporates // having the same number of owned properties (keys incorporates
// hasOwnProperty) // hasOwnProperty)
if (ka.length != kb.length) if (ka.length !== kb.length) {
return false; return false;
}
// the same set of keys (although not necessarily the same order), // the same set of keys (although not necessarily the same order),
ka.sort(); ka.sort();
kb.sort(); kb.sort();
// ~~~cheap key test // ~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) { for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i]) if (ka[i] !== kb[i]) {
return false; return false;
} }
}
// equivalent values for every corresponding key, and // equivalent values for every corresponding key, and
// ~~~possibly expensive deep test // ~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) { for (i = ka.length - 1; i >= 0; i--) {
key = ka[i]; key = ka[i];
if (!deepEqual(a[key], b[key], opts)) return false; if (!deepEqual(a[key], b[key], opts)) {
return false;
}
} }
return typeof a === typeof b; return typeof a === typeof b;
} catch (e) {// happens when one is a string literal and the other isn't } catch (e) {// happens when one is a string literal and the other isn't

View file

@ -34,7 +34,14 @@
"timeEnd", "timeEnd",
"trace" "trace"
] ]
},
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
} }
]
}, },
"jsRules": { "jsRules": {
"max-line-length": { "max-line-length": {