diff --git a/pkg/rove/world.go b/pkg/rove/world.go index 7e22323..dc163f3 100644 --- a/pkg/rove/world.go +++ b/pkg/rove/world.go @@ -63,7 +63,7 @@ func NewWorld(chunkSize int) *World { } } -// SpawnRover adds an rover to the game +// SpawnRover adds an rover to the game (without lock) func (w *World) SpawnRover(account string) (string, error) { w.worldMutex.Lock() defer w.worldMutex.Unlock() @@ -181,12 +181,26 @@ func (w *World) DestroyRover(rover string) error { w.worldMutex.Lock() defer w.worldMutex.Unlock() - _, ok := w.Rovers[rover] + r, ok := w.Rovers[rover] if !ok { return fmt.Errorf("no rover matching id") } + // Remove this rover from tracked rovers delete(w.Rovers, rover) + + r.Owner = "" + r.AddLogEntryf("rover destroyed") + + // Marshal the rover data + data, err := json.Marshal(r) + if err != nil { + return err + } + + // Place the dormant rover down + w.Atlas.SetObject(r.Pos, Object{Type: roveapi.Object_RoverDormant, Data: data}) + return nil } @@ -276,9 +290,6 @@ func (w *World) TryMoveRover(rover string, b roveapi.Bearing) (maths.Vector, err i.AddLogEntryf("tried to move %s to %+v", b.String(), newPos) i.Integrity = i.Integrity - 1 i.AddLogEntryf("had a collision, new integrity %d", i.Integrity) - // TODO: The rover needs to be left dormant with the player - //if i.Integrity == 0 { - //} } return i.Pos, nil @@ -669,6 +680,25 @@ func (w *World) Tick() { } } + // Check all rover integrities + for _, r := range w.Rovers { + if r.Integrity <= 0 { + // The rover has died destroy it + err := w.DestroyRover(r.Name) + if err != nil { + log.Println(err) + // TODO: Report this error somehow + } + + // Spawn a new one for this account + _, err = w.SpawnRover(r.Owner) + if err != nil { + log.Println(err) + // TODO: Report this error somehow + } + } + } + // Increment the current tick count w.CurrentTicks++ diff --git a/pkg/rove/world_test.go b/pkg/rove/world_test.go index 747a891..afc8f53 100644 --- a/pkg/rove/world_test.go +++ b/pkg/rove/world_test.go @@ -130,7 +130,9 @@ func TestWorld_RadarFromRover(t *testing.T) { func TestWorld_RoverDamage(t *testing.T) { world := NewWorld(2) - a, err := world.SpawnRover("") + acc, err := world.Accountant.RegisterAccount("tmp") + assert.NoError(t, err) + a, err := world.SpawnRover(acc.Name) assert.NoError(t, err) pos := maths.Vector{ @@ -155,6 +157,23 @@ func TestWorld_RoverDamage(t *testing.T) { assert.NoError(t, err, "couldn't get rover info") assert.Equal(t, info.Integrity-1, newinfo.Integrity, "rover should have lost integrity") assert.Contains(t, newinfo.Logs[len(newinfo.Logs)-1].Text, "collision", "Rover logs should contain the collision") + + // Keep moving to damage the rover + for i := 0; i < info.Integrity-1; i++ { + vec, err := world.TryMoveRover(a, roveapi.Bearing_North) + assert.NoError(t, err, "Failed to move rover") + assert.Equal(t, pos, vec, "Rover managed to move into large rock") + } + + // Tick the world to check for rover deaths + world.Tick() + + // Rover should have been destroyed now + _, err = world.GetRover(a) + assert.Error(t, err) + + _, obj := world.Atlas.QueryPosition(info.Pos) + assert.Equal(t, roveapi.Object_RoverDormant, obj.Type) } func TestWorld_Daytime(t *testing.T) {