mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
add explicit tick function to step trough demos
This commit is contained in:
parent
a36208c693
commit
58852ffac7
3 changed files with 58 additions and 22 deletions
|
|
@ -5,10 +5,11 @@ import {StringTable} from "./StringTable";
|
||||||
import {SendProp} from "./SendProp";
|
import {SendProp} from "./SendProp";
|
||||||
import {GameEventDefinitionMap} from "./GameEvent";
|
import {GameEventDefinitionMap} from "./GameEvent";
|
||||||
import {BitStream} from "bit-buffer";
|
import {BitStream} from "bit-buffer";
|
||||||
|
import {UserInfo} from "./UserInfo";
|
||||||
export class Match {
|
export class Match {
|
||||||
tick: number;
|
tick: number;
|
||||||
chat: any[];
|
chat: any[];
|
||||||
users: any;
|
users: UserInfo[];
|
||||||
deaths: any[];
|
deaths: any[];
|
||||||
rounds: any[];
|
rounds: any[];
|
||||||
startTick: number;
|
startTick: number;
|
||||||
|
|
@ -24,7 +25,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;
|
||||||
|
|
@ -69,9 +70,16 @@ export class Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacket(packet) {
|
handlePacket(packet) {
|
||||||
var userState;
|
|
||||||
switch (packet.packetType) {
|
switch (packet.packetType) {
|
||||||
case 'packetEntities':
|
case 'packetEntities':
|
||||||
|
for (const entity of this.entities) {
|
||||||
|
if (entity && entity.serverClass.name === 'CTFPlayer') {
|
||||||
|
// console.log(entity.props.map((prop: SendProp) => {
|
||||||
|
// return prop.definition.ownerTableName + '.' + prop.definition.name;
|
||||||
|
// }));
|
||||||
|
// console.log(this.getUserInfoForEntity(entity).name);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'netTick':
|
case 'netTick':
|
||||||
if (this.startTick === 0) {
|
if (this.startTick === 0) {
|
||||||
|
|
@ -95,12 +103,13 @@ export class Match {
|
||||||
if (table.name === 'userinfo') {
|
if (table.name === 'userinfo') {
|
||||||
for (const userData of table.entries) {
|
for (const userData of table.entries) {
|
||||||
if (userData.extraData) {
|
if (userData.extraData) {
|
||||||
const name = userData.extraData.readUTF8String(32);
|
const name = userData.extraData.readUTF8String(32);
|
||||||
const userId = userData.extraData.readUint32();
|
const userId = userData.extraData.readUint32();
|
||||||
const steamId = userData.extraData.readUTF8String();
|
const steamId = userData.extraData.readUTF8String();
|
||||||
userState = this.getUserState(userId);
|
const userState = this.getUserInfo(userId);
|
||||||
userState.name = name;
|
userState.name = name;
|
||||||
userState.steamId = steamId;
|
userState.steamId = steamId;
|
||||||
|
userState.entityId = parseInt(userData.text, 10) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,8 +121,8 @@ export class Match {
|
||||||
while (packet.event.values.assister > 256 && packet.event.values.assister < (1024 * 16)) {
|
while (packet.event.values.assister > 256 && packet.event.values.assister < (1024 * 16)) {
|
||||||
packet.event.values.assister -= 256;
|
packet.event.values.assister -= 256;
|
||||||
}
|
}
|
||||||
var assister = packet.event.values.assister < 256 ? packet.event.values.assister : null;
|
const assister = packet.event.values.assister < 256 ? packet.event.values.assister : null;
|
||||||
// todo get player names, not same id as the name string table
|
// todo get player names, not same id as the name string table (entity id)
|
||||||
while (packet.event.values.attacker > 256) {
|
while (packet.event.values.attacker > 256) {
|
||||||
packet.event.values.attacker -= 256;
|
packet.event.values.attacker -= 256;
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +148,7 @@ export class Match {
|
||||||
break;
|
break;
|
||||||
case 'player_spawn':
|
case 'player_spawn':
|
||||||
const userId = packet.event.values.userid;
|
const userId = packet.event.values.userid;
|
||||||
userState = this.getUserState(userId);
|
const userState = this.getUserInfo(userId);
|
||||||
if (!userState.team) { //only register first spawn
|
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'
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +163,7 @@ export class Match {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getUserState(userId) {
|
getUserInfo(userId: number): UserInfo {
|
||||||
// no clue why it does this
|
// no clue why it does this
|
||||||
// only seems to be the case with per user ready
|
// only seems to be the case with per user ready
|
||||||
while (userId > 256) {
|
while (userId > 256) {
|
||||||
|
|
@ -162,15 +171,26 @@ export class Match {
|
||||||
}
|
}
|
||||||
if (!this.users[userId]) {
|
if (!this.users[userId]) {
|
||||||
this.users[userId] = {
|
this.users[userId] = {
|
||||||
name: null,
|
name: '',
|
||||||
userId: userId,
|
userId: userId,
|
||||||
steamId: null,
|
steamId: '',
|
||||||
classes: {}
|
classes: {},
|
||||||
|
entityId: 0,
|
||||||
|
team: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.users[userId];
|
return this.users[userId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserInfoForEntity(entity: Entity): UserInfo {
|
||||||
|
for (const user of this.users) {
|
||||||
|
if (user && user.entityId === entity.entityIndex) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('User not found for entity ' + entity.entityIndex);
|
||||||
|
}
|
||||||
|
|
||||||
get classBits() {
|
get classBits() {
|
||||||
return Math.ceil(Math.log(this.serverClasses.length) * Math.LOG2E)
|
return Math.ceil(Math.log(this.serverClasses.length) * Math.LOG2E)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
src/Data/UserInfo.ts
Normal file
8
src/Data/UserInfo.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
export interface UserInfo {
|
||||||
|
name: string
|
||||||
|
userId: number;
|
||||||
|
steamId: string;
|
||||||
|
entityId: number;
|
||||||
|
classes: any;
|
||||||
|
team: string;
|
||||||
|
}
|
||||||
|
|
@ -46,16 +46,24 @@ export class Parser extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
parseBody() {
|
parseBody() {
|
||||||
let message;
|
let hasNext = true;
|
||||||
while (message = this.readMessage(this.stream, this.match)) {
|
while (hasNext) {
|
||||||
if (message instanceof MessageParser) {
|
hasNext = this.tick();
|
||||||
this.handleMessage(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.emit('done', this.match);
|
this.emit('done', this.match);
|
||||||
return this.match;
|
return this.match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tick() {
|
||||||
|
const message = this.readMessage(this.stream, this.match);
|
||||||
|
if (message instanceof MessageParser) {
|
||||||
|
this.handleMessage(message);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parseMessage(data: BitStream, type: MessageType, tick: number, length: number, match: Match): MessageParser {
|
parseMessage(data: BitStream, type: MessageType, tick: number, length: number, match: Match): MessageParser {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue