Skip to content

Incorrect entity parsing (with simple solution!) #11

@p2r3

Description

@p2r3

TL;DR - Remove this.

if (msg.UpdateBaseline) { // if update baseline then set the current baseline to the ent props, wacky
_demoRef.State.EntBaseLines.UpdateBaseLine(
u.ServerClass!,
e.Props.Select((property, i) => (i, property)).Where(tuple => tuple.property != null)!,
e.Props.Length);
}

Now for a slightly more in-depth explanation:

There are two types of baselines in demos, but UntitledParser seems to confuse the two into one. Though, given Valve's inconsistent naming, that's completely understandable. Basically, the two types are:

  • "Static" baselines, which store default properties for an entity class. These are the kind that UntitledParser tracks, and they're updated only by string tables.
  • "Entity" baselines, which are just a system for optimizing networked deltas per-entity. Two tables, one entry per entindex. This is the kind that UntitledParser doesn't track and, critically, mistakes for the static variant in this case.

For most demos, entity baselines are effectively the same as entity "snapshots", as you call them. They just track the current state of an entity slot, with maaaybe a few subtle differences. What's important is that UntitledParser already has the system for this.

So the reason there's a BaseLine field in SvcPacketEntities, or the reason why there are two tables for this baseline variant, is because networked games would otherwise have to wait for the player to ACK the last delta before sending another. By switching between them, and keeping the currently used baseline index in sync, the client and server can ensure consistency without stalling. At least that's my high-level understanding.

Ultimately, the issue here is that UntitledParser treats an update of entity baselines as an update of static baselines. This causes tons of weird behavior, like some entities doubling, or others being missing/mangled, and just removing this line should fix that. It did for my parser. The comment was right to call this "wacky", because it really doesn't make sense the way it's currently implemented. I suppose the correct implementation would be to replicate the two-table entity baseline system, but just removing this piece of code would already be far more accurate.

sidenote - valve refers to the first variant as "static", "instance" or "class" baselines interchangeably. the second variant is always "entity" baselines or just "baselines", though it's easy to see how that could still be confused with the term "instance" baseline. this is far worse than "send"/"recv"/"data"/"string" tables, so any confusion here is completely understandable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions