diff options
Diffstat (limited to 'server/level.go')
| -rw-r--r-- | server/level.go | 194 |
1 files changed, 97 insertions, 97 deletions
diff --git a/server/level.go b/server/level.go index 95f04ff..17f8eb8 100644 --- a/server/level.go +++ b/server/level.go @@ -4,15 +4,12 @@ import ( "io" "os" "fmt" - "bytes" + "math" "bufio" - "compress/gzip" - "encoding/binary" "git.citrons.xyz/metronode/phony" ) type levelId int32 -type blockType byte type levelPlayerId int8 type levelInfo struct { Id levelId @@ -25,7 +22,7 @@ type level struct { levelInfo loadingState int server *Server - blocks []byte + mapM *mapManager // is accessed without synchronization ids map[levelPlayerId]*player players map[*player]levelPlayerId } @@ -36,32 +33,30 @@ const ( levelLoaded ) -func newLevel(s *Server, info levelInfo) *level { +func initLevel(s *Server, info levelInfo) *level { return &level { levelInfo: info, server: s, - loadingState: levelLoading, - blocks: make([]byte, info.Size.X * info.Size.Y * info.Size.Z), + loadingState: levelUnloaded, + mapM: newMapManager(info.Size), ids: make(map[levelPlayerId]*player), players: make(map[*player]levelPlayerId), } } -func loadLevel(s *Server, id levelId, isSpawn bool) *level { - l := &level { - levelInfo: levelInfo {Id: id, IsSpawn: isSpawn}, - server: s, - ids: make(map[levelPlayerId]*player), - players: make(map[*player]levelPlayerId), - } - l.load() +func createNewLevel(s *Server, info levelInfo) *level { + l := initLevel(s, info) + l.loadingState = levelLoading return l } func (l *level) load() { if l.loadingState == levelUnloaded { l.loadingState = levelLoading - id := l.Id + var ( + id = l.Id + v = l.mapM.Blocks + ) dataManager.Act(l, func() { f, err := os.Open(fmt.Sprintf("world/level/%d.bin", id)) if l.handleLoadError(err) != nil { @@ -71,31 +66,34 @@ func (l *level) load() { var ( rd = bufio.NewReader(f) info levelInfo - blocks []byte ) readDataField(rd, &info) - z, err := gzip.NewReader(rd) - if l.handleLoadError(err) != nil { - return - } - z.Read(make([]byte, 4)) - blocks, err = io.ReadAll(z) + v.init(info.Size) + err = v.syncDecompressFromStorage(rd) if l.handleLoadError(err) != nil { return } l.Act(&dataManager, func() { - l.loadingState = levelLoaded l.levelInfo = info l.Id = id - l.blocks = blocks - for player := range l.players { - player.OnLevelData(l, l.levelInfo, l.compressLevelData()) - } + l.loadDone() }) }) } } +func (l *level) loadDone() { + if l.loadingState == levelLoaded { + return + } + l.loadingState = levelLoaded + for player := range l.players { + player.OnLevelData( + l, l.levelInfo, l.mapM.Blocks.syncCompressForNetwork(), + ) + } +} + func (l *level) handleLoadError(err error) error { if err == nil { return err @@ -133,87 +131,87 @@ func (l *level) save(done func()) { dataManager.errHand.OnSaveError(l, err) return } - defer f.Close() - - wr := bufio.NewWriter(f) - writeDataField(wr, l.levelInfo) - data := l.compressLevelData() - defer data.Close() - io.Copy(wr, data) - if wr.Flush() != nil { - dataManager.errHand.OnSaveError(l, err) - return - } -} - -func (l *level) blockIndex(pos blockPos) int { - return int(pos.X + pos.Z*l.Size.X + pos.Y*l.Size.X*l.Size.Z) -} - -func (l *level) setBlock(pos blockPos, block blockType) { - l.blocks[l.blockIndex(pos)] = byte(block) -} - -func (l *level) getBlock(pos blockPos) blockType { - return blockType(l.blocks[l.blockIndex(pos)]) -} - -func (l *level) compressLevelData() io.ReadCloser { - rd, wr := io.Pipe() - data := bytes.NewReader(bytes.Clone(l.blocks)) + data := l.mapM.Blocks.syncCompressForStorage() go func() { - defer wr.Close() - z := gzip.NewWriter(wr) - defer z.Close() - binary.Write(z, binary.BigEndian, uint32(len(l.blocks))) - io.Copy(z, data) + defer f.Close() + defer data.Close() + wr := bufio.NewWriter(f) + writeDataField(wr, l.levelInfo) + io.Copy(wr, data) + if wr.Flush() != nil { + dataManager.errHand.OnSaveError(l, err) + return + } }() - return rd } func (l *level) generateFlat() { - var p blockPos - for p.Z = 0; p.Z < l.levelInfo.Size.Z; p.Z++ { - for p.Y = 0; p.Y < l.levelInfo.Size.Y / 2; p.Y++ { - for p.X = 0; p.X < l.levelInfo.Size.X; p.X++ { - var block blockType - if p.Y == 0 { - block = 7 - } else if p.Y == l.levelInfo.Size.Y/2 - 1 { - block = 2 - } else if p.Y > l.levelInfo.Size.Y/2 - 15 { - block = 3 - } else { - block = 1 + v := l.mapM.Blocks + v.syncSetAll(func(yield func(blockType) bool) { + var p blockPos + for p.Y = 0; p.Y < v.size.Y / 2; p.Y++ { + for p.X = 0; p.X < v.size.X; p.X++ { + for p.Z = 0; p.Z < v.size.Z; p.Z++ { + var block blockType + if p.Y == 0 { + block = 7 + } else if p.Y == v.size.Y/2 - 1 { + block = 2 + } else if p.Y > v.size.Y/2 - 15 { + block = 3 + } else if p.Y < v.size.Y/2 { + block = 1 + } + if !yield(block) { + return + } } - l.setBlock(p, block) } } - } - l.save(nil) - l.loadingState = levelLoaded + }) + l.Act(nil, l.loadDone) } func (l *level) generateEmpty() { - l.save(nil) - l.loadingState = levelLoaded + l.Act(nil, l.loadDone) +} + +func (l *level) generateSphere() { + v := l.mapM.Blocks + v.syncSetAll(func(yield func(blockType) bool) { + var (p blockPos; radius = float64(v.size.X) / 2) + for p.Y = 0; p.Y < v.size.Y; p.Y++ { + for p.X = 0; p.X < v.size.X; p.X++ { + for p.Z = 0; p.Z < v.size.Z; p.Z++ { + var block blockType + dist := math.Sqrt( + float64(v.size.X/2 - p.X)*float64(v.size.X/2 - p.X) + + float64(v.size.Y/2 - p.Y)*float64(v.size.Y/2 - p.Y) + + float64(v.size.Z/2 - p.Z)*float64(v.size.Z/2 - p.Z), + ) + if dist > radius - 2 && dist <= radius { + block = 25 + } + if !yield(block) { + return + } + } + } + } + }) + l.Act(nil, l.loadDone) } func (l *level) generateDebug() { - if l.levelInfo.Size.X < 16 || l.levelInfo.Size.Z < 16 { - return - } - if l.levelInfo.Size.Y < 1 { - return - } - var p blockPos - for p.Z = 0; p.Z < 16; p.Z++ { - for p.X = 0; p.X < 16; p.X++ { - l.setBlock(p, blockType(p.X + p.Z * 16)) + v := l.mapM.Blocks + v.syncSetAll(func(yield func(blockType) bool) { + for i := 0; i < 256; i++ { + if !yield(blockType(i)) { + return + } } - } - l.save(nil) - l.loadingState = levelLoaded + }) + l.Act(nil, l.loadDone) } func (l *level) Save(from phony.Actor, done func()) { @@ -230,8 +228,8 @@ func (l *level) SetBlock(from phony.Actor, pos blockPos, block blockType) { if l.loadingState != levelLoaded { return } + l.mapM.SetBlock(from, pos, block) l.Act(from, func() { - l.setBlock(pos, block) for player := range l.players { player.OnSetBlock(l, pos, block) } @@ -242,7 +240,9 @@ func (l *level) OnAddPlayer(from *player, name string, pos entityPos) { l.Act(from, func() { l.load() if l.loadingState == levelLoaded { - from.OnLevelData(l, l.levelInfo, l.compressLevelData()) + from.OnLevelData( + l, l.levelInfo, l.mapM.Blocks.syncCompressForNetwork(), + ) } var newId levelPlayerId for newId = 0; newId <= 127; newId++ { |
