1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-03 16:44:12 +02:00

parse deaths and strictly type packet types

This commit is contained in:
Robin Appelman 2017-02-12 15:09:03 +01:00
commit cb02fdee9b
18 changed files with 217 additions and 119 deletions

7
src/Data/Death.ts Normal file
View file

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

View file

@ -9,11 +9,13 @@ import {UserInfo} from "./UserInfo";
import {World} from "./World";
import {Vector} from "./Vector";
import {Player} from "./Player";
import {Death} from "./Death";
import {HandlerMap} from "../PacketHandler/Handler";
export class Match {
tick: number;
chat: any[];
users: UserInfo[];
deaths: any[];
deaths: Death[];
rounds: any[];
startTick: number;
intervalPerTick: number;
@ -53,18 +55,18 @@ export class Match {
}
getSendTable(name) {
for (var i = 0; i < this.sendTables.length; i++) {
if (this.sendTables[i].name === name) {
return this.sendTables[i];
for (const table of this.sendTables) {
if (table.name === name) {
return table;
}
}
throw new Error("unknown SendTable " + name);
}
getStringTable(name) {
for (var i = 0; i < this.stringTables.length; i++) {
if (this.stringTables[i].name === name) {
return this.stringTables[i];
for (const table of this.stringTables) {
if (table.name === name) {
return table;
}
}
return null;
@ -112,7 +114,7 @@ export class Match {
if (table.name === 'userinfo') {
for (const userData of table.entries) {
if (userData.extraData) {
if (userData.extraData.bitsLeft > (32*8)) {
if (userData.extraData.bitsLeft > (32 * 8)) {
const name = userData.extraData.readUTF8String(32);
const userId = userData.extraData.readUint32();
const steamId = userData.extraData.readUTF8String();
@ -164,12 +166,11 @@ export class Match {
const userId = packet.event.values.userid;
const userState = this.getUserInfo(userId);
const player = this.playerMap[userState.entityId];
if (!userState.team) { //only register first spawn
userState.team = packet.event.values.team === 2 ? 'red' : 'blue'
}
userState.team = packet.event.values.team === 2 ? 'red' : 'blue';
const classId = packet.event.values.class;
if (player) {
player.classId = classId;
player.team = packet.event.values.team;
}
if (!userState.classes[classId]) {
userState.classes[classId] = 0;
@ -209,6 +210,15 @@ export class Match {
throw new Error('User not found for entity ' + entity.entityIndex);
}
getPlayerByUserId(userId: number): Player {
for (const player of this.players) {
if (player.user.userId === userId) {
return player;
}
}
throw new Error('player not found for user id');
}
get classBits() {
return Math.ceil(Math.log(this.serverClasses.length) * Math.LOG2E)
}
@ -220,11 +230,14 @@ export class Match {
this.world.boundaryMax = <Vector>entity.getProperty('DT_WORLD', 'm_WorldMaxs').value;
break;
case 'CTFPlayer':
try {
const player: Player = (this.playerMap[entity.entityIndex]) ? this.playerMap[entity.entityIndex] : {
user: this.getUserInfoForEntity(entity),
position: new Vector(0, 0, 0),
maxHealth: 0,
health: 0,
classId: 0,
team: 0
};
if (!this.playerMap[entity.entityIndex]) {
this.playerMap[entity.entityIndex] = player;
@ -257,6 +270,9 @@ export class Match {
break;
}
}
} catch (e) {
}
}
entity.updatedProps = [];

View file

@ -1,4 +1,93 @@
export interface Packet {
packetType: string;
[name: string]: any;
import {StringTable} from "./StringTable";
import {Vector} from "./Vector";
import {GameEvent} from "./GameEvent";
export interface StringTablePacket {
packetType: 'stringTable';
tables: StringTable[];
}
export interface BSPDecalPacket {
packetType: 'bspDecal';
position: Vector;
textureIndex: number;
entIndex: number;
modelIndex: number;
lowPriority: boolean;
}
export interface ClassInfoPacket {
packetType: 'classInfo';
number: number;
create: boolean;
entries: {
classId: number;
className: string;
dataTableName: string;
}[]
}
export interface EntityMessagePacket {
packetType: 'entityMessage';
classId: number;
length: number;
data: string;
}
export interface GameEventPacket {
packetType: 'gameEvent';
event: GameEvent;
}
export interface GameEventListPacket {
packetType: 'gameEventList';
}
export interface PacketEntitiesPacket {
packetType: 'packetEntities';
}
export interface ParseSoundsPacket {
packetType: 'parseSounds';
reliable: boolean;
num: number;
length: number;
}
export interface SetConVarPacket {
packetType: 'setConVar';
vars: {[key: string]: string};
}
export interface SayText2Packet {
packetType: 'sayText2';
client: number;
raw: number;
kind: string;
from: string;
text: string;
}
export interface TextMessagePacket {
packetType: 'textMsg';
destType: number;
text: string;
}
export interface UnknownUserMessagePacket {
packetType: 'unknownUserMessage';
type: number;
}
export type UserMessagePacket = SayText2Packet | TextMessagePacket | UnknownUserMessagePacket;
export type Packet = BSPDecalPacket |
StringTablePacket |
ClassInfoPacket |
EntityMessagePacket |
GameEventPacket |
GameEventListPacket |
PacketEntitiesPacket |
ParseSoundsPacket |
SetConVarPacket |
UserMessagePacket;

View file

@ -6,4 +6,5 @@ export interface Player {
health: number;
maxHealth: number;
classId: number;
team: number;
}

View file

@ -85,7 +85,7 @@ export class Packet extends Parser {
enum PacketType {
file = 2,
netTick = 3,
stringSmd = 4,
stringCmd = 4,
setConVar = 5,
sigOnState = 6,
print = 7,

View file

@ -1,5 +1,6 @@
import {Packet} from "../../Data/Packet";
import {BSPDecalPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {Vector} from "../../Data/Vector";
const getCoord = function (stream) {
const hasInt = !!stream.readBits(1);
@ -20,7 +21,7 @@ const getCoord = function (stream) {
return value;
};
const getVecCoord = function (stream) {
const getVecCoord = function (stream): Vector {
const hasX = !!stream.readBits(1);
const hasY = !!stream.readBits(1);
const hasZ = !!stream.readBits(1);
@ -31,7 +32,7 @@ const getVecCoord = function (stream) {
}
};
export function BSPDecal(stream: BitStream): Packet { // 21: BSPDecal
export function BSPDecal(stream: BitStream): BSPDecalPacket { // 21: BSPDecal
let modelIndex, entIndex;
const position = getVecCoord(stream);
const textureIndex = stream.readBits(9);
@ -39,7 +40,7 @@ export function BSPDecal(stream: BitStream): Packet { // 21: BSPDecal
entIndex = stream.readBits(11);
modelIndex = stream.readBits(12);
}
const lowPriority = !!stream.readBits(1);
const lowPriority = stream.readBoolean();
return {
packetType: 'bspDecal',
position: position,

View file

@ -1,10 +1,10 @@
import {Packet} from "../../Data/Packet";
import {ClassInfoPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {logBase2} from '../../Math';
export function ClassInfo(stream: BitStream): Packet { // 10: classInfo
export function ClassInfo(stream: BitStream): ClassInfoPacket { // 10: classInfo
const number = stream.readBits(16);
const create = !!stream.readBits(1);
const create = stream.readBoolean();
let entries: any[] = [];
if (!create) {
const bits = logBase2(number) + 1;

View file

@ -1,16 +1,14 @@
import {PacketStringTable} from './PacketStringTable';
import {Packet} from "../../Data/Packet";
import {StringTablePacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {logBase2} from "../../Math";
import {readBitVar, readVarInt} from "../readBitVar";
import {readVarInt} from "../readBitVar";
import {uncompress} from "snappyjs";
import {StringTable} from "../../Data/StringTable";
import {parseStringTable} from "../StringTableParser";
import {Match} from "../../Data/Match";
export function CreateStringTable(stream: BitStream, match: Match): Packet { // 12: createStringTable
export function CreateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: createStringTable
const tableName = stream.readASCIIString();
const maxEntries = stream.readUint16();
const encodeBits = logBase2(maxEntries);

View file

@ -1,10 +1,10 @@
import {make} from './ParserGenerator';
import {Packet} from "../../Data/Packet";
import {EntityMessagePacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
const baseParser = make('entityMessage', 'index{11}classId{9}length{11}data{$length}');
export function EntityMessage(stream:BitStream):Packet { // 24: entityMessage
return baseParser(stream); //todo parse data further?
export function EntityMessage(stream: BitStream): EntityMessagePacket { // 24: entityMessage
return <EntityMessagePacket>baseParser(stream); //todo parse data further?
};

View file

@ -1,4 +1,4 @@
import {Packet} from "../../Data/Packet";
import {GameEventPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {
GameEventType, GameEventValue, GameEventEntry, GameEventDefinition, GameEvent as IGameEvent,
@ -6,9 +6,9 @@ import {
} from "../../Data/GameEvent";
import {Match} from "../../Data/Match";
const parseGameEvent = function (eventId: number, stream: BitStream, events: GameEventDefinitionMap): IGameEvent|null {
const parseGameEvent = function (eventId: number, stream: BitStream, events: GameEventDefinitionMap): IGameEvent {
if (!events[eventId]) {
return null;
throw new Error('unknown event type')
}
const eventDescription: GameEventDefinition = events[eventId];
const values: GameEventValueMap = {};
@ -47,7 +47,7 @@ const getGameEventValue = function (stream: BitStream, entry: GameEventEntry): G
};
export function GameEvent(stream: BitStream, match: Match): Packet { // 25: game event
export function GameEvent(stream: BitStream, match: Match): GameEventPacket { // 25: game event
const length = stream.readBits(11);
const end = stream.index + length;
const eventId = stream.readBits(9);

View file

@ -1,9 +1,9 @@
import {Packet} from "../../Data/Packet";
import {GameEventListPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {GameEventEntry, GameEventDefinitionMap} from "../../Data/GameEvent";
import {Match} from "../../Data/Match";
export function GameEventList(stream: BitStream, match: Match): Packet { // 30: gameEventList
export function GameEventList(stream: BitStream, match: Match): GameEventListPacket { // 30: gameEventList
// list of game events and parameters
const numEvents = stream.readBits(9);
const length = stream.readBits(20);

View file

@ -1,9 +1,7 @@
import {SendPropParser} from '../../Parser/SendPropParser';
import {Entity} from '../../Data/Entity';
import {SendProp} from '../../Data/SendProp';
import {Packet} from "../../Data/Packet";
import {PacketEntitiesPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {GameEventDefinition} from "../../Data/GameEvent";
import {Match} from "../../Data/Match";
import {readUBitVar} from "../readBitVar";
import {applyEntityUpdate} from "../EntityDecoder";
@ -74,7 +72,7 @@ function readLeavePVS(match, entityId, shouldDelete) {
}
}
export function PacketEntities(stream: BitStream, match: Match): Packet { //26: packetEntities
export function PacketEntities(stream: BitStream, match: Match): PacketEntitiesPacket { //26: packetEntities
// 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/Entity.cs

View file

@ -1,12 +0,0 @@
import {BitStream} from "bit-buffer";
import {Packet} from "../../Data/Packet";
export function PacketStringTable(stream: BitStream):Packet {
//todo
// https://coldemoplayer.googlecode.com/svn/branches/2.0/code/plugins/CDP.Source/Messages/SvcCreateStringTable.cs
// throw new Error('packetstringtable not implemented');
stream.index = stream.length; // no idea, skip to the end of the
return {
packetType: 'stringTableTODO'
};
}

View file

@ -1,7 +1,7 @@
import {Packet} from "../../Data/Packet";
import {ParseSoundsPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
export function ParseSounds(stream: BitStream): Packet { // 17: parseSounds
export function ParseSounds(stream: BitStream): ParseSoundsPacket { // 17: parseSounds
const reliable = stream.readBoolean();
const num = (reliable) ? 1 : stream.readUint8();
const length = (reliable) ? stream.readUint8() : stream.readUint16();

View file

@ -1,9 +1,9 @@
import {Packet} from "../../Data/Packet";
import {SetConVarPacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
export function SetConVar(stream: BitStream): Packet { // 5: setconvar
export function SetConVar(stream: BitStream): SetConVarPacket { // 5: setconvar
const count = stream.readBits(8);
let vars = {};
let vars: {[key: string]: string} = {};
for (let i = 0; i < count; i++) {
vars[stream.readUTF8String()] = stream.readUTF8String();
}

View file

@ -1,10 +1,10 @@
import {PacketStringTable} from './PacketStringTable';
import {Packet} from "../../Data/Packet";
import {StringTablePacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {Match} from "../../Data/Match";
import {parseStringTable} from "../StringTableParser";
export function UpdateStringTable(stream: BitStream, match: Match): Packet { // 12: updateStringTable
export function UpdateStringTable(stream: BitStream, match: Match): StringTablePacket { // 12: updateStringTable
const tableId = stream.readBits(5);
const multipleChanged = stream.readBoolean();

View file

@ -1,4 +1,4 @@
import {Packet} from "../../Data/Packet";
import {UserMessagePacket} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
import {make} from './ParserGenerator';
import {SayText2} from '../UserMessage/SayText2';
@ -69,7 +69,7 @@ const userMessageParsers = {
5: make('textMsg', 'destType{8}text{s}')
};
export function UserMessage(stream: BitStream): Packet { // 23: user message
export function UserMessage(stream: BitStream): UserMessagePacket { // 23: user message
const type = stream.readBits(8);
const length = stream.readBits(11);
const pos = stream.index;

View file

@ -1,7 +1,7 @@
import {Packet} from "../../Data/Packet";
import {SayText2Packet} from "../../Data/Packet";
import {BitStream} from 'bit-buffer';
export function SayText2(stream: BitStream): Packet { // 4: SayText2
export function SayText2(stream: BitStream): SayText2Packet { // 4: SayText2
var client = stream.readBits(8);
var raw = stream.readBits(8);
var pos = stream.index;