1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-03 16:44:12 +02:00
This commit is contained in:
Robin Appelman 2017-12-09 17:02:52 +01:00
commit 787c6a0279
21 changed files with 118 additions and 115 deletions

View file

@ -76,19 +76,6 @@ export class ParserState {
return table;
}
private handleDataTableMessage(message: DataTablesMessage) {
for (const table of message.tables) {
this.sendTables.set(table.name, table);
}
this.serverClasses = message.serverClasses;
}
private handleStringTableMessage(message: StringTablesMessage) {
for (const table of message.tables) {
handleTable(table, this);
}
}
public getUserEntityInfo(userId: number): UserEntityInfo {
const info = this.userInfo.get(userId);
if (info) {
@ -101,6 +88,19 @@ export class ParserState {
entityId: 0
};
}
private handleDataTableMessage(message: DataTablesMessage) {
for (const table of message.tables) {
this.sendTables.set(table.name, table);
}
this.serverClasses = message.serverClasses;
}
private handleStringTableMessage(message: StringTablesMessage) {
for (const table of message.tables) {
handleTable(table, this);
}
}
}
export function getClassBits(state: ParserState) {

View file

@ -2,20 +2,6 @@ import {SendPropDefinition} from './SendPropDefinition';
import {Vector} from './Vector';
export class SendProp {
public definition: SendPropDefinition;
public value: SendPropValue | null;
constructor(definition: SendPropDefinition) {
this.definition = definition;
this.value = null;
}
public clone(): SendProp {
const prop = new SendProp(this.definition);
prop.value = this.value;
return prop;
}
public static areEqual(a: SendProp, b: SendProp) {
return a.definition.fullName !== b.definition.fullName ? false : SendProp.valuesAreEqual(a.value, b.value);
}
@ -37,6 +23,20 @@ export class SendProp {
return a === b;
}
}
public definition: SendPropDefinition;
public value: SendPropValue | null;
constructor(definition: SendPropDefinition) {
this.definition = definition;
this.value = null;
}
public clone(): SendProp {
const prop = new SendProp(this.definition);
prop.value = this.value;
return prop;
}
}
export type SendPropArrayValue = Vector | number | string;

View file

@ -66,7 +66,7 @@ export interface BaseDataUserPacket {
}
export interface SayText2Packet {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'sayText2';
client: number;
raw: number;
@ -83,24 +83,24 @@ export enum HudTextLocation {
}
export interface TextMessagePacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'textMsg';
destType: HudTextLocation;
text: string;
}
export interface ResetHUDPacket extends BaseDataUserPacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'resetHUD';
}
export interface TrainPacket extends BaseDataUserPacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'train';
}
export interface VoiceSubtitlePacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'voiceSubtitle';
client: number;
menu: number;
@ -108,7 +108,7 @@ export interface VoiceSubtitlePacket {
}
export interface ShakePacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'shake';
command: number;
amplitude: number;
@ -122,12 +122,12 @@ export interface UnknownUserMessageBasePacket {
}
export interface BreakModelPumpkinPacket extends UnknownUserMessageBasePacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'breakModelPumpkin';
}
export interface GenericUnknownUserMessagePacket extends UnknownUserMessageBasePacket {
packetType: 'userMessage',
packetType: 'userMessage';
userMessageType: 'unknownUserMessage';
}

View file

@ -1,4 +1,8 @@
export class Vector {
public static areEqual(a: Vector, b: Vector) {
return a.x === b.x && a.y === b.y && a.z === b.z;
}
public x: number;
public y: number;
public z: number;
@ -8,8 +12,4 @@ export class Vector {
this.y = y;
this.z = z;
}
public static areEqual(a: Vector, b: Vector) {
return a.x === b.x && a.y === b.y && a.z === b.z;
}
}

View file

@ -1,12 +1,12 @@
import {GameEventDefinition} from '../Data/GameEvent';
import {GameEventType} from '../Data/GameEventTypes';
import {GameEventListPacket} from '../Data/Packet';
import {ParserState} from '../Data/ParserState';
import {GameEventType} from '../Data/GameEventTypes';
import {GameEventDefinition} from '../Data/GameEvent';
export function handleGameEventList(packet: GameEventListPacket, state: ParserState) {
state.eventDefinitions = packet.eventList;
const entries: ([number, GameEventDefinition<GameEventType>])[] = Array.from(packet.eventList.entries());
const reversedEntries = entries.map(([type, definition]) => [definition.name, type]) as [GameEventType, number][];
const entries: Array<[number, GameEventDefinition<GameEventType>]> = Array.from(packet.eventList.entries());
const reversedEntries = entries.map(([type, definition]) => [definition.name, type]) as Array<[GameEventType, number]>;
state.eventDefinitionTypes = new Map(reversedEntries);
}

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer';
import {CreateStringTablePacket, StringTablePacket, UpdateStringTablePacket} from '../Data/Packet';
import {ParserState} from '../Data/ParserState';
import {StringTable, StringTableEntry} from '../Data/StringTable';
import {UserEntityInfo, UserInfo} from '../Data/UserInfo';
import {BitStream} from 'bit-buffer';
export function handleStringTable(packet: CreateStringTablePacket, state: ParserState) {
handleTable(packet.table, state);

View file

@ -3,6 +3,7 @@ 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 {parseHeader} from './Parser/Header';
import {ConsoleCmdHandler} from './Parser/Message/ConsoleCmd';
import {DataTableHandler} from './Parser/Message/DataTable';
import {PacketMessageHandler} from './Parser/Message/Packet';
@ -10,7 +11,6 @@ import {StopHandler} from './Parser/Message/Stop';
import {StringTableHandler} from './Parser/Message/StringTable';
import {SyncTickHandler} from './Parser/Message/SyncTick';
import {UserCmdHandler} from './Parser/Message/UserCmd';
import {parseHeader} from './Parser/Header';
export const messageHandlers: Map<MessageType, MessageHandler<Message>> = new Map<MessageType, MessageHandler<Message>>([
[MessageType.Sigon, PacketMessageHandler],
@ -50,6 +50,17 @@ export class Parser {
}
}
public * getMessages(): IterableIterator<Message> {
// ensure that we are past the header
this.getHeader();
for (const message of this.iterateMessages()) {
for (const _ of this.handleMessage(message)) {
// noop, loop needed to "drain" iterator
}
yield message;
}
}
protected * iterateMessages(): Iterable<Message> {
while (true) {
const message = this.readMessage(this.stream, this.parserState);
@ -60,18 +71,6 @@ export class Parser {
}
}
public * getMessages(): IterableIterator<Message> {
// ensure that we are past the header
this.getHeader();
for (const message of this.iterateMessages()) {
for (const _ of this.handleMessage(message)) {
//noop
}
// console.log(message.type);
yield message;
}
}
protected * handleMessage(message: Message): Iterable<Packet> {
this.parserState.handleMessage(message);
if (message.type === MessageType.Packet) {

View file

@ -1,5 +1,5 @@
import {Header} from '../Data/Header';
import {BitStream} from 'bit-buffer';
import {Header} from '../Data/Header';
export function parseHeader(stream: BitStream): Header {
return {

View file

@ -3,7 +3,7 @@ import {CreateStringTablePacket} from '../../Data/Packet';
import {logBase2} from '../../Math';
import {readVarInt, writeVarInt} from '../readBitVar';
import {uncompress, compress} from 'snappyjs';
import {compress, uncompress} from 'snappyjs';
import {StringTable} from '../../Data/StringTable';
import {encodeStringTableEntries, guessStringTableEntryLength, parseStringTableEntries} from '../StringTableParser';
@ -84,7 +84,7 @@ export function EncodeCreateStringTable(packet: CreateStringTablePacket, stream:
entryData.writeUint32(decompressedByteLength);
entryData.writeUint32(compressedData.byteLength + 4); // 4 magic bytes
entryData.writeASCIIString('SNAP', 4);
let typeForce: any = compressedData.buffer;
const typeForce: any = compressedData.buffer;
entryData.writeArrayBuffer(typeForce as BitStream);
}
const entryLength = entryData.index;

View file

@ -1,13 +1,18 @@
import {BitStream} from 'bit-buffer';
import {Packet, PacketMapType, PacketType} from '../../Data/Packet';
import {Encoder, PacketHandler, Parser} from './Parser';
import {UserMessagePacketType} from '../../Data/UserMessage';
import {Encoder, PacketHandler, Parser} from './Parser';
export interface NamedPacketHandler<P extends Packet, N extends PacketType | UserMessagePacketType> extends PacketHandler<P> {
name: N;
}
export function make<T extends PacketType | UserMessagePacketType>(name: T, definition: string, nameKey: string = 'packetType', extraData: any = {}): NamedPacketHandler<PacketMapType[T], T> {
export function make<T extends PacketType | UserMessagePacketType>(
name: T,
definition: string,
nameKey: string = 'packetType',
extraData: any = {}
): NamedPacketHandler<PacketMapType[T], T> {
const parts = definition.split('}');
const items = parts.map((part) => {
return part.split('{');

View file

@ -10,7 +10,9 @@ import {
import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
import {make, NamedPacketHandler} from './ParserGenerator';
function unknownPacketHandler<T extends UnknownUserMessagePacket['userMessageType']>(userMessageType: T): NamedPacketHandler<UserMessageTypeMap[T], UserMessagePacketType> {
type UnknownType = UnknownUserMessagePacket['userMessageType'];
function unknownPacketHandler<T extends UnknownType>(userMessageType: T): NamedPacketHandler<UserMessageTypeMap[T], UserMessagePacketType> {
return {
parser: (data: BitStream) => {
return {

View file

@ -95,7 +95,12 @@ export function guessStringTableEntryLength(table: StringTable, entries: StringT
}, 1);
}
export function encodeStringTableEntries(stream: BitStream, table: StringTable, entries: StringTableEntry[], oldEntries: StringTableEntry[] = []) {
export function encodeStringTableEntries(
stream: BitStream,
table: StringTable,
entries: StringTableEntry[],
oldEntries: StringTableEntry[] = []
) {
const entryBits = logBase2(table.maxEntries);
let lastIndex = -1;
const history: StringTableEntry[] = [];
@ -128,7 +133,6 @@ export function encodeStringTableEntries(stream: BitStream, table: StringTable,
stream.writeBoolean(false);
}
if (entry.extraData) {
stream.writeBoolean(true);
@ -145,7 +149,6 @@ export function encodeStringTableEntries(stream: BitStream, table: StringTable,
stream.writeBoolean(false);
}
history.push(entry);
if (history.length > 32) {
history.shift();

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer';
import {Parser} from './Parser';
import {Encoder} from './Encoder';
import {Packet} from './Data/Packet';
import {Message, MessageType} from './Data/Message';
import {Packet} from './Data/Packet';
import {Encoder} from './Encoder';
import {Parser} from './Parser';
export type PacketTransform = (packet: Packet) => Packet;

View file

@ -1,12 +1,12 @@
import * as assert from 'assert';
import {BitStream} from 'bit-buffer';
import {readFileSync, statSync, writeFileSync} from 'fs';
import {DynamicBitStream} from '../../DynamicBitStream';
import {MessageTransform, nullTransform, PacketTransform, Transformer} from '../../Transformer';
import {Parser} from '../../Parser';
import {Analyser} from '../../Analyser';
import {Encoder} from '../../Encoder';
import {Packet} from '../../Data/Packet';
import {DynamicBitStream} from '../../DynamicBitStream';
import {Encoder} from '../../Encoder';
import {Parser} from '../../Parser';
import {MessageTransform, nullTransform, PacketTransform, Transformer} from '../../Transformer';
function testDemo(name: string, packetTransform: PacketTransform, messageTransform: MessageTransform) {
const decodeStream = new BitStream(

View file

@ -1,6 +1,6 @@
import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, assertReEncode, getStream} from './Packet/PacketTest';
import {encodeHeader, parseHeader} from '../../../Parser/Header';
import {assertEncoder, assertParser, assertReEncode, getStream} from './Packet/PacketTest';
const data = [
72, 76, 50, 68,
@ -361,38 +361,37 @@ const data = [
147, 25, 115, 17
];
suite('Header', () => {
test('Parse header', () => {
assertParser(parseHeader, getStream(data), {
'type': 'HL2DEMO',
'version': 3,
'protocol': 24,
'server': 'FakkelBrigade #1 (#712133)',
'nick': 'SourceTV Demo',
'map': 'cp_prolands_b2c',
'game': 'tf',
'duration': 515.1900024414062,
'ticks': 34346,
'frames': 34334,
'sigon': 808977
type: 'HL2DEMO',
version: 3,
protocol: 24,
server: 'FakkelBrigade #1 (#712133)',
nick: 'SourceTV Demo',
map: 'cp_prolands_b2c',
game: 'tf',
duration: 515.1900024414062,
ticks: 34346,
frames: 34334,
sigon: 808977
}
, 8576);
});
test('Encode header', () => {
assertEncoder(parseHeader, encodeHeader, {
'type': 'HL2DEMO',
'version': 3,
'protocol': 24,
'server': 'FakkelBrigade #1 (#712133)',
'nick': 'SourceTV Demo',
'map': 'cp_prolands_b2c',
'game': 'tf',
'duration': 515.1900024414062,
'ticks': 34346,
'frames': 34334,
'sigon': 808977
type: 'HL2DEMO',
version: 3,
protocol: 24,
server: 'FakkelBrigade #1 (#712133)',
nick: 'SourceTV Demo',
map: 'cp_prolands_b2c',
game: 'tf',
duration: 515.1900024414062,
ticks: 34346,
frames: 34334,
sigon: 808977
}
, 8576);
});

View file

@ -47,12 +47,12 @@ suite('DataTable', () => {
test('Encode DataTable message', () => {
const source = getStream(data);
const expected = parser(source);
const expectedResult = parser(source);
const length = 947888;
const stream = new BitStream(new ArrayBuffer(length + 64000));
encoder(expected, stream);
encoder(expectedResult, stream);
const pos = stream.index;
@ -63,9 +63,9 @@ suite('DataTable', () => {
stream.index = 0;
const result = parser(stream);
assert.deepEqual(result.serverClasses, expected.serverClasses, 'Re-decoded value not equal to original value');
assert.deepEqual(result.tick, expected.tick, 'Re-decoded value not equal to original value');
assert.deepEqual(result.type, expected.type, 'Re-decoded value not equal to original value');
assert.deepEqual(result.serverClasses, expectedResult.serverClasses, 'Re-decoded value not equal to original value');
assert.deepEqual(result.tick, expectedResult.tick, 'Re-decoded value not equal to original value');
assert.deepEqual(result.type, expectedResult.type, 'Re-decoded value not equal to original value');
for (let i = 0; i < result.tables.length; i++) {
const resultTable = result.tables[i];
const expectedTable = expectedRaw.tables[i];

View file

@ -43,8 +43,8 @@ suite('Packet', () => {
});
test('Encode first packet message', () => {
const expected = parser(new BitStream(firstPacketData));
assertEncoder(parser, encoder, expected, 1032952, '');
const expectedResult = parser(new BitStream(firstPacketData));
assertEncoder(parser, encoder, expectedResult, 1032952, '');
});
// test('Re-encode first packet message', () => {

View file

@ -5,7 +5,7 @@ import {
} from '../../../../Parser/Packet/BSPDecal';
import {SendPropEncoder} from '../../../../Parser/SendPropEncoder';
import {SendPropParser} from '../../../../Parser/SendPropParser';
import {assertEncoder, assertParser, getStream, assertReEncode} from './PacketTest';
import {assertEncoder, assertParser, assertReEncode, getStream} from './PacketTest';
const data = [239, 236, 208, 85, 33, 127, 128, 9, 8];

View file

@ -14,7 +14,7 @@ function getExistingParserState() {
maxEntries: 2048,
fixedUserDataSize: 1,
fixedUserDataSizeBits: 1,
compressed: false,
compressed: false
};
existingTable.entries[70] = {text: 'maps\\pl_badwater_pro_v9.bsp'};
const state = createParserState();

View file

@ -1,8 +1,8 @@
import {BitStream} from 'bit-buffer';
import {assertEncoder, assertParser, assertReEncode} from './Packet/PacketTest';
import {readFileSync} from 'fs';
import {encodeStringTableEntries, parseStringTableEntries} from '../../../Parser/StringTableParser';
import {StringTableEntry} from '../../../Data/StringTable';
import {encodeStringTableEntries, parseStringTableEntries} from '../../../Parser/StringTableParser';
import {assertEncoder, assertParser, assertReEncode, getStream} from './Packet/PacketTest';
const baseTable = {
name: 'modelprecache',
@ -16,7 +16,6 @@ const baseTable = {
const data = readFileSync(__dirname + '/../../data/stringTableEntries.bin');
function ParseUpdate(stream: BitStream) {
//981
return parseStringTableEntries(stream, baseTable, 981);
}
@ -25,10 +24,6 @@ function EncodeUpdate(entries: StringTableEntry[], stream: BitStream) {
}
suite('string table parser', () => {
// test('Parse string table entries', () => {
// assertParser(ParseUpdate, getStream(exampleData), examplePacket, 41);
// });
test('Encode string table entries', () => {
const expected = ParseUpdate(new BitStream(data));
assertEncoder(ParseUpdate, EncodeUpdate, expected);