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

packetentities wip

This commit is contained in:
Robin Appelman 2016-12-18 00:30:48 +01:00
commit 8e286a17b1
7 changed files with 410 additions and 74 deletions

View file

@ -25,13 +25,13 @@ DataTableParser.prototype.parse = function () {
var propName = this.stream.readASCIIString(); var propName = this.stream.readASCIIString();
var nFlagsBits = 16; // might be 11 (old?), 13 (new?), 16(networked) or 17(??) var nFlagsBits = 16; // might be 11 (old?), 13 (new?), 16(networked) or 17(??)
var flags = this.stream.readBits(nFlagsBits); var flags = this.stream.readBits(nFlagsBits);
var prop = new SendProp(propType, propName, flags); var prop = new SendPropDefinition(propType, propName, flags);
if (propType === SendProp.types.DPT_DataTable) { if (propType === SendPropDefinition.types.DPT_DataTable) {
prop.excludeDTName = this.stream.readASCIIString(); prop.excludeDTName = this.stream.readASCIIString();
} else { } else {
if (prop.isExcludeProp()) { if (prop.isExcludeProp()) {
prop.excludeDTName = this.stream.readASCIIString(); prop.excludeDTName = this.stream.readASCIIString();
} else if (prop.type === SendProp.types.DPT_Array) { } else if (prop.type === SendPropDefinition.types.DPT_Array) {
prop.numElements = this.stream.readBits(10); prop.numElements = this.stream.readBits(10);
} else { } else {
prop.lowValue = this.stream.readFloat32(); prop.lowValue = this.stream.readFloat32();
@ -40,25 +40,25 @@ DataTableParser.prototype.parse = function () {
} }
} }
if (prop.hasFlag(SendProp.flags.SPROP_NOSCALE)) { if (prop.hasFlag(SendPropDefinition.flags.SPROP_NOSCALE)) {
if (prop.type === SendProp.types.DPT_Float) { if (prop.type === SendPropDefinition.types.DPT_Float) {
prop.bitCount = 32; prop.bitCount = 32;
} else if (prop.type === SendProp.types.DPT_Vector) { } else if (prop.type === SendPropDefinition.types.DPT_Vector) {
if (!prop.hasFlag(SendProp.flags.SPROP_NORMAL)) { if (!prop.hasFlag(SendPropDefinition.flags.SPROP_NORMAL)) {
prop.bitCount = 32 * 3; prop.bitCount = 32 * 3;
} }
} }
} }
if (arrayElementProp) { if (arrayElementProp) {
if (!prop.type === SendProp.types.DPT_Array) { if (!prop.type === SendPropDefinition.types.DPT_Array) {
throw "expected prop of type array"; throw "expected prop of type array";
} }
prop.arrayProperty = arrayElementProp; prop.arrayProperty = arrayElementProp;
arrayElementProp = null; arrayElementProp = null;
} }
if (prop.hasFlag(SendProp.flags.SPROP_INSIDEARRAY)) { if (prop.hasFlag(SendPropDefinition.flags.SPROP_INSIDEARRAY)) {
arrayElementProp = prop; arrayElementProp = prop;
} else { } else {
table.addProp(prop); table.addProp(prop);
@ -71,7 +71,7 @@ DataTableParser.prototype.parse = function () {
// link referenced tables // link referenced tables
for (i = 0; i < tables.length; i++) { for (i = 0; i < tables.length; i++) {
for (j = 0; j < tables[i].props.length; j++) { for (j = 0; j < tables[i].props.length; j++) {
if (tables[i].props[j].type === SendProp.types.DPT_DataTable) { if (tables[i].props[j].type === SendPropDefinition.types.DPT_DataTable) {
tables[i].props[j].table = this.match.getSendTable(tables[i].props[j].excludeDTName); tables[i].props[j].table = this.match.getSendTable(tables[i].props[j].excludeDTName);
tables[i].props[j].excludeDTName = null; tables[i].props[j].excludeDTName = null;
} }
@ -104,30 +104,87 @@ DataTableParser.prototype.parse = function () {
var SentTable = function (name) { var SentTable = function (name) {
this.name = name; this.name = name;
this.props = []; this.props = [];
this._flattenedProps = [];
}; };
Object.defineProperty(SentTable.prototype, 'flattenedProps', {
get: function () {
if (this._flattenedProps.length === 0) {
this.flatten();
}
return this._flattenedProps;
}
});
SentTable.prototype.addProp = function (prop) { SentTable.prototype.addProp = function (prop) {
this.props.push(prop); this.props.push(prop);
}; };
SentTable.prototype.flatten = function () {
var excludes = [];
var props = [];
this.getAllProps(excludes, props);
var SendProp = function (type, name, flags) { // sort often changed props before the others
var start = 0;
for (var i = 0; i < props.length; i++) {
if (props[i].hasFlag(SendPropDefinition.flags.SPROP_CHANGES_OFTEN)) {
if (i != start) {
var temp = props[i];
props[i] = props[start];
props[start] = temp;
}
start++;
}
}
this._flattenedProps = props;
};
SentTable.prototype.getAllProps = function (excludes, props) {
var localProps = [];
this.getAllPropsIteratorProps(excludes, localProps, props);
for (var i = 0; i < localProps.length; i++) {
props.push(localProps[i]);
}
};
SentTable.prototype.getAllPropsIteratorProps = function (excludes, props, childProps) {
for (var i = 0; i < this.props.length; i++) {
var prop = this.props[i];
if (prop.type === SendPropDefinition.types.DPT_DataTable) {
if (prop.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE)) {
excludes.push(prop.table);
} else if (excludes.indexOf(this) === -1) {
if (prop.hasFlag(SendPropDefinition.flags.SPROP_COLLAPSIBLE)) {
prop.table.getAllPropsIteratorProps(excludes, props, childProps);
} else {
prop.table.getAllProps(excludes, childProps);
}
}
} else if (!prop.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE)) {
props.push(prop);
}
}
};
var SendPropDefinition = function (type, name, flags) {
this.type = type; this.type = type;
this.name = name; this.name = name;
this.flags = flags; this.flags = flags;
this.excludeDTName = null; this.excludeDTName = null;
this.lowValue = 0; this.lowValue = 0;
this.highValue = 0; this.highValue = 0;
this.bits = 0; this.bitCount = 0;
this.table = null;
this.numElements = null;
this.arrayProperty = null;
}; };
SendProp.prototype.hasFlag = function (flag) { SendPropDefinition.prototype.hasFlag = function (flag) {
return (this.flags & flag) != 0; return (this.flags & flag) != 0;
}; };
SendProp.prototype.isExcludeProp = function () { SendPropDefinition.prototype.isExcludeProp = function () {
return this.hasFlag(SendProp.flags.SPROP_EXCLUDE); return this.hasFlag(SendPropDefinition.flags.SPROP_EXCLUDE);
}; };
SendProp.types = { SendPropDefinition.types = {
DPT_Int : 0, DPT_Int : 0,
DPT_Float : 1, DPT_Float : 1,
DPT_Vector : 2, DPT_Vector : 2,
@ -138,7 +195,7 @@ SendProp.types = {
DPT_NUMSendPropTypes: 7 DPT_NUMSendPropTypes: 7
}; };
SendProp.flags = { SendPropDefinition.flags = {
SPROP_UNSIGNED : (1 << 0),// Unsigned integer data. SPROP_UNSIGNED : (1 << 0),// Unsigned integer data.
SPROP_COORD : (1 << 1),// If this is set, the float/vector is treated like a world coordinate. 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. // Note that the bit count is ignored in this case.
@ -160,14 +217,15 @@ SendProp.flags = {
// trouble of walking the hierarchy more than necessary. // 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 : (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_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_COORD_MP_INTEGRAL : (1 << 15),// SPROP_COORD_MP, but coordinates are rounded to integral boundaries
SPROP_VARINT : (1 << 5) //reuse normal
}; };
SendProp.formatFlags = function (flags) { SendPropDefinition.formatFlags = function (flags) {
var names = []; var names = [];
for (var name in SendProp.flags) { for (var name in SendPropDefinition.flags) {
if (SendProp.flags.hasOwnProperty(name)) { if (SendPropDefinition.flags.hasOwnProperty(name)) {
if (flags & SendProp.flags[name]) { if (flags & SendPropDefinition.flags[name]) {
names.push(name); names.push(name);
} }
} }
@ -175,14 +233,150 @@ SendProp.formatFlags = function (flags) {
return names; return names;
}; };
SendPropDefinition.prototype.decode = function (stream) {
switch (this.type) {
case SendPropDefinition.types.DPT_Int:
return this.readInt(stream);
case SendPropDefinition.types.DPT_Vector:
return this.readVector(stream);
case SendPropDefinition.types.DPT_VectorXY:
return this.readVectorXY(stream);
case SendPropDefinition.types.DPT_Float:
return this.readFloat(stream);
case SendPropDefinition.types.DPT_String:
return this.readString(stream);
case SendPropDefinition.types.DPT_Array:
return this.readArray(stream);
}
};
SendPropDefinition.prototype.readInt = function (stream) {
if (this.hasFlag(SendPropDefinition.flags.SPROP_VARINT)) {
return readBitVar(stream, !this.hasFlag(SendPropDefinition.flags.SPROP_UNSIGNED));
} else {
return stream.readBits(this.bitCount, !this.hasFlag(SendPropDefinition.flags.SPROP_UNSIGNED));
}
};
SendPropDefinition.prototype.readArray = function (stream) {
var maxElements = this.numElements;
var numBits = 1;
while ((maxElements >>= 1) != 0)
numBits++;
var count = stream.readBits(numBits);
var values = [];
for (var i = 0; i < count; i++) {
values.push(this.arrayProperty.decode(stream));
}
return values;
};
SendPropDefinition.prototype.readString = function (stream) {
var length = stream.readBits(9);
return stream.readASCIIString(length);
};
SendPropDefinition.prototype.readVector = function (stream) {
var x = this.readFloat(stream);
var y = this.readFloat(stream);
if (this.hasFlag(SendPropDefinition.flags.SPROP_NORMAL)) {
var z = this.readFloat(stream);
} else {
z = 0; //guess
}
return new Vector(x, y, z);
};
SendPropDefinition.prototype.readVectorXY = function (stream) {
var x = this.readFloat(stream);
var y = this.readFloat(stream);
return new Vector(x, y, 0);
};
var Vector = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
SendPropDefinition.prototype.readFloat = function (stream) {
if (this.hasFlag(SendPropDefinition.flags.SPROP_COORD)) {
throw new Error("not implemented");
} else if (this.hasFlag(SendPropDefinition.flags.SPROP_COORD_MP)) {
return this.readBitCoord(stream, false, false);
} else if (this.hasFlag(SendPropDefinition.flags.SPROP_COORD_MP_LOWPRECISION)) {
return this.readBitCoord(stream, false, true);
} else if (this.hasFlag(SendPropDefinition.flags.SPROP_COORD_MP_INTEGRAL)) {
return this.readBitCoord(stream, true, false);
} else if (this.hasFlag(SendPropDefinition.flags.SPROP_NOSCALE)) {
return stream.readFloat32();
} else if (this.hasFlag(SendPropDefinition.flags.SPROP_NORMAL)) {
throw new Error("not implemented");
} else {
var raw = stream.readBits(this.bitCount);
var percentage = raw / ((1 << this.bitCount) - 1);
return this.lowValue + (this.highValue - this.lowValue) * percentage;
}
};
SendPropDefinition.prototype.readBitCoord = function (stream, isIntegral, isLowPercision) {
var value = 0;
var isNegative = false;
var inBounds = stream.readBoolean();
var hasIntVal = stream.readBoolean();
if (isIntegral) {
if (hasIntVal) {
isNegative = stream.readBoolean();
if (inBounds) {
value = stream.readBitVar(11) + 1;
} else {
value = stream.readBitVar(14) + 1;
if (value < (1 << 11)) {
throw new Error("Something's fishy...");
}
}
}
} else {
isNegative = stream.readBoolean();
if (hasIntVal) {
if (inBounds) {
value = stream.readBitVar(11) + 1;
} else {
value = stream.readBitVar(14) + 1;
if (value < (1 << 11)) {
throw new Error("Something's fishy...");
}
}
}
var fractalVal = stream.readBits(isLowPercision ? 3 : 5);
value += fractalVal * (1 / (1 << (isLowPercision ? 3 : 5)));
}
if (isNegative) {
value = -value;
}
return value;
};
var ServerClass = function (id, name, dataTable) { var ServerClass = function (id, name, dataTable) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.dataTable = dataTable; this.dataTable = dataTable;
}; };
function recvClassInfos(stream, needsDecoder) { var readBitVar = function (stream, signed) {
switch (stream.readBits(2)) {
} case 0:
return stream.readBits(4, signed);
case 1:
return stream.readBits(8, signed);
case 2:
return stream.readBits(12, signed);
case 3:
return stream.readBits(32, signed);
}
};
module.exports = DataTableParser; module.exports = DataTableParser;

View file

@ -1,23 +1,12 @@
var clone = require('clone');
var PVS = { var PVS = {
PRESERVE: 0, PRESERVE: 0,
ENTER : 1, ENTER : 1,
LEAVE : 2, LEAVE : 2,
DELETE : 3 DELETE : 4
}; };
function readIndex(stream, baseIndex) {
// https://github.com/skadistats/smoke/blob/a2954fbe2fa3936d64aee5b5567be294fef228e6/smoke/io/stream/entity.pyx#L15
var encodedIndex = stream.readBits(6);
if (encodedIndex & 0x30) {
var a = (encodedIndex >> 4) & 3;
var b = (a == 3) ? 16 : 0;
var i = stream.readBits(4 * a + b) << 4;
encodedIndex = i | (encodedIndex & 0x0f);
}
return baseIndex + encodedIndex + 1;
}
function readPVSType(stream) { function readPVSType(stream) {
// https://github.com/skadistats/smoke/blob/a2954fbe2fa3936d64aee5b5567be294fef228e6/smoke/io/stream/entity.pyx#L24 // https://github.com/skadistats/smoke/blob/a2954fbe2fa3936d64aee5b5567be294fef228e6/smoke/io/stream/entity.pyx#L24
var pvs; var pvs;
@ -35,14 +24,44 @@ function readPVSType(stream) {
return pvs; return pvs;
} }
function readEnterPVS(stream, entityId) { function readEnterPVS(stream, entityId, match, baseLine) {
// https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs#L198
var serverClass = match.serverClasses[stream.readBits(match.classBits)];
var sendTable = match.getSendTable(serverClass.dataTable);
var serialNumber = stream.readBits(10);
var entity = (match.entities[entityId]) ? match.entities[entityId] : new Entity(match, serverClass, sendTable, entityId, serialNumber);
var decodedBaseLine = match.instanceBaselines[baseLine][entityId];
if (decodedBaseLine) {
for (var i = 0; i < decodedBaseLine.length; i++) {
var newProp = decodedBaseLine[i];
if (!entity.getPropByDefinition(newProp.definition)) {
entity.props.push(newProp.clone(entity));
}
}
} else {
var staticBaseLine = match.staticBaseLines[serverClass.id];
if (staticBaseLine) {
var streamStart = staticBaseLine._index;
applyEntityUpdate(entity, staticBaseLine);
staticBaseLine._index = streamStart;
}
}
return entity;
} }
module.exports = function (stream, events, entities) { //26: packetEntities function readLeavePVS(match, entityId, shouldDelete) {
if (shouldDelete) {
match.entities[entityId] = null;
}
}
module.exports = function (stream, events, entities, match) { //26: packetEntities
// https://github.com/skadistats/smoke/blob/master/smoke/replay/handler/svc_packetentities.pyx // https://github.com/skadistats/smoke/blob/master/smoke/replay/handler/svc_packetentities.pyx
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Handler/PacketEntitesHandler.cs // https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Handler/PacketEntitesHandler.cs
// https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Entity.cs // https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/DP/Entity.cs
// https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs
// todo // todo
var maxEntries = stream.readBits(11); var maxEntries = stream.readBits(11);
var isDelta = !!stream.readBits(1); var isDelta = !!stream.readBits(1);
@ -51,31 +70,68 @@ module.exports = function (stream, events, entities) { //26: packetEntities
} else { } else {
delta = null; delta = null;
} }
var baseLink = !!stream.readBits(1); var baseLine = stream.readBits(1);
var updatedEntries = stream.readBits(11); var updatedEntries = stream.readBits(11);
var length = stream.readBits(20); var length = stream.readBits(20);
var updatedBaseLink = !!stream.readBits(1); var updatedBaseLine = stream.readBoolean();
var end = stream._index + length; var end = stream._index + length;
//console.log('max: ' + maxEntries);
var entityId = -1; var entityId = -1;
for (var i = 0; i < updatedEntries; i++) { if (updatedBaseLine) {
entityId = readIndex(stream, entityId); if (baseLine === 0) {
var pvs = readPVSType(stream); match.instanceBaselines[1] = match.instanceBaselines[0];
if (pvs = PVS.PRESERVE) { match.instanceBaselines[0] = new Array((1 << 11)); // array of SendPropDefinition with size MAX_EDICTS
var entity = readEnterPVS(stream, entityId) } else {
match.instanceBaselines[0] = match.instanceBaselines[1];
match.instanceBaselines[1] = new Array((1 << 11)); // array of SendPropDefinition with size MAX_EDICTS
} }
} }
for (var i = 0; i < updatedEntries; i++) {
entityId+= 1 + readUBitVar(stream);
var pvs = readPVSType(stream);
if (pvs === PVS.ENTER) {
var entity = readEnterPVS(stream, entityId, match, baseLine);
applyEntityUpdate(entity, stream);
match.entities[entityId] = entity;
if (updatedBaseLine) {
match.instanceBaselines[baseLine][entityId] = [].concat(entity.props);
}
entity.inPVS = true;
} else if (pvs === PVS.PRESERVE) {
entity = match.entities[entityId];
if (!entity) {
console.log(entityId, match.entities.length);
throw new Error("unknown entity");
}
applyEntityUpdate(entity, stream);
} else {
entity = match.entities[entityId];
if (entity) {
entity.inPVS = false;
}
readLeavePVS(match, entityId, pvs === PVS.DELETE);
}
}
if (isDelta) {
while (stream.readBoolean()) {
var ent = stream.readBits(11);
match.entities[ent] = null;
}
}
stream._index = end; stream._index = end;
//var ent = { //var ent = {
// packetType : 'packetEntities', // packetType : 'packetEntities',
// maxEntries : maxEntries, // maxEntries : maxEntries,
// isDelta : isDelta, // isDelta : isDelta,
// delta : delta, // delta : delta,
// baseLink : baseLink, // baseLine : baseLine,
// updatedEntries : updatedEntries, // updatedEntries : updatedEntries,
// length : length, // length : length,
// updatedBaseLink: updatedBaseLink // updatedBaseLine: updatedBaseLine
//}; //};
//console.log(ent); //console.log(ent);
//console.log(entities); //console.log(entities);
@ -85,3 +141,78 @@ module.exports = function (stream, events, entities) { //26: packetEntities
entities : entities entities : entities
}; };
}; };
var readFieldIndex = function (stream, lastIndex) {
if (!stream.readBoolean()) {
return -1;
}
var diff = readUBitVar(stream);
return lastIndex + diff + 1;
};
var applyEntityUpdate = function (entity, stream) {
var index = -1;
var allProps = entity.sendTable.flattenedProps;
while ((index = readFieldIndex(stream, index)) != -1) {
if (index > 4096) {
throw new Error('prop index out of bounds');
}
var propDefinition = allProps[index];
var existingProp = entity.getPropByDefinition(propDefinition);
var prop;
if (existingProp) {
prop = existingProp;
} else {
prop = new SentProp(propDefinition);
}
prop.value = propDefinition.decode(stream);
if (!existingProp) {
entity.props.push(prop);
}
}
return entity;
};
var readUBitVar = function (stream) {
switch (stream.readBits(2)) {
case 0:
return stream.readBits(4);
case 1:
return stream.readBits(8);
case 2:
return stream.readBits(12);
case 3:
return stream.readBits(32);
}
};
var Entity = function (match, serverClass, sentTable, entityIndex, serialNumber) {
this.match = match;
this.serverClass = serverClass;
this.sendTable = sentTable;
this.entityIndex = entityIndex;
this.serialNumber = serialNumber;
this.props = [];
this.inPVS = false;
};
Entity.prototype.getPropByDefinition = function (definition) {
for (var i = 0; i < this.props; i++) {
if (this.props[i].definition === definition) {
return this.props[i];
}
}
return null;
};
var SentProp = function (definition) {
this.definition = definition;
this.value = null;
};
SentProp.prototype.clone = function () {
var prop = new SentProp(this.definition);
prop.value = clone(this.value);
return prop;
};

View file

@ -10,6 +10,9 @@ var Match = function () {
this.stringTables = []; this.stringTables = [];
this.sendTables = []; this.sendTables = [];
this.serverClasses = []; this.serverClasses = [];
this.entities = [];
this.instanceBaselines = [[],[]];
this.staticBaseLines = [];
}; };
Match.prototype.getSendTable = function (name) { Match.prototype.getSendTable = function (name) {
@ -21,6 +24,15 @@ Match.prototype.getSendTable = function (name) {
return null; return null;
}; };
Match.prototype.getStringTable = function (name) {
for (var i = 0; i < this.stringTables.length; i++) {
if (this.stringTables[i].name === name) {
return this.stringTables[i];
}
}
return null;
};
Match.prototype.getState = function () { Match.prototype.getState = function () {
return { return {
'chat' : this.chat, 'chat' : this.chat,
@ -131,4 +143,10 @@ Match.prototype.getUserState = function (userId) {
return this.users[userId]; return this.users[userId];
}; };
Object.defineProperty(Match.prototype, 'classBits', {
get: function () {
return Math.ceil(Math.log(this.serverClasses.length) * Math.LOG2E)
}
});
module.exports = Match; module.exports = Match;

View file

@ -7,8 +7,10 @@
}, },
"main": "demo.js", "main": "demo.js",
"dependencies": { "dependencies": {
"bit-buffer": "icewind1991/bit-buffer", "bit-buffer": "icewind1991/bit-buffer#readBitStream",
"clone": "^2.1.0",
"minimist": "1.1.x", "minimist": "1.1.x",
"smart-buffer": "^1.0.1" "smart-buffer": "^1.0.1",
"typedarray-to-buffer": "^3.1.2"
} }
} }

View file

@ -32,7 +32,7 @@ Packet.prototype.parse = function () {
while (this.bitsLeft > 6) { // last 6 bits for NOOP while (this.bitsLeft > 6) { // last 6 bits for NOOP
var type = this.stream.readBits(6); var type = this.stream.readBits(6);
if (Packet.parsers[type]) { if (Packet.parsers[type]) {
var packet = Packet.parsers[type].call(this, this.stream, Packet.gameEventMap, entities); var packet = Packet.parsers[type].call(this, this.stream, Packet.gameEventMap, entities, this.match);
if (packet) { if (packet) {
packet.viewOrigin = this.viewOrigin; packet.viewOrigin = this.viewOrigin;
} }

View file

@ -1,3 +1,4 @@
var toBuffer = require('typedarray-to-buffer')
var util = require('util'); var util = require('util');
var Packet = require('./packet'); var Packet = require('./packet');
var ConsoleCmd = require('./consolecmd'); var ConsoleCmd = require('./consolecmd');
@ -134,7 +135,7 @@ Parser.prototype.readMessage = function (stream, match) {
length = stream.readInt32(); length = stream.readInt32();
start = stream.byteIndex; start = stream.byteIndex;
buffer = stream.buffer.slice(start, start + length); buffer = toBuffer(stream._view._view.slice(start, start + length));
stream.byteIndex += length; stream.byteIndex += length;
return this.parseMessage(buffer, type, tick, length, viewOrigin, match); return this.parseMessage(buffer, type, tick, length, viewOrigin, match);
}; };

View file

@ -1,3 +1,5 @@
var BitStream = require('bit-buffer').BitStream;
var StringTable = function (type, tick, stream, length, match) { var StringTable = function (type, tick, stream, length, match) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
@ -7,13 +9,14 @@ var StringTable = function (type, tick, stream, length, match) {
}; };
StringTable.prototype.parse = function () { StringTable.prototype.parse = function () {
var tableCount = this.stream.readBits(8); // https://github.com/StatsHelix/demoinfo/blob/3d28ea917c3d44d987b98bb8f976f1a3fcc19821/DemoInfo/ST/StringTableParser.cs
var tableCount = this.stream.readUint8();
var tables = {}; var tables = {};
var extraDataLength; var extraDataLength;
for (var i = 0; i < tableCount; i++) { for (var i = 0; i < tableCount; i++) {
var entries = []; var entries = [];
var tableName = this.stream.readASCIIString(); var tableName = this.stream.readASCIIString();
var entryCount = this.stream.readBits(16); var entryCount = this.stream.readUint16();
for (var j = 0; j < entryCount; j++) { for (var j = 0; j < entryCount; j++) {
try { try {
var entry = { var entry = {
@ -26,8 +29,12 @@ StringTable.prototype.parse = function () {
}]; }];
} }
if (this.stream.readBits(1)) { if (this.stream.readBits(1)) {
extraDataLength = this.stream.readBits(16); extraDataLength = this.stream.readUint16();
entry.extraData = this.readExtraData(extraDataLength); if (tableName === 'instancebaseline') {
this.match.staticBaseLines[parseInt(entry.text, 10)] = this.stream.readBitStream(8 * extraDataLength);
} else {
entry.extraData = this.readExtraData(extraDataLength);
}
} }
entries.push(entry); entries.push(entry);
} }
@ -52,23 +59,6 @@ StringTable.prototype.parse = function () {
}]; }];
}; };
StringTable.prototype.parsePlayerInfo = function (length) {
var pos = this.stream._index;
var name = this.stream.readUTF8String(128);
console.log(length);
//if (name === 'Icewind') {
console.log(name);
var userId = this.stream.readBits(32);
console.log(userId);
var guid = this.stream.readASCIIString(33);
console.log('guid: ' + guid);
//console.log(this.stream.readASCIIString(33));
//console.log(this.stream.readASCIIString());
//throw false;
//}
this.stream._index = pos + (length * 8);
};
StringTable.prototype.readExtraData = function (length) { StringTable.prototype.readExtraData = function (length) {
var end = this.stream._index + (length * 8); var end = this.stream._index + (length * 8);
var data = []; var data = [];