feat: Added in-memory server to the testing suite
This commit is contained in:
		
							
								
								
									
										104
									
								
								storage/inmemory_server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								storage/inmemory_server.go
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user