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:
parent
48b376fa2e
commit
ba7ce734e3
7 changed files with 146 additions and 95 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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[] {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue