mirror of
https://github.com/demostf/demo.js
synced 2026-06-03 16:44:12 +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 {
|
||||
weapon: string;
|
||||
victim: number;
|
||||
assister: number;
|
||||
assister: number|null;
|
||||
killer: number;
|
||||
tick: number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export interface GameEventDefinition {
|
|||
|
||||
export interface GameEvent {
|
||||
name: string;
|
||||
values: GameEventValueMap;
|
||||
values: GameEventValues;
|
||||
}
|
||||
|
||||
export interface GameEventEntry {
|
||||
|
|
@ -24,12 +24,36 @@ export enum GameEventType {
|
|||
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 GameEventValueMap = {
|
||||
[name: string]: GameEventValue;
|
||||
}
|
||||
|
||||
export type GameEventValues = GameEventValueMap |
|
||||
DeathEventValues |
|
||||
RoundWinEventValues |
|
||||
PlayerSpawnEventValues;
|
||||
|
||||
export type GameEventDefinitionMap = {
|
||||
[id: number]: GameEventDefinition;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {handlePacketEntities} from "../PacketHandler/PacketEntities";
|
|||
export class Match {
|
||||
tick: number;
|
||||
chat: any[];
|
||||
users: UserInfo[];
|
||||
users: {[id: string]: UserInfo};
|
||||
deaths: Death[];
|
||||
rounds: any[];
|
||||
startTick: number;
|
||||
|
|
@ -36,7 +36,7 @@ export class Match {
|
|||
constructor() {
|
||||
this.tick = 0;
|
||||
this.chat = [];
|
||||
this.users = [];
|
||||
this.users = {};
|
||||
this.deaths = [];
|
||||
this.rounds = [];
|
||||
this.startTick = 0;
|
||||
|
|
@ -76,9 +76,25 @@ export class Match {
|
|||
}
|
||||
|
||||
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 {
|
||||
'chat': this.chat,
|
||||
'users': this.users,
|
||||
'users': users,
|
||||
'deaths': this.deaths,
|
||||
'rounds': this.rounds,
|
||||
'startTick': this.startTick,
|
||||
|
|
@ -132,7 +148,8 @@ export class Match {
|
|||
}
|
||||
|
||||
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) {
|
||||
return user;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,58 @@
|
|||
import {GameEventPacket} from "../Data/Packet";
|
||||
import {Match} from "../Data/Match";
|
||||
import {DeathEventValues, RoundWinEventValues, PlayerSpawnEventValues} from "../Data/GameEvent";
|
||||
|
||||
export function handleGameEvent(packet: GameEventPacket, match: Match) {
|
||||
switch (packet.event.name) {
|
||||
case 'player_death':
|
||||
while (packet.event.values.assister > 256 && packet.event.values.assister < (1024 * 16)) {
|
||||
packet.event.values.assister -= 256;
|
||||
case 'player_death': {
|
||||
const values = <DeathEventValues>packet.event.values;
|
||||
while (values.assister > 256 && values.assister < (1024 * 16)) {
|
||||
values.assister -= 256;
|
||||
}
|
||||
const assister = packet.event.values.assister < 256 ? packet.event.values.assister : null;
|
||||
// todo get player names, not same id as the name string table (entity id)
|
||||
while (packet.event.values.attacker > 256) {
|
||||
packet.event.values.attacker -= 256;
|
||||
const assister = values.assister < 256 ? values.assister : null;
|
||||
// todo get player names, not same id as the name string table (entity id?)
|
||||
while (values.attacker > 256) {
|
||||
values.attacker -= 256;
|
||||
}
|
||||
while (packet.event.values.userid > 256) {
|
||||
packet.event.values.userid -= 256;
|
||||
while (values.userid > 256) {
|
||||
values.userid -= 256;
|
||||
}
|
||||
match.deaths.push({
|
||||
killer: packet.event.values.attacker,
|
||||
killer: values.attacker,
|
||||
assister: assister,
|
||||
victim: packet.event.values.userid,
|
||||
weapon: packet.event.values.weapon,
|
||||
victim: values.userid,
|
||||
weapon: values.weapon,
|
||||
tick: match.tick
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'teamplay_round_win':
|
||||
if (packet.event.values.winreason !== 6) {// 6 = timelimit
|
||||
case 'teamplay_round_win': {
|
||||
const values = <RoundWinEventValues>packet.event.values;
|
||||
if (values.winreason !== 6) {// 6 = timelimit
|
||||
match.rounds.push({
|
||||
winner: packet.event.values.team === 2 ? 'red' : 'blue',
|
||||
length: packet.event.values.round_time,
|
||||
winner: values.team === 2 ? 'red' : 'blue',
|
||||
length: values.round_time,
|
||||
end_tick: match.tick
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'player_spawn':
|
||||
const userId = packet.event.values.userid;
|
||||
case 'player_spawn': {
|
||||
const values = <PlayerSpawnEventValues>packet.event.values;
|
||||
const userId = values.userid;
|
||||
const userState = match.getUserInfo(userId);
|
||||
const player = match.playerMap[userState.entityId];
|
||||
userState.team = packet.event.values.team === 2 ? 'red' : 'blue';
|
||||
const classId = packet.event.values.class;
|
||||
userState.team = values.team === 2 ? 'red' : 'blue';
|
||||
const classId = values.class;
|
||||
if (player) {
|
||||
player.classId = classId;
|
||||
player.team = packet.event.values.team;
|
||||
player.team = values.team;
|
||||
}
|
||||
if (!userState.classes[classId]) {
|
||||
userState.classes[classId] = 0;
|
||||
}
|
||||
userState.classes[classId]++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,72 @@
|
|||
import {Parser} from './Parser';
|
||||
import {StringTableEntry} from "../../Data/StringTable";
|
||||
import {RemoteInfo} from "dgram";
|
||||
import {StringTablePacket} from "../../Data/Packet";
|
||||
|
||||
export class StringTable extends Parser {
|
||||
parse() {
|
||||
parse(): StringTablePacket[] {
|
||||
// we get the tables from the packets
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: []
|
||||
}];
|
||||
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs
|
||||
const tableCount = this.stream.readUint8();
|
||||
let tables = {};
|
||||
let extraDataLength;
|
||||
for (let i = 0; i < tableCount; i++) {
|
||||
let entries:StringTableEntry[] = [];
|
||||
const tableName = this.stream.readASCIIString();
|
||||
const entryCount = this.stream.readUint16();
|
||||
for (let j = 0; j < entryCount; j++) {
|
||||
let entry;
|
||||
try {
|
||||
entry = {
|
||||
text: this.stream.readUTF8String()
|
||||
};
|
||||
} catch (e) {
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
}];
|
||||
}
|
||||
if (this.stream.readBoolean()) {
|
||||
extraDataLength = this.stream.readUint16();
|
||||
if ((extraDataLength * 8) > this.stream.bitsLeft) {
|
||||
// extradata to long, can't continue parsing the tables
|
||||
// seems to happen in POV demos after the MyM update
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
}];
|
||||
}
|
||||
if (tableName === 'instancebaseline') {
|
||||
this.match.staticBaseLines[parseInt(entry.text, 10)] = this.stream.readBitStream(8 * extraDataLength);
|
||||
} else {
|
||||
entry.extraData = this.readExtraData(extraDataLength);
|
||||
}
|
||||
}
|
||||
entries.push(entry);
|
||||
}
|
||||
tables[tableName] = entries;
|
||||
this.match.stringTables.push({
|
||||
name: tableName,
|
||||
entries: entries
|
||||
});
|
||||
if (this.stream.readBits(1)) {
|
||||
this.stream.readASCIIString();
|
||||
if (this.stream.readBits(1)) {
|
||||
//throw 'more extra data not implemented';
|
||||
extraDataLength = this.stream.readBits(16);
|
||||
this.stream.readBits(extraDataLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [{
|
||||
packetType: 'stringTable',
|
||||
tables: tables
|
||||
}];
|
||||
// const tableCount = this.stream.readUint8();
|
||||
// let tables = {};
|
||||
// let extraDataLength;
|
||||
// for (let i = 0; i < tableCount; i++) {
|
||||
// let entries: StringTableEntry[] = [];
|
||||
// const tableName = this.stream.readASCIIString();
|
||||
// const entryCount = this.stream.readUint16();
|
||||
// for (let j = 0; j < entryCount; j++) {
|
||||
// let entry;
|
||||
// try {
|
||||
// entry = {
|
||||
// text: this.stream.readUTF8String()
|
||||
// };
|
||||
// } catch (e) {
|
||||
// return [{
|
||||
// packetType: 'stringTable',
|
||||
// tables: tables
|
||||
// }];
|
||||
// }
|
||||
// if (this.stream.readBoolean()) {
|
||||
// extraDataLength = this.stream.readUint16();
|
||||
// if ((extraDataLength * 8) > this.stream.bitsLeft) {
|
||||
// // extradata to long, can't continue parsing the tables
|
||||
// // seems to happen in POV demos after the MyM update
|
||||
// return [{
|
||||
// packetType: 'stringTable',
|
||||
// tables: tables
|
||||
// }];
|
||||
// }
|
||||
// if (tableName === 'instancebaseline') {
|
||||
// this.match.staticBaseLines[parseInt(entry.text, 10)] = this.stream.readBitStream(8 * extraDataLength);
|
||||
// } else {
|
||||
// entry.extraData = this.readExtraData(extraDataLength);
|
||||
// }
|
||||
// }
|
||||
// entries.push(entry);
|
||||
// }
|
||||
// tables[tableName] = entries;
|
||||
// this.match.stringTables.push({
|
||||
// name: tableName,
|
||||
// entries: entries,
|
||||
// maxEntries: 0
|
||||
// });
|
||||
// if (this.stream.readBits(1)) {
|
||||
// this.stream.readASCIIString();
|
||||
// if (this.stream.readBits(1)) {
|
||||
// //throw 'more extra data not implemented';
|
||||
// extraDataLength = this.stream.readBits(16);
|
||||
// this.stream.readBits(extraDataLength);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return [{
|
||||
// packetType: 'stringTable',
|
||||
// tables: tables
|
||||
// }];
|
||||
}
|
||||
|
||||
readExtraData(length): string[] {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import {Parser} from './Parser';
|
||||
import {Packet} from "../../Data/Packet";
|
||||
|
||||
export function make(name: string, definition: string): Parser {
|
||||
const parts = definition.substr(0, definition.length - 1).split('}');//remove leading } to prevent empty part
|
||||
const items = parts.map(function (part) {
|
||||
return part.split('{');
|
||||
});
|
||||
return function (stream) {
|
||||
return function (stream):Packet {
|
||||
let result = {
|
||||
'packetType': name
|
||||
};
|
||||
|
|
@ -19,7 +20,7 @@ export function make(name: string, definition: string): Parser {
|
|||
} catch (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 = {
|
||||
packetType: 'unknownUserMessage',
|
||||
type: type
|
||||
}
|
||||
};
|
||||
}
|
||||
stream.index = pos + length;
|
||||
return result;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue