def _create(self, command): """ create [ <filename> ] Create and load a new Minecraft Alpha world. This world will have no chunks and a random terrain seed. If run from the shell, filename is not needed because you already specified a filename earlier in the command. For example: mce.py MyWorld create """ if len(command) < 1: raise UsageError("Expected a filename") filename = command[0] if not os.path.exists(filename): os.mkdir(filename) if not os.path.isdir(filename): raise IOError("{0} already exists".format(filename)) if mclevel.MCInfdevOldLevel.isLevel(filename): raise IOError( "{0} is already a Minecraft Alpha world".format(filename)) level = mclevel.MCInfdevOldLevel(filename, create=True) self.level = level
numchunks += 1 world.saveInPlace() print "Saved %d chunks." % numchunks # Where does the world file go? i = 0 worlddir = None while not worlddir or os.path.exists(worlddir): i += 1 name = "world" + " " + map_type + " " + str(i) worlddir = os.path.join(minecraft_save_dir, name) print "Creating world %s" % worlddir world = mclevel.MCInfdevOldLevel(worlddir, create=True) from pymclevel.nbt import TAG_Int, TAG_String, TAG_Byte_Array tags = [ TAG_Int(0, "MapFeatures"), TAG_String("flat", "generatorName"), TAG_String("0", "generatorOptions") ] for tag in tags: world.root_tag['Data'].add(tag) peak = [10, 255, 10] print "Creating chunks." x_extent = len(elevation) x_min = 0
def __call__(self): """Actually build the Minecraft world that corresponds to a tile.""" # calculate offsets ox = (self.tilex - self.tiles['xmin']) * self.size oy = (self.tiley - self.tiles['ymin']) * self.size sx = self.size sy = self.size # load arrays from map file mapds = gdal.Open(self.mapfile, GA_ReadOnly) lcarray = mapds.GetRasterBand(Region.rasters['landcover']).ReadAsArray( ox, oy, sx, sy) elarray = mapds.GetRasterBand(Region.rasters['elevation']).ReadAsArray( ox, oy, sx, sy) bathyarray = mapds.GetRasterBand(Region.rasters['bathy']).ReadAsArray( ox, oy, sx, sy) crustarray = mapds.GetRasterBand(Region.rasters['crust']).ReadAsArray( ox, oy, sx, sy) # calculate Minecraft corners self.mcoffsetx = self.tilex * self.size self.mcoffsetz = self.tiley * self.size # build a Minecraft world via pymclevel from blocks and data self.world = mclevel.MCInfdevOldLevel(self.tiledir, create=True) tilebox = box.BoundingBox((self.mcoffsetx, 0, self.mcoffsetz), (self.size, self.world.Height, self.size)) self.world.createChunksInBox(tilebox) # do the terrain thing (no trees, ore or building) self.peak = [0, 0, 0] treeobjs = dict([(tree.name, tree) for tree in treeObjs]) self.trees = dict([(name, list()) for name in treeobjs]) for myx, myz in product(xrange(self.size), xrange(self.size)): mcx = int(self.mcoffsetx + myx) mcz = int(self.mcoffsetz + myz) mcy = int(elarray[myz, myx]) lcval = int(lcarray[myz, myx]) bathyval = int(bathyarray[myz, myx]) crustval = int(crustarray[myz, myx]) if mcy > self.peak[1]: self.peak = [mcx, mcy, mcz] (blocks, datas, tree) = Terrain.place(mcx, mcy, mcz, lcval, crustval, bathyval, self.doSchematics) [ self.world.setBlockAt(mcx, y, mcz, block) for (y, block) in blocks if block != 0 ] [ self.world.setBlockDataAt(mcx, y, mcz, data) for (y, data) in datas if data != 0 ] # if trees are placed, elevation cannot be changed if tree: Tree.placetreeintile(self, tree, mcx, mcy, mcz) # now that terrain and trees are done, place ore if self.doOre: Ore.placeoreintile(self) # stick the player and the spawn at the peak setspawnandsave(self.world, self.peak) # write Tile.yaml with relevant data (peak at least) # NB: world is not dump-friendly. :-) del self.world stream = file(os.path.join(self.tiledir, 'Tile.yaml'), 'w') yaml.dump(self, stream) stream.close() # return peak return self.peak
def main(): """Builds a region.""" # example: # ./BuildRegion.py --name BlockIsland # parse options and get results parser = argparse.ArgumentParser( description='Builds Minecraft worlds from regions.') parser.add_argument('--name', required=True, type=str, help='name of the region to be built') parser.add_argument('--debug', action='store_true', help='enable debug output') parser.add_argument( '--single', action='store_true', help='enable single-threaded mode for debugging or profiling') args = parser.parse_args() # enable debug if (args.debug): print "Do something!" # build the region print "Building region %s..." % args.name yamlfile = file(os.path.join('regions', args.name, 'Region.yaml')) myRegion = yaml.load(yamlfile) yamlfile.close() # exit if map does not exist if not os.path.exists(myRegion.mapfile): raise IOError('no map file exists') # tree and ore variables treeobjs = dict([(tree.name, tree) for tree in treeObjs]) trees = dict([(name, list()) for name in treeobjs]) oreobjs = dict([(ore.name, ore) for ore in oreObjs]) ores = dict([(name, list()) for name in oreobjs]) # generate overall world worlddir = os.path.join('worlds', args.name) world = mclevel.MCInfdevOldLevel(worlddir, create=True) peak = [0, 0, 0] # generate individual tiles tilexrange = xrange(myRegion.tiles['xmin'], myRegion.tiles['xmax']) tileyrange = xrange(myRegion.tiles['ymin'], myRegion.tiles['ymax']) name = myRegion.name tiles = [(name, x, y) for x, y in product(tilexrange, tileyrange)] if args.single: # single process version - works for tile in tiles: buildtile(tile) else: # multi-process ... let's see... pool = Pool() pool.map(buildtile, tiles) pool.close() pool.join() # merge individual worlds into it print "Merging %d tiles into one world..." % len(tiles) for tile in tiles: (name, x, y) = tile tiledir = os.path.join('regions', name, 'Tiles', '%dx%d' % (x, y)) tilefile = file(os.path.join(tiledir, 'Tile.yaml')) newtile = yaml.load(tilefile) tilefile.close() if (newtile.peak[1] > peak[1]): peak = newtile.peak for treetype in newtile.trees: trees.setdefault(treetype, []).extend(newtile.trees[treetype]) if myRegion.doOre: for oretype in newtile.ores: ores.setdefault(oretype, []).extend(newtile.ores[oretype]) tileworld = mclevel.MCInfdevOldLevel(tiledir, create=False) world.copyBlocksFrom(tileworld, tileworld.bounds, tileworld.bounds.origin) tileworld = False # plant trees in our world print "Planting %d trees at the region level..." % sum( [len(trees[treetype]) for treetype in trees]) Tree.placetreesinregion(trees, treeobjs, world) # deposit ores in our world if myRegion.doOre: print "Depositing %d ores at the region level..." % sum( [len(ores[oretype]) for oretype in ores]) Ore.placeoreinregion(ores, oreobjs, world) # replace all 'end stone' with stone print "Replacing all 'end stone' with stone..." EndStoneID = world.materials["End Stone"].ID StoneID = world.materials["Stone"].ID for xpos, zpos in world.allChunks: chunk = world.getChunk(xpos, zpos) chunk.Blocks[chunk.Blocks == EndStoneID] = StoneID # tie up loose ends setspawnandsave(world, peak)