Skip to content

Spawned gameplay objects are never wired into the level bus (flags don't capture, spawners don't spawn) #391

Description

@Powback

Full analysis committed as docs/entity-wiring-and-networking.md on live-ebx. This issue tracks the three High-severity gaps from it; G4-G11 are in the doc.

Findings are grounded in the Venice-EBX dumps, with verified vs inferred kept separate in the doc.


G1 — Level-bus connections are never authored (the headline)

Frostbite splits gameplay wiring in two:

  • Inside the prefab — CapturePointPrefab carries an InterfaceDescriptorData exposing CaptureRadius, OnCaptured/OnLost etc., plus internal PropertyConnections. This ships in the blueprint, so CreateEntitiesFromBlueprint rebuilds it for free.
  • In the level/subworld bus — the connections that make a flag a Conquest flag. Levels/MP_001/Conquest.txt (SubWorldData 539342BE-…) holds 49 PropertyConnections + 17+ EventConnections referencing the flag RODs (CQ_logic/8C5AF081-…, CQ_logic_US/10A70CA7-…). MP_001.txt (LevelData) has more, cross-partition into the world parts.

MapEditor only ever creates the object: LevelInjector:CreateWorldParts builds a WorldPartData() with only objects populated (no propertyConnections/linkConnections/eventConnections/descriptor), and InvokeBlueprintSpawn wires the new bus into nothing.

Result: spawn a CapturePointPrefab / vehicle spawner / MCOM and it renders, its internal wiring works, and the game mode never sees it. Flags never capture, spawners never spawn, MCOMs never arm. Note this is not addressed by parentRepresentative (#202) — that makes per-instance data unique, it doesn't wire anything into the level bus.

Also relevant: the networking realm of an event is carried on the connection (EventConnectionTargetType: Client / Server / NetworkedClient / …), not on the object.

G2 — Editing a networked object desyncs it

Any EBX edit re-instantiates via InvokeBlueprintSpawnFromClone, which hardcodes networked = false and runs client-only. CapturePointPrefab is NeedNetworkId True (verified). So the client ends up rendering a local non-networked copy while the server still owns the real entity.

networked can't simply be restored: the clone DC isn't registered in ResourceManager, so a networked spawn hands the peer an unresolvable blueprint guid and crashes it — which is exactly why it's false. Options: (a) keep client-only preview and re-sync authoritatively on save, (b) register the clone so peers can resolve it, (c) skip re-instantiation for needNetworkId objects and fall back to Disable/Enable. Needs a design decision.

G3 — Entity buses leak on every edit

GameObject:Destroy calls Disable() on its entities; GameEntity:Destroy has zero callers. Every (debounced) re-instantiation therefore abandons an entity bus.

Constraint that must survive any fix: destroying a vanilla entity crashes the game. That is why the code disables rather than destroys. It is also subtler than it looks — a vanilla object is re-registered as Custom after its first EBX edit, so from then on its entities descend from level data. A fix has to destroy only entities we created via CreateEntitiesFromBlueprint, e.g. by tagging them in the create hook. See §4.1 of the doc.


Useful adjacent finding: the field-id hash -> name table needed to make connections human-readable (838548383 -> Geometry, 2099208964 -> OnCaptured) is already shipped in data.zip as EventHashes.json and simply discarded at load — see #388.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions