Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions pkg/plugin/physics2d/component/active_contacts.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package component

import "github.com/argus-labs/world-engine/pkg/cardinal"

// PhysicsSingletonTag marks the single entity that holds physics plugin state (ActiveContacts).
type PhysicsSingletonTag struct{}

Expand All @@ -8,11 +10,11 @@ func (PhysicsSingletonTag) Name() string { return "physics_singleton_tag" }
// ContactPairEntry is one active contact pair tracked by the physics engine. Entries are
// normalized: EntityA < EntityB (or if equal, ShapeIndexA <= ShapeIndexB).
type ContactPairEntry struct {
EntityA uint64 `json:"a"`
ShapeIndexA int `json:"sa"`
EntityB uint64 `json:"b"`
ShapeIndexB int `json:"sb"`
IsSensor bool `json:"sensor"`
EntityA cardinal.EntityID `json:"a"`
ShapeIndexA int `json:"sa"`
EntityB cardinal.EntityID `json:"b"`
ShapeIndexB int `json:"sb"`
IsSensor bool `json:"sensor"`
// Fixture filters for normalized EntityA/B (recovery End / trigger vs contact routing).
// Omitempty keeps older snapshots valid.
FilterACategoryBits uint64 `json:"fa_cat,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions pkg/plugin/physics2d/internal/contact_flush.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ func lessBufferedContactEvent(a, b BufferedContactEvent) bool {
return a.Kind < b.Kind
}
return lessContactPairByEndpoints(
uint64(a.EntityA), a.ShapeIndexA, uint64(a.EntityB), a.ShapeIndexB,
uint64(b.EntityA), b.ShapeIndexA, uint64(b.EntityB), b.ShapeIndexB,
a.EntityA, a.ShapeIndexA, a.EntityB, a.ShapeIndexB,
b.EntityA, b.ShapeIndexA, b.EntityB, b.ShapeIndexB,
)
}

Expand Down
27 changes: 6 additions & 21 deletions pkg/plugin/physics2d/internal/runtime.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package internal

import (
"math"
"sort"

"github.com/argus-labs/world-engine/pkg/cardinal"
Expand Down Expand Up @@ -125,15 +124,10 @@ func (rt *PhysicsRuntime) PruneActiveContactsInvolvingEntity(entityID cardinal.E
func (rt *PhysicsRuntime) LoadActiveContactsFromComponent(ac component.ActiveContacts) {
rt.ActiveContacts = make(map[ContactPairKey]ContactPairInfo, len(ac.Pairs))
for _, p := range ac.Pairs {
entityA, okA := entityIDFromUint64(p.EntityA)
entityB, okB := entityIDFromUint64(p.EntityB)
if !okA || !okB {
continue
}
key := ContactPairKey{
EntityA: entityA,
EntityA: p.EntityA,
ShapeIndexA: p.ShapeIndexA,
EntityB: entityB,
EntityB: p.EntityB,
ShapeIndexB: p.ShapeIndexB,
}
rt.ActiveContacts[key] = ContactPairInfo{
Expand All @@ -153,15 +147,6 @@ func (rt *PhysicsRuntime) LoadActiveContactsFromComponent(ac component.ActiveCon
rt.ActiveContactsDirty = false
}

// entityIDFromUint64 maps persisted wire format (uint64) to cardinal.EntityID (uint32).
// Oversized values are rejected so corrupt snapshots cannot truncate silently.
func entityIDFromUint64(u uint64) (cardinal.EntityID, bool) {
if u > math.MaxUint32 {
return 0, false
}
return cardinal.EntityID(uint32(u)), true
}

// ActiveContactsToComponent converts the working map to the ECS component format (sorted
// slice for deterministic snapshots).
func (rt *PhysicsRuntime) ActiveContactsToComponent() component.ActiveContacts {
Expand All @@ -171,9 +156,9 @@ func (rt *PhysicsRuntime) ActiveContactsToComponent() component.ActiveContacts {
pairs := make([]component.ContactPairEntry, 0, len(rt.ActiveContacts))
for key, info := range rt.ActiveContacts {
pairs = append(pairs, component.ContactPairEntry{
EntityA: uint64(key.EntityA),
EntityA: key.EntityA,
ShapeIndexA: key.ShapeIndexA,
EntityB: uint64(key.EntityB),
EntityB: key.EntityB,
ShapeIndexB: key.ShapeIndexB,
IsSensor: info.IsSensor,
FilterACategoryBits: info.FilterA.CategoryBits,
Expand Down Expand Up @@ -208,8 +193,8 @@ func lessContactPairEntry(a, b component.ContactPairEntry) bool {

// lessContactPairByEndpoints compares (entityA, shapeIndexA, entityB, shapeIndexB) lexicographically.
func lessContactPairByEndpoints(
aEA uint64, aSA int, aEB uint64, aSB int,
bEA uint64, bSA int, bEB uint64, bSB int,
aEA cardinal.EntityID, aSA int, aEB cardinal.EntityID, aSB int,
bEA cardinal.EntityID, bSA int, bEB cardinal.EntityID, bSB int,
) bool {
if aEA != bEA {
return aEA < bEA
Expand Down
Loading