MP task #47: DISPROVE the Entity-layout root cause; correct the record

The prior commit (c78662a) filed cross-pod damage failure under a
"cross-TU Entity/EntityID layout divergence" (and the P5 base-region
audit). A compile-time offsetof probe injected into BOTH translation
units disproves that: game/reconstructed AND engine/MUNGA compute an
IDENTICAL Entity layout --

  sizeof(Entity)=444  offsetof(entityID)=380 (0x17C)
  offsetof(ownerID)=388  offsetof(simulationFlags)=32
  offsetof(Mech,entityID)=380  (Entity subobject at 0)

So Entity::Dispatch reads this->entityID at the SAME offset mech4's
GetEntityID() does -- there is no per-TU read difference, and the
logged 3:22 (mech4 candidate) vs 3:19 (engine Dispatch) cannot be one
object read two ways. Those lines were different objects/messages,
mis-correlated. The distinct, REAL P5 "base-region layout divergence"
(HARD_PROBLEMS.md) is about raw-offset stomps at this+0x2d4..0x2f0 --
far above entityID -- and is unrelated to #47.

Changes:
- Revert the committed BT_MP_NET engine diagnostics (ENTITY/EVENT/
  NTTMGR/RECEIVER/L4NET) to the clean a9c3e96 baseline -- those are
  the very instruments that produced the mis-correlated data.
- mech4 BT_MP_FORCE_DMG hook: dispatch via the real m->Dispatch(&td)
  path (no false id stamping); comment records the offsetof finding.
- context/multiplayer.md: layout-divergence RULED OUT; 3:22/3:19 marked
  unconfirmed; leading hypotheses reframed as H2 (wire host-relative
  (de)serialization) vs H3 (replicant id != master's registered key),
  to be distinguished by a 2-node run with per-message correlation.

Solo un-regressed (mech walks + targets, 0 faults). Cross-pod delivery
remains open, but the investigation is redirected off the wrong (large,
structural) layout-audit path onto the EntityID wire/id-assignment path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-09 12:09:50 -05:00
co-authored by Claude Fable 5
parent c78662a0f1
commit 04a2049ce2
7 changed files with 55 additions and 75 deletions
-7
View File
@@ -241,13 +241,6 @@ void
// If this is a replicant instance, reroute the message to the master
//-------------------------------------------------------------------
//
if (getenv("BT_MP_NET") && message->messageID != 6)
DEBUG_STREAM << "[mp-disp] Entity::Dispatch msgID=" << (int)message->messageID
<< " inst=" << (int)GetInstance()
<< (GetInstance() == ReplicantInstance ? " REPLICANT -> reroute to master"
: (IsValid() ? " master/valid -> local Receive" : " INVALID -> Post"))
<< "\n" << std::flush;
if (GetInstance() == ReplicantInstance)
{
application->SendMessage(
-5
View File
@@ -258,11 +258,6 @@ void
Event::Process()
{
Check(this);
// MP DIAGNOSTIC (task #47): a network-delivered TakeDamage (msgID 21) is
// carried by an event -- confirm it actually gets Processed (vs deferred).
if (messageToSend && messageToSend->messageID == 21 && getenv("BT_MP_NET"))
DEBUG_STREAM << "[mp-evt] Event::Process TakeDamage target="
<< (void*)targetReceiver.GetCurrent() << "\n" << std::flush;
targetReceiver.GetCurrent()->Receive(this);
}
-17
View File
@@ -130,23 +130,6 @@ void
Entity
*entity =
application->GetHostManager()->GetEntityPointer(message->entityID);
// MP DIAGNOSTIC (task #47, BT_MP_NET): log every incoming entity-manager
// message (a dispatched cross-pod message arrives here) + whether the
// target entity was found. msgID 6 (update records) filtered as noise.
if (getenv("BT_MP_NET") && message->messageID != 6)
DEBUG_STREAM << "[mp-recv] msgID=" << (int)message->messageID
<< " entityID=" << message->entityID
<< " len=" << (int)message->messageLength
<< (entity ? " ENTITY FOUND" : " NO ENTITY (remake?)")
<< (entity ? " ptr=" : "") << (entity ? (void*)entity : (void*)0)
<< (entity ? " classID=" : "") ;
if (getenv("BT_MP_NET") && message->messageID != 6 && entity)
DEBUG_STREAM << (int)entity->GetClassID()
<< ((int)entity->GetClassID() == 0xBB9 ? " (MECH) -> Post" : " (NOT MECH!) -> Post");
if (getenv("BT_MP_NET") && message->messageID != 6)
DEBUG_STREAM << "\n" << std::flush;
if (entity)
{
//
-6
View File
@@ -98,12 +98,6 @@ void
//
Receiver::SharedData *sharedData = GetSharedData();
Handler handler = sharedData->activeMessageHandlers->Find(what->messageID);
// MP DIAGNOSTIC (task #47): for a TakeDamage (msgID 21), report whether a
// handler is found on this receiver (the cross-pod delivery endpoint).
if (what->messageID == 21 && getenv("BT_MP_NET"))
DEBUG_STREAM << "[mp-recv2] Receive TakeDamage this=" << (void*)this
<< " handler=" << (handler != Receiver::NullHandler ? "FOUND" : "NULL")
<< "\n" << std::flush;
if (handler != Receiver::NullHandler)
{
(this->*handler)(what);
-8
View File
@@ -1140,14 +1140,6 @@ void L4NetworkManager::Send(
//Net_Common_Ptr->Buffer_Length = (short)SEND_BUFFER_SIZE(packet_size);
//send_packet_request->Socket_Ptr = l4host->GetNetworkSocket();
//NetNub::SendCommand();
// MP DIAGNOSTIC (task #47, BT_MP_NET): log every non-update send so a
// dispatched cross-pod message (e.g. TakeDamage) is visible on the wire.
// (Update records are msgID 6, ~144 bytes -- filtered out to cut noise.)
if (getenv("BT_MP_NET") && !(message->messageID == 6 && message->messageLength <= 160))
DEBUG_STREAM << "[mp-send] host=" << (long)host_ID << " client=" << (int)client
<< " msgID=" << (int)message->messageID
<< " len=" << (int)message->messageLength << "\n" << std::flush;
send(l4host->GetNetworkSocket(), (char *)my_temp_packet, packet_size, 0);
free(my_temp_packet);
// Check for errors and abort if there were any