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:
parent
2d26dfdfb5
commit
c43627e3c1
11 changed files with 75 additions and 92 deletions
|
|
@ -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));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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 = {};
|
||||||
|
|
|
||||||
30
parser.js
30
parser.js
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
||||||
30
usercmd.js
30
usercmd.js
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue