From 8ae838cc2ff9396ff00779122ac8626751942efd Mon Sep 17 00:00:00 2001 From: Nicholas Novak <34256932+NickyBoy89@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:55:09 -0800 Subject: [PATCH] feat: Added in-memory server to the testing suite --- storage/inmemory_server.go | 104 +++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 storage/inmemory_server.go diff --git a/storage/inmemory_server.go b/storage/inmemory_server.go new file mode 100644 index 0000000..c2c9dab --- /dev/null +++ b/storage/inmemory_server.go @@ -0,0 +1,104 @@ +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) +}