refactor: Moved the servers to their separate directories

This commit is contained in:
Nicholas Novak
2023-12-08 19:30:19 -08:00
parent 2f4303ddb8
commit df2a128e1b
4 changed files with 18 additions and 13 deletions

View File

@@ -1,86 +0,0 @@
package storage
import (
"encoding/json"
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
"git.nicholasnovak.io/nnovak/spatial-db/world"
)
type HashServer struct {
blocks map[world.BlockPos]world.BlockID
}
func (hs *HashServer) SetStorageRoot(path string) {
hs.blocks = make(map[world.BlockPos]world.BlockID)
chunkFiles, err := os.ReadDir(path)
if err != nil {
panic(err)
}
for chunkIndex, chunkFile := range chunkFiles {
var data world.ChunkData
log.Infof("Reading in chunk %d of %d", chunkIndex, len(chunkFiles))
f, err := os.Open(filepath.Join(path, chunkFile.Name()))
if err != nil {
panic(err)
}
// Read each file from disk
if err := json.NewDecoder(f).Decode(&data); err != nil {
panic(err)
}
// Load in each data point from disk
for _, section := range data.Sections {
for blockIndex, blockState := range section.BlockStates {
pos := data.IndexToBlockPos(blockIndex)
hs.blocks[pos] = blockState
}
}
f.Close()
}
}
func (hs *HashServer) FetchChunk(pos world.ChunkPos) (world.ChunkData, error) {
panic("Unimplemented")
}
func (hs *HashServer) ChangeBlock(
worldPosition world.BlockPos,
targetState world.BlockID,
) error {
hs.blocks[worldPosition] = targetState
return nil
}
func (hs *HashServer) ChangeBlockRange(
targetState world.BlockID,
start, end world.BlockPos,
) error {
panic("Unimplemented")
}
func (hs *HashServer) ReadBlockAt(pos world.BlockPos) (world.BlockID, error) {
return hs.blocks[pos], nil
}
func (hs *HashServer) ReadChunkAt(pos world.ChunkPos) (world.ChunkData, error) {
var data world.ChunkData
data.Pos = pos
for blockPos, state := range hs.blocks {
if blockPos.ToChunkPos() == pos {
sec := data.SectionFor(blockPos)
sec.UpdateBlock(blockPos, state)
}
}
return data, nil
}

View File

@@ -1,104 +0,0 @@
package storage
import (
"errors"
"io/fs"
"os"
"path/filepath"
"strings"
"git.nicholasnovak.io/nnovak/spatial-db/world"
)
type InMemoryServer struct {
StorageDir string
Chunks map[world.ChunkPos]world.ChunkData
}
func (s *InMemoryServer) SetStorageRoot(path string) {
s.StorageDir = path
chunkFiles, err := os.ReadDir(s.StorageDir)
if err != nil {
panic(err)
}
s.Chunks = make(map[world.ChunkPos]world.ChunkData)
for _, chunkFile := range chunkFiles {
if chunkFile.IsDir() || !strings.HasSuffix(chunkFile.Name(), ".chunk") {
continue
}
file, err := os.Open(filepath.Join(s.StorageDir, chunkFile.Name()))
if err != nil {
panic(err)
}
chunkData, err := ReadChunkFromFile(file)
if err != nil {
panic(err)
}
file.Close()
s.Chunks[chunkData.Pos] = chunkData
}
}
func (s *InMemoryServer) FetchOrCreateChunk(pos world.ChunkPos) (world.ChunkData, error) {
return s.Chunks[pos], nil
}
func (s *InMemoryServer) FetchChunk(pos world.ChunkPos) (world.ChunkData, error) {
chunkFileName := filepath.Join(s.StorageDir, pos.ToFileName())
var chunkData world.ChunkData
chunkFile, err := os.Open(chunkFileName)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return chunkData, ChunkNotFoundError
} else {
return chunkData, err
}
}
defer chunkFile.Close()
return ReadChunkFromFile(chunkFile)
}
// Voxel server implementation
func (s *InMemoryServer) ChangeBlock(
worldPosition world.BlockPos,
targetState world.BlockID,
) error {
chunk, err := s.FetchOrCreateChunk(worldPosition.ToChunkPos())
if err != nil {
return err
}
chunk.SectionFor(worldPosition).UpdateBlock(worldPosition, targetState)
return nil
}
func (s *InMemoryServer) ChangeBlockRange(
targetState world.BlockID,
start, end world.BlockPos,
) error {
panic("ChangeBlockRange is unimplemented")
}
func (s *InMemoryServer) ReadBlockAt(pos world.BlockPos) (world.BlockID, error) {
chunk, err := s.FetchOrCreateChunk(pos.ToChunkPos())
if err != nil {
return world.Empty, err
}
return chunk.SectionFor(pos).FetchBlock(pos), nil
}
func (s *InMemoryServer) ReadChunkAt(pos world.ChunkPos) (world.ChunkData, error) {
return s.FetchOrCreateChunk(pos)
}

View File

@@ -1,114 +0,0 @@
package storage
import (
"encoding/json"
"errors"
"io/fs"
"os"
"path/filepath"
"git.nicholasnovak.io/nnovak/spatial-db/world"
)
const fileCacheSize = 8
var (
ChunkNotFoundError = errors.New("chunk was not found in storage")
)
type SimpleServer struct {
StorageDir string
cache FileCache
}
func (s *SimpleServer) SetStorageRoot(path string) {
s.StorageDir = path
s.cache = NewFileCache(256)
}
// Filesystem operations
func (s *SimpleServer) FetchOrCreateChunk(pos world.ChunkPos) (world.ChunkData, error) {
chunkFileName := filepath.Join(s.StorageDir, pos.ToFileName())
var chunkData world.ChunkData
chunkFile, err := os.Open(chunkFileName)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// There was no chunk that exists, create a blank one
chunkFile, err = os.Create(chunkFileName)
if err != nil {
return chunkData, err
}
// Initilize the file with some blank data
if err := json.NewEncoder(chunkFile).Encode(chunkData); err != nil {
return chunkData, err
}
if _, err := chunkFile.Seek(0, 0); err != nil {
return chunkData, err
}
} else {
return chunkData, err
}
}
defer chunkFile.Close()
return ReadChunkFromFile(chunkFile)
}
// `FetchChunk' fetches the chunk's data, given the chunk's position
func (s *SimpleServer) FetchChunk(pos world.ChunkPos) (world.ChunkData, error) {
chunkFileName := filepath.Join(s.StorageDir, pos.ToFileName())
var chunkData world.ChunkData
chunkFile, err := s.cache.FetchFile(chunkFileName)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return chunkData, ChunkNotFoundError
} else {
return chunkData, err
}
}
return ReadChunkFromFile(chunkFile)
}
// Voxel server implementation
func (s *SimpleServer) ChangeBlock(
worldPosition world.BlockPos,
targetState world.BlockID,
) error {
chunk, err := s.FetchOrCreateChunk(worldPosition.ToChunkPos())
if err != nil {
return err
}
chunk.SectionFor(worldPosition).UpdateBlock(worldPosition, targetState)
return nil
}
func (s *SimpleServer) ChangeBlockRange(
targetState world.BlockID,
start, end world.BlockPos,
) error {
panic("ChangeBlockRange is unimplemented")
}
func (s *SimpleServer) ReadBlockAt(pos world.BlockPos) (world.BlockID, error) {
chunk, err := s.FetchChunk(pos.ToChunkPos())
if err != nil {
return world.Empty, err
}
return chunk.SectionFor(pos).FetchBlock(pos), nil
}
func (s *SimpleServer) ReadChunkAt(pos world.ChunkPos) (world.ChunkData, error) {
return s.FetchOrCreateChunk(pos)
}

View File

@@ -1,6 +1,10 @@
package storage
import "git.nicholasnovak.io/nnovak/spatial-db/world"
import (
"errors"
"git.nicholasnovak.io/nnovak/spatial-db/world"
)
type StorageServer interface {
// Individual operations
@@ -16,3 +20,7 @@ type StorageServer interface {
// Network-level operations
ReadChunkAt(pos world.ChunkPos) error
}
var (
ChunkNotFoundError = errors.New("chunk was not found in storage")
)