Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@demostf/demo.js

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@demostf/demo.js - npm Package Compare versions

Comparing version 2.1.0 to 2.1.1

build/es6/PacketHandler/BaseEntityHandler.d.ts

3

build/es6/Data/Match.js

@@ -84,2 +84,5 @@ import { handleGameEvent } from '../PacketHandler/GameEvent';

const user = this.users.get(userId);
if (user && user.userId !== userId) {
throw new Error(`Invalid user info id`);
}
if (!user) {

@@ -86,0 +89,0 @@ const entityInfo = this.parserState.getUserEntityInfo(userId);

3

build/es6/Data/Packet.d.ts

@@ -5,2 +5,3 @@ import { BitStream } from 'bit-buffer';

import { EntityId, PacketEntity } from './PacketEntity';
import { Game } from './ParserState';
import { SendTable } from './SendTable';

@@ -154,3 +155,3 @@ import { ServerClass } from './ServerClass';

platform: string;
game: string;
game: Game;
skybox: string;

@@ -157,0 +158,0 @@ serverName: string;

@@ -43,4 +43,6 @@ import { SendProp } from './SendProp';

}
result.serialNumber = this.serialNumber;
if (this.delay) {
if (this.serialNumber) {
result.serialNumber = this.serialNumber;
}
if (typeof this.delay !== 'undefined') {
result.delay = this.delay;

@@ -47,0 +49,0 @@ }

@@ -12,2 +12,3 @@ import { BitStream } from 'bit-buffer';

import { UserEntityInfo, UserId } from './UserInfo';
export declare type Game = 'tf' | 'hl2mp';
export declare class ParserState {

@@ -27,2 +28,3 @@ version: number;

tick: number;
game: Game;
handlePacket(packet: Packet): void;

@@ -29,0 +31,0 @@ handleMessage(message: Message): void;

@@ -28,2 +28,3 @@ import { handleGameEventList } from '../PacketHandler/GameEventList';

this.version = packet.version;
this.game = packet.game;
break;

@@ -65,3 +66,3 @@ case 'stringTable':

getUserEntityInfo(userId) {
const info = this.userInfo.get(userId);
const info = this.userInfo.get(JSON.parse(JSON.stringify(userId)));
if (info) {

@@ -68,0 +69,0 @@ return info;

import { PVS } from '../Data/PacketEntity';
import { Player } from '../Data/Player';
import { Vector } from '../Data/Vector';
import { handleBaseEntity } from './BaseEntityHandler';
import { handleHL2DMEntity } from './HL2DMEntityHandler';
import { handleTFEntity } from './TFEntityHandler';
export function handlePacketEntities(packet, match, message) {
for (const entity of packet.entities) {
handleEntity(entity, match, message);
handleBaseEntity(entity, match, message);
switch (match.parserState.game) {
case 'tf':
handleTFEntity(entity, match, message);
break;
case 'hl2mp':
handleHL2DMEntity(entity, match, message);
break;
}
}

@@ -23,463 +32,2 @@ }

}
function handleEntity(entity, match, message) {
for (const prop of entity.props) {
if (prop.definition.ownerTableName === 'DT_AttributeContainer' && prop.definition.name === 'm_hOuter') {
if (!match.outerMap.has(prop.value)) {
match.outerMap.set(prop.value, entity.entityIndex);
}
}
}
for (const prop of entity.props) {
if (prop.definition.ownerTableName === 'DT_BaseCombatWeapon' && prop.definition.name === 'm_hOwner') {
if (!match.weaponMap.has(entity.entityIndex)) {
match.weaponMap.set(entity.entityIndex, {
className: entity.serverClass.name,
owner: prop.value
});
}
}
}
switch (entity.serverClass.name) {
case 'CWorld':
match.world.boundaryMin = entity.getProperty('DT_WORLD', 'm_WorldMins').value;
match.world.boundaryMax = entity.getProperty('DT_WORLD', 'm_WorldMaxs').value;
break;
case 'CTFPlayer':
/**
* "DT_TFPlayerScoringDataExclusive.m_iCaptures": 0,
* "DT_TFPlayerScoringDataExclusive.m_iDefenses": 0,
* "DT_TFPlayerScoringDataExclusive.m_iKills": 5,
* "DT_TFPlayerScoringDataExclusive.m_iDeaths": 17,
* "DT_TFPlayerScoringDataExclusive.m_iSuicides": 7,
* "DT_TFPlayerScoringDataExclusive.m_iDominations": 0,
* "DT_TFPlayerScoringDataExclusive.m_iRevenge": 0,
* "DT_TFPlayerScoringDataExclusive.m_iBuildingsBuilt": 0,
* "DT_TFPlayerScoringDataExclusive.m_iBuildingsDestroyed": 0,
* "DT_TFPlayerScoringDataExclusive.m_iHeadshots": 0,
* "DT_TFPlayerScoringDataExclusive.m_iBackstabs": 0,
* "DT_TFPlayerScoringDataExclusive.m_iHealPoints": 0,
* "DT_TFPlayerScoringDataExclusive.m_iInvulns": 0,
* "DT_TFPlayerScoringDataExclusive.m_iTeleports": 0,
* "DT_TFPlayerScoringDataExclusive.m_iDamageDone": 847,
* "DT_TFPlayerScoringDataExclusive.m_iCrits": 0,
* "DT_TFPlayerScoringDataExclusive.m_iResupplyPoints": 0,
* "DT_TFPlayerScoringDataExclusive.m_iKillAssists": 0,
* "DT_TFPlayerScoringDataExclusive.m_iBonusPoints": 0,
* "DT_TFPlayerScoringDataExclusive.m_iPoints": 6,
* "DT_TFPlayerSharedLocal.m_nDesiredDisguiseTeam": 0,
* "DT_TFPlayerSharedLocal.m_nDesiredDisguiseClass": 0,
* "DT_TFPlayerShared.m_iKillStreak": 0,
* "DT_TFPlayerShared.m_flCloakMeter": 100,
*/
const userInfo = match.getUserInfoForEntity(entity);
if (!userInfo) {
throw new Error(`No user info for entity ${entity.entityIndex}`);
}
const player = (match.playerEntityMap.has(entity.entityIndex)) ?
match.playerEntityMap.get(entity.entityIndex) :
new Player(match, userInfo);
if (!match.playerEntityMap.has(entity.entityIndex)) {
match.playerEntityMap.set(entity.entityIndex, player);
}
for (const prop of entity.props) {
if (prop.definition.ownerTableName === 'm_hMyWeapons') {
if (prop.value !== 2097151) {
player.weaponIds[parseInt(prop.definition.name, 10)] = prop.value;
}
}
if (prop.definition.ownerTableName === 'm_iAmmo') {
if (prop.value !== null && prop.value > 0) {
player.ammo[parseInt(prop.definition.name, 10)] = prop.value;
}
}
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
switch (propName) {
case 'DT_BasePlayer.m_iHealth':
player.health = prop.value;
break;
case 'DT_BasePlayer.m_iMaxHealth':
player.maxHealth = prop.value;
break;
case 'DT_TFLocalPlayerExclusive.m_vecOrigin':
player.position.x = prop.value.x;
player.position.y = prop.value.y;
// set the view angles for the local player since that prop isn't send
player.viewAngle = message.localViewAngles[0].y;
break;
case 'DT_TFNonLocalPlayerExclusive.m_vecOrigin':
player.position.x = prop.value.x;
player.position.y = prop.value.y;
break;
case 'DT_TFLocalPlayerExclusive.m_vecOrigin[2]':
player.position.z = prop.value;
break;
case 'DT_TFNonLocalPlayerExclusive.m_vecOrigin[2]':
player.position.z = prop.value;
break;
case 'DT_TFNonLocalPlayerExclusive.m_angEyeAngles[1]':
player.viewAngle = prop.value;
break;
case 'DT_TFLocalPlayerExclusive.m_angEyeAngles[1]':
player.viewAngle = prop.value;
break;
case 'DT_BasePlayer.m_lifeState':
player.lifeState = prop.value;
break;
case 'DT_BaseCombatCharacter.m_hActiveWeapon':
for (let i = 0; i < player.weapons.length; i++) {
if (player.weaponIds[i] === prop.value) {
player.activeWeapon = i;
}
}
}
}
break;
case 'CWeaponMedigun':
const weapon = match.weaponMap.get(entity.entityIndex);
if (weapon && weapon.className === 'CWeaponMedigun') {
for (const prop of entity.props) {
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
switch (propName) {
case 'DT_WeaponMedigun.m_hHealingTarget':
weapon.healTarget = prop.value;
break;
case 'DT_TFWeaponMedigunDataNonLocal.m_flChargeLevel':
weapon.chargeLevel = prop.value;
break;
case 'DT_LocalTFWeaponMedigunData.m_flChargeLevel':
weapon.chargeLevel = prop.value;
break;
}
}
}
break;
case 'CTFTeam':
if (entity.hasProperty('DT_Team', 'm_iTeamNum')) {
const teamId = entity.getProperty('DT_Team', 'm_iTeamNum').value;
if (!match.teams.has(teamId)) {
const team = {
name: entity.getProperty('DT_Team', 'm_szTeamname').value,
score: entity.getProperty('DT_Team', 'm_iScore').value,
roundsWon: entity.getProperty('DT_Team', 'm_iRoundsWon').value,
players: entity.getProperty('DT_Team', '"player_array"').value,
teamNumber: teamId
};
match.teams.set(teamId, team);
match.teamEntityMap.set(entity.entityIndex, team);
}
}
else {
const team = match.teamEntityMap.get(entity.entityIndex);
if (!team) {
throw new Error(`No team with entity id: ${entity.entityIndex}`);
}
for (const prop of entity.props) {
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
switch (propName) {
case 'DT_Team.m_iScore':
team.score = prop.value;
break;
case 'DT_Team.m_szTeamname':
team.name = prop.value;
break;
case 'DT_Team.m_iRoundsWon':
team.roundsWon = prop.value;
break;
case 'DT_Team."player_array"':
team.players = prop.value;
break;
}
}
}
break;
case 'CObjectSentrygun':
if (!match.buildings.has(entity.entityIndex)) {
match.buildings.set(entity.entityIndex, {
type: 'sentry',
ammoRockets: 0,
ammoShells: 0,
autoAimTarget: 0,
builder: 0,
health: 0,
isBuilding: false,
isSapped: false,
level: 0,
maxHealth: 0,
playerControlled: false,
position: new Vector(0, 0, 0),
shieldLevel: 0,
isMini: false,
team: 0,
angle: 0
});
}
const sentry = match.buildings.get(entity.entityIndex);
for (const prop of entity.props) {
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
applyBuildingProp(sentry, prop, propName);
switch (propName) {
case 'DT_ObjectSentrygun.m_bPlayerControlled':
sentry.playerControlled = prop.value > 0;
break;
case 'DT_ObjectSentrygun.m_hAutoAimTarget':
sentry.autoAimTarget = prop.value;
break;
case 'DT_ObjectSentrygun.m_nShieldLevel':
sentry.shieldLevel = prop.value;
break;
case 'DT_ObjectSentrygun.m_iAmmoShells':
sentry.ammoShells = prop.value;
break;
case 'DT_ObjectSentrygun.m_iAmmoRockets':
sentry.ammoRockets = prop.value;
break;
case 'DT_BaseObject.m_bMiniBuilding':
sentry.isMini = prop.value > 1;
break;
case 'DT_TFNonLocalPlayerExclusive.m_angEyeAngles[1]':
sentry.angle = prop.value;
break;
}
}
if (entity.pvs & PVS.LEAVE) {
match.buildings.delete(entity.entityIndex);
}
break;
case 'CObjectDispenser':
if (!match.buildings.has(entity.entityIndex)) {
match.buildings.set(entity.entityIndex, {
type: 'dispenser',
builder: 0,
health: 0,
isBuilding: false,
isSapped: false,
level: 0,
maxHealth: 0,
position: new Vector(0, 0, 0),
team: 0,
healing: [],
metal: 0,
angle: 0
});
}
const dispenser = match.buildings.get(entity.entityIndex);
for (const prop of entity.props) {
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
applyBuildingProp(dispenser, prop, propName);
switch (propName) {
case 'DT_ObjectDispenser.m_iAmmoMetal':
dispenser.metal = prop.value;
break;
case 'DT_ObjectDispenser."healing_array"':
dispenser.healing = prop.value;
break;
}
}
if (entity.pvs & PVS.LEAVE) {
match.buildings.delete(entity.entityIndex);
}
break;
case 'CObjectTeleporter':
if (!match.buildings.has(entity.entityIndex)) {
match.buildings.set(entity.entityIndex, {
type: 'teleporter',
builder: 0,
health: 0,
isBuilding: false,
isSapped: false,
level: 0,
maxHealth: 0,
position: new Vector(0, 0, 0),
team: 0,
isEntrance: false,
otherEnd: 0,
rechargeTime: 0,
rechargeDuration: 0,
timesUsed: 0,
angle: 0,
yawToExit: 0
});
}
const teleporter = match.buildings.get(entity.entityIndex);
for (const prop of entity.props) {
const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
applyBuildingProp(teleporter, prop, propName);
switch (propName) {
case 'DT_ObjectTeleporter.m_flRechargeTime':
teleporter.rechargeTime = prop.value;
break;
case 'DT_ObjectTeleporter.m_flCurrentRechargeDuration':
teleporter.rechargeDuration = prop.value;
break;
case 'DT_ObjectTeleporter.m_iTimesUsed':
teleporter.timesUsed = prop.value;
break;
case 'DT_ObjectTeleporter.m_bMatchBuilding':
teleporter.otherEnd = prop.value;
break;
case 'DT_ObjectTeleporter.m_flYawToExit':
teleporter.yawToExit = prop.value;
break;
case 'DT_BaseObject.m_iObjectMode':
teleporter.isEntrance = prop.value === 0;
break;
}
}
if (entity.pvs & PVS.LEAVE) {
match.buildings.delete(entity.entityIndex);
}
break;
case 'CTFPlayerResource':
for (const prop of entity.props) {
const playerId = parseInt(prop.definition.name, 10);
const value = prop.value;
if (!match.playerResources[playerId]) {
match.playerResources[playerId] = {
alive: false,
arenaSpectator: false,
bonusPoints: 0,
chargeLevel: 0,
connected: false,
damageAssists: 0,
damageBlocked: 0,
deaths: 0,
dominations: 0,
healing: 0,
healingAssist: 0,
health: 0,
killStreak: 0,
maxBuffedHealth: 0,
maxHealth: 0,
nextRespawn: 0,
ping: 0,
playerClass: 0,
playerLevel: 0,
score: 0,
team: 0,
totalScore: 0,
damage: 0
};
}
const playerResource = match.playerResources[playerId];
switch (prop.definition.ownerTableName) {
case 'm_iPing':
playerResource.ping = value;
break;
case 'm_iScore':
playerResource.score = value;
break;
case 'm_iDeaths':
playerResource.deaths = value;
break;
case 'm_bConnected':
playerResource.connected = value > 0;
break;
case 'm_iTeam':
playerResource.team = value;
break;
case 'm_bAlive':
playerResource.alive = value > 0;
break;
case 'm_iHealth':
playerResource.health = value;
break;
case 'm_iTotalScore':
playerResource.totalScore = value;
break;
case 'm_iMaxHealth':
playerResource.maxHealth = value;
break;
case 'm_iMaxBuffedHealth':
playerResource.maxBuffedHealth = value;
break;
case 'm_iPlayerClass':
playerResource.playerClass = value;
break;
case 'm_bArenaSpectator':
playerResource.arenaSpectator = value > 0;
break;
case 'm_iActiveDominations':
playerResource.dominations = value;
break;
case 'm_flNextRespawnTime':
playerResource.nextRespawn = value;
break;
case 'm_iChargeLevel':
playerResource.chargeLevel = value;
break;
case 'm_iDamage':
playerResource.damage = value;
break;
case 'm_iDamageAssist':
playerResource.damageAssists = value;
break;
case 'm_iHealing':
playerResource.healing = value;
break;
case 'm_iHealingAssist':
playerResource.healingAssist = value;
break;
case 'm_iDamageBlocked':
playerResource.damageBlocked = value;
break;
case 'm_iBonusPoints':
playerResource.bonusPoints = value;
break;
case 'm_iPlayerLevel':
playerResource.playerLevel = value;
break;
case 'm_iKillstreak':
playerResource.killStreak = value;
break;
}
}
break;
case 'CTeamRoundTimer':
break;
case 'CLaserDot':
// for (const prop of entity.props) {
// const propName = prop.definition.ownerTableName + '.' + prop.definition.name;
// switch (propName) {
// case 'DT_BaseEntity.m_iParentAttachment':
// console.log(prop.value);
// process.exit();
// break;
//
// }
// }
// console.log(match.getSendTable(entity.serverClass.dataTable).flattenedProps);
break;
}
}
function applyBuildingProp(building, prop, propName) {
switch (propName) {
case 'DT_BaseObject.m_iUpgradeLevel':
building.level = prop.value;
break;
case 'DT_BaseObject.m_hBuilder':
building.builder = prop.value;
break;
case 'DT_BaseObject.m_iMaxHealth':
building.maxHealth = prop.value;
break;
case 'DT_BaseObject.m_iHealth':
building.health = prop.value;
break;
case 'DT_BaseObject.m_bBuilding':
building.isBuilding = prop.value > 0;
break;
case 'DT_BaseObject.m_bHasSapper':
building.isSapped = prop.value > 0;
break;
case 'DT_BaseEntity.m_vecOrigin':
building.position = prop.value;
break;
case 'DT_BaseEntity.m_iTeamNum':
building.team = prop.value;
break;
case 'DT_BaseEntity.m_angRotation':
building.angle = prop.value.y;
break;
}
}
//# sourceMappingURL=PacketEntities.js.map

@@ -38,5 +38,9 @@ export function handleStringTable(packet, state) {

const name = extraData.readUTF8String(32);
const userId = extraData.readUint32();
let userId = extraData.readUint32();
while (userId > 256) {
userId -= 256;
}
const steamId = extraData.readUTF8String();
if (steamId) {
const entityId = parseInt(text, 10) + 1;
let userState = state.userInfo.get(userId);

@@ -48,9 +52,8 @@ if (!userState) {

steamId: '',
entityId: 0
entityId
};
state.userInfo.set(userState.userId, userState);
}
userState.name = name;
userState.steamId = steamId;
userState.entityId = parseInt(text, 10) + 1;
state.userInfo.set(userId, userState);
}

@@ -57,0 +60,0 @@ }

import { MessageType } from './Data/Message';
import { PacketTypeId } from './Data/Packet';
import { ParserState } from './Data/ParserState';

@@ -27,3 +28,9 @@ import { parseHeader } from './Parser/Header';

this.parserState = new ParserState();
this.parserState.skippedPackets = skipPackets;
if (this.getHeader().game === 'hl2mp') {
// for hl2dm we always need packet entities for team info and never tempEntities since it crashes the parser
this.parserState.skippedPackets = [PacketTypeId.tempEntities];
}
else {
this.parserState.skippedPackets = skipPackets;
}
}

@@ -30,0 +37,0 @@ getHeader() {

@@ -31,3 +31,9 @@ import * as assert from 'assert';

});
test('Parse hl2dm ffa demo', () => {
testDemo('hl2dm_ffa');
});
test('Parse hl2dm 2v2 demo', () => {
testDemo('hl2dm_2v2');
});
});
//# sourceMappingURL=parse.js.map

@@ -37,2 +37,4 @@ "use strict";

}
player.team = prop.value;
break;
case 'DT_BasePlayer.m_iHealth':

@@ -39,0 +41,0 @@ player.health = prop.value;

{
"name": "@demostf/demo.js",
"description": "A parser for TF2 demo files",
"version": "2.1.0",
"version": "2.1.1",
"bin": {

@@ -6,0 +6,0 @@ "demo-analyse": "./bin/analyse.js"

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc