func (l *Loader) reset() {
	for pos := range l.loaded {
		l.w.removeViewer(pos, l.viewer)
	}
	l.loaded = map[ChunkPos]struct{}{}
	l.w.removeWorldViewer(l.viewer)
}
reset clears the Loader so that it may be used as if it was created again with NewLoader.
package world
import (
	"github.com/go-gl/mathgl/mgl64"
	"math"
	"sync"
)
type Loader struct {
	r      int
	w      *World
	viewer Viewer
	mu        sync.RWMutex
	pos       ChunkPos
	loadQueue []ChunkPos
	loaded    map[ChunkPos]struct{}
	closed bool
}
func NewLoader(chunkRadius int, world *World, v Viewer) *Loader {
	l := &Loader{r: chunkRadius, loaded: make(map[ChunkPos]struct{}), viewer: v}
	l.world(world)
	return l
}
func (l *Loader) World() *World {
	l.mu.RLock()
	w := l.w
	l.mu.RUnlock()
	return w
}
func (l *Loader) ChangeWorld(new *World) {
	l.mu.Lock()
	l.reset()
	l.world(new)
	l.mu.Unlock()
}
func (l *Loader) ChangeRadius(new int) {
	l.mu.Lock()
	l.r = new
	l.evictUnused()
	l.populateLoadQueue()
	l.mu.Unlock()
}
func (l *Loader) Move(pos mgl64.Vec3) {
	l.mu.Lock()
	floorX, floorZ := math.Floor(pos[0]), math.Floor(pos[2])
	chunkPos := ChunkPos{int32(floorX) >> 4, int32(floorZ) >> 4}
	if chunkPos == l.pos {
		l.mu.Unlock()
		return
	}
	l.pos = chunkPos
	l.evictUnused()
	l.populateLoadQueue()
	l.mu.Unlock()
}
func (l *Loader) Load(n int) error {
	if n == 0 {
		return nil
	}
	l.mu.Lock()
	if l.closed || l.w == nil {
		l.mu.Unlock()
		return nil
	}
	for i := 0; i < n; i++ {
		if len(l.loadQueue) == 0 {
			break
		}
		pos := l.loadQueue[0]
		c, err := l.w.chunk(pos)
		if err != nil {
			l.mu.Unlock()
			return err
		}
		l.viewer.ViewChunk(pos, c.Chunk, c.e)
		l.w.addViewer(c, l.viewer)
		l.loaded[pos] = struct{}{}
		l.loadQueue = l.loadQueue[1:]
	}
	l.mu.Unlock()
	return nil
}
func (l *Loader) Close() error {
	l.mu.Lock()
	l.reset()
	l.closed = true
	l.viewer = nil
	l.mu.Unlock()
	return nil
}