mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 09:04:13 +02:00
more typescript conversions
This commit is contained in:
parent
06860cc3fe
commit
94383f447f
48 changed files with 1204 additions and 1051 deletions
35
src/Data/GameEvent.ts
Normal file
35
src/Data/GameEvent.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
export interface GameEventDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
entries: GameEventEntry[];
|
||||
}
|
||||
|
||||
export interface GameEvent {
|
||||
name: string;
|
||||
values: GameEventValueMap;
|
||||
}
|
||||
|
||||
export interface GameEventEntry {
|
||||
name: string;
|
||||
type: GameEventType;
|
||||
}
|
||||
|
||||
export enum GameEventType {
|
||||
STRING = 1,
|
||||
FLOAT = 2,
|
||||
LONG = 3,
|
||||
SHORT = 4,
|
||||
BYTE = 5,
|
||||
BOOLEAN = 6,
|
||||
LOCAL = 7
|
||||
}
|
||||
|
||||
export type GameEventValue = string|number|boolean;
|
||||
|
||||
export type GameEventValueMap = {
|
||||
[name: string]: GameEventValue;
|
||||
}
|
||||
|
||||
export type GameEventDefinitionMap = {
|
||||
[id: number]: GameEventDefinition;
|
||||
}
|
||||
168
src/Data/Match.ts
Normal file
168
src/Data/Match.ts
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
import {Entity} from "./Entity";
|
||||
import {ServerClass} from "./ServerClass";
|
||||
import {SendTable} from "./SendTable";
|
||||
import {StringTable} from "./StringTable";
|
||||
export class Match {
|
||||
tick: number;
|
||||
chat: any[];
|
||||
users: any;
|
||||
deaths: any[];
|
||||
rounds: any[];
|
||||
startTick: number;
|
||||
intervalPerTick: number;
|
||||
entities: Entity[];
|
||||
stringTables: StringTable[];
|
||||
serverClasses: ServerClass[];
|
||||
sendTables: SendTable[];
|
||||
instanceBaselines: any[][];
|
||||
staticBaseLines: any[];
|
||||
|
||||
constructor() {
|
||||
this.tick = 0;
|
||||
this.chat = [];
|
||||
this.users = {};
|
||||
this.deaths = [];
|
||||
this.rounds = [];
|
||||
this.startTick = 0;
|
||||
this.intervalPerTick = 0;
|
||||
this.entities = [];
|
||||
this.stringTables = [];
|
||||
this.sendTables = [];
|
||||
this.serverClasses = [];
|
||||
this.entities = [];
|
||||
this.instanceBaselines = [[], []];
|
||||
this.staticBaseLines = [];
|
||||
}
|
||||
|
||||
getSendTable(name) {
|
||||
for (var i = 0; i < this.sendTables.length; i++) {
|
||||
if (this.sendTables[i].name === name) {
|
||||
return this.sendTables[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getStringTable(name) {
|
||||
for (var i = 0; i < this.stringTables.length; i++) {
|
||||
if (this.stringTables[i].name === name) {
|
||||
return this.stringTables[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getState() {
|
||||
return {
|
||||
'chat': this.chat,
|
||||
'users': this.users,
|
||||
'deaths': this.deaths,
|
||||
'rounds': this.rounds,
|
||||
'startTick': this.startTick,
|
||||
'intervalPerTick': this.intervalPerTick
|
||||
};
|
||||
}
|
||||
|
||||
handlePacket(packet) {
|
||||
var userState;
|
||||
switch (packet.packetType) {
|
||||
case 'netTick':
|
||||
if (this.startTick === 0) {
|
||||
this.startTick = packet.tick;
|
||||
}
|
||||
this.tick = packet.tick;
|
||||
break;
|
||||
case 'serverInfo':
|
||||
this.intervalPerTick = packet.intervalPerTick;
|
||||
break;
|
||||
case 'sayText2':
|
||||
this.chat.push({
|
||||
kind: packet.kind,
|
||||
from: packet.from,
|
||||
text: packet.text,
|
||||
tick: this.tick
|
||||
});
|
||||
break;
|
||||
case 'stringTable':
|
||||
if (packet.tables.userinfo) {
|
||||
for (var j = 0; j < packet.tables.userinfo.length; j++) {
|
||||
if (packet.tables.userinfo[j].extraData) {
|
||||
var name = packet.tables.userinfo[j].extraData[0];
|
||||
var steamId = packet.tables.userinfo[j].extraData[2];
|
||||
var userId = packet.tables.userinfo[j].extraData[1].charCodeAt(0);
|
||||
userState = this.getUserState(userId);
|
||||
userState.name = name;
|
||||
userState.steamId = steamId;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'gameEvent':
|
||||
switch (packet.event.name) {
|
||||
case 'player_death':
|
||||
while (packet.event.values.assister > 256 && packet.event.values.assister < (1024 * 16)) {
|
||||
packet.event.values.assister -= 256;
|
||||
}
|
||||
var assister = packet.event.values.assister < 256 ? packet.event.values.assister : null;
|
||||
// todo get player names, not same id as the name string table
|
||||
while (packet.event.values.attacker > 256) {
|
||||
packet.event.values.attacker -= 256;
|
||||
}
|
||||
while (packet.event.values.userid > 256) {
|
||||
packet.event.values.userid -= 256;
|
||||
}
|
||||
this.deaths.push({
|
||||
killer: packet.event.values.attacker,
|
||||
assister: assister,
|
||||
victim: packet.event.values.userid,
|
||||
weapon: packet.event.values.weapon,
|
||||
tick: this.tick
|
||||
});
|
||||
break;
|
||||
case 'teamplay_round_win':
|
||||
if (packet.event.values.winreason !== 6) {// 6 = timelimit
|
||||
this.rounds.push({
|
||||
winner: packet.event.values.team === 2 ? 'red' : 'blue',
|
||||
length: packet.event.values.round_time,
|
||||
end_tick: this.tick
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'player_spawn':
|
||||
userId = packet.event.values.userid;
|
||||
userState = this.getUserState(userId);
|
||||
if (!userState.team) { //only register first spawn
|
||||
userState.team = packet.event.values.team === 2 ? 'red' : 'blue'
|
||||
}
|
||||
var classId = packet.event.values.class;
|
||||
if (!userState.classes[classId]) {
|
||||
userState.classes[classId] = 0;
|
||||
}
|
||||
userState.classes[classId]++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getUserState(userId) {
|
||||
// no clue why it does this
|
||||
// only seems to be the case with per user ready
|
||||
while (userId > 256) {
|
||||
userId -= 256;
|
||||
}
|
||||
if (!this.users[userId]) {
|
||||
this.users[userId] = {
|
||||
name: null,
|
||||
userId: userId,
|
||||
steamId: null,
|
||||
classes: {}
|
||||
}
|
||||
}
|
||||
return this.users[userId];
|
||||
}
|
||||
|
||||
get classBits() {
|
||||
return Math.ceil(Math.log(this.serverClasses.length) * Math.LOG2E)
|
||||
}
|
||||
}
|
||||
4
src/Data/Packet.ts
Normal file
4
src/Data/Packet.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface Packet {
|
||||
packetType: string;
|
||||
[name: string]: any;
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import * as clone from 'clone';
|
||||
import {SendPropDefinition} from "./SendPropDefinition";
|
||||
import {Vector} from "./Vector";
|
||||
|
||||
export class SendProp {
|
||||
definition: SendPropDefinition;
|
||||
value: any;
|
||||
value: SendPropValue|null;
|
||||
|
||||
constructor(definition: SendPropDefinition) {
|
||||
this.definition = definition;
|
||||
|
|
@ -17,3 +18,5 @@ export class SendProp {
|
|||
}
|
||||
}
|
||||
|
||||
export type SendPropArrayValue = Vector | number | string;
|
||||
export type SendPropValue = Vector | number | string | SendPropArrayValue[];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
import {SendTable} from "./SendTable";
|
||||
export class SendPropDefinition {
|
||||
type: SendPropType;
|
||||
name: string;
|
||||
flags: number;
|
||||
excludeDTName: string|null;
|
||||
lowValue: number;
|
||||
highValue: number;
|
||||
bitCount: number;
|
||||
table: SendTable|null;
|
||||
numElements: number|null;
|
||||
arrayProperty: SendPropDefinition|null;
|
||||
|
||||
constructor(type, name, flags) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
|
|
@ -12,79 +24,70 @@ export class SendPropDefinition {
|
|||
this.arrayProperty = null;
|
||||
}
|
||||
|
||||
hasFlag(flag) {
|
||||
hasFlag(flag: SendPropFlag) {
|
||||
return (this.flags & flag) != 0;
|
||||
}
|
||||
|
||||
isExcludeProp() {
|
||||
return this.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE);
|
||||
return this.hasFlag(SendPropFlag.SPROP_EXCLUDE);
|
||||
}
|
||||
|
||||
inspect() {
|
||||
return {
|
||||
name : this.name,
|
||||
type : SendPropDefinition.formatType(this.type),
|
||||
name: this.name,
|
||||
type: SendPropType[this.type],
|
||||
flags: SendPropDefinition.formatFlags(this.flags)
|
||||
}
|
||||
}
|
||||
|
||||
static formatFlags(flags) {
|
||||
let names = [];
|
||||
for (const name in SendPropDefinition.flags) {
|
||||
if (SendPropDefinition.flags.hasOwnProperty(name)) {
|
||||
if (flags & SendPropDefinition.flags[name]) {
|
||||
static formatFlags(flags: number) {
|
||||
let names: string[] = [];
|
||||
for (const name in SendPropFlag) {
|
||||
const flagValue = <SendPropFlag|string>SendPropFlag[name];
|
||||
if (typeof flagValue === 'number') {
|
||||
if (flags & flagValue) {
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
static formatType(type) {
|
||||
for (let name in SendPropDefinition.types) {
|
||||
if (SendPropDefinition.types.hasOwnProperty(name)) {
|
||||
if (SendPropDefinition.types[name] === type) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
SendPropDefinition.types = {
|
||||
DPT_Int : 0,
|
||||
DPT_Float : 1,
|
||||
DPT_Vector : 2,
|
||||
DPT_VectorXY : 3,// Only encodes the XY of a vector, ignores Z
|
||||
DPT_String : 4,
|
||||
DPT_Array : 5,
|
||||
DPT_DataTable : 6,
|
||||
DPT_NUMSendPropTypes: 7
|
||||
};
|
||||
export enum SendPropType {
|
||||
DPT_Int,
|
||||
DPT_Float,
|
||||
DPT_Vector,
|
||||
DPT_VectorXY,
|
||||
DPT_String,
|
||||
DPT_Array,
|
||||
DPT_DataTable,
|
||||
DPT_NUMSendPropTypes
|
||||
}
|
||||
|
||||
SendPropDefinition.flags = {
|
||||
SPROP_UNSIGNED : (1 << 0),// Unsigned integer data.
|
||||
SPROP_COORD : (1 << 1),// If this is set, the float/vector is treated like a world coordinate.
|
||||
// Note that the bit count is ignored in this case.
|
||||
SPROP_NOSCALE : (1 << 2),// For floating point, don't scale into range, just take value as is.
|
||||
SPROP_ROUNDDOWN : (1 << 3),// For floating point, limit high value to range minus one bit unit
|
||||
SPROP_ROUNDUP : (1 << 4),// For floating point, limit low value to range minus one bit unit
|
||||
SPROP_NORMAL : (1 << 5),// If this is set, the vector is treated like a normal (only valid for vectors)
|
||||
SPROP_EXCLUDE : (1 << 6),// This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
||||
SPROP_XYZE : (1 << 7),// Use XYZ/Exponent encoding for vectors.
|
||||
SPROP_INSIDEARRAY : (1 << 8),// This tells us that the property is inside an array, so it shouldn't be put into the
|
||||
// flattened property list. Its array will point at it when it needs to.
|
||||
SPROP_PROXY_ALWAYS_YES : (1 << 9),// Set for datatable props using one of the default datatable proxies like
|
||||
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
||||
SPROP_CHANGES_OFTEN : (1 << 10),// this is an often changed field, moved to head of sendtable so it gets a small index
|
||||
SPROP_IS_A_VECTOR_ELEM : (1 << 11),// Set automatically if SPROP_VECTORELEM is used.
|
||||
SPROP_COLLAPSIBLE : (1 << 12),// Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
||||
// (ie: for all automatically-chained base classes).
|
||||
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
||||
// trouble of walking the hierarchy more than necessary.
|
||||
SPROP_COORD_MP : (1 << 13),// Like SPROP_COORD, but special handling for multiplayer games
|
||||
SPROP_COORD_MP_LOWPRECISION: (1 << 14),// Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5
|
||||
SPROP_COORD_MP_INTEGRAL : (1 << 15),// SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
||||
SPROP_VARINT : (1 << 5) //reuse normal
|
||||
};
|
||||
|
||||
export enum SendPropFlag {
|
||||
SPROP_UNSIGNED = (1 << 0),// Unsigned integer data.
|
||||
SPROP_COORD = (1 << 1),// If this is set, the float/vector is treated like a world coordinate.
|
||||
// Note that the bit count is ignored in this case.
|
||||
SPROP_NOSCALE = (1 << 2),// For floating point, don't scale into range, just take value as is.
|
||||
SPROP_ROUNDDOWN = (1 << 3),// For floating point, limit high value to range minus one bit unit
|
||||
SPROP_ROUNDUP = (1 << 4),// For floating point, limit low value to range minus one bit unit
|
||||
SPROP_NORMAL = (1 << 5),// If this is set, the vector is treated like a normal (only valid for vectors)
|
||||
SPROP_EXCLUDE = (1 << 6),// This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
||||
SPROP_XYZE = (1 << 7),// Use XYZ/Exponent encoding for vectors.
|
||||
SPROP_INSIDEARRAY = (1 << 8),// This tells us that the property is inside an array, so it shouldn't be put into the
|
||||
// flattened property list. Its array will point at it when it needs to.
|
||||
SPROP_PROXY_ALWAYS_YES = (1 << 9),// Set for datatable props using one of the default datatable proxies like
|
||||
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
||||
SPROP_CHANGES_OFTEN = (1 << 10),// this is an often changed field, moved to head of sendtable so it gets a small index
|
||||
SPROP_IS_A_VECTOR_ELEM = (1 << 11),// Set automatically if SPROP_VECTORELEM is used.
|
||||
SPROP_COLLAPSIBLE = (1 << 12),// Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
||||
// (ie: for all automatically-chained base classes).
|
||||
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
||||
// trouble of walking the hierarchy more than necessary.
|
||||
SPROP_COORD_MP = (1 << 13),// Like SPROP_COORD, but special handling for multiplayer games
|
||||
SPROP_COORD_MP_LOWPRECISION = (1 << 14),// Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5
|
||||
SPROP_COORD_MP_INTEGRAL = (1 << 15),// SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
||||
SPROP_VARINT = (1 << 5)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import {SendPropDefinition} from './SendPropDefinition';
|
||||
import {SendPropDefinition, SendPropType, SendPropFlag} from './SendPropDefinition';
|
||||
|
||||
export class SendTable {
|
||||
name: string;
|
||||
props: SendPropDefinition[];
|
||||
private _flattenedProps: SendPropDefinition[];
|
||||
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.props = [];
|
||||
|
|
@ -13,13 +17,13 @@ export class SendTable {
|
|||
|
||||
flatten() {
|
||||
let excludes = [];
|
||||
let props = [];
|
||||
let props: SendPropDefinition[] = [];
|
||||
this.getAllProps(excludes, props);
|
||||
|
||||
// sort often changed props before the others
|
||||
let start = 0;
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
if (props[i].hasFlag(SendPropDefinition.flags.SPROP_CHANGES_OFTEN)) {
|
||||
if (props[i].hasFlag(SendPropFlag.SPROP_CHANGES_OFTEN)) {
|
||||
if (i != start) {
|
||||
const temp = props[i];
|
||||
props[i] = props[start];
|
||||
|
|
@ -31,7 +35,7 @@ export class SendTable {
|
|||
this._flattenedProps = props;
|
||||
}
|
||||
|
||||
getAllProps(excludes, props) {
|
||||
getAllProps(excludes: SendTable[], props: SendPropDefinition[]) {
|
||||
let localProps = [];
|
||||
this.getAllPropsIteratorProps(excludes, localProps, props);
|
||||
for (let i = 0; i < localProps.length; i++) {
|
||||
|
|
@ -39,26 +43,26 @@ export class SendTable {
|
|||
}
|
||||
}
|
||||
|
||||
getAllPropsIteratorProps(excludes, props, childProps) {
|
||||
getAllPropsIteratorProps(excludes: SendTable[], props: SendPropDefinition[], childProps: SendPropDefinition[]) {
|
||||
for (let i = 0; i < this.props.length; i++) {
|
||||
const prop = this.props[i];
|
||||
if (prop.type === SendPropDefinition.types.DPT_DataTable) {
|
||||
if (prop.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE)) {
|
||||
if (prop.type === SendPropType.DPT_DataTable && prop.table) {
|
||||
if (prop.hasFlag(SendPropFlag.SPROP_EXCLUDE)) {
|
||||
excludes.push(prop.table);
|
||||
} else if (excludes.indexOf(this) === -1) {
|
||||
if (prop.hasFlag(SendPropDefinition.flags.SPROP_COLLAPSIBLE)) {
|
||||
if (prop.hasFlag(SendPropFlag.SPROP_COLLAPSIBLE)) {
|
||||
prop.table.getAllPropsIteratorProps(excludes, props, childProps);
|
||||
} else {
|
||||
prop.table.getAllProps(excludes, childProps);
|
||||
}
|
||||
}
|
||||
} else if (!prop.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE)) {
|
||||
} else if (!prop.hasFlag(SendPropFlag.SPROP_EXCLUDE)) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get flattenedProps(){
|
||||
get flattenedProps() {
|
||||
if (this._flattenedProps.length === 0) {
|
||||
this.flatten();
|
||||
}
|
||||
|
|
|
|||
9
src/Data/StringTable.ts
Normal file
9
src/Data/StringTable.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
export interface StringTable {
|
||||
name: string;
|
||||
entries: StringTableEntry[];
|
||||
}
|
||||
|
||||
export interface StringTableEntry {
|
||||
text: string;
|
||||
extraData: string[];
|
||||
}
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
export class Vector {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
|
||||
constructor(x, y, z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue