def createSchematic(): e = MCSchematic(shape=(9, 6, 3), filename='') e._Blocks = [[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 20, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 19, 0], [0, 0, 0, 0, 0, 0, 20, 0, 20], [1, 0, 1, 0, 0, 1, 1, 23, 1]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 1, 93, 1, 75, 55, 55, 93, 55]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 76, 1, 55, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 55, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 55, 0, 0, 0, 0, 0, 0, 0]]] e.root_tag['Data'] = TAG_Byte_Array([[[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 2, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 9, 0, 1, 0, 0, 9, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 5, 0, 14, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 15, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 15, 0, 0, 0, 0, 0, 0, 0]]]) return e
def repeated(): e = MCSchematic(shape=(3, 3, 3), filename='') e._Blocks = [[[0, 0, 0], [0, 20, 0], [0, 0, 0]], [[0, 19, 0], [20, 0, 20], [1, 23, 1]], [[0, 0, 0], [0, 0, 0], [55, 93, 55]]] e.root_tag['Data'] = TAG_Byte_Array([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 2, 0]], [[0, 0, 0], [0, 0, 0], [0, 9, 0]]]) return e
def repeated(): e = MCSchematic(shape=(3, 3, 3), filename="") e._Blocks = [ [[0, 0, 0], [0, 20, 0], [0, 0, 0]], [[0, 19, 0], [20, 0, 20], [1, 23, 1]], [[0, 0, 0], [0, 0, 0], [55, 93, 55]], ] e.root_tag["Data"] = TAG_Byte_Array( [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 2, 0]], [[0, 0, 0], [0, 0, 0], [0, 9, 0]]] ) return e
def testImportSchematic(self): level = self.anvilLevel.level cx, cz = level.allChunks.next() schem = mclevel.fromFile("schematics/CreativeInABox.schematic") box = BoundingBox((cx * 16, 64, cz * 16), schem.bounds.size) level.copyBlocksFrom(schem, schem.bounds, (0, 64, 0)) schem = MCSchematic(shape=schem.bounds.size) schem.copyBlocksFrom(level, box, (0, 0, 0)) convertedSourceBlocks, convertedSourceData = block_copy.convertBlocks(schem, level, schem.Blocks, schem.Data) assert (level.getChunk(cx, cz).Blocks[0:1, 0:3, 64:65] == convertedSourceBlocks).all()
def testImportSchematic(self): level = self.anvilLevel.level cx, cz = level.allChunks.next() schem = mclevel.fromFile("schematics/CreativeInABox.schematic") box = BoundingBox((cx * 16, 64, cz * 16), schem.bounds.size) level.copyBlocksFrom(schem, schem.bounds, (0, 64, 0)) schem = MCSchematic(shape=schem.bounds.size) schem.copyBlocksFrom(level, box, (0, 0, 0)) convertedSourceBlocks, convertedSourceData = block_copy.convertBlocks( schem, level, schem.Blocks, schem.Data) assert (level.getChunk( cx, cz).Blocks[0:1, 0:3, 64:65] == convertedSourceBlocks).all()
def createLamp(): e = MCSchematic(shape=(3, 6, 3), filename='') e._Blocks = [[[0, 0, 0], [0, 0, 85], [0, 0, 0]], [[0, 0, 0], [0, 0, 85], [0, 0, 0]], [[0, 0, 0], [0, 0, 85], [0, 0, 0]], [[0, 0, 0], [0, 0, 85], [0, 0, 0]], [[0, 85, 0], [85, 89, 85], [0, 85, 0]], [[0, 53, 0], [53, 5, 53], [0, 53, 0]]] e.root_tag['Data'] = TAG_Byte_Array([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 2, 0], [0, 0, 1], [0, 3, 0]]]) return e
def createSchematic(): e = MCSchematic(shape=(9, 6, 3), filename="") e._Blocks = [ [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 20, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 19, 0], [0, 0, 0, 0, 0, 0, 20, 0, 20], [1, 0, 1, 0, 0, 1, 1, 23, 1]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [93, 1, 93, 1, 75, 55, 55, 93, 55]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 76, 1, 55, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 55, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 55, 0, 0, 0, 0, 0, 0, 0]], ] e.root_tag["Data"] = TAG_Byte_Array( [ [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 2, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 9, 0, 1, 0, 0, 9, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 5, 0, 14, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 15, 0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 15, 0, 0, 0, 0, 0, 0, 0]], ] ) return e
def createLamp(): e = MCSchematic(shape=(3,6,3),filename='') e._Blocks = [[[0,0,0],[0,0,85],[0,0,0]],[[0,0,0],[0,0,85],[0,0,0]],[[0,0,0],[0,0,85],[0,0,0]],[[0,0,0],[0,0,85],[0,0,0]],[[0,85,0],[85,89,85],[0,85,0]],[[0,53,0],[53,5,53],[0,53,0]]] e.root_tag['Data'] = TAG_Byte_Array([[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,2,0],[0,0,1],[0,3,0]]]) return e
def fit_elements(meta_input, element_list, OPTIONS): schematic_bufferX = 3 #schematic_bufferZ = 4 # Also, the schematics must be spaced out a certain length as well total_schematic_lengthX = sum(s.size[0] for s in element_list) sizeX = total_schematic_lengthX + schematic_bufferX * len(element_list) + 2 sizeZ = element_list[0].size[2] sizeZ += 2 * max(len(meta_input.input_domain), len( meta_input.output_range)) + 6 sizeY = max(s.size[1] for s in element_list) + 5 level = MCSchematic(shape=(sizeX, sizeY, sizeZ)) box = BoundingBox((0, 0, 0), (sizeX, sizeY, sizeZ)) cx, cy, cz = 2, 0, 0 schematic_origins = {} for s in element_list: schematic_origins[s] = [cx, cy, cz] level.copyBlocksFrom(s.schematic, BoundingBox((0, 0, 0), s.size), (cx, cy, cz)) cx += s.size[0] + schematic_bufferX # The schematics contain their own *relative* input locations in a dict of the form # input name --> (x, y, z). We wish to make a giant composite list of all the *absolute* locations # of the inputs, this time of the form (x, y, z) --> input name. We obtain the absolute # location by adding the individual schematic origin (in our coordinate system) with the # schematic's relative coordinate. absolute_input_locations = {} for s in element_list: for key, value in s.relative_input_locations.items(): abs_loc = add_tuples(schematic_origins[s], value) absolute_input_locations[abs_loc] = key # The z value for all the input locations will be the same. We just need to grab an arbitrary # one and use it to define the starting z location for the input rails input_z = 5 + absolute_input_locations.keys()[0][2] input_rail_z_values = {} for i in meta_input.input_domain: input_rail_z_values[i] = input_z input_z += 2 absolute_output_locations = {} for s in element_list: for key, value in s.relative_output_locations.items(): abs_loc = add_tuples(schematic_origins[s], value) absolute_output_locations[abs_loc] = key output_z = 4 + absolute_output_locations.keys()[0][2] output_rail_z_values = {} for i in meta_input.output_range: output_rail_z_values[i] = output_z output_z += 2 # Step through the input locations and build backward to to the point where it joins # up with the appropriate input rail. The rail will actually be built later. for input_loc, input_name in absolute_input_locations.items(): cx, cy, cz = input_loc[0], input_loc[1], input_loc[2] cz += 1 while (cz < input_rail_z_values[input_name] - 1): level.setBlockAt(cx, cy, cz, REDSTONE) cz += 1 level.setBlockAt(cx, cy, cz, REPEATER) cz += 1 level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt(cx, cy, cz, meta_input.input_color_key[input_name]) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) # Step through the output locations and build backward to to the point where it joins # up with the appropriate output rail. The rail will actually be built later. for output_loc, output_name in absolute_output_locations.items(): if OPTIONS["make_output_rail"] == False: continue cx, cy, cz = output_loc[0], output_loc[1], output_loc[2] cz += 1 while (cz < output_rail_z_values[output_name] - 1): level.setBlockAt(cx, cy, cz, REDSTONE) cy -= 1 level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt(cx, cy, cz, meta_input.output_color_key[output_name]) cy += 1 cz += 1 level.setBlockAt(cx, cy, cz, REPEATER) level.setBlockDataAt(cx, cy, cz, REPEATER_TOWARD_POS_Z) cy -= 1 level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt(cx, cy, cz, meta_input.output_color_key[output_name]) cy += 1 cz += 1 level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt(cx, cy, cz, meta_input.output_color_key[output_name]) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) # Now build the input rails! for input_name, input_z_value in input_rail_z_values.items(): cx, cy, cz = 0, 2, input_z_value while cx < sizeX: cy -= 1 if level.blockAt(cx, cy, cz) != REDSTONE: level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt(cx, cy, cz, meta_input.input_color_key[input_name]) level.setBlockAt(cx, cy, cz - 1, WOOL) level.setBlockDataAt(cx, cy, cz - 1, WOOL_BLACK) level.setBlockAt(cx, cy, cz + 1, WOOL) level.setBlockDataAt(cx, cy, cz + 1, WOOL_BLACK) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) cx += 1 # We need to put repeaters on the input rail. There are multiple ways to do so. If POSSIBLE, # use the gap method. To do this we need to perform the following algorithm to find the # gaps inbetween inputs. # Find the x values of the 'gaps' between clusters # of inputs. These are nice open spots to put repeaters. The following is a 'find the gap' # algorithm that ends up with a list of x values where repeaters should be placed (rep_locs) # Get the x values of the inputs input_x_values = list(x[0] for x in absolute_input_locations.keys()) input_x_values.sort() # Get the differences between each pair of input x values diffs = list(input_x_values[i] - input_x_values[i - 1] for i in range(1, len(input_x_values))) # Where these differences are more than 2, that means that we had a jump in the x values. # Obtain the indexes of the two input x values on either side of the jump gap_index_pairs = list( (i, i + 1) for i in range(len(diffs)) if diffs[i] > 2) # Finally, for each index pair, we want the x value in between the x values at those indices: # input_x_values[x] ---------------- (*) --------------- input_x_values[y] for each (x, y) pair in gap_index_pairs rep_locs = list(input_x_values[x] + int((input_x_values[y] - input_x_values[x]) / 2) for x, y in gap_index_pairs) # Now put repeaters on the input rail # We can get away with gap method if the rep_locs are within 15 spaces apart. Otherwise, # we'll HAVE to use an ugly-ass method rep_loc_spacings = list(rep_locs[i] - rep_locs[i - 1] for i in range(1, len(rep_locs))) if len(rep_loc_spacings) > 0: rep_loc_max_spacing = max(rep_loc_spacings) else: # The method fails... just set max spacing to something ridiculous so that it does the other method rep_loc_max_spacing = 100 if rep_loc_max_spacing <= 14: print "inputs - gap method" # GAP METHOD -- very nice looking, but doesn't work when the input domain is very large # because there *won't be any* gaps within 15 units, so it will place no repeaters. cy = 2 for iter_cx in rep_locs: for iter_cz in input_rail_z_values.values(): level.setBlockAt(iter_cx, cy, iter_cz, REPEATER) level.setBlockDataAt(iter_cx, cy, iter_cz, REPEATER_TOWARD_POS_X) else: print "inputs - method 2" # Method 2 -- aesthetically displeasing... has to fudge around the block edges and produces # lines of repeaters with 'imperfections' from scooting the necessary ones for input_name, input_z_value in input_rail_z_values.items(): cx, cy, cz = 12, 2, input_z_value while cx < sizeX: if level.blockAt(cx, cy - 1, cz) == REDSTONE: level.setBlockAt(cx - 2, cy, cz, REPEATER) level.setBlockDataAt(cx - 2, cy, cz, REPEATER_TOWARD_POS_X) elif level.blockAt(cx - 1, cy - 1, cz) == REDSTONE: level.setBlockAt(cx + 1, cy, cz, REPEATER) level.setBlockDataAt(cx + 1, cy, cz, REPEATER_TOWARD_POS_X) elif level.blockAt(cx + 1, cy - 1, cz) == REDSTONE: level.setBlockAt(cx - 1, cy, cz, REPEATER) level.setBlockDataAt(cx - 1, cy, cz, REPEATER_TOWARD_POS_X) else: level.setBlockAt(cx, cy, cz, REPEATER) level.setBlockDataAt(cx, cy, cz, REPEATER_TOWARD_POS_X) cx += 12 if OPTIONS["make_output_rail"]: # Now build the output rails! outputHeight = absolute_output_locations.keys()[0][1] + 2 for output_name, output_z_value in output_rail_z_values.items(): cx, cy, cz = 0, outputHeight, output_z_value while cx < sizeX: cy -= 1 if level.blockAt(cx, cy, cz) != REDSTONE: level.setBlockAt(cx, cy, cz, WOOL) level.setBlockDataAt( cx, cy, cz, meta_input.output_color_key[output_name]) level.setBlockAt(cx, cy, cz - 1, WOOL) level.setBlockDataAt(cx, cy, cz - 1, WOOL_BLACK) level.setBlockAt(cx, cy, cz + 1, WOOL) level.setBlockDataAt(cx, cy, cz + 1, WOOL_BLACK) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) cx += 1 # We need to find gaps for the gap method again output_x_values = list(x[0] for x in absolute_output_locations.keys()) output_x_values.sort() diffs = list(output_x_values[i] - output_x_values[i - 1] for i in range(1, len(output_x_values))) gap_index_pairs = list( (i, i + 1) for i in range(len(diffs)) if diffs[i] > 2) rep_locs = list(output_x_values[x] + int((output_x_values[y] - output_x_values[x]) / 2) for x, y in gap_index_pairs) if len(rep_loc_spacings) > 0: rep_loc_max_spacing = max(rep_loc_spacings) else: # The method fails... just set max spacing to something ridiculous so that it does the other method rep_loc_max_spacing = 100 if rep_loc_max_spacing < 14: print "outputs - gap method" # GAP METHOD -- very nice looking, but doesn't work when the input domain is very large # because there *won't be any* gaps within 15 units, so it will place no repeaters. cy = outputHeight for iter_cx in rep_locs: for iter_cz in output_rail_z_values.values(): level.setBlockAt(iter_cx, cy, iter_cz, REPEATER) level.setBlockDataAt(iter_cx, cy, iter_cz, REPEATER_TOWARD_NEG_X) else: print "outputs - method 2" # Method 2 -- aesthetically displeasing... has to fudge around the block edges and produces # lines of repeaters with 'imperfections' from scooting the necessary ones for output_name, output_z_value in output_rail_z_values.items(): cx, cy, cz = 12, outputHeight, output_z_value while cx < sizeX: if level.blockAt(cx, cy - 1, cz) == REDSTONE: level.setBlockAt(cx - 2, cy, cz, REPEATER) level.setBlockDataAt(cx - 2, cy, cz, REPEATER_TOWARD_NEG_X) elif level.blockAt(cx - 1, cy - 1, cz) == REDSTONE: level.setBlockAt(cx + 1, cy, cz, REPEATER) level.setBlockDataAt(cx + 1, cy, cz, REPEATER_TOWARD_NEG_X) elif level.blockAt(cx + 1, cy - 1, cz) == REDSTONE: level.setBlockAt(cx - 1, cy, cz, REPEATER) level.setBlockDataAt(cx - 1, cy, cz, REPEATER_TOWARD_NEG_X) else: level.setBlockAt(cx, cy, cz, REPEATER) level.setBlockDataAt(cx, cy, cz, REPEATER_TOWARD_NEG_X) cx += 12 return level
def lvl5(): e = MCSchematic(shape=(9,1,9),filename='') e._Blocks = [[[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block],[block,block,block,block,block,block,block,block,block]]] e.root_tag['Data'] = TAG_Byte_Array([[[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data],[data,data,data,data,data,data,data,data,data]]]) return e
def generate(comb_equation, use_input_color_key=None, use_output_color_key=None): inputs = comb_equation.inputs minterms = comb_equation.minterms form = form_tall if len(minterms) > 5 else form_short formBox = formBox_tall if len(minterms) > 5 else formBox_short implicantLimit = 13 if len(minterms) > 5 else 5 while len(minterms) % implicantLimit != 0: minterms.append({}) numXCopies = int(math.ceil(len(inputs) / 4)) sizeX = numXCopies * form.Width + 2 numYCopies = int(math.ceil(len(minterms) / implicantLimit)) sizeY = numYCopies * form.Height + 3 sizeZ = form.Length + 1 # print sizeX, sizeY, sizeZ level = MCSchematic(shape=(sizeX, sizeY, sizeZ)) box = BoundingBox((0, 0, 0), (sizeX, sizeY, sizeZ)) # ================================================================================================ # Paste the schematic the number of times we know we'll need pasteX = 0 for i in range(numXCopies): pasteY = 1 for i in range(numYCopies): level.copyBlocksFrom(form, formBox, (pasteX, pasteY, 0)) pasteY += form.Height pasteX += form.Width # Fill the bottom plane with a ground # level.fillBlocks(BoundingBox((0, 0, 0), (sizeX, 1, sizeZ)), alphaMaterials.BlockofIron) # Build X-ways across each row corresponding to each term cx = 0 cy = 2 cz = 1 numTerms = 0 side = CLOSE_SIDE relative_input_locations = {} for termIndex in range(len(minterms)): term = minterms[termIndex] cx = 0 for i in inputs: if i in term.keys(): mat = TORCH if term[i] else REDSTONE else: mat = AIR data = TORCH_POINTING_NEG_Z if (cz == 1) else TORCH_POINTING_POS_Z level.setBlockAt(cx, cy, cz, mat) level.setBlockDataAt(cx, cy, cz, data) if termIndex == 0: sx = cx sy = cy - 2 sz = cz + 4 for iter_sz in [sz, sz + 1, sz + 2, sz + 3]: level.setBlockAt(sx, sy, iter_sz, WOOL) data = WOOL_BLACK if use_input_color_key == None else use_input_color_key[ i] level.setBlockDataAt(sx, sy, iter_sz, data) relative_input_locations[i] = [sx, sy, sz + 2] cx += 2 # Build the slice of the side scaffolding that goes on this row's height level: # ----------------------------------------------------------------------------- prevCy = cy prevCz = cz cx = box.width - 2 if side == CLOSE_SIDE: cz -= 1 cy -= 1 elif side == FAR_SIDE: cz += 1 cy -= 1 if len(term) > 0: level.setBlockAt(cx, cy, cz, TORCH) level.setBlockDataAt(cx, cy, cz, TORCH_POINTING_POS_X) cx += 1 cy -= 1 if numTerms in [0, 1]: level.setBlockAt(cx, cy, cz, DOUBLE_SLAB) level.setBlockDataAt(cx, cy, cz, DOUBLE_SLAB_STONE) else: level.setBlockAt(cx, cy, cz, SLAB) level.setBlockDataAt(cx, cy, cz, STONE_SLAB_TOP) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) if side == CLOSE_SIDE: cz += 1 elif side == FAR_SIDE: cz -= 1 level.setBlockAt(cx, cy, cz, SLAB) level.setBlockDataAt(cx, cy, cz, STONE_SLAB_TOP) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) if side == CLOSE_SIDE: currentCloseTowerTopY = cy currentCloseTowerTopZ = cz elif side == FAR_SIDE: currentFarTowerTopY = cy currentFarTowerTopZ = cz cy = prevCy cz = prevCz # ----------------------------------------------------------------------------- # Switch sides side = FAR_SIDE if (side == CLOSE_SIDE) else CLOSE_SIDE # The z location alternates depending on the side if side == CLOSE_SIDE: cz = 1 if side == FAR_SIDE: cz = 8 # Keep track of the number of terms numTerms += 1 # JUMP LOGIC # Normal case: cy goes up by one, we are working term by term up one paste of the schematic # Special case: We have done 13 terms, and need to 'jump' to the next paste of the schematic # This requires some special connecting and bridging. # ------------------------------------------------------------------------------------------ if numTerms == implicantLimit: sx = box.width - 1 sy = currentCloseTowerTopY sz = currentCloseTowerTopZ sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_POINTING_POS_Z) sy += 1 for itr_sz in [sz, sz - 1, sz - 2]: level.setBlockAt(sx, sy, itr_sz, WOOL) level.setBlockDataAt(sx, sy, itr_sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_ON_GROUND) sz -= 1 level.setBlockAt(sx, sy, sz, REDSTONE) sz -= 1 level.setBlockAt(sx, sy, sz, REPEATER) # If we are finished with the whole thing, make the lead the exposes # The signal to the rest of the world if termIndex == len(minterms) - 1: sz += 2 sy += 1 data = WOOL_BLACK if use_output_color_key == None else use_output_color_key[ comb_equation.name] for iter_sz in range(sz, sz + 7, 1): level.setBlockAt(sx, sy, iter_sz, WOOL) level.setBlockDataAt(sx, sy, iter_sz, data) sy += 1 level.setBlockAt(sx, sy, iter_sz, REDSTONE) sy -= 1 sz += 7 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, data) sy += 1 level.setBlockAt(sx, sy, sz, REPEATER) level.setBlockDataAt(sx, sy, sz, REPEATER_TOWARD_POS_Z) lead_location = [sx, sy, sz] # ----------------------------------------------------- sx = box.width - 1 sy = currentFarTowerTopY sz = currentFarTowerTopZ sz -= 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, 75) level.setBlockDataAt(sx, sy, sz, 5) sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz -= 1 sy += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz += 1 level.setBlockAt(sx, sy, sz, REDSTONE) sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_ON_GROUND) # Now reset the variables for working up the next paste: cy += 4 numTerms = 0 side = CLOSE_SIDE cz = 1 else: cy += 1 # level.setBlockAt(0, 0, 0, 20) # level.setBlockAt(box.width-1, box.height-1, box.length-1, 20) # # Flip the entire schematic around to help make the fitting routine more 'sane' # # Also adjust location variables (like the locations of the lead and inputs) to # # reflect the Z-flip # # level.flipEastWest() # lead_location[2] = sizeZ - 1 - lead_location[2] # for ril in relative_input_locations.values(): # ril[2] = sizeZ - 1 - ril[2] # level.setBlockAt(*lead_location, blockID = 35) # level.setBlockDataAt(*lead_location, newdata = 0) # # for ril in relative_input_locations.values(): # level.setBlockAt(*ril, blockID = GLASS) ret = CombinationalElement(level) ret.relative_output_locations = {comb_equation.name: lead_location} ret.relative_input_locations = relative_input_locations ret.size = (sizeX, sizeY, sizeZ) return ret
from __future__ import division import os, math me = os.path.dirname(__file__) from block_constants import * from Element import CombinationalElement from pymclevel.schematic import MCSchematic from pymclevel.box import BoundingBox from pymclevel import alphaMaterials form_tall = MCSchematic( filename=os.path.join(me, "..", "res", "generic_boolean_blank.schematic")) form_short = MCSchematic(filename=os.path.join( me, "..", "res", "generic_boolean_short_blank.schematic")) formBox_tall = BoundingBox( (0, 0, 0), (form_tall.Width, form_tall.Height, form_tall.Length)) formBox_short = BoundingBox( (0, 0, 0), (form_short.Width, form_short.Height, form_short.Length)) def generate(comb_equation, use_input_color_key=None, use_output_color_key=None): inputs = comb_equation.inputs minterms = comb_equation.minterms form = form_tall if len(minterms) > 5 else form_short formBox = formBox_tall if len(minterms) > 5 else formBox_short implicantLimit = 13 if len(minterms) > 5 else 5
def testCreate(self): # log.info("Schematic from indev") size = (64, 64, 64) temp = mktemp("testcreate.schematic") schematic = MCSchematic(shape=size, filename=temp, mats='Classic') level = self.indevLevel.level schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), (64, 64, 64,)), (0, 0, 0)) assert((schematic.Blocks[0:64, 0:64, 0:64] == level.Blocks[0:64, 0:64, 0:64]).all()) schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), (64, 64, 64,)), (-32, -32, -32)) assert((schematic.Blocks[0:32, 0:32, 0:32] == level.Blocks[32:64, 32:64, 32:64]).all()) schematic.saveInPlace() schem = mclevel.fromFile("schematics/CreativeInABox.schematic") tempSchematic = MCSchematic(shape=(1, 1, 3)) tempSchematic.copyBlocksFrom(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 0, 0)) level = self.anvilLevel.level for cx, cz in itertools.product(xrange(0, 4), xrange(0, 4)): try: level.createChunk(cx, cz) except ValueError: pass schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), (64, 64, 64,)), (0, 0, 0)) schematic.close() os.remove(temp)
def test_schematic_extended_ids(): s = MCSchematic(shape=(1, 1, 5)) s.Blocks[0, 0, 0] = 2048 temp = TempLevel("schematic", createFunc=s.saveToFile) s = temp.level assert s.Blocks[0, 0, 0] == 2048
def testCreate(self): # log.info("Schematic from indev") size = (64, 64, 64) temp = mktemp("testcreate.schematic") schematic = MCSchematic(shape=size, filename=temp, mats='Classic') level = self.indevLevel.level schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), ( 64, 64, 64, )), (0, 0, 0)) assert ((schematic.Blocks[0:64, 0:64, 0:64] == level.Blocks[0:64, 0:64, 0:64]).all()) schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), ( 64, 64, 64, )), (-32, -32, -32)) assert ((schematic.Blocks[0:32, 0:32, 0:32] == level.Blocks[32:64, 32:64, 32:64]).all()) schematic.saveInPlace() schem = mclevel.fromFile("schematics/CreativeInABox.schematic") tempSchematic = MCSchematic(shape=(1, 1, 3)) tempSchematic.copyBlocksFrom(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 0, 0)) level = self.anvilLevel.level for cx, cz in itertools.product(xrange(0, 4), xrange(0, 4)): try: level.createChunk(cx, cz) except ValueError: pass schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), ( 64, 64, 64, )), (0, 0, 0)) schematic.close() os.remove(temp)
def generate(comb_equation, use_input_color_key = None, use_output_color_key = None): inputs = comb_equation.inputs minterms = comb_equation.minterms form = form_tall if len(minterms) > 5 else form_short formBox = formBox_tall if len(minterms) > 5 else formBox_short implicantLimit = 13 if len(minterms) > 5 else 5 while len(minterms) % implicantLimit != 0: minterms.append({}) numXCopies = int(math.ceil(len(inputs) / 4)) sizeX = numXCopies * form.Width + 2 numYCopies = int(math.ceil(len(minterms) / implicantLimit)) sizeY = numYCopies * form.Height + 3 sizeZ = form.Length + 1 # print sizeX, sizeY, sizeZ level = MCSchematic(shape=(sizeX, sizeY, sizeZ)) box = BoundingBox((0, 0, 0), (sizeX, sizeY, sizeZ)) # ================================================================================================ # Paste the schematic the number of times we know we'll need pasteX = 0 for i in range(numXCopies): pasteY = 1 for i in range(numYCopies): level.copyBlocksFrom(form, formBox, (pasteX, pasteY, 0)) pasteY += form.Height pasteX += form.Width # Fill the bottom plane with a ground # level.fillBlocks(BoundingBox((0, 0, 0), (sizeX, 1, sizeZ)), alphaMaterials.BlockofIron) # Build X-ways across each row corresponding to each term cx = 0 cy = 2 cz = 1 numTerms = 0 side = CLOSE_SIDE relative_input_locations = {} for termIndex in range(len(minterms)): term = minterms[termIndex] cx = 0 for i in inputs: if i in term.keys(): mat = TORCH if term[i] else REDSTONE else: mat = AIR data = TORCH_POINTING_NEG_Z if (cz == 1) else TORCH_POINTING_POS_Z level.setBlockAt(cx, cy, cz, mat) level.setBlockDataAt(cx, cy, cz, data) if termIndex == 0: sx = cx sy = cy - 2 sz = cz + 4 for iter_sz in [sz, sz+1, sz+2, sz+3]: level.setBlockAt(sx, sy, iter_sz, WOOL) data = WOOL_BLACK if use_input_color_key == None else use_input_color_key[i] level.setBlockDataAt(sx, sy, iter_sz, data) relative_input_locations[i] = [sx, sy, sz+2] cx += 2 # Build the slice of the side scaffolding that goes on this row's height level: # ----------------------------------------------------------------------------- prevCy = cy prevCz = cz cx = box.width - 2 if side == CLOSE_SIDE: cz -= 1 cy -= 1 elif side == FAR_SIDE: cz += 1 cy -= 1 if len(term) > 0: level.setBlockAt(cx, cy, cz, TORCH) level.setBlockDataAt(cx, cy, cz, TORCH_POINTING_POS_X) cx += 1 cy -= 1 if numTerms in [0, 1]: level.setBlockAt(cx, cy, cz, DOUBLE_SLAB) level.setBlockDataAt(cx, cy, cz, DOUBLE_SLAB_STONE) else: level.setBlockAt(cx, cy, cz, SLAB) level.setBlockDataAt(cx, cy, cz, STONE_SLAB_TOP) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) if side == CLOSE_SIDE: cz += 1 elif side == FAR_SIDE: cz -= 1 level.setBlockAt(cx, cy, cz, SLAB) level.setBlockDataAt(cx, cy, cz, STONE_SLAB_TOP) cy += 1 level.setBlockAt(cx, cy, cz, REDSTONE) if side == CLOSE_SIDE: currentCloseTowerTopY = cy currentCloseTowerTopZ = cz elif side == FAR_SIDE: currentFarTowerTopY = cy currentFarTowerTopZ = cz cy = prevCy cz = prevCz # ----------------------------------------------------------------------------- # Switch sides side = FAR_SIDE if (side == CLOSE_SIDE) else CLOSE_SIDE # The z location alternates depending on the side if side == CLOSE_SIDE: cz = 1 if side == FAR_SIDE: cz = 8 # Keep track of the number of terms numTerms += 1 # JUMP LOGIC # Normal case: cy goes up by one, we are working term by term up one paste of the schematic # Special case: We have done 13 terms, and need to 'jump' to the next paste of the schematic # This requires some special connecting and bridging. # ------------------------------------------------------------------------------------------ if numTerms == implicantLimit: sx = box.width - 1 sy = currentCloseTowerTopY sz = currentCloseTowerTopZ sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_POINTING_POS_Z) sy += 1 for itr_sz in [sz, sz-1, sz-2]: level.setBlockAt(sx, sy, itr_sz, WOOL) level.setBlockDataAt(sx, sy, itr_sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_ON_GROUND) sz -= 1 level.setBlockAt(sx, sy, sz, REDSTONE) sz -= 1 level.setBlockAt(sx, sy, sz, REPEATER) # If we are finished with the whole thing, make the lead the exposes # The signal to the rest of the world if termIndex == len(minterms) - 1: sz += 2 sy += 1 data = WOOL_BLACK if use_output_color_key == None else use_output_color_key[comb_equation.name] for iter_sz in range(sz, sz+7, 1): level.setBlockAt(sx, sy, iter_sz, WOOL) level.setBlockDataAt(sx, sy, iter_sz, data) sy += 1 level.setBlockAt(sx, sy, iter_sz, REDSTONE) sy -= 1 sz += 7 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, data) sy += 1 level.setBlockAt(sx, sy, sz, REPEATER) level.setBlockDataAt(sx, sy, sz, REPEATER_TOWARD_POS_Z) lead_location = [sx, sy, sz] # ----------------------------------------------------- sx = box.width - 1 sy = currentFarTowerTopY sz = currentFarTowerTopZ sz -= 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, 75) level.setBlockDataAt(sx, sy, sz, 5) sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz -= 1 sy += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sz += 1 level.setBlockAt(sx, sy, sz, REDSTONE) sz += 1 level.setBlockAt(sx, sy, sz, WOOL) level.setBlockDataAt(sx, sy, sz, WOOL_BLACK) sy += 1 level.setBlockAt(sx, sy, sz, TORCH) level.setBlockDataAt(sx, sy, sz, TORCH_ON_GROUND) # Now reset the variables for working up the next paste: cy += 4 numTerms = 0 side = CLOSE_SIDE cz = 1 else: cy += 1 # level.setBlockAt(0, 0, 0, 20) # level.setBlockAt(box.width-1, box.height-1, box.length-1, 20) # # Flip the entire schematic around to help make the fitting routine more 'sane' # # Also adjust location variables (like the locations of the lead and inputs) to # # reflect the Z-flip # # level.flipEastWest() # lead_location[2] = sizeZ - 1 - lead_location[2] # for ril in relative_input_locations.values(): # ril[2] = sizeZ - 1 - ril[2] # level.setBlockAt(*lead_location, blockID = 35) # level.setBlockDataAt(*lead_location, newdata = 0) # # for ril in relative_input_locations.values(): # level.setBlockAt(*ril, blockID = GLASS) ret = CombinationalElement(level) ret.relative_output_locations = {comb_equation.name : lead_location} ret.relative_input_locations = relative_input_locations ret.size = (sizeX, sizeY, sizeZ) return ret
def perform(level, box, options): forward_offset = options['Forward offset'] right_offset = options['Right offset'] up_offset = options['Up offset'] relative_position = options['Relative position'] generate_surrounding_box = options['Generate surrounding box'] if generate_surrounding_box: forward_offset += 1 up_offset += 1 if relative_position == 'North': execution_center = ((box.minx + box.maxx) // 2 - right_offset, box.miny - up_offset + 2, box.maxz + forward_offset - 1) elif relative_position == 'East': execution_center = (box.minx - forward_offset, box.miny - up_offset + 2, (box.minz + box.maxz) // 2 - right_offset) elif relative_position == 'South': execution_center = ((box.minx + box.maxx) // 2 + right_offset, box.miny - up_offset + 2, box.minz - forward_offset) elif relative_position == 'West': execution_center = (box.maxx + forward_offset - 1, box.miny - up_offset + 2, (box.minz + box.maxz) // 2 + right_offset) include_air = options['Include air'] include_blocks = options['Include blocks'] include_null_block_data = options['Include null block data'] include_entities = options['Include entities'] include_commandblockoutput_command = options['Include "gamerule commandBlockOutput false" command'] include_logadmincommands_command = options['Include "gamerule logAdminCommands false" command'] add_initialization_commands = options['Add initialization commands'] add_finalization_commands = options['Add finalization commands'] block_to_enqueue_input = re.split(r'\s*,\s*', options['Blocks to enqueue'].strip()) blocks_to_enqueue = [] for block_id in xrange(0, len(materials.block_map) - 1): if materials.block_map[block_id] in block_to_enqueue_input: blocks_to_enqueue.append(block_id) nbt_tags_to_ignore = re.split(r'\s*,\s*', options['NBT tags to ignore']) + ['x', 'y', 'z'] save_command_to_file = options['Save the command to a file instead of to a Command Block'] ignore_maximum_command_block_command_length = options['Ignore maximum Command Block command length'] box_wall_material_block = options['Box wall material block'] box_wall_material_data = options['Box wall material data value'] box_floor_material_block = options['Box floor material block'] box_floor_material_data = options['Box floor material data value'] box_ceiling_material_block = options['Box ceiling material block'] box_ceiling_material_data = options['Box ceiling material data value'] add_box_signs = options['Add box signs'] add_credits = True command = 'summon minecraft:falling_block ~ ~1 ~ {id:"minecraft:falling_block",Block:"minecraft:redstone_block",Time:1,Passengers:[{id:"minecraft:falling_block",Block:"minecraft:activator_rail",Time:1,Passengers:[' unformatted_command = command first_element = True if include_commandblockoutput_command: command_part = '{id:"minecraft:commandblock_minecart",Command:"gamerule commandBlockOutput false"}' command += '\n\t' + command_part unformatted_command += command_part first_element = False if include_logadmincommands_command: if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"gamerule logAdminCommands false"}' command += '\n\t' + command_part unformatted_command += command_part if add_initialization_commands: file = mcplatform.askOpenFile('Select the text file containing the initialization commands...', False, ['txt']) if file is not None: input = open(file) if input is not None: for line in input.read().splitlines(): if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"' + escape_string(line) + '"}' command += '\n\t' + command_part unformatted_command += command_part input.close() if include_blocks: if include_air: air_blocks = [] for x in xrange(box.minx, box.maxx): air_blocks.append([]) for y in xrange(box.miny, box.maxy): air_blocks[x - box.minx].append([]) for z in xrange(box.minz, box.maxz): air_blocks[x - box.minx][y - box.miny].append(True) for cuboid in subdivide_in_cuboids(air_blocks, 32768, False, True, False): if not first_element: command += ',' unformatted_command += ',' first_element = False if volume(cuboid[0][0], cuboid[0][1], cuboid[0][2], cuboid[1][0], cuboid[1][1], cuboid[1][2]) == 1: command_part = '{id:"minecraft:commandblock_minecart",Command:"setblock ~' + str(cuboid[0][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] + box.minz - execution_center[2]) + ' minecraft:air' else: command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(cuboid[0][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] + box.minz - execution_center[2]) + ' ~' + str(cuboid[1][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[1][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[1][2] + box.minz - execution_center[2]) + ' minecraft:air' if include_null_block_data: command_part += ' 0' command_part += '"}' command += '\n\t' + command_part unformatted_command += command_part blocks = [] for x in xrange(box.minx, box.maxx): blocks.append([]) for y in xrange(box.miny, box.maxy): blocks[x - box.minx].append([]) for z in xrange(box.minz, box.maxz): blocks[x - box.minx][y - box.miny].append((level.blockAt(x, y, z), level.blockDataAt(x, y, z), level.tileEntityAt(x, y, z))) enqueued = [] for x in xrange(0, len(blocks)): for y in xrange(0, len(blocks[x])): for z in xrange(0, len(blocks[x][y])): block = blocks[x][y][z] if block[0] >= 1: for cuboid in subdivide_in_cuboids(blocks, 32768, False, block, (-1, 0, None)): if volume(cuboid[0][0], cuboid[0][1], cuboid[0][2], cuboid[1][0], cuboid[1][1], cuboid[1][2]) == 1: command_part = '{id:"minecraft:commandblock_minecart",Command:"setblock ~' + str(cuboid[0][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] + box.minz - execution_center[2]) + ' ' + materials.block_map[block[0]] else: command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(cuboid[0][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] + box.minz - execution_center[2]) + ' ~' + str(cuboid[1][0] + box.minx - execution_center[0]) + ' ~' + str(cuboid[1][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[1][2] + box.minz - execution_center[2]) + ' ' + materials.block_map[block[0]] if include_null_block_data or block[1] != 0 or (block[1] == 0 and block[2] is not None): command_part += ' ' + str(block[1]) if block[2] is not None: command_part += ' replace ' + escape_string(nbt_to_string(block[2], nbt_tags_to_ignore)) command_part += '"}' if block[0] not in blocks_to_enqueue: if not first_element: command += ',' unformatted_command += ',' first_element = False command += '\n\t' + command_part unformatted_command += command_part else: enqueued.append(command_part) for enqueued_command in enqueued: if not first_element: command += ',' unformatted_command += ',' first_element = False command += '\n\t' + enqueued_command unformatted_command += enqueued_command if include_entities: for (chunk, slices, point) in level.getChunkSlices(box): for entity in chunk.Entities: entity_x = entity['Pos'][0].value entity_y = entity['Pos'][1].value entity_z = entity['Pos'][2].value if (entity_x, entity_y, entity_z) in box: if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"summon ' + str(entity['id'].value) + ' ~' + str((Decimal(entity_x - execution_center[0]) - Decimal('0.5')).normalize()) + ' ~' + str((Decimal(entity_y - execution_center[1]) - Decimal('0.0625')).normalize()) + ' ~' + str((Decimal(entity_z - execution_center[2]) - Decimal('0.5')).normalize()) + ' ' + escape_string(nbt_to_string(entity, nbt_tags_to_ignore)) + '"}' command += '\n\t' + command_part unformatted_command += command_part if generate_surrounding_box: if volume(box.minx - 1, box.miny - 1, box.minz - 1, box.maxx, box.maxy, box.maxz) <= 32768: if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(box.minx - 1 - execution_center[0]) + ' ~' + str(box.miny - 1 - execution_center[1]) + ' ~' + str(box.minz - 1 - execution_center[2]) + ' ~' + str(box.maxx - execution_center[0]) + ' ~' + str(box.maxy - execution_center[1]) + ' ~' + str(box.maxz - execution_center[2]) + ' ' + escape_string(box_wall_material_block) + ' ' + str(box_wall_material_data) + ' outline"}' command += '\n\t' + command_part unformatted_command += command_part else: wall_blocks = [] for x in xrange(0, box.maxx - box.minx + 2): wall_blocks.append([]) for y in xrange(0, box.maxy - box.miny): wall_blocks[x].append([]) for z in xrange(0, box.maxz - box.minz + 2): if x == 0 or x == box.maxx - box.minx + 1 or z == 0 or z == box.maxz - box.minz + 1: wall_blocks[x][y].append(True) else: wall_blocks[x][y].append(False) for cuboid in subdivide_in_cuboids(wall_blocks, 32768, False, True, False): if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(cuboid[0][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] - 1 + box.minz - execution_center[2]) + ' ~' + str(cuboid[1][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[1][1] + box.miny - execution_center[1]) + ' ~' + str(cuboid[1][2] - 1 + box.minz - execution_center[2]) + ' ' + escape_string(box_wall_material_block) if include_null_block_data or box_wall_material_data != 0: command_part += ' ' + str(box_wall_material_data) command_part += '"}' command += '\n\t' + command_part unformatted_command += command_part if add_box_signs: file = mcplatform.askOpenFile('Select the text file containing the signs to put on front of the box...', False, ['txt']) if file is not None: input = open(file) if input is not None: signs = OrderedDict() signs_line = 0 coordinate = (0, 0) for line in input.read().splitlines(): if signs_line == 0: if line != '': coordinates = re.split(r'\s*,\s*', line.strip()) coordinate = (int(coordinates[0]), int(coordinates[1])) signs[coordinate] = [] signs_line += 1 else: signs[coordinate].append(line) signs_line += 1 if signs_line == 9: signs_line = 0 for coordinate, sign in signs.items(): if relative_position == 'North': world_coordinate = (box.minx - 1 + coordinate[0] - execution_center[0], box.miny - 1 + coordinate[1] - execution_center[1], box.maxz + 1 - execution_center[2]) sign_data = 3 elif relative_position == 'East': world_coordinate = (box.minx - 2 - execution_center[0], box.miny - 1 + coordinate[1] - execution_center[1], box.minz - 1 + coordinate[0] - execution_center[2]) sign_data = 4 elif relative_position == 'South': world_coordinate = (box.maxx - coordinate[0] - execution_center[0], box.miny - 1 + coordinate[1] - execution_center[1], box.minz - 2 - execution_center[2]) sign_data = 2 else: world_coordinate = (box.maxx + 1 - execution_center[0], box.miny - 1 + coordinate[1] - execution_center[1], box.maxz - coordinate[0] - execution_center[2]) sign_data = 5 if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"setblock ~' + str(world_coordinate[0]) + ' ~' + str(world_coordinate[1]) + ' ~' + str(world_coordinate[2]) + ' minecraft:wall_sign ' + str(sign_data) + ' replace {' for i in xrange(0, min(4, len(sign))): sign_text = sign[i] sign_command = sign[i + 4] if len(sign) > i + 4 and len(sign[i + 4]) > 0 else '' if i > 0: command_part += ',' command_part += 'Text' + str(i + 1) + r':\"' if sign_text.startswith('{'): if sign_command != '': command_part += escape_string(escape_string('{"text":"","extra":[' + sign_text + ']')) else: command_part += escape_string(escape_string(sign_text)) elif sign_text.startswith('['): if sign_command != '': command_part += escape_string(escape_string('{"text":"","extra":' + sign_text)) else: command_part += escape_string(escape_string(sign_text)) elif sign_text.startswith('"'): if sign_command != '': command_part += escape_string(escape_string('{"text":' + sign_text)) else: command_part += escape_string(escape_string(sign_text)) else: if sign_command != '': command_part += escape_string(escape_string('{"text":"' + escape_string(sign_text) + '"')) else: command_part += escape_string(escape_string('"' + sign_text + '"')) if sign_command != '': command_part += escape_string(escape_string(',"clickEvent":{"action":"run_command","value":"' + escape_string(sign_command) + '"}}')) command_part += r'\"' command_part += '}"}' command += '\n\t' + command_part unformatted_command += command_part floor_ceiling_blocks = [] for x in xrange(0, box.maxx - box.minx + 2): floor_ceiling_blocks.append([]) floor_ceiling_blocks[x].append([]) for z in xrange(0, box.maxz - box.minz + 2): floor_ceiling_blocks[x][0].append(True) for cuboid in subdivide_in_cuboids(floor_ceiling_blocks, 32768, False, True, False): if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(cuboid[0][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] - 1 + box.miny - execution_center[1]) + ' ~' + str(cuboid[0][2] - 1 + box.minz - execution_center[2]) + ' ~' + str(cuboid[1][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[1][1] - 1 + box.miny - execution_center[1]) + ' ~' + str(cuboid[1][2] - 1 + box.minz - execution_center[2]) + ' ' + escape_string(box_floor_material_block) if include_null_block_data or box_floor_material_data != 0: command_part += ' ' + str(box_floor_material_data) command_part += '"}' command += '\n\t' + command_part unformatted_command += command_part command_part = '{id:"minecraft:commandblock_minecart",Command:"fill ~' + str(cuboid[0][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[0][1] + box.maxy - execution_center[1]) + ' ~' + str(cuboid[0][2] - 1 + box.minz - execution_center[2]) + ' ~' + str(cuboid[1][0] - 1 + box.minx - execution_center[0]) + ' ~' + str(cuboid[1][1] + box.maxy - execution_center[1]) + ' ~' + str(cuboid[1][2] - 1 + box.minz - execution_center[2]) + ' ' + escape_string(box_ceiling_material_block) if include_null_block_data or box_ceiling_material_data != 0: command_part += ' ' + str(box_ceiling_material_data) command_part += '"}' command += ',\n\t' + command_part unformatted_command += ',' + command_part if add_finalization_commands: file = mcplatform.askOpenFile('Select the text file containing the finalization commands...', False, ['txt']) if file is not None: input = open(file) if input is not None: for line in input.read().splitlines(): if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"' + escape_string(line) + '"}' command += '\n\t' + command_part unformatted_command += command_part input.close() if add_credits: if not first_element: command += ',' unformatted_command += ',' first_element = False command_part = '{id:"minecraft:commandblock_minecart",Command:"' + escape_string('tellraw @p {"color":"yellow","text":"Generated with Mamo\'s ","extra":[{"color":"blue","underlined":true,"text":"Structure spawner generator","clickEvent":{"action":"open_url","value":"https://github.com/xMamo/Structure-spawner-generator"},"hoverEvent":{"action":"show_text","value":"Click here if you want this filter too!"}},"."]}') + '"}' command += '\n\t' + command_part unformatted_command += command_part if not first_element: command += ',' unformatted_command += ',' command_part = r'{id:"minecraft:commandblock_minecart",Command:"setblock ~ ~1 ~ minecraft:command_block 0 replace {auto:1b,Command:\"fill ~ ~-3 ~ ~ ~ ~ minecraft:air' if include_null_block_data: command_part += ' 0' command_part += r'\"}"}' command += '\n\t' + command_part unformatted_command += command_part command_part = '{id:"minecraft:commandblock_minecart",Command:"kill @e[type=minecraft:commandblock_minecart,r=0]"}' command += ",\n\t" + command_part + '\n]}]}' unformatted_command += "," + command_part + ']}]}' if not ignore_maximum_command_block_command_length and len(unformatted_command) > 32500: editor.Notify('Unfortunately no command could be generated, as it would be longer than the Command Block command length limit of 32500 characters.') return command_output = None if save_command_to_file: output_file = mcplatform.askSaveFile(None, 'Select the text file to which you want to save the command...', 'command.txt', 'Text file (*.txt)\0*.txt\0\0', None) if output_file is not None: command_output = open(output_file, mode = 'w') if save_command_to_file and command_output is not None: command_output.write((command + '\n').encode('UTF-8')) command_output.flush() command_output.close() else: schematic = MCSchematic((1, 1, 1), None, None, level.materials) schematic.setBlockAt(0, 0, 0, 137) command_block = TAG_Compound() command_block['id'] = TAG_String('minecraft:command_block') command_block['x'] = TAG_Int(0) command_block['y'] = TAG_Int(0) command_block['z'] = TAG_Int(0) command_block['Command'] = TAG_String(unformatted_command) schematic.addTileEntity(command_block) editor.addCopiedSchematic(schematic)
def test_schematic_extended_ids(): s = MCSchematic(shape=(1, 1, 5)) s.Blocks[0,0,0] = 2048 temp = TempLevel("schematic", createFunc=s.saveToFile) s = temp.level assert s.Blocks[0,0,0] == 2048