def Fractal(level, box, options): # CONSTANTS method = "FRACTAL" print '%s: Started at %s' % (method, time.ctime()) (width, height, depth) = getBoxSize(box) centreWidth = (int)(width / 2) centreHeight = (int)(height / 2) centreDepth = (int)(depth / 2) AIR = (0, 0) schematic = level.extractSchematic( BoundingBox((box.minx, box.miny, box.minz), (width, height, depth))) for y in xrange(0, height): print '%s: Examining the selection area - step %s of %s' % (method, y, height - 1) for x in xrange(0, width): for z in xrange(0, depth): # If the current block is not air, blit the schematic into the corresponding area in space tempBlock = (schematic.blockAt(x, y, z), schematic.blockDataAt(x, y, z)) if tempBlock != AIR: level.copyBlocksFrom( schematic, BoundingBox((0, 0, 0), (width, height, depth)), (box.minx + x * width, box.miny + y * height, box.minz + z * height)) print '%s: Ended at %s' % (method, time.ctime())
def perform(level, box, options): b=range(4096) b.remove(0) # @CodeWarrior0 and @Wout12345 explained how to merge schematics buildingSize = options["Building Size"] width = box.maxx-box.minx depth = box.maxz-box.minz height = box.maxy-box.miny x = 0 cursor = 0 while x+buildingSize < width: z = 0 while z+buildingSize < depth: print "Building "+str(x)+","+str(z) p1 = (buildingSize,randint(height-1,height),buildingSize) #p1 = (buildingSize,height,buildingSize) buildingBox = BoundingBox((0,0,0),p1) buildingSchema = level.extractSchematic(BoundingBox((box.minx+x,box.miny,box.minz+z),p1)) building(buildingSchema, buildingBox,options) level.copyBlocksFrom(buildingSchema, buildingBox, (box.minx+x, box.miny, box.minz+z ),b) buildingSchema.saveToFile(filename="BuildingGotham_"+str(randint(1000000000,9999999999))+".schematic") z += buildingSize+options["Building Gap"] x += buildingSize+options["Building Gap"] cursor += 1 if cursor%3 == 2: x += 2*options["Path Gap"] + options["Road Gap"] level.markDirtyBox(box)
def perform(level,box, options): ''' Feedback to [email protected] ''' # Local variables method = options["Operation"] (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(level,box,options,method) # Log start level0 = level.extractSchematic(box) # Copy the area of interest into a working area, mostly for 'speed' box0 = BoundingBox((0,0,0),(width,height,depth)) b=range(4096) b.remove(0) # @CodeWarrior0 and @Wout12345 explained how to merge schematics if method == "Islands": for i in xrange(0,1000): print i radius = randint(10,50) centrex = randint(radius+2,width-radius-2) centrez = randint(radius+2,depth-radius-2) maxy = randint(radius+2,height-radius-2) theBox = BoundingBox((0,0,0),(2*radius-1,maxy-1,2*radius-1)) theObj = MCSchematic((2*radius-1,maxy-1,2*radius-1)) island(theObj,theBox,options) level0.copyBlocksFrom(theObj, theBox, (box0.minx+centrex-radius,box0.miny,box0.minz+centrez-radius),b) elif method == "Island": theBox = BoundingBox((0,0,0),(width,height,depth)) theObj = MCSchematic((width,height,depth)) island(theObj, theBox, options) level0.copyBlocksFrom(theObj, theBox, (box0.minx,box0.miny,box0.minz),b) level.copyBlocksFrom(level0, box0, (box.minx, box.miny, box.minz )) # Copy the working area back into the world level.markDirtyBox(box) FuncEnd(level,box,options,method) # Log end
def Surface(level,box,spacing): op = "Surface" #level2 = level.extractSchematic(box) # Working set level2 = MCSchematic((box.width,box.height,box.length)) box2 = BoundingBox((0,0,0),(box.width,box.height,box.length)) airlevel = MCSchematic((box.width,box.height,box.length)) airbox = BoundingBox((0,0,0),(box.width,box.height,box.length)) for x in xrange(box.minx,box.maxx): if x%10 == 0: print str(time.ctime())+" Scanning for surfaces "+op+" "+str(x) for z in xrange(box.minz,box.maxz): for y in xrange(box.miny,box.maxy): if getBlock(level,x,y,z) != (0,0): for ddx in xrange(-1,2): for ddz in xrange(-1,2): for ddy in xrange(-1,2): if not (ddx == 0 and ddy == 0 and ddz == 0): if getBlock(level,x+ddx,y+ddy,z+ddz) == (0,0): setBlock(airlevel,(1,0),x-box.minx,y-box.miny,z-box.minz) # Adjacent to air / surface else: setBlock(airlevel,(2,0),x-box.minx,y-box.miny,z-box.minz) # Airblock here for x in xrange(box.minx,box.maxx): if x%10 == 0: print str(time.ctime())+" Running "+op+" "+str(x) for z in xrange(box.minz,box.maxz): for y in xrange(box.miny,box.maxy): if getBlock(airlevel,x-box.minx,y-box.miny,z-box.minz) == (1,0): # This is a surface block setBlock(level2,getBlock(level,x,y,z),x-box.minx,y-box.miny,z-box.minz) level.copyBlocksFrom(level2, box2, (box.minx, box.miny, box.minz ))
def makeATower(stats, level, box, wallMaterials, floorMaterials, glassMaterials, lightMaterials): width = box.maxx - box.minx height = box.maxy - box.miny depth = box.maxz - box.minz roofy = int(height / 4) * randint(2, 3) roofBox = BoundingBox((box.minx, box.maxy - roofy, box.minz), (width, roofy, depth)) makeASpire(stats, level, roofBox, wallMaterials, floorMaterials, glassMaterials, lightMaterials) y = 0 while y < height - roofy: dy = randint(3, 5) dr = randint(3, 9) w = 2 + int(width / dr) d = 2 + int(depth / dr) h = dr baseBox = BoundingBox( (box.minx + (w >> 1), box.miny + y, box.minz + (d >> 1)), (width - w, h, depth - d)) cylinderVertical(stats, level, baseBox, wallMaterials[0]) baseBox = BoundingBox( (box.minx + (w >> 1) + 1, box.miny + y + 1, box.minz + (d >> 1) + 1), (width - w - 2, h - 2, depth - d - 2)) cylinderVertical(stats, level, baseBox, (0, 0)) y += dr
def binaryPartition(box): partitions = [] # create a queue which holds the next areas to be partitioned queue = [] queue.append(box) # for as long as the queue still has boxes to partition... count = 0 while len(queue) > 0: count += 1 splitMe = queue.pop(0) (width, height, depth) = utilityFunctions.getBoxSize(splitMe) # print "Current partition width,depth",width,depth centre = 0 # this bool lets me know which dimension I will be splitting on. It matters when we create the new outer bound size isWidth = False # find the larger dimension and divide in half # if the larger dimension is < 10, then block this from being partitioned minSize = 12 if width > depth: # roll a random die, 1% change we stop anyways chance = random.randint(100) if depth < minSize or chance == 1: partitions.append(splitMe) continue isWidth = True centre = width / 2 else: chance = random.randint(10) if width < minSize or chance == 1: partitions.append(splitMe) continue centre = depth / 2 # a random modifier for binary splitting which is somewhere between 0 and 1/16 the total box side length randomPartition = random.randint(0, (centre / 8) + 1) # creating the new bound newBound = centre + randomPartition #creating the outer edge bounds outsideNewBounds = 0 if isWidth: outsideNewBound = width - newBound - 1 else: outsideNewBound = depth - newBound - 1 # creating the bounding boxes # NOTE: BoundingBoxes are objects contained within pymclevel and can be instantiated as follows # BoundingBox((x,y,z), (sizex, sizey, sizez)) # in this instance, you specifiy which corner to start, and then the size of the box dimensions # this is an if statement to separate out binary partitions by dimension (x and z) if isWidth: queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz), (newBound-1, 256, depth))) queue.append(BoundingBox((splitMe.minx + newBound + 1, splitMe.miny, splitMe.minz), (outsideNewBound - 1, 256, depth))) else: queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz), (width, 256, newBound - 1))) queue.append(BoundingBox((splitMe.minx, splitMe.miny, splitMe.minz + newBound + 1), (width, 256, outsideNewBound - 1))) return partitions
def __init__(self, plot, **kwargs): self.plot = plot groundlevel = int( np.mean( [ plot.site.surfaceHeightAt(pos) for pos in bu.floor(plot).positions ] ) ) self.box = BoundingBox( (plot.minx, groundlevel, plot.minz), plot.size ) # front is towards the widest road if not plot.hasNeighbourWithTag('road'): self.front = random.choice( [Direction.North, Direction.East, Direction.South, Direction.West] ) else: widestRoad = max( plot.neighboursWithTag('road'), key=lambda road: min(road.width, road.length)) self.front = bu.touchDirection(plot, widestRoad) # lay out the building shell roomHeight = kwargs.get("roomHeight", 2) storeySize = Vector(self.box.width, roomHeight, self.box.length) self.storeys = [] self.floors = [] nStoreys = kwargs.get("nStoreys", 2) # split the house into a sequence alternating between height=one floors and height=x storeys for s in range(nStoreys): self.floors.append( BoundingBox(self.box.origin + (0, s*(roomHeight+1), 0), (self.box.width, 1, self.box.length)) ) self.storeys.append( BoundingBox(self.box.origin + (0, s*(roomHeight+1) +1, 0), storeySize) ) # update height of bounds self.box = bu.expandMax(self.box, dy = nStoreys*(roomHeight+1) - self.box.height) # the roof is the final, topmost 'floor' self.roof = BoundingBox(self.box.origin + (0, nStoreys*(roomHeight+1), 0), (self.box.width, 1, self.box.length))
def BlockRandomiserThing(level, box, options): # Prototype - works upwards AIR = (0, 0) method = "BlockRandomiserThing" print '%s: Started at %s' % (method, time.ctime()) # Rearranges the blocks in the selection, randomly, with a chance of leaving some of them out of the result (width, height, depth) = getBoxSize(box) schematic = level.extractSchematic( BoundingBox((box.minx, box.miny, box.minz), (width, height, depth))) for y in xrange(0, height): print '%s: Examining the selection area - step %s of %s' % (method, y, height - 1) for x in xrange(0, width): for z in xrange(0, depth): tempBlock = (schematic.blockAt(x, y, z), schematic.blockDataAt(x, y, z)) tempBlockBelow = (schematic.blockAt(x, y - 1, z), schematic.blockDataAt(x, y - 1, z)) if y > 0: if tempBlockBelow == AIR: setBlock(schematic, AIR, x, y, z) if randint(0, 100) < options["Chance of air"]: setBlock(schematic, AIR, x, y, z) level.copyBlocksFrom(schematic, BoundingBox((0, 0, 0), (width, height, depth)), (box.minx, box.miny, box.minz))
def QuadraticSurface(level, box, options): # CONSTANTS method = "QUADRATIC SURFACE" print '%s: Started at %s' % (method, time.ctime()) (width, height, depth) = getBoxSize(box) centreWidth = (int)(width / 2) centreHeight = (int)(height / 2) centreDepth = (int)(depth / 2) AIR = (0,0) BLOCKID = options["Pick a block:"].ID BLOCKDATA = options["Pick a block:"].blockData VERTMAGSCALE = options["Vertical Magnification"] HORIZMAGSCALE = options["Horizontal Magnification"] TOLERANCE = options["Tolerance"] PARAMETERS = options["Random"] schematic = level.extractSchematic(BoundingBox((box.minx, box.miny, box.minz), (width, height, depth))) # Mirror the blocks - in memory working read only copy a = random.uniform(-2, 2) b = random.uniform(-2, 2) c = random.uniform(-2, 2) f = random.uniform(-2, 2) g = random.uniform(-2, 2) h = random.uniform(-2, 2) p = random.uniform(-2, 2) q = random.uniform(-2, 2) r = random.uniform(-2, 2) d = random.uniform(-2, 2) if PARAMETERS == False: a = options["a"] b = options["b"] c = options["c"] f = options["f"] g = options["g"] h = options["h"] p = options["p"] q = options["q"] r = options["r"] d = options["d"] for xx in xrange(-centreWidth, centreWidth): print '%s of %s' % (xx, centreWidth) x = xx * HORIZMAGSCALE for yy in xrange(-centreHeight, centreHeight): y = yy * VERTMAGSCALE for zz in xrange(-centreDepth, centreDepth): z = zz * HORIZMAGSCALE if abs(a*x*x+b*y*y+c*z*z+2*f*y*z+2*g*z*x+2*h*x*y+2*p*x+2*q*y+2*r*z+d) <= TOLERANCE: setBlock(schematic, (BLOCKID, BLOCKDATA), (int)(centreWidth+xx), (int)(centreHeight+yy), (int)(centreDepth+zz)) level.copyBlocksFrom(schematic, BoundingBox((0,0,0),(width,height,depth)), (box.minx, box.miny, box.minz )) print 'a=%s b=%s c=%s f=%s g=%s h=%s p=%s q=%s r=%s d=%s' % (a,b,c,f,g,h,p,q,r,d) print '%s: Ended at %s' % (method, time.ctime())
def Fractal(level, box, options): # CONSTANTS method = "FRACTAL" print '%s: Started at %s' % (method, time.ctime()) (width, height, depth) = getBoxSize(box) centreWidth = (int)(width / 2) centreHeight = (int)(height / 2) centreDepth = (int)(depth / 2) AIR = (0, 0) XComponent = options["X Component?"] YComponent = options["Y Component?"] ZComponent = options["Z Component?"] Solid = options["Solid?"] schematic = level.extractSchematic( BoundingBox((box.minx, box.miny, box.minz), (width, height, depth))) for y in xrange(0, height): print '%s: Examining the selection area - step %s of %s' % (method, y, height - 1) for x in xrange(0, width): for z in xrange(0, depth): # If the current block is not air, blit the schematic into the corresponding area in space tempBlock = (schematic.blockAt(x, y, z), schematic.blockDataAt(x, y, z)) tempBlockAbove = (schematic.blockAt(x, y + 1, z), schematic.blockDataAt(x, y + 1, z)) if tempBlock != AIR: XModifier = 0 YModifier = 0 ZModifier = 0 if XComponent == True: XModifier = x * width if YComponent == True: YModifier = y * height if ZComponent == True: ZModifier = z * depth if Solid == False or (Solid == True and tempBlockAbove == AIR): level.copyBlocksFrom( schematic, BoundingBox((0, 0, 0), (width, height, depth)), (box.minx + XModifier, box.miny + YModifier, box.minz + ZModifier)) elif Solid == True and tempBlockAbove != AIR: fill(level, tempBlockAbove, (box.minx + XModifier, box.miny + YModifier, box.minz + ZModifier), (width, height, depth)) print '%s: Ended at %s' % (method, time.ctime())
def cantorCity(level, box, options, RAND, iter): print iter, box width = box.maxx - box.minx depth = box.maxz - box.minz height = box.maxy - box.miny # Draw the current layer if height > 0: material = getBlockFromOptions(options, "Material:") floorHeight = options["Floor Height:"] if floorHeight < 1: floorHeight = RAND.randint(1, 16) if iter > floorHeight and RAND.random() > 0.1: floorHeight = iter - floorHeight for y in xrange(box.miny, box.miny + floorHeight): for z in xrange(box.minz, box.maxz): for x in xrange(box.minx, box.maxx): setBlock(level, material, x, y, z) # Draw draw draw! # Now spawn the NEXT layer up in each corner if True: if height > 1: RATIO = options["Ratio:"] if RATIO < 1.0: RATIO = 1.0 + random() # Random splits! widthThird = int(width / RATIO) depthThird = int(depth / RATIO) MINDIM = options["Min Dimension:"] if widthThird >= MINDIM and depthThird >= MINDIM: # We stop when either dimension trends to 0 CHANCE = options["Chance:"] y = y + 1 if y < box.maxy: # Conditionally create a new box and build the next layer NewBox1 = BoundingBox( (box.minx, y, box.minz), (widthThird, box.maxy - y, depthThird)) NewBox2 = BoundingBox( (box.maxx - widthThird, y, box.minz), (widthThird, box.maxy - y, depthThird)) NewBox3 = BoundingBox( (box.maxx - widthThird, y, box.maxz - depthThird), (widthThird, box.maxy - y, depthThird)) NewBox4 = BoundingBox( (box.minx, y, box.maxz - depthThird), (widthThird, box.maxy - y, depthThird)) if RAND.random() < CHANCE: cantorCity(level, NewBox1, options, RAND, iter + 1) if RAND.random() < CHANCE: cantorCity(level, NewBox2, options, RAND, iter + 1) if RAND.random() < CHANCE: cantorCity(level, NewBox3, options, RAND, iter + 1) if RAND.random() < CHANCE: cantorCity(level, NewBox4, options, RAND, iter + 1)
def tileWindow(level,WINDOW): b=range(4096) b.remove(0) # @CodeWarrior0 and @Wout12345 explained how to merge schematics #describe(WINDOW) y = 0 while y < level.Height: x = 0 while x < (level.Width)>>1: level.copyBlocksFrom(WINDOW, BoundingBox((0,0,0),(WINDOW.Width,WINDOW.Height,WINDOW.Length)),(x,y,0),b) level.copyBlocksFrom(WINDOW, BoundingBox((0,0,0),(WINDOW.Width,WINDOW.Height,WINDOW.Length)),(level.Width-WINDOW.Width-x,y,0),b) x += WINDOW.Width y += WINDOW.Height
def jiggle(olevel, obox, level, box, options): method = "Jiggle" (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(level, box, options, method) # Log start # Displace each column in the level into the original level according to the operation DX = options["Delta X:"] DY = options["Delta Y:"] DZ = options["Delta Z:"] OP = options["Operation:"] DEL = options["Delete source?"] # fill the original selection box if DEL == True: olevel.fillBlocks(obox, alphaMaterials.Air) abox = BoundingBox((0, 0, 0), (1, height, 1)) for iterX in xrange(0, width): if iterX % 10 == 0: print iterX for iterZ in xrange(0, depth): # Extract a column of blocks from the copy of the original space cbox = BoundingBox((iterX, 0, iterZ), (1, height, 1)) clevel = level.extractSchematic(cbox) # Working set dx = DX dy = DY dz = DZ if OP == "Random": if dx > 0: dx = randint(0, dx) elif dx < 0: dx = randint(dx, 0) if dy > 0: dy = randint(0, dy) elif dy < 0: dy = randint(dy, 0) if dz > 0: dz = randint(0, dz) elif dz < 0: dz = randint(dz, 0) #print cbox #print obox olevel.copyBlocksFrom(clevel, abox, (obox.minx + iterX + dx, obox.miny + dy, obox.minz + iterZ + dz)) FuncEnd(level, box, options, method)
def perform(level, box, options): minY = findBottom(level, box) fillBox = BoundingBox((box.minx, box.miny, box.minz), (box.width, max(minY - box.miny, 1), box.length)) box = BoundingBox((box.minx, minY, box.minz), (box.width, options["Max Height"], box.length)) utilityFunctions.fillBox(level, box, (0, 0)) utilityFunctions.fillBoxEmpty(level, fillBox, (alphaMaterials.Grass.ID, 0)) (houses, roads) = idonknowPartition(box) test, house_matrix = getPlanMatrix(level, box, houses) for house in houses: chooseHouse(level, house, options) for road in roads: utilityFunctions.fillBox(level, road, (208, 0)) utilityFunctions.fillBox( level, CutBar(road, 0, 0, 0, 0, options["Max Height"], 1).middle, (0, 0)) ########################## # build road # house_matrix = getPlanMatrix(level, box, houses) global tm tm = detectMap(level, box, options, house_matrix) global width width = box.maxx - box.minx global height height = box.maxz - box.minz tm_to_test_map() find_path(box) print_test_map() #clearTerrain(level,box) for i in range(len(test_map)): for j in range(len(test_map[0])): if (test_map[i][j] == '*'): print i, j utilityFunctions.setBlock(level, (options["Road Material"].ID, 0), box.minx + j, box.miny, box.minz + i) if box.minx + j + 1 < box.maxx: utilityFunctions.setBlock(level, (options["Road Material"].ID, 0), box.minx + j + 1, box.miny, box.minz + i) if box.minz + i + 1 < box.maxz: utilityFunctions.setBlock(level, (options["Road Material"].ID, 0), box.minx + j, box.miny, box.minz + i + 1)
def create(generatorName, level, boxGlobal, box, agents, allStructures, materialScans, agent): print "Building a", generatorName, "at", box, " by ", str(agent) areas = GEN_Cottage.create(generatorName, level, boxGlobal, box, agents, allStructures, materialScans, agent) # Create a chimney or two for i in xrange(0, randint(1, 2)): size = randint(0, 1) for area in areas: width = area.maxx - area.minx depth = area.maxz - area.minz cx = (area.maxx + area.minx) >> 1 cz = (area.maxz + area.minz) >> 1 px = cx pz = cz if size > 0 and width > 3 and depth > 3: px = randint(area.minx + size, area.maxx - 1 - size) pz = randint(area.minz + size, area.maxz - 1 - size) height = box.maxy - area.miny chimneyHeight = randint(2 * height, 3 * height) + 1 chimneybox = BoundingBox( (px - size, area.miny, pz - size), (size * 2 + 1, chimneyHeight, size * 2 + 1)) Settlevolver.fill(level, chimneybox, (45, 0)) # Bricks if size > 0: chimneybox = BoundingBox((px, area.miny, pz), (1, chimneyHeight, 1)) Settlevolver.fill(level, chimneybox, (0, 0)) # Bricks chimneybox = BoundingBox((px - size, area.miny, pz), (size * 2 + 1, 1, 1)) Settlevolver.fill(level, chimneybox, (0, 0)) # Air chimneybox = BoundingBox((px, area.miny, pz - size), (1, 1, size * 2 + 1)) Settlevolver.fill(level, chimneybox, (0, 0)) # Air else: level.setBlockAt(px, area.miny + chimneyHeight, pz, 145) # Anvil level.setBlockDataAt(px, area.miny + chimneyHeight, pz, randint(0, 11)) if level.blockAt(px, area.miny - 1, pz) != 0: level.setBlockAt(px, area.miny, pz, 61) # Furnace level.setBlockDataAt(px, area.miny, cz, randint(2, 5)) return areas
def perform(level, box, options): print "ALife generation: Start." width = box.maxx - box.minx height = box.maxy - box.miny depth = box.maxz - box.minz material = getBlockFromOptions(options, "Material:") b = range(4096) b.remove( 0) # @CodeWarrior0 and @Wout12345 explained how to merge schematics planes = [] prevTickPlane = MCSchematic((width, height, depth)) print options["Mode"] if options["Mode"] == "Randomise": # Randomise to initialise initialise(prevTickPlane, options["Initial chance:"], material) elif options["Mode"] == "Load image": # Use black pixels to seed the generation initialiseFromImageFile( prevTickPlane, options["File path"], material, (options["Red"], options["Green"], options["Blue"])) else: # Use what's in the lowest plane of the selection box (i.e. the SOUTH most layer). Not air equals an alive cell. prevTickPlane = level.extractSchematic( BoundingBox((box.minx, box.miny, box.minz), (width, height, 1))) numTicksToRun = options["Number of ticks"] if numTicksToRun > depth: numTicksToRun = depth level.copyBlocksFrom(prevTickPlane, BoundingBox((0, 0, 0), (width, height, 1)), (box.minx, box.miny, box.minz), b) #First layer for z in xrange(1, numTicksToRun): print "Ticking", z TickPlane = MCSchematic((width, height, depth)) calculateLifeTick(prevTickPlane, TickPlane, material) # planes.append(TickPlane) # History level.copyBlocksFrom(TickPlane, BoundingBox((0, 0, 0), (width, height, 1)), (box.minx, box.miny, box.minz + z), b) prevTickPlane = TickPlane if options[ "Mode"] == "File path": # Save the last plane so it can be the next input if required. img.save(options["File path"] + "_end.png") level.markDirtyBox(box) print "ALife generation: Done." print "Complete!"
def analyse(level): ''' Examine the object in the schematic for min, max non-empty co-ordinates so we can pack-them-in! ''' # Find the bounding box for the object within this schematic. i.e. clip empty space method = "MINETEXT" print '%s: Started at %s' % (method, time.ctime()) box = level.bounds (width, height, depth) = getBoxSize(level.bounds) print 'ANALYSE %s %s %s' % (width, height, depth) minX = width minY = height minZ = depth maxX = 0 maxY = 0 maxZ = 0 found = False for iterY in xrange(0, height): for iterX in xrange(0, width): for iterZ in xrange(0, depth): if level.blockAt(iterX, iterY, iterZ) != 0: #print 'ANALYSING %s %s %s' % (iterX, iterY, iterZ) if iterX > maxX: maxX = iterX if iterY > maxY: maxY = iterY if iterZ > maxZ: maxZ = iterZ if iterX < minX: minX = iterX if iterY < minY: minY = iterY if iterZ < minZ: minZ = iterZ found = True print 'ANALYSE RESULT %s %s %s %s %s %s' % (minX, minY, minZ, maxX, maxY, maxZ) print '%s: Ended at %s' % (method, time.ctime()) if found == False: return BoundingBox((0, 0, 0), (width, height, depth)) else: return BoundingBox((minX, 0, minZ), (maxX + 1, maxY + 1, maxZ + 1))
def _getWorldBounds(self): if len(self.allChunks) == 0: return BoundingBox((0, 0, 0), (0, 0, 0)) allChunks = numpy.array(list(self.allChunks)) min_cx = (allChunks[:, 0]).min() max_cx = (allChunks[:, 0]).max() min_cz = (allChunks[:, 1]).min() max_cz = (allChunks[:, 1]).max() origin = (min_cx << 4, 0, min_cz << 4) size = ((max_cx - min_cx + 1) << 4, self.Height, (max_cz - min_cz + 1) << 4) return BoundingBox(origin, size)
def drawToolReticle(self): if self.level is None: return GL.glPolygonOffset(DepthOffset.CloneMarkers, DepthOffset.CloneMarkers) color = self.color if self.destPoint is not None: color = (self.color[0], self.color[1], self.color[2], 0.06) box = self.getDestBox() if self.draggingFace is not None: o = list(self.draggingOrigin()) s = list(box.size) for i in range(3): if i == self.draggingFace >> 1: continue o[i] -= 1000 s[i] += 2000 guideBox = BoundingBox(o, s) color = self.draggingColor GL.glColor(1.0, 1.0, 1.0, 0.33) with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D, GL.GL_DEPTH_TEST): self.editor.sixteenBlockTex.bind() drawFace(guideBox, self.draggingFace ^ 1) else: box = self.getReticleBox() if box is None: return self.drawRepeatedCube(box, color) GL.glPolygonOffset(DepthOffset.CloneReticle, DepthOffset.CloneReticle) if self.destPoint: box = self.getDestBox() if self.draggingFace is not None: face = self.draggingFace box = BoundingBox(self.draggingOrigin(), box.size) face, point = self.boxFaceUnderCursor(box) if face is not None: GL.glEnable(GL.GL_BLEND) GL.glDisable(GL.GL_DEPTH_TEST) GL.glColor(*self.color) drawFace(box, face) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST)
def perform(self, recordUndo=True): if self.level.saving: alert(_("Cannot perform action while saving is taking place")) return if recordUndo: self.canUndo = True self.undoLevel = self.extractUndo( self.level, BoundingBox(self.destPoint, self.sourceBox.size)) blocksToCopy = None if not (self.copyAir and self.copyWater): blocksToCopy = range(pymclevel.materials.id_limit) if not self.copyAir: blocksToCopy.remove(0) if not self.copyWater: blocksToCopy.remove(8) if not self.copyWater: blocksToCopy.remove(9) with setWindowCaption("Copying - "): i = self.level.copyBlocksFromIter( self.sourceLevel, self.sourceBox, self.destPoint, blocksToCopy, create=True, biomes=self.copyBiomes, staticCommands=self.staticCommands, moveSpawnerPos=self.moveSpawnerPos, regenerateUUID=self.regenerateUUID, first=False) showProgress( _("Copying {0:n} blocks...").format(self.sourceBox.volume), i)
def selectionBoxForCorners(self, p1, p2): ''' considers p1,p2 as the marked corners of a selection. returns a BoundingBox containing all the blocks within.''' if self.editor.level is None: return None p1, p2 = list(p1), list(p2) # d = [(a-b) for a,b in zip(p1,p2)] for i in range(3): if p1[i] > p2[i]: t = p2[i] p2[i] = p1[i] p1[i] = t p2[i] += 1 size = list(map(lambda a, b: a - b, p2, p1)) if p1[1] < 0: size[1] += p1[1] p1[1] = 0 h = self.editor.level.Height if p1[1] >= h: p1[1] = h - 1 size[1] = 1 if p1[1] + size[1] >= h: size[1] = h - p1[1] return BoundingBox(p1, size)
def getChunk(self, cx, cz): if (cx, cz) in self.chunkCache: return self.chunkCache[cx, cz] class FakeBrushChunk(pymclevel.level.FakeChunk): Entities = [] TileEntities = [] f = FakeBrushChunk() f.world = self f.chunkPosition = (cx, cz) mask = createBrushMask( brushSize, brushStyle, (0, 0, 0), BoundingBox((cx << 4, 0, cz << 4), (16, self.Height, 16))) f.Blocks = numpy.zeros(mask.shape, dtype='uint8') f.Data = numpy.zeros(mask.shape, dtype='uint8') f.BlockLight = self.zerolight f.SkyLight = self.zerolight if blockInfo.ID: f.Blocks[mask] = blockInfo.ID f.Data[mask] = blockInfo.blockData else: f.Blocks[mask] = 255 self.chunkCache[cx, cz] = f return f
def perform(originalLevel, originalBox, options): ''' Feedback to [email protected] ''' # Local variables method = options["Operation"] (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(originalLevel, originalBox, options, method) # Log start SUCCESS = False level = originalLevel.extractSchematic(originalBox) # Working set box = BoundingBox((0, 0, 0), (width, height, depth)) # Operations go here - switch to the function based on selected operation SUCCESS = Bridge(level, box, options) # Conditionally copy back the working area into the world if SUCCESS == True: # Copy from work area back into the world b = range(4096) b.remove( 0 ) # @CodeWarrior0 and @Wout12345 explained how to merge schematics originalLevel.copyBlocksFrom( level, box, (originalBox.minx, originalBox.miny, originalBox.minz), b) originalLevel.markDirtyBox(originalBox) FuncEnd(originalLevel, box, options, method) # Log end
def perform(self, recordUndo=True): if recordUndo: self.undoLevel = self.extractUndo(self.level, self.box) self.filter.perform(self.level, BoundingBox(self.box), self.options) pass
def perform(originalLevel, originalBox, options): ''' Feedback to [email protected] ''' # Local variables method = "perform" (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(originalLevel, originalBox, options, method) # Log start SUCCESS = True level = originalLevel.extractSchematic(originalBox) # Working set box = BoundingBox((0, 0, 0), (width, height, depth)) stairSmooth(level, box, options) if SUCCESS == True: # Copy from work area back into the world b = range(4096) b.remove( 0 ) # @CodeWarrior0 and @Wout12345 explained how to merge schematics originalLevel.copyBlocksFrom( level, box, (originalBox.minx, originalBox.miny, originalBox.minz), b) originalLevel.markDirtyBox(originalBox) FuncEnd(originalLevel, box, options, method) # Log end
def processCoords(coords): newcoords = collections.deque() for (x, y, z) in coords: for _dir, offsets in pymclevel.faceDirections: dx, dy, dz = offsets p = (x + dx, y + dy, z + dz) nx, ny, nz = p b = op.level.blockAt(nx, ny, nz) if indiscriminate: if b == 2: b = 3 if b == doomedBlock: if checkData: if op.level.blockDataAt(nx, ny, nz) != doomedBlockData: continue saveUndoChunk(nx // 16, nz // 16) op.level.setBlockAt(nx, ny, nz, op.options['Block'].ID) op.level.setBlockDataAt(nx, ny, nz, op.options['Block'].blockData) if tileEntity: if op.level.tileEntityAt(nx, ny, nz): op.level.removeTileEntitiesInBox(BoundingBox((nx, ny, nz), (1, 1, 1))) tileEntityObject = TileEntity.Create(tileEntity, (nx, ny, nz)) createTileEntities(tileEntityObject, op.level) newcoords.append(p) return newcoords
def makePyramid(level, box, options, floors): [cx,cy,cz]=[(box.minx+box.maxx)/2, (box.miny+box.maxy)/2, (box.minz+box.maxz)/2] boxSize = utilityFunctions.getBoxSize(box) minWidth = min(boxSize[0], boxSize[2]) step = 2 count=0 for floor in range(floors-1): subBox = BoundingBox((box.minx+floor,floor+box.miny,box.minz+floor),(boxSize[0]-step*floor, 1, boxSize[2]-step*floor)) if subBox.width>1 and subBox.length>1: utilityFunctions.setSquareFrame(level,(options["Wall"].ID,0), subBox.minx, subBox.miny, subBox.minz, subBox.length,subBox.width) count += 1 else: break subBox = BoundingBox((box.minx+count,count+box.miny,box.minz+count),(boxSize[0]-step*count, 1, boxSize[2]-step*count)) print subBox makeFloor(level, subBox, options)
def buildSimpleFarmHouse(level, box, options): #fencesBox = CutBar(box,1,1,1,1,boxSize[1]).middle #baseBox = CutBar(fencesBox, 2,2,2,2, boxSize[1]).middle #build fences and base #fenceLeft, fenceRight,fenceFront, fenceBack = buildFence(level, fencesBox, options,1) centerX = (box.minx+box.maxx)//2 centerZ = (box.minz + box.minz)//2 for y in range(0, 250): if level.blockAt(centerX, y, centerZ) != 0 and level.blockAt(centerX, y+1, centerZ)==0: minY = y break box = BoundingBox((box.minx, minY+1, box.minz),(box.width, box.height, box.length)) utilityFunctions.fillBox(level, CutBar(box,0,0,0,0,options["Max Height"],2).middle,(0,0)) wallPartBox = buildBase(level,box,(options["Base"].ID, 0), 1) floorBoxes = buildWall(level, wallPartBox,(options["Base"].ID, 0), random.randint(5,25)) for i in range(size(floorBoxes)-1): fillFrame(level, floorBoxes[i], (45,0), floorBoxes[i].height) #build the wall of the house if size(floorBoxes)>=2: buildRoof(level,AddBar(floorBoxes[-1],2,2,3,3).full, (options["Roof"].ID, 0),1, 10) else: buildRoof(level,AddBar(floorBoxes[-1],2,2,3,3).full, (options["Roof"].ID, 0),1, 1)
def perform(self, recordUndo=True): sourceBox = self.sourceBox if recordUndo: self.undoLevel = self.extractUndo( self.level, BoundingBox(self.destPoint, self.sourceBox.size)) blocksToCopy = None if not (self.copyAir and self.copyWater): blocksToCopy = range(pymclevel.materials.id_limit) if not self.copyAir: blocksToCopy.remove(0) if not self.copyWater: blocksToCopy.remove(8) if not self.copyWater: blocksToCopy.remove(9) with setWindowCaption("Copying - "): i = self.level.copyBlocksFromIter( self.sourceLevel, self.sourceBox, self.destPoint, blocksToCopy, create=True, biomes=self.copyBiomes, staticCommands=self.staticCommands, first=False) showProgress( _("Copying {0:n} blocks...").format(self.sourceBox.volume), i)
def tryToPlaceStructure(level, box, allStructures, potentialStructureSize, potentialStructureLocation, resource, recurse): (resourceBlockID, resourceBlockData), (resourceX, resourceY, resourceZ) = resource szx, szy, szz = potentialStructureSize pslx, psly, pslz = potentialStructureLocation if not (pslx < box.minx or pslx + szx >= box.maxx or pslz < box.minz or pslz + szz >= box.maxz): # Ok to try to position this structure. Check for height here y = psly # Some past solutions I've seen to this problem don't work with the existing terrain and, instead, create a bit of urban sprawl. if not (y < box.miny or y + szy >= box.maxy): # It can fit in the allocated space! Check for collisions newBox = BoundingBox((pslx, y, pslz), (szx, szy, szz)) collidesWith = checkForCollisions(newBox, allStructures) if len(collidesWith) == 0: return newBox # All good - pop this thing here else: # Else... Merge? Stack? Ignore? # Try stacking topY = newBox.maxy topBox = newBox for t, b in collidesWith: if b.maxy > topY: topBox = b if topBox != newBox and recurse == True: # Found a new box. Try to place this one on top of it. tryToPlaceStructure(level, box, allStructures, potentialStructureSize, (pslx, topY, pslz), resource, recurse) else: return None # We cannot place this box, sadly.
def createBrushMask(shape, style="Round", offset=(0, 0, 0), box=None, chance=100, hollow=False): """ Return a boolean array for a brush with the given shape and style. If 'offset' and 'box' are given, then the brush is offset into the world and only the part of the world contained in box is returned as an array. :param shape, UNKWOWN :param style, style of the brush. Round if not given. :param offset, UNKWOWN :param box, UNKWOWN :param chance, also known as Noise. Input in stock-brushes like Fill and Replace. :param hollow, input to calculate a hollow brush. """ #We are returning indices for a Blocks array, so swap axes if box is None: box = BoundingBox(offset, shape) if chance < 100 or hollow: box = box.expand(1) outputShape = box.size outputShape = (outputShape[0], outputShape[2], outputShape[1]) shape = shape[0], shape[2], shape[1] offset = numpy.array(offset) - numpy.array(box.origin) offset = offset[[0, 2, 1]] inds = numpy.indices(outputShape, dtype=float) halfshape = numpy.array([(i >> 1) - ((i & 1 == 0) and 0.5 or 0) for i in shape]) blockCenters = inds - halfshape[:, newaxis, newaxis, newaxis] blockCenters -= offset[:, newaxis, newaxis, newaxis] # odd diameter means measure from the center of the block at 0,0,0 to each block center # even diameter means measure from the 0,0,0 grid point to each block center # if diameter & 1 == 0: blockCenters += 0.5 shape = numpy.array(shape, dtype='float32') # if not isSphere(shape): if style == "Round": blockCenters *= blockCenters shape /= 2 shape *= shape blockCenters /= shape[:, newaxis, newaxis, newaxis] distances = sum(blockCenters, 0) mask = distances < 1 elif style == "Cylinder": pass elif style == "Square": blockCenters /= shape[:, None, None, None] distances = numpy.absolute(blockCenters).max(0) mask = distances < .5 elif style == "Diamond": blockCenters = numpy.abs(blockCenters) shape /= 2 blockCenters /= shape[:, newaxis, newaxis, newaxis] distances = sum(blockCenters, 0) mask = distances < 1 else: raise ValueError("Unknown style: " + style) if (chance < 100 or hollow) and max(shape) > 1: threshold = chance / 100.0 exposedBlockMask = numpy.ones(shape=outputShape, dtype='bool') exposedBlockMask[:] = mask submask = mask[1:-1, 1:-1, 1:-1] exposedBlockSubMask = exposedBlockMask[1:-1, 1:-1, 1:-1] exposedBlockSubMask[:] = False for dim in (0, 1, 2): slices = [slice(1, -1), slice(1, -1), slice(1, -1)] slices[dim] = slice(None, -2) exposedBlockSubMask |= (submask & (mask[slices] != submask)) slices[dim] = slice(2, None) exposedBlockSubMask |= (submask & (mask[slices] != submask)) if hollow: mask[~exposedBlockMask] = False if chance < 100: rmask = numpy.random.random(mask.shape) < threshold mask[exposedBlockMask] = rmask[exposedBlockMask] if chance < 100 or hollow: return mask[1:-1, 1:-1, 1:-1] else: return mask