138 lines
4.5 KiB
Python
138 lines
4.5 KiB
Python
#!/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
|