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

refactor state handling a bit

+ some random other changes I forgot to commit earlier
This commit is contained in:
Robin Appelman 2016-04-23 15:41:56 +02:00
commit c43627e3c1
11 changed files with 75 additions and 92 deletions

View file

@ -1,12 +1,11 @@
var util = require('util'); var util = require('util');
var Parser = require('./parser'); var Parser = require('./parser');
var State = require('./state');
var BitStream = require('bit-buffer').BitStream; var BitStream = require('bit-buffer').BitStream;
var StreamParser = function (stream) { var StreamParser = function (stream) {
this.stream = stream; this.stream = stream;
this.state = new State(); this.match = new Match();
this.on('packet', this.state.updateState.bind(this.state)); this.on('packet', this, match.handlePacket.bind(this.match));
this.header = null; this.header = null;
this.buffer = new Buffer(0); this.buffer = new Buffer(0);
}; };
@ -27,7 +26,7 @@ StreamParser.prototype.eatBuffer = function (length) {
StreamParser.prototype.start = function () { StreamParser.prototype.start = function () {
this.stream.on('data', this.handleData.bind(this)); this.stream.on('data', this.handleData.bind(this));
this.stream.on('end', function () { this.stream.on('end', function () {
this.emit('done', this.state.get()); this.emit('done', this.match);
}.bind(this)); }.bind(this));
}; };

View file

@ -30,12 +30,12 @@ fs.readFile(argv._[0], function (err, data) {
echo(head); echo(head);
return; return;
} }
var body = parser.parseBody(); var match = parser.parseBody();
if (argv.dump) { if (argv.dump) {
echo(parser.packets); echo(parser.match.packets);
} else if (argv.strings) { } else if (argv.strings) {
echo(parser.strings); echo(parser.match.strings);
} else { } else {
echo(body); echo(match.getState());
} }
}); });

View file

@ -1,8 +1,9 @@
var ConsoleCmd = function (type, tick, stream, length) { var ConsoleCmd = function (type, tick, stream, length, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
this.stream = stream; this.stream = stream;
this.length = length;//length in bytes this.length = length;//length in bytes
this.match = match;
}; };
ConsoleCmd.prototype.parse = function () { ConsoleCmd.prototype.parse = function () {

View file

@ -1,8 +1,9 @@
var DataTable = function (type, tick, stream, length) { var DataTable = function (type, tick, stream, length, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
this.stream = stream; this.stream = stream;
this.length = length;//length in bytes this.length = length;//length in bytes
this.match = match;
}; };
DataTable.prototype.parse = function () { DataTable.prototype.parse = function () {

View file

@ -3,5 +3,7 @@ var ParserGenerator = require('../../parsergenerator');
var baseParser = ParserGenerator.make('entityMessage', 'index{11}classId{9}length{11}data{$length}'); var baseParser = ParserGenerator.make('entityMessage', 'index{11}classId{9}length{11}data{$length}');
module.exports = function (stream) { // 24: entityMessage module.exports = function (stream) { // 24: entityMessage
return baseParser(stream); //todo parse data further? var data = baseParser(stream); //todo parse data further?
// console.log(data.index);
return data;
}; };

View file

@ -36,6 +36,7 @@ function readPVS(stream) {
} }
module.exports = function (stream, events, entities) { //26: packetEntities module.exports = function (stream, events, entities) { //26: packetEntities
// https://github.com/skadistats/smoke/blob/master/smoke/replay/handler/svc_packetentities.pyx
// todo // todo
var maxEntries = stream.readBits(11); var maxEntries = stream.readBits(11);
var isDelta = !!stream.readBits(1); var isDelta = !!stream.readBits(1);
@ -50,15 +51,15 @@ module.exports = function (stream, events, entities) { //26: packetEntities
var updatedBaseLink = !!stream.readBits(1); var updatedBaseLink = !!stream.readBits(1);
var end = stream._index + length; var end = stream._index + length;
//console.log('max: ' + maxEntries); //console.log('max: ' + maxEntries);
//var entityId = -1; var entityId = -1;
//
//for (var i = 0; i < updatedEntries; i++) { for (var i = 0; i < updatedEntries; i++) {
// entityId = readIndex(stream, entityId); entityId = readIndex(stream, entityId);
// var pvs = readPVS(stream); var pvs = readPVS(stream);
// if (pvs = PVS.PRESERVE) { if (pvs = PVS.PRESERVE) {
//
// } }
//} }
stream._index = end; stream._index = end;
//var ent = { //var ent = {
// packetType : 'packetEntities', // packetType : 'packetEntities',

View file

@ -1,33 +1,40 @@
var State = function () { var Match = function () {
this.tick = 0; this.tick = 0;
this.state = { this.chat = [];
chat : [], this.users = {};
users : {}, this.deaths = [];
deaths : [], this.rounds = [];
rounds : [], this.startTick = 0;
startTick : 0, this.intervalPerTick = 0;
intervalPerTick: 0 this.entities = [];
this.stringTables = [];
};
Match.prototype.getState = function () {
return {
'chat' : this.chat,
'users' : this.users,
'deaths' : this.deaths,
'rounds' : this.rounds,
'startTick' : this.startTick,
'intervalPerTick': this.intervalPerTick
}; };
}; };
State.prototype.get = function () { Match.prototype.handlePacket = function (packet) {
return this.state;
};
State.prototype.updateState = function (packet) {
var userState; var userState;
switch (packet.packetType) { switch (packet.packetType) {
case 'netTick': case 'netTick':
if (this.state.startTick === 0) { if (this.startTick === 0) {
this.state.startTick = packet.tick; this.startTick = packet.tick;
} }
this.tick = packet.tick; this.tick = packet.tick;
break; break;
case 'serverInfo': case 'serverInfo':
this.state.intervalPerTick = packet.intervalPerTick; this.intervalPerTick = packet.intervalPerTick;
break; break;
case 'sayText2': case 'sayText2':
this.state.chat.push({ this.chat.push({
kind: packet.kind, kind: packet.kind,
from: packet.from, from: packet.from,
text: packet.text, text: packet.text,
@ -62,7 +69,7 @@ State.prototype.updateState = function (packet) {
while (packet.event.values.userid > 256) { while (packet.event.values.userid > 256) {
packet.event.values.userid -= 256; packet.event.values.userid -= 256;
} }
this.state.deaths.push({ this.deaths.push({
killer : packet.event.values.attacker, killer : packet.event.values.attacker,
assister: assister, assister: assister,
victim : packet.event.values.userid, victim : packet.event.values.userid,
@ -72,7 +79,7 @@ State.prototype.updateState = function (packet) {
break; break;
case 'teamplay_round_win': case 'teamplay_round_win':
if (packet.event.values.winreason !== 6) {// 6 = timelimit if (packet.event.values.winreason !== 6) {// 6 = timelimit
this.state.rounds.push({ this.rounds.push({
winner : packet.event.values.team === 2 ? 'red' : 'blue', winner : packet.event.values.team === 2 ? 'red' : 'blue',
length : packet.event.values.round_time, length : packet.event.values.round_time,
end_tick: this.tick end_tick: this.tick
@ -96,21 +103,21 @@ State.prototype.updateState = function (packet) {
} }
}; };
State.prototype.getUserState = function (userId) { Match.prototype.getUserState = function (userId) {
// 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) {
userId -= 256; userId -= 256;
} }
if (!this.state.users[userId]) { if (!this.users[userId]) {
this.state.users[userId] = { this.users[userId] = {
name : null, name : null,
userId : userId, userId : userId,
steamId: null, steamId: null,
classes: {} classes: {}
} }
} }
return this.state.users[userId]; return this.users[userId];
}; };
module.exports = State; module.exports = Match;

View file

@ -5,12 +5,13 @@ var ParserGenerator = require('./parsergenerator');
// https://github.com/stgn/netdecode/blob/master/Packet.cs // https://github.com/stgn/netdecode/blob/master/Packet.cs
// https://github.com/LestaD/SourceEngine2007/blob/master/src_main/common/netmessages.cpp // https://github.com/LestaD/SourceEngine2007/blob/master/src_main/common/netmessages.cpp
var Packet = function (type, tick, stream, length, viewOrigin) { var Packet = function (type, tick, stream, length, viewOrigin, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
this.stream = stream; this.stream = stream;
this.length = length;//length in bytes this.length = length;//length in bytes
this.viewOrigin = viewOrigin; this.viewOrigin = viewOrigin;
this.match = match;
}; };
Packet.gameEventMap = {}; Packet.gameEventMap = {};

View file

@ -1,19 +1,18 @@
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');
var UserCmd = require('./usercmd'); var UserCmd = require('./usercmd');
var BitStream = require('bit-buffer').BitStream; var BitStream = require('bit-buffer').BitStream;
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var Match = require('./match');
var Parser = function (stream) { var Parser = function (stream) {
this.stream = stream; this.stream = stream;
this.state = new State();
this.packets = []; this.packets = [];
this.strings = {}; this.match = new Match();
this.on('packet', this.state.updateState.bind(this.state)); this.on('packet', this.match.handlePacket.bind(this.match));
this.on('packet', function (packet) { this.on('packet', function (packet) {
this.packets.push(packet); this.packets.push(packet);
}); });
@ -54,29 +53,28 @@ Parser.prototype.parseHeader = function (stream) {
Parser.prototype.parseBody = function () { Parser.prototype.parseBody = function () {
var message; var message;
while (message = this.readMessage(this.stream)) { while (message = this.readMessage(this.stream, this.match)) {
this.handleMessage(message); this.handleMessage(message);
} }
this.strings = StringTable.tables; this.emit('done', this.match);
this.emit('done', this.state.get()); return this.match;
return this.state.get();
}; };
Parser.prototype.parseMessage = function (buffer, type, tick, length, viewOrigin) { Parser.prototype.parseMessage = function (buffer, type, tick, length, viewOrigin, match) {
var data = new BitStream(buffer); var data = new BitStream(buffer);
switch (type) { switch (type) {
case Parser.MessageType.Sigon: case Parser.MessageType.Sigon:
case Parser.MessageType.Packet: case Parser.MessageType.Packet:
return new Packet(type, tick, data, length, viewOrigin); return new Packet(type, tick, data, length, viewOrigin, match);
case Parser.MessageType.ConsoleCmd: case Parser.MessageType.ConsoleCmd:
return new ConsoleCmd(type, tick, data, length); return new ConsoleCmd(type, tick, data, length, match);
case Parser.MessageType.UserCmd: case Parser.MessageType.UserCmd:
return new UserCmd(type, tick, data, length, this.viewOrigin, this.viewAngles); return new UserCmd(type, tick, data, length, match);
case Parser.MessageType.DataTables: case Parser.MessageType.DataTables:
return new DataTable(type, tick, data, length); return new DataTable(type, tick, data, length, match);
case Parser.MessageType.StringTables: case Parser.MessageType.StringTables:
return new StringTable(type, tick, data, length); return new StringTable(type, tick, data, length, match);
default: default:
return true; return true;
} }
@ -94,7 +92,7 @@ Parser.prototype.handleMessage = function (message) {
} }
}; };
Parser.prototype.readMessage = function (stream) { Parser.prototype.readMessage = function (stream, match) {
var type = stream.readBits(8); var type = stream.readBits(8);
if (type === Parser.MessageType.Stop) { if (type === Parser.MessageType.Stop) {
return null; return null;
@ -138,7 +136,7 @@ Parser.prototype.readMessage = function (stream) {
start = stream.byteIndex; start = stream.byteIndex;
buffer = stream.buffer.slice(start, start + length); buffer = stream.buffer.slice(start, start + length);
stream.byteIndex += length; stream.byteIndex += length;
return this.parseMessage(buffer, type, tick, length, viewOrigin); return this.parseMessage(buffer, type, tick, length, viewOrigin, match);
}; };
module.exports = Parser; module.exports = Parser;

View file

@ -1,12 +1,11 @@
var StringTable = function (type, tick, stream, length) { var StringTable = function (type, tick, stream, length, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
this.stream = stream; this.stream = stream;
this.length = length;//length in bytes this.length = length;//length in bytes
this.match = match;
}; };
StringTable.tables = [];
StringTable.prototype.parse = function () { StringTable.prototype.parse = function () {
var tableCount = this.stream.readBits(8); var tableCount = this.stream.readBits(8);
var tables = {}; var tables = {};
@ -33,7 +32,7 @@ StringTable.prototype.parse = function () {
entries.push(entry); entries.push(entry);
} }
tables[tableName] = entries; tables[tableName] = entries;
StringTable.tables.push({ this.match.stringTables.push({
name : tableName, name : tableName,
entries: entries entries: entries
}); });

View file

@ -1,39 +1,13 @@
var UserCMD = function (type, tick, stream, length, viewOrigin, viewAngles) { var UserCMD = function (type, tick, stream, length, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
this.stream = stream; this.stream = stream;
this.length = length;//length in bytes this.length = length;//length in bytes
this.viewOrigin = viewOrigin; this.match = match;
this.viewAngles = viewAngles;
}; };
UserCMD.prototype.parse = function () { UserCMD.prototype.parse = function () {
return []; return [];
var divSize = Math.floor((this.length + 2) / 4);
var byteShift = new Array(3);
var lastByte = this.stream.readBits(8);
var TempUCMD = 0;
for (var i = 1; i < divSize; i++) {
var byte = this.stream.readBits(8);
if (i <= 4) {
byteShift[0] = lastByte >> i;
byteShift[1] = byte << 32 - i;
} else {
byteShift[0] = lastByte >> 9;
byteShift[1] = byte << 32 - i;
}
byteShift[2] = byteShift[0] | byteShift[0];
if (i == divSize - 1) {
if (byteShift[2] > 0 && byteShift[2] < 1321100) {
TempUCMD = byteShift[2];
} else {
TempUCMD = null;
}
}
lastByte = byte;
}
// console.log('move', this.tick, this.viewOrigin[0][0], this.viewOrigin[0][1], this.viewAngles[0][0], this.viewAngles[0][1], TempUCMD);
return [];
}; };
module.exports = UserCMD; module.exports = UserCMD;