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

fix some typings

This commit is contained in:
Robin Appelman 2017-02-12 16:32:38 +01:00
commit ba7ce734e3
7 changed files with 146 additions and 95 deletions

View file

@ -1,7 +1,7 @@
export interface Death { export interface Death {
weapon: string; weapon: string;
victim: number; victim: number;
assister: number; assister: number|null;
killer: number; killer: number;
tick: number; tick: number;
} }

View file

@ -6,7 +6,7 @@ export interface GameEventDefinition {
export interface GameEvent { export interface GameEvent {
name: string; name: string;
values: GameEventValueMap; values: GameEventValues;
} }
export interface GameEventEntry { export interface GameEventEntry {
@ -24,12 +24,36 @@ export enum GameEventType {
LOCAL = 7 LOCAL = 7
} }
export interface DeathEventValues {
attacker: number;
userid: number;
assister: number;
weapon: string;
}
export interface RoundWinEventValues {
winreason: number;
team: number;
round_time: number;
}
export interface PlayerSpawnEventValues {
userid: number;
team: number;
'class': number
}
export type GameEventValue = string|number|boolean; export type GameEventValue = string|number|boolean;
export type GameEventValueMap = { export type GameEventValueMap = {
[name: string]: GameEventValue; [name: string]: GameEventValue;
} }
export type GameEventValues = GameEventValueMap |
DeathEventValues |
RoundWinEventValues |
PlayerSpawnEventValues;
export type GameEventDefinitionMap = { export type GameEventDefinitionMap = {
[id: number]: GameEventDefinition; [id: number]: GameEventDefinition;
} }

View file

@ -17,7 +17,7 @@ import {handlePacketEntities} from "../PacketHandler/PacketEntities";
export class Match { export class Match {
tick: number; tick: number;
chat: any[]; chat: any[];
users: UserInfo[]; users: {[id: string]: UserInfo};
deaths: Death[]; deaths: Death[];
rounds: any[]; rounds: any[];
startTick: number; startTick: number;
@ -36,7 +36,7 @@ export class Match {
constructor() { constructor() {
this.tick = 0; this.tick = 0;
this.chat = []; this.chat = [];
this.users = []; this.users = {};
this.deaths = []; this.deaths = [];
this.rounds = []; this.rounds = [];
this.startTick = 0; this.startTick = 0;
@ -76,9 +76,25 @@ export class Match {
} }
getState() { getState() {
const users = {};
for (const key in this.users) {
const user = this.users[key];
if (this.users.hasOwnProperty(key)) {
users[key] = {
classes: user.classes,
name: user.name,
steamId: user.steamId,
userId: user.userId,
};
if (user.team) {
users[key].team = user.team;
}
}
}
return { return {
'chat': this.chat, 'chat': this.chat,
'users': this.users, 'users': users,
'deaths': this.deaths, 'deaths': this.deaths,
'rounds': this.rounds, 'rounds': this.rounds,
'startTick': this.startTick, 'startTick': this.startTick,
@ -132,7 +148,8 @@ export class Match {
} }
getUserInfoForEntity(entity: Entity): UserInfo { getUserInfoForEntity(entity: Entity): UserInfo {
for (const user of this.users) { for (const id of Object.keys(this.users)) {
const user = this.users[id];
if (user && user.entityId === entity.entityIndex) { if (user && user.entityId === entity.entityIndex) {
return user; return user;
} }

View file

@ -1,51 +1,58 @@
import {GameEventPacket} from "../Data/Packet"; import {GameEventPacket} from "../Data/Packet";
import {Match} from "../Data/Match"; import {Match} from "../Data/Match";
import {DeathEventValues, RoundWinEventValues, PlayerSpawnEventValues} from "../Data/GameEvent";
export function handleGameEvent(packet: GameEventPacket, match: Match) { export function handleGameEvent(packet: GameEventPacket, match: Match) {
switch (packet.event.name) { switch (packet.event.name) {
case 'player_death': case 'player_death': {
while (packet.event.values.assister > 256 && packet.event.values.assister < (1024 * 16)) { const values = <DeathEventValues>packet.event.values;
packet.event.values.assister -= 256; while (values.assister > 256 && values.assister < (1024 * 16)) {
values.assister -= 256;
} }
const assister = packet.event.values.assister < 256 ? packet.event.values.assister : null; const assister = values.assister < 256 ? values.assister : null;
// todo get player names, not same id as the name string table (entity id) // todo get player names, not same id as the name string table (entity id?)
while (packet.event.values.attacker > 256) { while (values.attacker > 256) {
packet.event.values.attacker -= 256; values.attacker -= 256;
} }
while (packet.event.values.userid > 256) { while (values.userid > 256) {
packet.event.values.userid -= 256; values.userid -= 256;
} }
match.deaths.push({ match.deaths.push({
killer: packet.event.values.attacker, killer: values.attacker,
assister: assister, assister: assister,
victim: packet.event.values.userid, victim: values.userid,
weapon: packet.event.values.weapon, weapon: values.weapon,
tick: match.tick tick: match.tick
}); });
}
break; break;
case 'teamplay_round_win': case 'teamplay_round_win': {
if (packet.event.values.winreason !== 6) {// 6 = timelimit const values = <RoundWinEventValues>packet.event.values;
if (values.winreason !== 6) {// 6 = timelimit
match.rounds.push({ match.rounds.push({
winner: packet.event.values.team === 2 ? 'red' : 'blue', winner: values.team === 2 ? 'red' : 'blue',
length: packet.event.values.round_time, length: values.round_time,
end_tick: match.tick end_tick: match.tick
}); });
} }
}
break; break;
case 'player_spawn': case 'player_spawn': {
const userId = packet.event.values.userid; const values = <PlayerSpawnEventValues>packet.event.values;
const userId = values.userid;
const userState = match.getUserInfo(userId); const userState = match.getUserInfo(userId);
const player = match.playerMap[userState.entityId]; const player = match.playerMap[userState.entityId];
userState.team = packet.event.values.team === 2 ? 'red' : 'blue'; userState.team = values.team === 2 ? 'red' : 'blue';
const classId = packet.event.values.class; const classId = values.class;
if (player) { if (player) {
player.classId = classId; player.classId = classId;
player.team = packet.event.values.team; player.team = values.team;
} }
if (!userState.classes[classId]) { if (!userState.classes[classId]) {
userState.classes[classId] = 0; userState.classes[classId] = 0;
} }
userState.classes[classId]++; userState.classes[classId]++;
}
break; break;
} }
} }

View file

@ -1,70 +1,72 @@
import {Parser} from './Parser'; import {Parser} from './Parser';
import {StringTableEntry} from "../../Data/StringTable"; import {StringTableEntry} from "../../Data/StringTable";
import {RemoteInfo} from "dgram"; import {RemoteInfo} from "dgram";
import {StringTablePacket} from "../../Data/Packet";
export class StringTable extends Parser { export class StringTable extends Parser {
parse() { parse(): StringTablePacket[] {
// we get the tables from the packets // we get the tables from the packets
return [{ return [{
packetType: 'stringTable', packetType: 'stringTable',
tables: [] tables: []
}]; }];
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs // https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs
const tableCount = this.stream.readUint8(); // const tableCount = this.stream.readUint8();
let tables = {}; // let tables = {};
let extraDataLength; // let extraDataLength;
for (let i = 0; i < tableCount; i++) { // for (let i = 0; i < tableCount; i++) {
let entries:StringTableEntry[] = []; // let entries: StringTableEntry[] = [];
const tableName = this.stream.readASCIIString(); // const tableName = this.stream.readASCIIString();
const entryCount = this.stream.readUint16(); // const entryCount = this.stream.readUint16();
for (let j = 0; j < entryCount; j++) { // for (let j = 0; j < entryCount; j++) {
let entry; // let entry;
try { // try {
entry = { // entry = {
text: this.stream.readUTF8String() // text: this.stream.readUTF8String()
}; // };
} catch (e) { // } catch (e) {
return [{ // return [{
packetType: 'stringTable', // packetType: 'stringTable',
tables: tables // tables: tables
}]; // }];
} // }
if (this.stream.readBoolean()) { // if (this.stream.readBoolean()) {
extraDataLength = this.stream.readUint16(); // extraDataLength = this.stream.readUint16();
if ((extraDataLength * 8) > this.stream.bitsLeft) { // if ((extraDataLength * 8) > this.stream.bitsLeft) {
// extradata to long, can't continue parsing the tables // // extradata to long, can't continue parsing the tables
// seems to happen in POV demos after the MyM update // // seems to happen in POV demos after the MyM update
return [{ // return [{
packetType: 'stringTable', // packetType: 'stringTable',
tables: tables // tables: tables
}]; // }];
} // }
if (tableName === 'instancebaseline') { // if (tableName === 'instancebaseline') {
this.match.staticBaseLines[parseInt(entry.text, 10)] = this.stream.readBitStream(8 * extraDataLength); // this.match.staticBaseLines[parseInt(entry.text, 10)] = this.stream.readBitStream(8 * extraDataLength);
} else { // } else {
entry.extraData = this.readExtraData(extraDataLength); // entry.extraData = this.readExtraData(extraDataLength);
} // }
} // }
entries.push(entry); // entries.push(entry);
} // }
tables[tableName] = entries; // tables[tableName] = entries;
this.match.stringTables.push({ // this.match.stringTables.push({
name: tableName, // name: tableName,
entries: entries // entries: entries,
}); // maxEntries: 0
if (this.stream.readBits(1)) { // });
this.stream.readASCIIString(); // if (this.stream.readBits(1)) {
if (this.stream.readBits(1)) { // this.stream.readASCIIString();
//throw 'more extra data not implemented'; // if (this.stream.readBits(1)) {
extraDataLength = this.stream.readBits(16); // //throw 'more extra data not implemented';
this.stream.readBits(extraDataLength); // extraDataLength = this.stream.readBits(16);
} // this.stream.readBits(extraDataLength);
} // }
} // }
return [{ // }
packetType: 'stringTable', // return [{
tables: tables // packetType: 'stringTable',
}]; // tables: tables
// }];
} }
readExtraData(length): string[] { readExtraData(length): string[] {

View file

@ -1,11 +1,12 @@
import {Parser} from './Parser'; import {Parser} from './Parser';
import {Packet} from "../../Data/Packet";
export function make(name: string, definition: string): Parser { export function make(name: string, definition: string): Parser {
const parts = definition.substr(0, definition.length - 1).split('}');//remove leading } to prevent empty part const parts = definition.substr(0, definition.length - 1).split('}');//remove leading } to prevent empty part
const items = parts.map(function (part) { const items = parts.map(function (part) {
return part.split('{'); return part.split('{');
}); });
return function (stream) { return function (stream):Packet {
let result = { let result = {
'packetType': name 'packetType': name
}; };
@ -19,7 +20,7 @@ export function make(name: string, definition: string): Parser {
} catch (e) { } catch (e) {
throw new Error('Failed reading pattern ' + definition + '. ' + e); throw new Error('Failed reading pattern ' + definition + '. ' + e);
} }
return result; return <Packet>result;
} }
} }

View file

@ -80,7 +80,7 @@ export function UserMessage(stream: BitStream): UserMessagePacket { // 23: user
result = { result = {
packetType: 'unknownUserMessage', packetType: 'unknownUserMessage',
type: type type: type
} };
} }
stream.index = pos + length; stream.index = pos + length;
return result; return result;