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

handle duplicated sendprops

This commit is contained in:
Robin Appelman 2017-09-16 17:58:39 +02:00
commit 79c4782806
4 changed files with 46 additions and 48 deletions

View file

@ -28,7 +28,7 @@ export class PacketEntity {
this.pvs = pvs; this.pvs = pvs;
} }
private static getPropByFullName(props: SendProp[], fullName: string): SendProp | null { public static getPropByFullName(props: SendProp[], fullName: string): SendProp | null {
for (const prop of props) { for (const prop of props) {
if (prop.definition.fullName === fullName) { if (prop.definition.fullName === fullName) {
return prop; return prop;
@ -56,7 +56,9 @@ export class PacketEntity {
result.props.push(prop.clone()); result.props.push(prop.clone());
} }
result.serialNumber = this.serialNumber; result.serialNumber = this.serialNumber;
if (this.delay) {
result.delay = this.delay; result.delay = this.delay;
}
result.inPVS = this.inPVS; result.inPVS = this.inPVS;
return result; return result;
} }

View file

@ -8,7 +8,7 @@ import {SendPropEncoder} from './SendPropEncoder';
export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[] { export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendProp[] {
let index = -1; let index = -1;
const allProps = sendTable.flattenedProps; const allProps = sendTable.flattenedProps;
const props: SendProp[] = []; const props: Map<string, SendProp> = new Map();
while (stream.readBoolean()) { while (stream.readBoolean()) {
index = readFieldIndex(stream, index); index = readFieldIndex(stream, index);
if (index >= 4096 || index > allProps.length) { if (index >= 4096 || index > allProps.length) {
@ -19,9 +19,9 @@ export function getEntityUpdate(sendTable: SendTable, stream: BitStream): SendPr
const propDefinition = allProps[index]; const propDefinition = allProps[index];
const prop = new SendProp(propDefinition); const prop = new SendProp(propDefinition);
prop.value = SendPropParser.decode(propDefinition, stream); prop.value = SendPropParser.decode(propDefinition, stream);
props.push(prop); props.set(propDefinition.fullName, prop);
} }
return props; return Array.from(props.values());
} }
export function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stream: BitStream) { export function encodeEntityUpdate(props: SendProp[], sendTable: SendTable, stream: BitStream) {

View file

@ -34,7 +34,7 @@ function writePVSType(pvs: PVS, stream: BitStream) {
stream.writeBits(raw, 2); stream.writeBits(raw, 2);
} }
function readEnterPVS(stream: BitStream, entityId: EntityId, state: ParserState, baseLine: number): PacketEntity { function readEnterPVS(stream: BitStream, entityId: EntityId, state: ParserState, baseLineIndex: number): PacketEntity {
// https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs#L198 // https://github.com/PazerOP/DemoLib/blob/5f9467650f942a4a70f9ec689eadcd3e0a051956/TF2Net/NetMessages/NetPacketEntitiesMessage.cs#L198
const classBits = getClassBits(state); const classBits = getClassBits(state);
const serverClass = state.serverClasses[stream.readBits(classBits)]; const serverClass = state.serverClasses[stream.readBits(classBits)];
@ -42,7 +42,7 @@ function readEnterPVS(stream: BitStream, entityId: EntityId, state: ParserState,
const sendTable = getSendTable(state, serverClass.dataTable); const sendTable = getSendTable(state, serverClass.dataTable);
const instanceBaseline = state.instanceBaselines[baseLine].get(entityId); const instanceBaseline = state.instanceBaselines[baseLineIndex].get(entityId);
const entity = new PacketEntity(serverClass, entityId, PVS.ENTER); const entity = new PacketEntity(serverClass, entityId, PVS.ENTER);
entity.serialNumber = serial; entity.serialNumber = serial;
if (instanceBaseline) { if (instanceBaseline) {
@ -52,23 +52,24 @@ function readEnterPVS(stream: BitStream, entityId: EntityId, state: ParserState,
} else { } else {
const staticBaseLine = state.staticBaseLines.get(serverClass.id); const staticBaseLine = state.staticBaseLines.get(serverClass.id);
if (staticBaseLine) { if (staticBaseLine) {
let baseline = state.staticBaselineCache.get(serverClass.id); let parsedBaseLine = state.staticBaselineCache.get(serverClass.id);
if (!baseline) { if (!parsedBaseLine) {
staticBaseLine.index = 0; staticBaseLine.index = 0;
baseline = getEntityUpdate(sendTable, staticBaseLine); parsedBaseLine = getEntityUpdate(sendTable, staticBaseLine);
state.staticBaselineCache.set(serverClass.id, baseline); state.staticBaselineCache.set(serverClass.id, parsedBaseLine);
} }
entity.applyPropUpdate(baseline); entity.applyPropUpdate(parsedBaseLine);
// if (staticBaseLine.bitsLeft > 7) { // if (staticBaseLine.bitsLeft > 7) {
// console.log(staticBaseLine.length, staticBaseLine.index); // console.log(staticBaseLine.length, staticBaseLine.index);
// throw new Error('Unexpected data left at the end of staticBaseline, ' + staticBaseLine.bitsLeft + ' bits left'); // throw new Error('Unexpected data left at the end of staticBaseline, ' + staticBaseLine.bitsLeft + ' bits left');
// } // }
} }
return entity; return entity;
} }
} }
function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserState, baseLine: number) { function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserState, baseLineIndex: number) {
const serverClassId = state.serverClasses.findIndex(serverClass => serverClass && entity.serverClass.id === serverClass.id); const serverClassId = state.serverClasses.findIndex(serverClass => serverClass && entity.serverClass.id === serverClass.id);
if (serverClassId === -1) { if (serverClassId === -1) {
throw new Error(`Unknown server class ${entity.serverClass.name}(${entity.serverClass.id})`); throw new Error(`Unknown server class ${entity.serverClass.name}(${entity.serverClass.id})`);
@ -81,20 +82,21 @@ function writeEnterPVS(entity: PacketEntity, stream: BitStream, state: ParserSta
const sendTable = getSendTable(state, serverClass.dataTable); const sendTable = getSendTable(state, serverClass.dataTable);
let instanceBaseLine = state.instanceBaselines[baseLine].get(entity.entityIndex); let instanceBaseLine = state.instanceBaselines[baseLineIndex].get(entity.entityIndex);
if (!instanceBaseLine) { if (!instanceBaseLine) {
const staticBaseLine = state.staticBaseLines.get(serverClass.id); const staticBaseLine = state.staticBaseLines.get(serverClass.id);
if (staticBaseLine) { if (staticBaseLine) {
instanceBaseLine = state.staticBaselineCache.get(serverClass.id);
if (!instanceBaseLine) {
staticBaseLine.index = 0; staticBaseLine.index = 0;
instanceBaseLine = getEntityUpdate(sendTable, staticBaseLine); instanceBaseLine = getEntityUpdate(sendTable, staticBaseLine);
// state.instanceBaselines.set(serverClass, instanceBaseLine.clone()); state.staticBaselineCache.set(serverClass.id, instanceBaseLine);
}
} }
} }
const propsToEncode = instanceBaseLine ? entity.diffFromBaseLine(instanceBaseLine) : entity.props; const propsToEncode = instanceBaseLine ? entity.diffFromBaseLine(instanceBaseLine) : entity.props;
// console.log(propsToEncode.map(prop => `${prop.definition.name}: ${prop.value}`));
const allProps = sendTable.flattenedProps; const allProps = sendTable.flattenedProps;
propsToEncode.sort((a, b) => allProps.findIndex(propDef => propDef.fullName === a.definition.fullName) - propsToEncode.sort((a, b) => allProps.findIndex(propDef => propDef.fullName === a.definition.fullName) -
allProps.findIndex(propDef => propDef.fullName === b.definition.fullName)); allProps.findIndex(propDef => propDef.fullName === b.definition.fullName));
@ -112,9 +114,6 @@ function getPacketEntityForExisting(entityId: EntityId, state: ParserState, pvs:
} }
export function ParsePacketEntities(stream: BitStream, state: ParserState, skip: boolean = false): PacketEntitiesPacket { // 26: packetEntities export function ParsePacketEntities(stream: BitStream, state: ParserState, skip: boolean = false): PacketEntitiesPacket { // 26: packetEntities
// require('fs').writeFileSync('src/tests/data/packetEntitiesParserState.json', JSON.stringify(state), 'utf8');
// process.exit();
// 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

View file

@ -124,35 +124,32 @@ const sunEntityData = {
}; };
suite('PacketEntities', () => { suite('PacketEntities', () => {
// test('Parse packetEntities', () => { test('Parse packetEntities', () => {
// const length = 130435; const length = 130435;
// const stream = getStream(data); const stream = getStream(data);
// const start = stream.index; const start = stream.index;
// const resultPacket = parse(stream); const resultPacket = parse(stream);
// assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream'); assert.equal(stream.index - start, length, 'Unexpected number of bits consumed from stream');
//
// for (let i = 0; i < resultPacket.entities.length; i++) { for (let i = 0; i < resultPacket.entities.length; i++) {
// const resultEntity = resultPacket.entities[i]; const resultEntity = resultPacket.entities[i];
// const expectedEntity = expected.entities[i]; const expectedEntity = expected.entities[i];
// assert.deepEqual(expectedEntity.serverClass, resultEntity.serverClass); assert.deepEqual(expectedEntity.serverClass, resultEntity.serverClass);
// assert.equal(expectedEntity.serialNumber, resultEntity.serialNumber); assert.equal(expectedEntity.serialNumber, resultEntity.serialNumber);
// assert.equal(expectedEntity.entityIndex, resultEntity.entityIndex); assert.equal(expectedEntity.entityIndex, resultEntity.entityIndex);
// if (!deepEqual(resultEntity, expectedEntity)) { if (!deepEqual(resultEntity, expectedEntity)) {
// for (let i = 0; i < expectedEntity.props.length; i++) { for (let i = 0; i < expectedEntity.props.length; i++) {
// console.log(resultEntity.getPropByDefinition(expectedEntity.props[i].definition),expectedEntity.props[i].definition); console.log(resultEntity.getPropByDefinition(expectedEntity.props[i].definition),expectedEntity.props[i].definition);
// assert.deepEqual(resultEntity.getPropByDefinition(expectedEntity.props[i].definition), expectedEntity.props[i], `invalid property #${i} for ${resultEntity.serverClass.name}`); assert.deepEqual(resultEntity.getPropByDefinition(expectedEntity.props[i].definition), expectedEntity.props[i], `invalid property #${i} for ${resultEntity.serverClass.name}`);
// } }
// assert.equal(resultEntity.props.length, expectedEntity.props.length, `Unexpected number of props for ${resultEntity.serverClass.name}`); assert.equal(resultEntity.props.length, expectedEntity.props.length, `Unexpected number of props for ${resultEntity.serverClass.name}`);
// assert(false, 'Invalid entity ' + resultEntity.serverClass.name); assert(false, 'Invalid entity ' + resultEntity.serverClass.name);
// } }
// } }
// }); });
test('Encode packetEntities', () => { test('Encode packetEntities', () => {
const toEncode = {...expected}; const toEncode = {...expected};
// entity.props.map(prop => console.log(`${prop.definition.fullName}: ${prop.value}`));
// entity.props = [entity.props[0]];
toEncode.entities = toEncode.entities.slice(281, 282);
assertEncoder(parse, encode, toEncode, 0); assertEncoder(parse, encode, toEncode, 0);
}); });