mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
refactor out state handling
This commit is contained in:
parent
ff1b2b17b3
commit
ec63085fba
2 changed files with 118 additions and 103 deletions
128
parser.js
128
parser.js
|
|
@ -1,5 +1,6 @@
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var Packet = require('./packet');
|
var Packet = require('./packet');
|
||||||
|
var State = require('./state');
|
||||||
var ConsoleCmd = require('./consolecmd');
|
var ConsoleCmd = require('./consolecmd');
|
||||||
var StringTable = require('./stringtable');
|
var StringTable = require('./stringtable');
|
||||||
var DataTable = require('./datatable');
|
var DataTable = require('./datatable');
|
||||||
|
|
@ -8,18 +9,13 @@ var EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
var Parser = function (steam) {
|
var Parser = function (steam) {
|
||||||
this.stream = steam;
|
this.stream = steam;
|
||||||
this.state = {
|
this.state = new State();
|
||||||
tick : 0,
|
|
||||||
chat : [],
|
|
||||||
users : {},
|
|
||||||
deaths : [],
|
|
||||||
rounds : [],
|
|
||||||
startTick : 0,
|
|
||||||
intervalPerTick: 0
|
|
||||||
};
|
|
||||||
this.packets = [];
|
this.packets = [];
|
||||||
this.strings = {};
|
this.strings = {};
|
||||||
this.on('packet', this.updateState.bind(this));
|
this.on('packet', this.state.updateState.bind(this.state));
|
||||||
|
this.on('packet', function (packet) {
|
||||||
|
this.packets.push(packet);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
util.inherits(Parser, EventEmitter);
|
util.inherits(Parser, EventEmitter);
|
||||||
|
|
@ -36,28 +32,32 @@ Parser.MessageType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.readHeader = function () {
|
Parser.prototype.readHeader = function () {
|
||||||
|
return this.parseHeader(this.stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parser.prototype.parseHeader = function (stream) {
|
||||||
return {
|
return {
|
||||||
'type' : this.stream.readASCIIString(8),
|
'type' : stream.readASCIIString(8),
|
||||||
'version' : this.stream.readInt32(),
|
'version' : stream.readInt32(),
|
||||||
'protocol': this.stream.readInt32(),
|
'protocol': stream.readInt32(),
|
||||||
'server' : this.stream.readASCIIString(260),
|
'server' : stream.readASCIIString(260),
|
||||||
'nick' : this.stream.readASCIIString(260),
|
'nick' : stream.readASCIIString(260),
|
||||||
'map' : this.stream.readASCIIString(260),
|
'map' : stream.readASCIIString(260),
|
||||||
'game' : this.stream.readASCIIString(260),
|
'game' : stream.readASCIIString(260),
|
||||||
'duration': this.stream.readFloat32(),
|
'duration': stream.readFloat32(),
|
||||||
'ticks' : this.stream.readInt32(),
|
'ticks' : stream.readInt32(),
|
||||||
'frames' : this.stream.readInt32(),
|
'frames' : stream.readInt32(),
|
||||||
'sigon' : this.stream.readInt32()
|
'sigon' : stream.readInt32()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseBody = function () {
|
Parser.prototype.parseBody = function () {
|
||||||
var message, i;
|
var message;
|
||||||
while (message = this.readMessage(this.stream)) {
|
while (message = this.readMessage(this.stream)) {
|
||||||
this.handleMessage(message);
|
this.handleMessage(message);
|
||||||
}
|
}
|
||||||
this.strings = StringTable.tables;
|
this.strings = StringTable.tables;
|
||||||
return this.state;
|
return this.state.get();
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseMessage = function (buffer, type, tick, length) {
|
Parser.prototype.parseMessage = function (buffer, type, tick, length) {
|
||||||
|
|
@ -84,100 +84,22 @@ Parser.prototype.parseMessage = function (buffer, type, tick, length) {
|
||||||
Parser.prototype.handleMessage = function (message) {
|
Parser.prototype.handleMessage = function (message) {
|
||||||
if (message.parse) {
|
if (message.parse) {
|
||||||
var packets = message.parse();
|
var packets = message.parse();
|
||||||
for (i = 0; i < packets.length; i++) {
|
for (var i = 0; i < packets.length; i++) {
|
||||||
var packet = packets[i];
|
var packet = packets[i];
|
||||||
if (packet) {
|
if (packet) {
|
||||||
this.emit('packet', packet);
|
this.emit('packet', packet);
|
||||||
this.packets.push(packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.updateState = function (packet) {
|
|
||||||
switch (packet.packetType) {
|
|
||||||
case 'netTick':
|
|
||||||
if (this.state.startTick === 0) {
|
|
||||||
this.state.startTick = packet.tick;
|
|
||||||
}
|
|
||||||
this.state.tick = packet.tick;
|
|
||||||
break;
|
|
||||||
case 'serverInfo':
|
|
||||||
this.state.intervalPerTick = packet.intervalPerTick;
|
|
||||||
break;
|
|
||||||
case 'sayText2':
|
|
||||||
this.state.chat.push({
|
|
||||||
kind: packet.kind,
|
|
||||||
from: packet.from,
|
|
||||||
text: packet.text,
|
|
||||||
tick: this.state.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);
|
|
||||||
this.state.users[userId] = {
|
|
||||||
name : name,
|
|
||||||
userId : userId,
|
|
||||||
steamId: steamId,
|
|
||||||
classes: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'gameEvent':
|
|
||||||
switch (packet.event.name) {
|
|
||||||
case 'player_death':
|
|
||||||
// todo get player names, not same id as the name string table
|
|
||||||
var assister = packet.event.values.assister < 32 ? packet.event.values.assister : null;
|
|
||||||
this.state.deaths.push({
|
|
||||||
killer : packet.event.values.attacker,
|
|
||||||
assister: assister,
|
|
||||||
victim : packet.event.values.userid,
|
|
||||||
weapon : packet.event.values.weapon,
|
|
||||||
tick : this.state.tick
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'teamplay_round_win':
|
|
||||||
if (packet.event.values.winreason !== 6) {// 6 = timelimit
|
|
||||||
this.state.rounds.push({
|
|
||||||
winner : packet.event.values.team === 2 ? 'red' : 'blue',
|
|
||||||
length : packet.event.values.round_time,
|
|
||||||
end_tick: this.state.tick
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'player_spawn':
|
|
||||||
userId = packet.event.values.userid;
|
|
||||||
if (this.state.users[userId]) {
|
|
||||||
if (!this.state.users[userId].team) { //only register first spawn
|
|
||||||
this.state.users[userId].team = packet.event.values.team === 2 ? 'red' : 'blue'
|
|
||||||
}
|
|
||||||
var classId = packet.event.values.class;
|
|
||||||
if (!this.state.users[userId].classes[classId]) {
|
|
||||||
this.state.users[userId].classes[classId] = 0;
|
|
||||||
}
|
|
||||||
this.state.users[userId].classes[classId]++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Parser.prototype.readMessage = function (stream) {
|
Parser.prototype.readMessage = function (stream) {
|
||||||
var type = stream.readBits(8);
|
var type = stream.readBits(8);
|
||||||
//console.log(type);
|
|
||||||
if (type === Parser.MessageType.Stop) {
|
if (type === Parser.MessageType.Stop) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var tick = stream.readInt32();
|
var tick = stream.readInt32();
|
||||||
var data, start, length, buffer;
|
var start, length, buffer;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Parser.MessageType.Sigon:
|
case Parser.MessageType.Sigon:
|
||||||
|
|
|
||||||
93
state.js
Normal file
93
state.js
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
var State = function () {
|
||||||
|
this.tick = 0;
|
||||||
|
this.state = {
|
||||||
|
chat : [],
|
||||||
|
users : {},
|
||||||
|
deaths : [],
|
||||||
|
rounds : [],
|
||||||
|
startTick : 0,
|
||||||
|
intervalPerTick: 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
State.prototype.get = function () {
|
||||||
|
return this.state;
|
||||||
|
};
|
||||||
|
|
||||||
|
State.prototype.updateState = function (packet) {
|
||||||
|
switch (packet.packetType) {
|
||||||
|
case 'netTick':
|
||||||
|
if (this.state.startTick === 0) {
|
||||||
|
this.state.startTick = packet.tick;
|
||||||
|
}
|
||||||
|
this.tick = packet.tick;
|
||||||
|
break;
|
||||||
|
case 'serverInfo':
|
||||||
|
this.state.intervalPerTick = packet.intervalPerTick;
|
||||||
|
break;
|
||||||
|
case 'sayText2':
|
||||||
|
this.state.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);
|
||||||
|
this.state.users[userId] = {
|
||||||
|
name : name,
|
||||||
|
userId : userId,
|
||||||
|
steamId: steamId,
|
||||||
|
classes: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'gameEvent':
|
||||||
|
switch (packet.event.name) {
|
||||||
|
case 'player_death':
|
||||||
|
// todo get player names, not same id as the name string table
|
||||||
|
var assister = packet.event.values.assister < 32 ? packet.event.values.assister : null;
|
||||||
|
this.state.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.state.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;
|
||||||
|
if (this.state.users[userId]) {
|
||||||
|
if (!this.state.users[userId].team) { //only register first spawn
|
||||||
|
this.state.users[userId].team = packet.event.values.team === 2 ? 'red' : 'blue'
|
||||||
|
}
|
||||||
|
var classId = packet.event.values.class;
|
||||||
|
if (!this.state.users[userId].classes[classId]) {
|
||||||
|
this.state.users[userId].classes[classId] = 0;
|
||||||
|
}
|
||||||
|
this.state.users[userId].classes[classId]++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = State;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue