def CreateNewMapFileJava(path, number, colors): map = TAG_Compound() map["data"] = TAG_Compound() map["data"]["scale"] = TAG_Byte(4) map["data"]["dimension"] = TAG_Byte(0) map["data"]["height"] = TAG_Short(128) map["data"]["width"] = TAG_Short(128) map["data"]["xCenter"] = TAG_Int(2147483647) map["data"]["yCenter"] = TAG_Int(2147483647) map["data"]["colors"] = TAG_Byte_Array(colors) map.save(os.path.join(path, "map_" + str(number) + ".dat"))
def CreateNewMapFilePE(level, number, colors): map = TAG_Compound() map["mapId"] = TAG_Long(number) map["parentMapId"] = TAG_Long(-1) map["decorations"] = TAG_List() map["dimension"] = TAG_Byte(0) map["fullyExplored"] = TAG_Byte(1) map["scale"] = TAG_Byte(4) map["height"] = TAG_Short(128) map["width"] = TAG_Short(128) map["xCenter"] = TAG_Int(2147483647) map["zCenter"] = TAG_Int(2147483647) map["colors"] = TAG_Byte_Array(colors) with level.worldFile.world_db() as db: wop = level.worldFile.writeOptions with nbt.littleEndianNBT(): db.Put(wop, 'map_' + str(number), map.save(compressed=False))
def perform(level, box, options): try: level.gamePlatform except: raise Exception( 'This filter requires level.gamePlatform. You will need a version of MCedit that has this' ) global idcount nearest = options[ "Use Nearest-Color Transparency (recommended for lossy image formats):"] tmode = options["Transparency Mode:"] tcolor = options["Transparency Color:"] if tmode == "Use Default Color (#FF00FF)": transparent = (255, 0, 255) elif tmode == "User-Specified Color Below": if tcolor[0] == "#": alphacolor = int(tcolor[1:7], 16) transparent = (alphacolor >> 16, (alphacolor >> 8) & 0xff, alphacolor & 0xff) else: raise Exception( "ERROR! The provided transparency color was formatted incorrectly! Colors must in hexadecimal format, in the form #RRGGBB" ) return else: transparent = None invulnerable = options["Item Frames are invulnerable:"] imgpath = options["Image path:"] facing = options["Item Frames are facing:"] backing = options["Item Frame backing block (replaces air blocks only):"] if backing.ID == 0: raise Exception("ERROR! The backing block CANNOT be air!") return toosmall = options["If selection is too small for image size:"] if level.gamePlatform == 'Java': if level.dimNo: datafolder = level.parentWorld.worldFolder.getFolderPath("data") else: datafolder = level.worldFolder.getFolderPath("data") if not os.path.exists(datafolder): try: os.makedirs(datafolder) except: raise OSError( "ERROR! Data folder does not exist and could not be created. Please create a \"data\" folder at: " + datafolder) return idcountpath = os.path.join(datafolder, "idcounts.dat") if os.path.exists(idcountpath): idcountfile = nbt.load(idcountpath) if "map" in idcountfile: idcount = idcountfile["map"].value else: idcount = 0 idcountfile["map"] = TAG_Short(0) else: idcount = 0 idcountfile = TAG_Compound() idcountfile["map"] = TAG_Short(0) elif level.gamePlatform == 'PE': try: with level.worldFile.world_db() as db: rop = level.worldFile.readOptions idcountfile = loadNBTCompoundList(db.Get(rop, 'MCeditMapIt'))[0] if "map" in idcountfile: idcount = idcountfile["map"].value else: idcount = 0 idcountfile["map"] = TAG_Long(0) except: idcount = 0 idcountfile = TAG_Compound() idcountfile["map"] = TAG_Long(0) if imgpath != "None": if os.path.exists(imgpath): image_path = imgpath else: image_path = mcplatform.askOpenFile(title="Select an Image", schematics=False) else: image_path = mcplatform.askOpenFile(title="Select an Image", schematics=False) if image_path == None: raise Exception("ERROR: No file provided!") return surface = pygame.image.load(image_path) # Adrian Brightmoore # Modification to allow auto-resize to selection dimensions sx, sy, sz = box.size xsize, ysize, zsize = box.size * 128 if toosmall == "Scale to selection": if (facing == "Eastwards (-X to +X)" or facing == "Westwards (+X to -X)"): surface = pygame.transform.smoothscale(surface, (zsize, ysize)) elif (facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)"): surface = pygame.transform.smoothscale(surface, (xsize, ysize)) (height, width) = surface.get_size() # End modification to allow auto-resize to selection dimensions loopx = int(math.ceil(float(width) / 128.0)) loopy = int(math.ceil(float(height) / 128.0)) if level.gamePlatform == 'Java': if (loopx * loopy) + idcount > 32767: raise Exception( "\nERROR! The image size is too large or there are not enough maps left for this world.\n" "Only 32,767 map files are allowed per world, and there are", idcount, "maps in this world.\n" "The image specified requires", (loopx * loopy), "maps.\n") return # elif level.gamePlatform == 'PE': # could do similar code to above but the limit is 2^63 rather than 2^15 so it will never be reached ever chestorframe = "item frames" if ysize < width: if toosmall == "Cancel Image Processing": raise Exception( "\nERROR! The selection height is too small! Your selection should be at least " + str(loopx) + "H in size.\n" "\n" "Cancelled image processing.") else: print "Creating chests instead of Item Frames" chestorframe = "chests" if chestorframe == "item frames" and (facing == "Eastwards (-X to +X)" or facing == "Westwards (+X to -X)"): if zsize < height or sx < 2: if toosmall == "Cancel Image Processing": raise Exception( "\nERROR! The selection size is too small; it selection should be at least\n" "2W x " + str(loopy) + "L x " + str(loopx) + "H in size.\n" "\n" "Cancelled image processing.") else: print "Creating chests instead of Item Frames" chestorframe = "chests" elif chestorframe == "item frames" and (facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)"): if xsize < height or sz < 2: if toosmall == "Cancel Image Processing": raise Exception( "\nERROR! The selection size is too small; it should be at least\n" "" + str(loopy) + "W x 2L x " + str(loopx) + "H in size.\n" "\n" "Cancelled image processing.") else: print "Creating chests instead of Item Frames" chestorframe = "chests" image = numpy.fromstring(pygame.image.tostring(surface, "RGB"), dtype=numpy.uint8).reshape(width, height, 3) progresscount = 1 progressmax = loopx * loopy startid = idcount + 1 def processImageJava(image, loopx, loopy, width, height, cache, transparent, nearest, image_path, progresscount, progressmax): global idcount for lx in xrange(loopx): for ly in xrange(loopy): yield idcount - 1, progressmax, "of image " + image_path progresscount += 1 idcount += 1 converted = numpy.zeros((128, 128), dtype=numpy.uint8) offsetx = lx * 128 offsety = ly * 128 for x in xrange(128): for y in xrange(128): if (offsetx + x) >= width: break elif (offsety + y) >= height: break r, g, b = (image[offsetx + x, offsety + y, 0], image[offsetx + x, offsety + y, 1], image[offsetx + x, offsety + y, 2]) if (r, g, b) in cache: converted[x, y] = cache[(r, g, b)] else: converted[x, y] = FindClosestPaletteIndex( r, g, b, transparent, nearest) if (offsetx + x) >= width: break CreateNewMapFileJava(datafolder, idcount, converted) def processImagePE(image, loopx, loopy, width, height, image_path, progresscount, progressmax): global idcount for lx in xrange(loopx): for ly in xrange(loopy): yield idcount - 1, progressmax, "of image " + image_path progresscount += 1 idcount += 1 print idcount converted = numpy.zeros((65536), dtype=numpy.uint8) offsetx = lx * 128 offsety = ly * 128 for x in xrange(128): for y in xrange(128): if (offsetx + x) >= width: break elif (offsety + y) >= height: break r, g, b = (image[offsetx + x, offsety + y, 0], image[offsetx + x, offsety + y, 1], image[offsetx + x, offsety + y, 2]) converted[4 * (x * 128 + y)] = r converted[4 * (x * 128 + y) + 1] = g converted[4 * (x * 128 + y) + 2] = b converted[4 * (x * 128 + y) + 3] = 255 if (offsetx + x) >= width: break CreateNewMapFilePE(level, idcount, converted) if level.gamePlatform == 'Java': level.showProgress( "Processing image pieces:", processImageJava(image, loopx, loopy, width, height, cache, transparent, nearest, image_path, progresscount, progressmax)) elif level.gamePlatform == 'PE': level.showProgress( "Processing image pieces:", processImagePE(image, loopx, loopy, width, height, image_path, progresscount, progressmax)) print idcount endid = idcount print endid if level.gamePlatform == 'Java': idcountfile["map"] = TAG_Short(idcount) idcountfile.save(idcountpath, compressed=False) elif level.gamePlatform == 'PE': idcountfile["map"] = TAG_Long(idcount) with level.worldFile.world_db() as db: wop = level.worldFile.writeOptions with nbt.littleEndianNBT(): db.Put(wop, 'MCeditMapIt', idcountfile.save(compressed=False)) print "Finished processing image " + image_path + ". Creating " + chestorframe + "..." if chestorframe == "item frames": if level.gamePlatform == 'Java': if facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)": if facing == "Northwards (+Z to -Z)": dir = 0 posIncrement = False else: dir = 2 posIncrement = True else: if facing == "Eastwards (-X to +X)": dir = 3 posIncrement = True else: dir = 1 posIncrement = False if facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)": z = box.minz if posIncrement: z += 1 for y in xrange(box.miny - 1 + loopx, box.miny - 1, -1): for x in xrange(box.minx, box.minx + loopy) if posIncrement else xrange( box.minx - 1 + loopy, box.minx - 1, -1): level.setBlockAt(x, y, z, 0) level.setBlockDataAt(x, y, z, 0) if level.blockAt(x, y, z + (-1 if posIncrement else 1)) == 0: level.setBlockAt(x, y, z + (-1 if posIncrement else 1), backing.ID) level.setBlockDataAt( x, y, z + (-1 if posIncrement else 1), backing.blockData) chunk = level.getChunk(x >> 4, z >> 4) chunk.Entities.append( CreateItemFrameJava(x, y, z, dir, startid, invulnerable)) chunk.dirty = True startid += 1 elif facing == "Eastwards (-X to +X)" or facing == "Westwards (+X to -X)": x = box.minx if posIncrement: x += 1 for y in xrange(box.miny - 1 + loopx, box.miny - 1, -1): for z in xrange(box.minz, box.minz + loopy) if not posIncrement else xrange( box.minz - 1 + loopy, box.minz - 1, -1): level.setBlockAt(x, y, z, 0) level.setBlockDataAt(x, y, z, 0) if level.blockAt(x + (-1 if posIncrement else 1), y, z) == 0: level.setBlockAt(x + (-1 if posIncrement else 1), y, z, backing.ID) level.setBlockDataAt( x + (-1 if posIncrement else 1), y, z, backing.blockData) chunk = level.getChunk(x >> 4, z >> 4) chunk.Entities.append( CreateItemFrameJava(x, y, z, dir, startid, invulnerable)) chunk.dirty = True startid += 1 elif level.gamePlatform == 'PE': if facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)": if facing == "Northwards (+Z to -Z)": dir = 3 posIncrement = False else: dir = 2 posIncrement = True else: if facing == "Eastwards (-X to +X)": dir = 0 posIncrement = True else: dir = 1 posIncrement = False if facing == "Northwards (+Z to -Z)" or facing == "Southwards (-Z to +Z)": z = box.minz if posIncrement: z += 1 for y in xrange(box.miny - 1 + loopx, box.miny - 1, -1): for x in xrange(box.minx, box.minx + loopy) if posIncrement else xrange( box.minx - 1 + loopy, box.minx - 1, -1): level.setBlockAt(x, y, z, 199) level.setBlockDataAt(x, y, z, dir) if level.blockAt(x, y, z + (-1 if posIncrement else 1)) == 0: level.setBlockAt(x, y, z + (-1 if posIncrement else 1), backing.ID) level.setBlockDataAt( x, y, z + (-1 if posIncrement else 1), backing.blockData) chunk = level.getChunk(x >> 4, z >> 4) chunk.TileEntities.append( CreateItemFramePE(x, y, z, startid)) chunk.dirty = True startid += 1 elif facing == "Eastwards (-X to +X)" or facing == "Westwards (+X to -X)": x = box.minx if posIncrement: x += 1 for y in xrange(box.miny - 1 + loopx, box.miny - 1, -1): for z in xrange(box.minz, box.minz + loopy) if not posIncrement else xrange( box.minz - 1 + loopy, box.minz - 1, -1): level.setBlockAt(x, y, z, 199) level.setBlockDataAt(x, y, z, dir) if level.blockAt(x + (-1 if posIncrement else 1), y, z) == 0: level.setBlockAt(x + (-1 if posIncrement else 1), y, z, backing.ID) level.setBlockDataAt( x + (-1 if posIncrement else 1), y, z, backing.blockData) chunk = level.getChunk(x >> 4, z >> 4) chunk.TileEntities.append( CreateItemFramePE(x, y, z, startid)) chunk.dirty = True startid += 1 else: if level.gamePlatform == 'Java': breakout = False entsToAdd = [] for y in xrange(box.miny, box.maxy): for z in xrange(box.minz, box.maxz): for x in xrange(box.minx, box.maxx): newchest = TAG_Compound() newchest["id"] = TAG_String("Chest") newchest["x"] = TAG_Int(x) newchest["y"] = TAG_Int(y) newchest["z"] = TAG_Int(z) newchest["Lock"] = TAG_String() newchest["Items"] = TAG_List() mapitem = TAG_Compound() mapitem["id"] = TAG_String("minecraft:filled_map") mapitem["Count"] = TAG_Byte(1) mapitem["Damage"] = TAG_Short(0) mapitem["Slot"] = TAG_Byte(0) for c in xrange(27): newitem = deepcopy(mapitem) newitem["Slot"] = TAG_Byte(c) newitem["Damage"] = TAG_Short(startid) newchest["Items"].append(newitem) startid += 1 if startid > endid: breakout = True break level.setBlockAt(x, y, z, 54) level.setBlockDataAt(x, y, z, 4) entsToAdd.append( (level.getChunk(x >> 4, z >> 4), deepcopy(newchest))) if breakout: break if breakout: break if breakout: break elif level.gamePlatform == 'PE': breakout = False entsToAdd = [] for y in xrange(box.miny, box.maxy): for z in xrange(box.minz, box.maxz): for x in xrange(box.minx, box.maxx): newchest = TAG_Compound() newchest["id"] = TAG_String("Chest") newchest["x"] = TAG_Int(x) newchest["y"] = TAG_Int(y) newchest["z"] = TAG_Int(z) newchest["Items"] = TAG_List() mapitem = TAG_Compound() mapitem["id"] = TAG_Short(358) mapitem["Count"] = TAG_Byte(16) mapitem["Damage"] = TAG_Short(0) mapitem["tag"] = TAG_Compound() for c in xrange(27): newitem = deepcopy(mapitem) newitem["Slot"] = TAG_Byte(c) newitem["tag"]["map_uuid"] = TAG_Long(startid) newchest["Items"].append(newitem) startid += 1 if startid > endid: breakout = True break level.setBlockAt(x, y, z, 54) level.setBlockDataAt(x, y, z, 4) entsToAdd.append( (level.getChunk(x >> 4, z >> 4), deepcopy(newchest))) if breakout: break if breakout: break if breakout: break for (chunk, entity) in entsToAdd: chunk.TileEntities.append(entity) chunk.dirty = True print "-------------------" print "Filtering complete."
def genWallMap(level, box, options): mapScale = options["Scale"] wallMapCentreX = options["x"] wallMapCentreZ = options["z"] gridAlign = options["Align with Grid"] renderMaps = options["Render Maps"] if dimNo != 0: dataFolder = level.parentWorld.worldFolder.getFolderPath("data") else: dataFolder = level.worldFolder.getFolderPath("data") if os.path.exists(os.path.join(dataFolder, "idcounts.dat")): idcountsTag = nbt.load(os.path.join(dataFolder, "idcounts.dat")) # Value of last existing map, new map should be map_(mapCount+1) mapCount = idcountsTag["map"].value else: mapCount = -1 if gridAlign: wallMapCentreX = int(round(wallMapCentreX/8.0))*8 wallMapCentreZ = int(round(wallMapCentreZ/8.0))*8 # if the box is not 1 thick if box.width != 1 and box.length != 1: raise Exception("The selection box needs to be 1 block thick") for chunk, slices, point in level.getChunkSlices(box): if chunk.Blocks[slices].any(): raise Exception("The selection box should be clear of blocks") # facing # 0 : south, +x map left to right # 1 : west, +z # 2 : north, -x # 3 : east, -z positive = 0 negative = 0 if box.width == 1: # wall map along y-z plane for chunk, slices, point in level.getChunkSlices(pymclevel.box.BoundingBox(box.origin + (1, 0, 0), box.size)): positive += chunk.Blocks[slices][chunk.Blocks[slices] != 0].size for chunk, slices, point in level.getChunkSlices(pymclevel.box.BoundingBox(box.origin + (-1, 0, 0), box.size)): negative += chunk.Blocks[slices][chunk.Blocks[slices] != 0].size if positive > negative: facing = 1 else: facing = 3 wallMapWidth = box.length else: # wall map along x-y plane for chunk, slices, point in level.getChunkSlices(pymclevel.box.BoundingBox(box.origin + (0, 0, 1), box.size)): positive += chunk.Blocks[slices][chunk.Blocks[slices] != 0].size for chunk, slices, point in level.getChunkSlices(pymclevel.box.BoundingBox(box.origin + (0, 0, -1), box.size)): negative += chunk.Blocks[slices][chunk.Blocks[slices] != 0].size if positive > negative: facing = 2 else: facing = 0 wallMapWidth = box.width wallMapHeight = box.height for chunk, slices, point in level.getChunkSlices(pymclevel.box.BoundingBox(box.origin + (1*[0, 1, 0, -1][facing], 0, 1*[-1, 0, 1, 0][facing], box.size))): if not chunk.Blocks[slices].all(): raise Exception("The selection box should be against a wall") def itemFramePosIter(box, facing): if facing == 0: return ((x, y, box.minz) for y in xrange(box.maxy-1, box.miny-1, -1) for x in xrange(box.minx, box.maxx)) elif facing == 1: return ((box.minx, y, z) for y in xrange(box.maxy-1, box.miny-1, -1) for z in xrange(box.minz, box.maxz)) elif facing == 2: return ((x, y, box.minz) for y in xrange(box.maxy-1, box.miny-1, -1) for x in xrange(box.maxx-1, box.minx-1, -1)) elif facing == 3: return ((box.minx, y, z) for y in xrange(box.maxy-1, box.miny-1, -1) for z in xrange(box.maxz-1, box.minz-1, -1)) def mapCentreIter(wallMapCentreX, wallMapCentreZ, wallMapWidth, wallMapHeight, mapScale, upDir): mapWidthInBlocks = 128 * 2**mapScale if upDir == 2: topLeftMapCentreX = wallMapCentreX - wallMapWidth*mapWidthInBlocks/2 + mapWidthInBlocks/2 topLeftMapCentreZ = wallMapCentreZ - wallMapHeight*mapWidthInBlocks/2 + mapWidthInBlocks/2 for h in xrange(wallMapHeight): for w in xrange(wallMapWidth): yield (topLeftMapCentreX + w * mapWidthInBlocks, topLeftMapCentreZ + h * mapWidthInBlocks) elif upDir == 3: topLeftMapCentreX = wallMapCentreX + wallMapHeight*mapWidthInBlocks/2 - mapWidthInBlocks/2 topLeftMapCentreZ = wallMapCentreZ - wallMapWidth*mapWidthInBlocks/2 + mapWidthInBlocks/2 for h in xrange(wallMapHeight): for w in xrange(wallMapWidth): yield (topLeftMapCentreX - h * mapWidthInBlocks, topLeftMapCentreZ + w * mapWidthInBlocks) elif upDir == 0: topLeftMapCentreX = wallMapCentreX + wallMapWidth*mapWidthInBlocks/2 - mapWidthInBlocks/2 topLeftMapCentreZ = wallMapCentreZ + wallMapHeight*mapWidthInBlocks/2 - mapWidthInBlocks/2 for h in xrange(wallMapHeight): for w in xrange(wallMapWidth): yield (topLeftMapCentreX - w * mapWidthInBlocks, topLeftMapCentreZ - h * mapWidthInBlocks) elif upDir == 1: topLeftMapCentreX = wallMapCentreX - wallMapHeight*mapWidthInBlocks/2 + mapWidthInBlocks/2 topLeftMapCentreZ = wallMapCentreZ + wallMapWidth*mapWidthInBlocks/2 - mapWidthInBlocks/2 for h in xrange(wallMapHeight): for w in xrange(wallMapWidth): yield (topLeftMapCentreX + h * mapWidthInBlocks, topLeftMapCentreZ - w * mapWidthInBlocks) upDir = {"North":2, "East":3, "South":0, "West":1}[options["Up is"]] itemRotation = [2, 1, 0, 3][upDir] progressBarMapCount = 0 numMaps = wallMapWidth * wallMapHeight numCols = numMaps * 128 for itemFramePos, mapCentre in itertools.izip(itemFramePosIter(box, facing), mapCentreIter(wallMapCentreX, wallMapCentreZ, wallMapWidth, wallMapHeight, mapScale, upDir)): mapCount += 1 mapTag = makeMapTag(*mapCentre, scale=mapScale) if renderMaps: for column in renderMap(level, mapTag): yield progressBarMapCount * 128 + column, numCols, "Map: "+str(progressBarMapCount)+"/"+str(numMaps) saveMapTag(level, mapTag, mapCount) mapItem = makeMapItemTag(mapCount) itemFrame = makeItemFrameEntity(*itemFramePos, facing=facing, itemtag=mapItem, itemRotation=itemRotation) level.addEntity(itemFrame) progressBarMapCount += 1 if mapCount >= 0: idcountsTag = TAG_Compound() idcountsTag["map"] = TAG_Short(mapCount) idcountsTag.save(os.path.join(dataFolder, "idcounts.dat"))