mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
handle duplicated sendprops
This commit is contained in:
parent
358aa6aa21
commit
79c4782806
4 changed files with 46 additions and 48 deletions
|
|
@ -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;
|
||||||
result.delay = this.delay;
|
if (this.delay) {
|
||||||
|
result.delay = this.delay;
|
||||||
|
}
|
||||||
result.inPVS = this.inPVS;
|
result.inPVS = this.inPVS;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
staticBaseLine.index = 0;
|
instanceBaseLine = state.staticBaselineCache.get(serverClass.id);
|
||||||
instanceBaseLine = getEntityUpdate(sendTable, staticBaseLine);
|
if (!instanceBaseLine) {
|
||||||
// state.instanceBaselines.set(serverClass, instanceBaseLine.clone());
|
staticBaseLine.index = 0;
|
||||||
|
instanceBaseLine = getEntityUpdate(sendTable, staticBaseLine);
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue