VoxelServer/ServerCore/WorldManager.py

138 lines
4.5 KiB
Python
Raw Permalink Normal View History

2018-10-17 23:13:32 +02:00
#!/usr/bin/env python3
import numpy as np
import Chunk
2018-10-20 09:59:53 +02:00
import random
from PerlinGenerator import PerlinGenerator
2018-11-27 12:49:50 +01:00
from threading import Lock
2018-10-17 23:13:32 +02:00
2018-10-20 09:59:53 +02:00
from typing import Tuple
2018-10-17 23:13:32 +02:00
2018-11-24 16:19:29 +01:00
2018-10-17 23:13:32 +02:00
class WorldManager(object):
2018-11-27 12:49:50 +01:00
def __init__(self, world_seed: int,
raw_noise_cell_size: int,
raw_noise_chunk_size: int):
2018-10-17 23:13:32 +02:00
self.world_seed = world_seed
2018-10-20 09:59:53 +02:00
# create Perlin Generator
2018-11-24 16:19:29 +01:00
self.pg = PerlinGenerator(raw_noise_cell_size=raw_noise_cell_size,
2018-11-27 12:49:50 +01:00
raw_noise_chunk_size=raw_noise_chunk_size,
world_seed=world_seed)
2018-10-20 09:59:53 +02:00
2018-11-27 12:49:50 +01:00
# dictionary of dictionaries of dictionaries --> 3D hasmap
# (assume that's more efficient than using tuples as keys,
2018-10-17 23:13:32 +02:00
# but future me should do further investigation into that [TODO!])
2018-11-24 16:19:29 +01:00
self.chunks = {}
2018-10-17 23:13:32 +02:00
2018-11-27 12:49:50 +01:00
# will be a list with locked chunks
self.chunk_locks = {}
2018-10-20 09:59:53 +02:00
# 2Dimensional map. Will be 3D in future [TODO]
self.perlin_maps = {}
2018-10-17 23:13:32 +02:00
# create initial chunk
2018-11-27 16:21:31 +01:00
# self.createEmptyChunk(0, 0, 0)
2018-11-24 16:19:29 +01:00
2018-11-27 12:49:50 +01:00
# 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()
2018-11-24 16:19:29 +01:00
def isChunkKnown(self, chunk_x: int, chunk_y: int, chunk_z: int) -> bool:
2018-10-17 23:13:32 +02:00
# TODO: this should be done more efficient!
2018-11-29 00:07:05 +01:00
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
2018-11-27 12:49:50 +01:00
def createEmptyChunk(self,
chunk_x: int,
chunk_y: int,
chunk_z: int) -> None:
2018-11-24 16:19:29 +01:00
2018-11-27 12:49:50 +01:00
assert not self.isChunkKnown(chunk_x, chunk_y, chunk_z)
2018-10-17 23:13:32 +02:00
2018-11-29 00:07:05 +01:00
self.world_lock.acquire()
2018-11-27 12:49:50 +01:00
if chunk_x not in self.chunks:
2018-10-20 09:59:53 +02:00
self.chunks[chunk_x] = {}
2018-11-27 12:49:50 +01:00
self.chunk_locks[chunk_x] = {}
2018-11-24 16:19:29 +01:00
2018-11-27 12:49:50 +01:00
if chunk_y not in self.chunks[chunk_x]:
2018-10-20 09:59:53 +02:00
self.chunks[chunk_x][chunk_y] = {}
2018-11-27 12:49:50 +01:00
self.chunk_locks[chunk_x][chunk_y] = {}
2018-11-24 16:19:29 +01:00
self.chunks[chunk_x][chunk_y][chunk_z] = Chunk.Chunk(
chunk_x, chunk_y, chunk_z)
2018-11-27 12:49:50 +01:00
self.chunk_locks[chunk_x][chunk_y][chunk_z] = Lock()
2018-11-29 00:07:05 +01:00
self.world_lock.release()
2018-11-27 12:49:50 +01:00
def applyPerlinToChunk(self,
chunk_x: int,
chunk_y: int,
chunk_z: int) -> None:
2018-10-23 23:29:26 +02:00
pm = np.copy(self.getPerlinMap(chunk_x, chunk_z))
pm += 1
2018-11-29 00:07:05 +01:00
pm *= 16 # TODO, FIXME: not adjustable
2018-10-23 23:29:26 +02:00
2018-11-27 12:49:50 +01:00
self.acquireChunk(chunk_x, chunk_y, chunk_z)
c = self.chunks[chunk_x][chunk_y][chunk_z]
2018-10-23 23:29:26 +02:00
for x in range(Chunk.Chunk.CHUNK_SIDELENGTH):
for y in range(Chunk.Chunk.CHUNK_SIDELENGTH):
for z in range(Chunk.Chunk.CHUNK_SIDELENGTH):
2018-11-24 16:19:29 +01:00
c.block_data[x, y, z] = 1 if pm[x, z] > y + \
chunk_y*Chunk.Chunk.CHUNK_SIDELENGTH else 0
2018-11-27 12:49:50 +01:00
self.releaseChunk(chunk_x, chunk_y, chunk_z)
2018-11-24 16:19:29 +01:00
def hasPerlinMap(self, chunk_x: int, chunk_z: int) -> bool:
2018-11-27 12:49:50 +01:00
return (chunk_x in self.perlin_maps and
chunk_z in self.perlin_maps[chunk_x])
2018-10-20 09:59:53 +02:00
2018-11-24 16:19:29 +01:00
def __createPerlinMap(self, chunk_x: int, chunk_z: int) -> None:
pm = self.perlin_maps[chunk_x][chunk_z] = np.zeros(
2018-11-27 12:49:50 +01:00
shape=(Chunk.Chunk.CHUNK_SIDELENGTH, Chunk.Chunk.CHUNK_SIDELENGTH),
dtype=float)
2018-10-20 09:59:53 +02:00
2018-11-27 12:49:50 +01:00
x0 = chunk_x * Chunk.Chunk.CHUNK_SIDELENGTH
z0 = chunk_z * Chunk.Chunk.CHUNK_SIDELENGTH
2018-11-24 16:19:29 +01:00
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):
2018-11-27 12:49:50 +01:00
if x not in self.perlin_maps:
2018-10-20 09:59:53 +02:00
self.perlin_maps[x] = {}
2018-11-24 16:19:29 +01:00
2018-10-20 09:59:53 +02:00
if z in self.perlin_maps[x]:
return self.perlin_maps[x][z]
2018-10-17 23:13:32 +02:00
2018-11-24 16:19:29 +01:00
self.__createPerlinMap(x, z)
2018-10-17 23:13:32 +02:00
2018-11-24 16:19:29 +01:00
return self.perlin_maps[x][z]
2018-11-27 16:21:31 +01:00
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