Per-client emit: redirect-src fix + SendFake one-shot
Per-client field substitution reached the emit but no-oped on the wire: calling the field encoder directly against WriteFieldList's stack-local value buffer did not change the value clients decoded. Overnight RE of libnetworksystem.so (WriteFieldList FUN_00443b60, uint encoder FUN_004c8e90, varint writer FUN_00500890, BitCopyPrimitive FUN_00500b70) confirmed every mechanic of the direct call individually, so the no-op isn't explained by the decompile alone. Fix: reproduce the *proven* uniform mechanism. Encode the fake into a fresh byte-aligned scratch bf_write, then call the original BitCopyPrimitive with src redirected to that scratch. The write into the live value buffer is then 100% the engine's own primitive (identical to the working uniform path); only the source of the fake bits differs (per-client scratch at copy time vs the shared pre-encoded pack). Correct for all field families: fixed-width gives N==bitcount; varint/string/bytes are self-delimiting and the flush uses the intermediate buffer's own cursor. valuePtr-building is unchanged and is byte-identical to the working UniformEncoderHook scratch layout. SendFake(IGameClient, IBaseEntity, ser, field, value): one-shot push to a single client without a persistent hook. Registers an entity-scoped one-shot bound to the target CServerSideClient*, then force-dirties the field via IBaseEntity.NetworkStateChanged (SchemaSystem.NetVarStateChanged -> Entity.SetStateChanged) so it re-transmits next snapshot even if the real value is unchanged. Fires once for that client, self-removes; other clients pass through. Rides the same per-client emit path. Adds SUBST-EMIT / SUBST-EMIT-DONE diagnostics (dst cursor delta confirms the fake bits land) and an sp_sendfake example command. Full RE writeup + morning test plan in docs/RE_PERCLIENT_EMIT.md. Not deployed; gamedata unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
P
Prefix committed
7635a191dbf20ed212964c46bb382ecf28cb7d37
Parent: 8e9e887