151 lines
3.8 KiB
Go
151 lines
3.8 KiB
Go
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")
|
|
}
|
|
}
|