Skip to content

Commit

Permalink
world/world.go: Introduce a Save() method for saving worlds at runtime (
Browse files Browse the repository at this point in the history
  • Loading branch information
cqdetdev authored Aug 15, 2024
1 parent ae88a9c commit b186364
Showing 1 changed file with 29 additions and 10 deletions.
39 changes: 29 additions & 10 deletions server/world/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package world

import (
"errors"
"github.com/df-mc/goleveldb/leveldb"
"math/rand"
"sync"
"time"

"github.com/df-mc/goleveldb/leveldb"

"slices"

"github.com/df-mc/atomic"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/event"
Expand All @@ -15,7 +18,6 @@ import (
"github.com/go-gl/mathgl/mgl64"
"github.com/google/uuid"
"golang.org/x/exp/maps"
"slices"
)

// World implements a Minecraft world. It manages all aspects of what players can see, such as blocks,
Expand Down Expand Up @@ -1016,6 +1018,19 @@ func (w *World) PortalDestination(dim Dimension) *World {
return w
}

// Save saves the World to the provider.
func (w *World) Save() {
w.conf.Log.Debugf("Saving chunks in memory to disk...")

w.chunkMu.Lock()
toSave := maps.Clone(w.chunks)
w.chunkMu.Unlock()

for pos, c := range toSave {
w.saveChunk(pos, c, false)
}
}

// Close closes the world and saves all chunks currently loaded.
func (w *World) Close() error {
if w == nil {
Expand Down Expand Up @@ -1043,7 +1058,7 @@ func (w *World) close() {
w.chunkMu.Unlock()

for pos, c := range toSave {
w.saveChunk(pos, c)
w.saveChunk(pos, c, true)
}

w.set.ref.Dec()
Expand Down Expand Up @@ -1313,20 +1328,24 @@ func (w *World) spreadLight(pos ChunkPos) {

// saveChunk is called when a chunk is removed from the cache. We first compact the chunk, then we write it to
// the provider.
func (w *World) saveChunk(pos ChunkPos, c *Column) {
func (w *World) saveChunk(pos ChunkPos, c *Column, closeEntities bool) {
c.Lock()
if !w.conf.ReadOnly && c.modified {
c.Compact()
if err := w.provider().StoreColumn(pos, w.conf.Dim, c); err != nil {
w.conf.Log.Errorf("save chunk: %v", err)
}
}
ent := c.Entities
c.Entities = nil
c.Unlock()
if closeEntities {
ent := c.Entities
c.Entities = nil
c.Unlock()

for _, e := range ent {
_ = e.Close()
for _, e := range ent {
_ = e.Close()
}
} else {
c.Unlock()
}
}

Expand Down Expand Up @@ -1356,7 +1375,7 @@ func (w *World) chunkCacheJanitor() {
w.chunkMu.Unlock()

for pos, c := range chunksToRemove {
w.saveChunk(pos, c)
w.saveChunk(pos, c, true)
delete(chunksToRemove, pos)
}
case <-w.closing:
Expand Down

0 comments on commit b186364

Please sign in to comment.