minecraft-python / world.py
Minecraft3193092's picture
Upload 15 files
f92c150
import math
import random
import save
import chunk
import block_type
import texture_manager
# import custom block models
import models
class World:
def __init__(self):
self.texture_manager = texture_manager.Texture_manager(16, 16, 256)
self.block_types = [None]
# parse block type data file
blocks_data_file = open("data/blocks.mcpy")
blocks_data = blocks_data_file.readlines()
blocks_data_file.close()
for block in blocks_data:
if block[0] in ['\n', '#']: # skip if empty line or comment
continue
number, props = block.split(':', 1)
number = int(number)
# default block
name = "Unknown"
model = models.cube
texture = {"all": "unknown"}
# read properties
for prop in props.split(','):
prop = prop.strip()
prop = list(filter(None, prop.split(' ', 1)))
if prop[0] == "sameas":
sameas_number = int(prop[1])
name = self.block_types[sameas_number].name
texture = self.block_types[sameas_number].block_face_textures
model = self.block_types[sameas_number].model
elif prop[0] == "name":
name = eval(prop[1])
elif prop[0][:7] == "texture":
_, side = prop[0].split('.')
texture[side] = prop[1].strip()
elif prop[0] == "model":
model = eval(prop[1])
# add block type
_block_type = block_type.Block_type(self.texture_manager, name, texture, model)
if number < len(self.block_types):
self.block_types[number] = _block_type
else:
self.block_types.append(_block_type)
self.texture_manager.generate_mipmaps()
# load the world
self.save = save.Save(self)
self.chunks = {}
self.save.load()
for chunk_position in self.chunks:
self.chunks[chunk_position].update_subchunk_meshes()
self.chunks[chunk_position].update_mesh()
def get_chunk_position(self, position):
x, y, z = position
return (
math.floor(x / chunk.CHUNK_WIDTH),
math.floor(y / chunk.CHUNK_HEIGHT),
math.floor(z / chunk.CHUNK_LENGTH))
def get_local_position(self, position):
x, y, z = position
return (
int(x % chunk.CHUNK_WIDTH),
int(y % chunk.CHUNK_HEIGHT),
int(z % chunk.CHUNK_LENGTH))
def get_block_number(self, position):
x, y, z = position
chunk_position = self.get_chunk_position(position)
if not chunk_position in self.chunks:
return 0
lx, ly, lz = self.get_local_position(position)
block_number = self.chunks[chunk_position].blocks[lx][ly][lz]
return block_number
def is_opaque_block(self, position):
# get block type and check if it's opaque or not
# air counts as a transparent block, so test for that too
block_type = self.block_types[self.get_block_number(position)]
if not block_type:
return False
return not block_type.transparent
def set_block(self, position, number): # set number to 0 (air) to remove block
x, y, z = position
chunk_position = self.get_chunk_position(position)
if not chunk_position in self.chunks: # if no chunks exist at this position, create a new one
if number == 0:
return # no point in creating a whole new chunk if we're not gonna be adding anything
self.chunks[chunk_position] = chunk.Chunk(self, chunk_position)
if self.get_block_number(position) == number: # no point updating mesh if the block is the same
return
lx, ly, lz = self.get_local_position(position)
self.chunks[chunk_position].blocks[lx][ly][lz] = number
self.chunks[chunk_position].modified = True
self.chunks[chunk_position].update_at_position((x, y, z))
self.chunks[chunk_position].update_mesh()
cx, cy, cz = chunk_position
def try_update_chunk_at_position(chunk_position, position):
if chunk_position in self.chunks:
self.chunks[chunk_position].update_at_position(position)
self.chunks[chunk_position].update_mesh()
if lx == chunk.CHUNK_WIDTH - 1: try_update_chunk_at_position((cx + 1, cy, cz), (x + 1, y, z))
if lx == 0: try_update_chunk_at_position((cx - 1, cy, cz), (x - 1, y, z))
if ly == chunk.CHUNK_HEIGHT - 1: try_update_chunk_at_position((cx, cy + 1, cz), (x, y + 1, z))
if ly == 0: try_update_chunk_at_position((cx, cy - 1, cz), (x, y - 1, z))
if lz == chunk.CHUNK_LENGTH - 1: try_update_chunk_at_position((cx, cy, cz + 1), (x, y, z + 1))
if lz == 0: try_update_chunk_at_position((cx, cy, cz - 1), (x, y, z - 1))
def try_set_block(self, pos, num, collider):
# if we're trying to remove a block, whatever let it go through
if not num:
return self.set_block(pos, 0)
# make sure the block doesn't intersect with the passed collider
for block_collider in self.block_types[num].colliders:
if collider & (block_collider + pos):
return
self.set_block(pos, num)
def draw(self):
for chunk_position in self.chunks:
self.chunks[chunk_position].draw()