* refactor(config): replace singleton with dependency injection
* refactor(client_player): return ChunkPosSet by value in non-const getter
Copy the internal set under the mutex lock to avoid exposing a mutable reference that could be used unsafely after the lock is released. This fixes a potential data race when the caller holds the returned reference beyond the critical section. Also update the caller in `client_world` to remove the now-unnecessary `std::move`.
* fix(gameplay): prevent use-after-free in pending delete queues during destruction
* refactor(config): separate game and server configuration with explicit paths
* refactor(render): move render files to subdirectory, add RAII vertex buffer/array classes
* refactor(render): encapsulate OpenGL textures into Texture class
* refactor(texture): encapsulate textures with unique_ptr and bind methods
Replace raw GLuint framebuffer textures with std::unique_ptr<Texture>. Update TextureManager to return const Texture* instead of GLuint. Use Texture::bind() for active texture binding. Add RGBA16F and RGB formats. Add texture parameter methods. Update destructors accordingly.
* refactor(render): use Texture, VertexBuffer, VertexArray classes
* feat(render): add FrameBuffer class to encapsulate framebuffer operations
* refactor(render): extract world rendering into WorldRenderer class
* refactor(render): rename projection and model matrix members for clarity
* chore(render): remove unused matrix members
* fix(texture-manager): correct delet_texture typo and add null checks for textures