diff options
| -rw-r--r-- | server/data.go | 36 | ||||
| -rw-r--r-- | server/level.go | 51 | ||||
| -rw-r--r-- | server/player.go | 3 | ||||
| -rw-r--r-- | server/server.go | 25 | ||||
| -rw-r--r-- | world/1787964105.tmp | 0 | ||||
| -rw-r--r-- | world/level/0.bin | bin | 18106 -> 0 bytes | |||
| -rw-r--r-- | world/player/Oivee.bin | bin | 30 -> 0 bytes | |||
| -rw-r--r-- | world/player/citrons.bin | bin | 30 -> 0 bytes | |||
| -rw-r--r-- | world/player/gideonnav.bin | bin | 30 -> 0 bytes |
9 files changed, 71 insertions, 44 deletions
diff --git a/server/data.go b/server/data.go index b7ed280..331ac38 100644 --- a/server/data.go +++ b/server/data.go @@ -2,7 +2,8 @@ package server import ( "os" - "encoding/binary" + "bufio" + "encoding/json" "git.citrons.xyz/metronode/phony" ) @@ -53,13 +54,14 @@ func (f atomicWriter) Close() error { } func saveDataFile[T any](from phony.Actor, name string, data T) { - f, err := createAtomic(from, "world/" + name + ".bin") + f, err := createAtomic(from, "world/" + name + ".json") if err != nil { dataManager.errHand.OnSaveError(from, err) return } defer f.Close() - err = binary.Write(f, binary.BigEndian, data) + enc := json.NewEncoder(f) + err = enc.Encode(data) if err != nil { dataManager.errHand.OnSaveError(from, err) } @@ -68,7 +70,14 @@ func saveDataFile[T any](from phony.Actor, name string, data T) { func loadDataFile[T any]( from phony.Actor, name string, reply func(data T, ok bool)) { dataManager.Act(from, func() { - f, err := os.Open("world/" + name + ".bin") + var ( + data T + f *os.File + err error + ) + defer from.Act(nil, func() {reply(data, err == nil)}) + + f, err = os.Open("world/" + name + ".json") if err != nil { if !os.IsNotExist(err) { dataManager.errHand.OnLoadError(&dataManager, err) @@ -76,12 +85,25 @@ func loadDataFile[T any]( return } defer f.Close() - var data T - err = binary.Read(f, binary.BigEndian, &data) + + dec := json.NewDecoder(f) + err = dec.Decode(&data) if err != nil { dataManager.errHand.OnLoadError(&dataManager, err) + return } - from.Act(nil, func() {reply(data, err == nil)}) }) } +func readDataField(rd *bufio.Reader, data any) error { + line, err := rd.ReadBytes('\n') + if err != nil { + return err + } + return json.Unmarshal(line, data) +} + +func writeDataField(wr *bufio.Writer, data any) error { + enc := json.NewEncoder(wr) + return enc.Encode(data) +} diff --git a/server/level.go b/server/level.go index 577d0dc..f36babe 100644 --- a/server/level.go +++ b/server/level.go @@ -5,6 +5,7 @@ import ( "os" "fmt" "bytes" + "bufio" "compress/gzip" "encoding/binary" "git.citrons.xyz/metronode/phony" @@ -63,25 +64,23 @@ func (l *level) load() { id := l.Id dataManager.Act(l, func() { f, err := os.Open(fmt.Sprintf("world/level/%d.bin", id)) - if l.OnLevelError(&dataManager, err) != nil { + if l.handleLoadError(err) != nil { return } defer f.Close() var ( + rd = bufio.NewReader(f) info levelInfo blocks []byte ) - err = binary.Read(f, binary.BigEndian, &info) - if l.OnLevelError(&dataManager, err) != nil { - return - } - z, err := gzip.NewReader(f) - if l.OnLevelError(&dataManager, err) != nil { + readDataField(rd, &info) + z, err := gzip.NewReader(rd) + if l.handleLoadError(err) != nil { return } z.Read(make([]byte, 4)) blocks, err = io.ReadAll(z) - if l.OnLevelError(&dataManager, err) != nil { + if l.handleLoadError(err) != nil { return } l.Act(&dataManager, func() { @@ -97,25 +96,34 @@ func (l *level) load() { } } -func (l *level) OnLevelError(from phony.Actor, err error) error { +func (l *level) handleLoadError(err error) error { if err == nil { return err } - l.Act(from, func() { + l.Act(&dataManager, func() { l.loadingState = levelUnloaded dataManager.errHand.OnLoadError(l, err) - errString := err.Error() + errString := "load level: " + err.Error() if os.IsNotExist(err) { errString = "level not found" } + l.LevelError(nil, errString) + }) + return err +} + +func (l *level) LevelError(from phony.Actor, err string) { + l.Act(from, func() { for player := range l.players { - player.OnLevelError(l, errString, l.levelInfo) + player.OnLevelError(l, err, l.levelInfo) } }) - return err } func (l *level) save(done func()) { + if done != nil { + defer dataManager.Act(nil, done) + } if l.loadingState != levelLoaded { return } @@ -127,20 +135,15 @@ func (l *level) save(done func()) { } defer f.Close() - err = binary.Write(f, binary.BigEndian, l.levelInfo) - if err != nil { - dataManager.errHand.OnSaveError(l, err) - return - } + wr := bufio.NewWriter(f) + writeDataField(wr, l.levelInfo) data := l.compressLevelData() - _, err = io.Copy(f, data) - if err != nil { + defer data.Close() + io.Copy(wr, data) + if wr.Flush() != nil { dataManager.errHand.OnSaveError(l, err) return } - if done != nil { - dataManager.Act(nil, done) - } } func (l *level) blockIndex(pos blockPos) int { @@ -155,7 +158,7 @@ func (l *level) getBlock(pos blockPos) blockType { return blockType(l.blocks[l.blockIndex(pos)]) } -func (l *level) compressLevelData() io.Reader { +func (l *level) compressLevelData() io.ReadCloser { rd, wr := io.Pipe() data := bytes.NewReader(bytes.Clone(l.blocks)) go func() { diff --git a/server/player.go b/server/player.go index bc6ee38..7f64c58 100644 --- a/server/player.go +++ b/server/player.go @@ -149,8 +149,9 @@ func (p *player) OnPlayerMessage(from *Server, name string, message string) { p.SendMessage(from, fmt.Sprintf("&7<&b%s&7>&f %s", name, message)) } -func (p *player) OnLevelData(from *level, info levelInfo, data io.Reader) { +func (p *player) OnLevelData(from *level, info levelInfo, data io.ReadCloser) { p.Act(from, func() { + defer data.Close() if from != p.level { return } diff --git a/server/server.go b/server/server.go index 13e06f6..8499301 100644 --- a/server/server.go +++ b/server/server.go @@ -6,7 +6,6 @@ import ( "log" "fmt" "time" - "binary" "os/signal" "git.citrons.xyz/metronode/classic" "git.citrons.xyz/metronode/phony" @@ -58,14 +57,12 @@ func NewServer(info ServerInfo) *Server { 128*blockSize, } } else { - f, err := os.Open("world/world.bin") - if err != nil { - log.Fatal(err) - } - err = binary.Read(f, binary.BigEndian, &s.worldState) - if err != nil { - log.Fatal("read world data: %s", err) - } + loaded := make(chan worldState, 1) + loadDataFile(s, "world", func(state worldState, ok bool) { + loaded <- state + }) + s.worldState = <-loaded + } return s } @@ -117,10 +114,13 @@ func (s *Server) stop() { ) checkSaved := func() { if savedLevels >= len(s.levels) && savedPlayers >= len(s.players) { - close(s.stopped) for client := range s.clients { client.Disconnect(s, "Shutting down...") } + saveDataFile(s, "world", s.worldState) + dataManager.Act(s, func() { + close(s.stopped) + }) } } for _, player := range s.players { @@ -143,6 +143,7 @@ func (s *Server) Stop(from phony.Actor) { func (s *Server) Save(from phony.Actor) { s.Act(from, func() { + saveDataFile(s, "world", s.worldState) for _, player := range s.players { player.Save(s, nil) } @@ -229,7 +230,7 @@ func (s *Server) NewPlayer( func (s *Server) getLevel(lvl levelId) *level { if s.levels[lvl] == nil { - s.levels[lvl] = loadLevel(s, lvl, lvl == s.spawnLevel) + s.levels[lvl] = loadLevel(s, lvl, lvl == s.SpawnLevel) } return s.levels[lvl] } @@ -247,7 +248,7 @@ func (s *Server) GetLevel( func (s *Server) SendToSpawn(from phony.Actor, pl *player) { s.Act(from, func() { - pl.ChangeLevel(s, s.spawnLevel, s.spawnPos) + pl.ChangeLevel(s, s.SpawnLevel, s.SpawnPos) }) } diff --git a/world/1787964105.tmp b/world/1787964105.tmp deleted file mode 100644 index e69de29..0000000 --- a/world/1787964105.tmp +++ /dev/null diff --git a/world/level/0.bin b/world/level/0.bin Binary files differdeleted file mode 100644 index b514ec1..0000000 --- a/world/level/0.bin +++ /dev/null diff --git a/world/player/Oivee.bin b/world/player/Oivee.bin Binary files differdeleted file mode 100644 index dc53ce7..0000000 --- a/world/player/Oivee.bin +++ /dev/null diff --git a/world/player/citrons.bin b/world/player/citrons.bin Binary files differdeleted file mode 100644 index cef1136..0000000 --- a/world/player/citrons.bin +++ /dev/null diff --git a/world/player/gideonnav.bin b/world/player/gideonnav.bin Binary files differdeleted file mode 100644 index bad50a1..0000000 --- a/world/player/gideonnav.bin +++ /dev/null |
