#!/usr/bin/env python3 import numpy as np import Chunk import random from PerlinGenerator import PerlinGenerator from threading import Lock from typing import Tuple class WorldManager(object): def __init__(self, world_seed: int, raw_noise_cell_size: int, raw_noise_chunk_size: int): self.world_seed = world_seed # create Perlin Generator self.pg = PerlinGenerator(raw_noise_cell_size=raw_noise_cell_size, raw_noise_chunk_size=raw_noise_chunk_size, world_seed=world_seed) # dictionary of dictionaries of dictionaries --> 3D hasmap # (assume that's more efficient than using tuples as keys, # but future me should do further investigation into that [TODO!]) self.chunks = {} # will be a list with locked chunks self.chunk_locks = {} # 2Dimensional map. Will be 3D in future [TODO] self.perlin_maps = {} # create initial chunk # self.createEmptyChunk(0, 0, 0) # create lock object self.world_lock = Lock() def acquireChunk(self, chunk_x: int, chunk_y: int, chunk_z: int) -> bool: assert self.isChunkKnown(chunk_x, chunk_y, chunk_z) return self.chunk_locks[chunk_x][chunk_y][chunk_z].acquire() def releaseChunk(self, chunk_x: int, chunk_y: int, chunk_z: int) -> bool: assert self.isChunkKnown(chunk_x, chunk_y, chunk_z) lock = self.chunk_locks[chunk_x][chunk_y][chunk_z] assert lock.locked() return lock.release() def isChunkKnown(self, chunk_x: int, chunk_y: int, chunk_z: int) -> bool: # TODO: this should be done more efficient! self.world_lock.acquire() is_known = (chunk_x in self.chunks and chunk_y in self.chunks[chunk_x] and chunk_z in self.chunks[chunk_x][chunk_y]) self.world_lock.release() return is_known def createEmptyChunk(self, chunk_x: int, chunk_y: int, chunk_z: int) -> None: assert not self.isChunkKnown(chunk_x, chunk_y, chunk_z) self.world_lock.acquire() if chunk_x not in self.chunks: self.chunks[chunk_x] = {} self.chunk_locks[chunk_x] = {} if chunk_y not in self.chunks[chunk_x]: self.chunks[chunk_x][chunk_y] = {} self.chunk_locks[chunk_x][chunk_y] = {} self.chunks[chunk_x][chunk_y][chunk_z] = Chunk.Chunk( chunk_x, chunk_y, chunk_z) self.chunk_locks[chunk_x][chunk_y][chunk_z] = Lock() self.world_lock.release() def applyPerlinToChunk(self, chunk_x: int, chunk_y: int, chunk_z: int) -> None: pm = np.copy(self.getPerlinMap(chunk_x, chunk_z)) pm += 1 pm *= 16 # TODO, FIXME: not adjustable self.acquireChunk(chunk_x, chunk_y, chunk_z) c = self.chunks[chunk_x][chunk_y][chunk_z] for x in range(Chunk.Chunk.CHUNK_SIDELENGTH): for y in range(Chunk.Chunk.CHUNK_SIDELENGTH): for z in range(Chunk.Chunk.CHUNK_SIDELENGTH): c.block_data[x, y, z] = 1 if pm[x, z] > y + \ chunk_y*Chunk.Chunk.CHUNK_SIDELENGTH else 0 self.releaseChunk(chunk_x, chunk_y, chunk_z) def hasPerlinMap(self, chunk_x: int, chunk_z: int) -> bool: return (chunk_x in self.perlin_maps and chunk_z in self.perlin_maps[chunk_x]) def __createPerlinMap(self, chunk_x: int, chunk_z: int) -> None: pm = self.perlin_maps[chunk_x][chunk_z] = np.zeros( shape=(Chunk.Chunk.CHUNK_SIDELENGTH, Chunk.Chunk.CHUNK_SIDELENGTH), dtype=float) x0 = chunk_x * Chunk.Chunk.CHUNK_SIDELENGTH z0 = chunk_z * Chunk.Chunk.CHUNK_SIDELENGTH for i, j in np.ndindex(pm.shape): pm[i, j] = self.pg.perlin(i + x0, j + z0) def getPerlinMap(self, x: int, z: int): if x not in self.perlin_maps: self.perlin_maps[x] = {} if z in self.perlin_maps[x]: return self.perlin_maps[x][z] self.__createPerlinMap(x, z) return self.perlin_maps[x][z] def getChunkAsJson(self, chunk_x: int, chunk_y: int, chunk_z: int) -> str: assert self.isChunkKnown(chunk_x, chunk_y, chunk_z) self.acquireChunk(0, 0, 0) json = repr(self.chunks[chunk_x][chunk_y][chunk_z]) self.releaseChunk(0, 0, 0) return json