import sys import struct from pprint import pprint from itertools import chain from collections import defaultdict import functools import mcregion import vec3 import vertex_buffer import data def wrap_n(nc, chunk_c): if nc < 0: nc = 15 chunk_c = chunk_c - 1 if nc > 15: nc = 0 chunk_c = chunk_c + 1 return nc, chunk_c non_solid_blocks = { data.BlockID.TALL_GRASS, data.BlockID.MUSHROOM_1, data.BlockID.MUSHROOM_2, data.BlockID.FLOWER, data.BlockID.ROSE, data.BlockID.SAPLING, } def neighbor_exists(level_table, chunk_x, chunk_z, nx, ny, nz): if ny > 127 or ny < 0: return False nx, n_chunk_x = wrap_n(nx, chunk_x) nz, n_chunk_z = wrap_n(nz, chunk_z) assert nx <= 15 and nx >= 0 assert nz <= 15 and nz >= 0 key = (n_chunk_x, n_chunk_z) if key not in level_table: return True n_block_index = mcregion.block_index_from_xyz(nx, ny, nz) n_block_id = level_table[key].blocks[n_block_index] has_neighbor = (n_block_id != data.BlockID.AIR) and (n_block_id not in non_solid_blocks) return has_neighbor def block_neighbors(level_table, chunk_x, chunk_z, block_index): block_id = level_table[(chunk_x, chunk_z)].blocks[block_index] if block_id == data.BlockID.AIR: return xyz = mcregion.xyz_from_block_index(block_index) center_position = vec3.add(xyz, (chunk_x * 16, 0, chunk_z * 16)) def find_non_neighbors(): for i, normal in enumerate(vertex_buffer.normals): neighbor = vec3.add(normal, xyz) if not neighbor_exists(level_table, chunk_x, chunk_z, *neighbor): yield i normal_indices = list(find_non_neighbors()) if block_id in non_solid_blocks or normal_indices: yield center_position, block_id, normal_indices def devoxelize_region(level_table, level_table_keys): for chunk_x, chunk_z in level_table_keys: for block_index in range(128 * 16 * 16): yield from block_neighbors(level_table, chunk_x, chunk_z, block_index) def build_level_table(level_table, mem, locations): for location in locations: try: level = mcregion.parse_location(mem, location) except CountZeroException: continue x, z = level.x_pos, level.z_pos level_table[(x, z)] = level return level_table def normal_indices_as_block_configuration(normal_indices): acc = 0 for i in normal_indices: acc |= (1 << i) return acc def build_block_configuration_table(): for i in range(64): indices = [] for j in range(6): if ((i >> j) & 1) != 0: indices.extend(vertex_buffer.faces_by_normal[vertex_buffer.normals[j]]) yield indices non_cube_blocks = { data.BlockID.TALL_GRASS, data.BlockID.MUSHROOM_1, data.BlockID.MUSHROOM_2, data.BlockID.FLOWER, data.BlockID.ROSE, data.BlockID.SAPLING, } def pack_instance_data(position, block_id): packed = struct.pack("