1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-04 00:54:14 +02:00

more typescript conversions

This commit is contained in:
Robin Appelman 2016-12-18 17:45:16 +01:00
commit 94383f447f
48 changed files with 1204 additions and 1051 deletions

35
src/Data/GameEvent.ts Normal file
View 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
View 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
View file

@ -0,0 +1,4 @@
export interface Packet {
packetType: string;
[name: string]: any;
}

View file

@ -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[];

View file

@ -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)
}

View file

@ -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
View file

@ -0,0 +1,9 @@
export interface StringTable {
name: string;
entries: StringTableEntry[];
}
export interface StringTableEntry {
text: string;
extraData: string[];
}

View file

@ -1,4 +1,8 @@
export class Vector {
x: number;
y: number;
z: number;
constructor(x, y, z) {
this.x = x;
this.y = y;