first commit
This commit is contained in:
150
internal/world/aoi_test.go
Normal file
150
internal/world/aoi_test.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package world
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"a301_game_server/internal/entity"
|
||||
"a301_game_server/pkg/mathutil"
|
||||
pb "a301_game_server/proto/gen/pb"
|
||||
)
|
||||
|
||||
// mockEntity is a minimal entity for testing.
|
||||
type mockEntity struct {
|
||||
id uint64
|
||||
pos mathutil.Vec3
|
||||
}
|
||||
|
||||
func (m *mockEntity) EntityID() uint64 { return m.id }
|
||||
func (m *mockEntity) EntityType() entity.Type { return entity.TypePlayer }
|
||||
func (m *mockEntity) Position() mathutil.Vec3 { return m.pos }
|
||||
func (m *mockEntity) SetPosition(p mathutil.Vec3) { m.pos = p }
|
||||
func (m *mockEntity) Rotation() float32 { return 0 }
|
||||
func (m *mockEntity) SetRotation(float32) {}
|
||||
func (m *mockEntity) ToProto() *pb.EntityState { return &pb.EntityState{EntityId: m.id} }
|
||||
|
||||
func TestBroadcastAllAOI_GetNearby(t *testing.T) {
|
||||
aoi := NewBroadcastAllAOI()
|
||||
|
||||
e1 := &mockEntity{id: 1, pos: mathutil.NewVec3(0, 0, 0)}
|
||||
e2 := &mockEntity{id: 2, pos: mathutil.NewVec3(100, 0, 100)}
|
||||
e3 := &mockEntity{id: 3, pos: mathutil.NewVec3(999, 0, 999)}
|
||||
|
||||
aoi.Add(e1)
|
||||
aoi.Add(e2)
|
||||
aoi.Add(e3)
|
||||
|
||||
// With broadcast-all, everyone sees everyone.
|
||||
nearby := aoi.GetNearby(e1)
|
||||
if len(nearby) != 2 {
|
||||
t.Errorf("expected 2 nearby, got %d", len(nearby))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBroadcastAllAOI_Remove(t *testing.T) {
|
||||
aoi := NewBroadcastAllAOI()
|
||||
|
||||
e1 := &mockEntity{id: 1}
|
||||
e2 := &mockEntity{id: 2}
|
||||
aoi.Add(e1)
|
||||
aoi.Add(e2)
|
||||
|
||||
events := aoi.Remove(e1)
|
||||
if len(events) != 1 {
|
||||
t.Errorf("expected 1 leave event, got %d", len(events))
|
||||
}
|
||||
if events[0].Type != AOILeave {
|
||||
t.Errorf("expected AOILeave event")
|
||||
}
|
||||
|
||||
nearby := aoi.GetNearby(e2)
|
||||
if len(nearby) != 0 {
|
||||
t.Errorf("expected 0 nearby after removal, got %d", len(nearby))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGridAOI_NearbyInSameCell(t *testing.T) {
|
||||
aoi := NewGridAOI(50, 2)
|
||||
|
||||
e1 := &mockEntity{id: 1, pos: mathutil.NewVec3(10, 0, 10)}
|
||||
e2 := &mockEntity{id: 2, pos: mathutil.NewVec3(20, 0, 20)}
|
||||
|
||||
aoi.Add(e1)
|
||||
aoi.Add(e2)
|
||||
|
||||
nearby := aoi.GetNearby(e1)
|
||||
if len(nearby) != 1 {
|
||||
t.Errorf("expected 1 nearby, got %d", len(nearby))
|
||||
}
|
||||
if nearby[0].EntityID() != 2 {
|
||||
t.Errorf("expected entity 2, got %d", nearby[0].EntityID())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGridAOI_FarAwayNotVisible(t *testing.T) {
|
||||
aoi := NewGridAOI(50, 1) // viewRange=1 means 3x3 grid = 150 units visibility
|
||||
|
||||
e1 := &mockEntity{id: 1, pos: mathutil.NewVec3(0, 0, 0)}
|
||||
e2 := &mockEntity{id: 2, pos: mathutil.NewVec3(500, 0, 500)} // far away
|
||||
|
||||
aoi.Add(e1)
|
||||
aoi.Add(e2)
|
||||
|
||||
nearby := aoi.GetNearby(e1)
|
||||
if len(nearby) != 0 {
|
||||
t.Errorf("expected 0 nearby for far entity, got %d", len(nearby))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGridAOI_MoveGeneratesEvents(t *testing.T) {
|
||||
aoi := NewGridAOI(50, 1)
|
||||
|
||||
e1 := &mockEntity{id: 1, pos: mathutil.NewVec3(0, 0, 0)}
|
||||
e2 := &mockEntity{id: 2, pos: mathutil.NewVec3(200, 0, 200)}
|
||||
|
||||
aoi.Add(e1)
|
||||
aoi.Add(e2)
|
||||
|
||||
// Initially not visible to each other.
|
||||
nearby := aoi.GetNearby(e1)
|
||||
if len(nearby) != 0 {
|
||||
t.Fatalf("expected not visible initially, got %d", len(nearby))
|
||||
}
|
||||
|
||||
// Move e2 close to e1.
|
||||
oldPos := e2.pos
|
||||
e2.pos = mathutil.NewVec3(10, 0, 10)
|
||||
events := aoi.UpdatePosition(e2, oldPos, e2.pos)
|
||||
|
||||
// Should generate enter events (e1 sees e2, e2 sees e1).
|
||||
enterCount := 0
|
||||
for _, evt := range events {
|
||||
if evt.Type == AOIEnter {
|
||||
enterCount++
|
||||
}
|
||||
}
|
||||
if enterCount != 2 {
|
||||
t.Errorf("expected 2 enter events, got %d", enterCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGridAOI_ToggleComparison(t *testing.T) {
|
||||
// Demonstrates the difference between BroadcastAll and Grid AOI.
|
||||
e1 := &mockEntity{id: 1, pos: mathutil.NewVec3(0, 0, 0)}
|
||||
e2 := &mockEntity{id: 2, pos: mathutil.NewVec3(500, 0, 500)}
|
||||
|
||||
// BroadcastAll: both visible
|
||||
broadcast := NewBroadcastAllAOI()
|
||||
broadcast.Add(e1)
|
||||
broadcast.Add(e2)
|
||||
if len(broadcast.GetNearby(e1)) != 1 {
|
||||
t.Error("broadcast-all should see all entities")
|
||||
}
|
||||
|
||||
// Grid: e2 not visible from e1 (too far)
|
||||
grid := NewGridAOI(50, 1)
|
||||
grid.Add(e1)
|
||||
grid.Add(e2)
|
||||
if len(grid.GetNearby(e1)) != 0 {
|
||||
t.Error("grid AOI should NOT see distant entities")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user