def __init__(self, filename=None, root_tag=None, size=None, mats=alphaMaterials): if not 'blockstateToID' in globals().keys(): from materials import blockstateToID self._author = None self._blocks = None self._palette = None self._entities = [] self._tile_entities = None self._size = None self._version = None self._mat = mats if filename: root_tag = nbt.load(filename) if root_tag: self._root_tag = root_tag self._size = (self._root_tag["size"][0].value, self._root_tag["size"][1].value, self._root_tag["size"][2].value) self._author = self._root_tag.get("author", nbt.TAG_String()).value self._version = self._root_tag.get("version", nbt.TAG_Int(1)).value self._version = self._root_tag.get("DataVersion", nbt.TAG_Int(1)).value self._palette = self.__toPythonPrimitive(self._root_tag["palette"]) self._blocks = zeros(self.Size, dtype=tuple) self._blocks.fill((0, 0)) self._entities = [] self._tile_entities = zeros(self.Size, dtype=nbt.TAG_Compound) self._tile_entities.fill({}) for block in self._root_tag["blocks"]: x, y, z = [p.value for p in block["pos"].value] self._blocks[x, y, z] = blockstateToID( *self.get_state(block["state"].value)) if "nbt" in block: compound = nbt.TAG_Compound() compound.update(block["nbt"]) self._tile_entities[x, y, z] = compound for e in self._root_tag["entities"]: entity = e["nbt"] entity["Pos"] = e["pos"] self._entities.append(entity) elif size: self._root_tag = nbt.TAG_Compound() self._size = size self._blocks = zeros(self.Size, dtype=tuple) self._blocks.fill((0, 0)) self._entities = [] self._tile_entities = zeros(self.Size, dtype=nbt.TAG_Compound) self._tile_entities.fill({})
def toNBT(self): root = nbt.TAG_Compound() root['Name'] = nbt.TAG_String('{}:{}'.format(self._resource_location, self._basename)) if self._properties: props = nbt.TAG_Compound() for (key, value) in self._properties.iteritems(): props[key] = nbt.TAG_String(value) root['Properties'] = props return root
def setup(self): if not self._scs: self.root_tag = nbt.load( self.level.worldFolder.getFolderPath("data") + "/scoreboard.dat") for objective in self.root_tag["data"]["Objectives"]: self.objectives.append(Objective(objective)) for team in self.root_tag["data"]["Teams"]: self.teams.append(Team(team)) else: self.root_tag = nbt.TAG_Compound() self.root_tag["data"] = nbt.TAG_Compound()
def testCreate(self): "Create an indev level." "The root of an NBT file is always a TAG_Compound." level = nbt.TAG_Compound(name="MinecraftLevel") "Subtags of a TAG_Compound are automatically named when you use the [] operator." level["About"] = nbt.TAG_Compound() level["About"]["Author"] = nbt.TAG_String("codewarrior") level["Environment"] = nbt.TAG_Compound() level["Environment"]["SkyBrightness"] = nbt.TAG_Byte(16) level["Environment"]["SurroundingWaterHeight"] = nbt.TAG_Short(32) "You can also create and name a tag before adding it to the compound." spawn = nbt.TAG_List( (nbt.TAG_Short(100), nbt.TAG_Short(45), nbt.TAG_Short(55))) spawn.name = "Spawn" mapTag = nbt.TAG_Compound() mapTag.add(spawn) mapTag.name = "Map" level.add(mapTag) "I think it looks more familiar with [] syntax." l, w, h = 128, 128, 128 mapTag["Height"] = nbt.TAG_Short(h) # y dimension mapTag["Length"] = nbt.TAG_Short(l) # z dimension mapTag["Width"] = nbt.TAG_Short(w) # x dimension "Byte arrays are stored as numpy.uint8 arrays. " mapTag["Blocks"] = nbt.TAG_Byte_Array() mapTag["Blocks"].value = numpy.zeros( l * w * h, dtype=numpy.uint8) # create lots of air! "The blocks array is indexed (y,z,x) for indev levels, so reshape the blocks" mapTag["Blocks"].value.shape = (h, l, w) "Replace the bottom layer of the indev level with wood" mapTag["Blocks"].value[0, :, :] = 5 "This is a great way to learn the power of numpy array slicing and indexing." mapTag["Data"] = nbt.TAG_Byte_Array() mapTag["Data"].value = numpy.zeros(l * w * h, dtype=numpy.uint8) return level
def getTAGStructure(self): tag = nbt.TAG_Compound() tag["Name"] = nbt.TAG_String(self.name) tag["RenderType"] = nbt.TAG_String(self.renderType) tag["DisplayName"] = nbt.TAG_String(self.displayName) tag["CriteriaName"] = nbt.TAG_String(self.criteria) return tag
def getChunk(self, cx, cz): """Synthesize a FakeChunk object representing the chunk at the given position. Subclasses override fakeBlocksForChunk and fakeDataForChunk to fill in the chunk arrays""" f = FakeChunk() f.world = self f.chunkPosition = (cx, cz) f.Blocks = self.fakeBlocksForChunk(cx, cz) f.Data = self.fakeDataForChunk(cx, cz) whiteLight = zeros_like(f.Blocks) whiteLight[:] = 15 f.BlockLight = whiteLight f.SkyLight = whiteLight f.Entities, f.TileEntities, f.TileTicks = self._getFakeChunkEntities( cx, cz) f.root_tag = nbt.TAG_Compound() return f
def Create(cls, tileEntityID, pos=(0, 0, 0), **kw): tileEntityTag = nbt.TAG_Compound() # Refresh the MCEDIT_DEFS and MCEDIT_IDS objects from pymclevel import MCEDIT_DEFS, MCEDIT_IDS _id = MCEDIT_DEFS.get(tileEntityID, tileEntityID) tileEntityTag["id"] = nbt.TAG_String(_id) base = cls.baseStructures.get(tileEntityID, None) if base: for (name, tag) in base: tileEntityTag[name] = tag() if tileEntityID == "Control": if name == "CustomName": tileEntityTag[name] = nbt.TAG_String("@") elif name == "SuccessCount": tileEntityTag[name] = nbt.TAG_Int(0) elif tileEntityID == "MobSpawner": entity = kw.get("entity") if name == "EntityId": tileEntityTag[name] = nbt.TAG_String(MCEDIT_DEFS.get("Pig", "Pig")) if name == "SpawnData": spawn_id = nbt.TAG_String(MCEDIT_DEFS.get("Pig", "Pig"), "id") tileEntityTag["SpawnData"] = tag() if entity: for k, v in entity.iteritems(): tileEntityTag["SpawnData"][k] = deepcopy(v) else: tileEntityTag["SpawnData"].add(spawn_id) cls.setpos(tileEntityTag, pos) return tileEntityTag
def saveToFile(self, filename): schematicDat = nbt.TAG_Compound() schematicDat.name = "Mega Schematic" schematicDat["Width"] = nbt.TAG_Int(self.size[0]) schematicDat["Height"] = nbt.TAG_Int(self.size[1]) schematicDat["Length"] = nbt.TAG_Int(self.size[2]) schematicDat["Materials"] = nbt.TAG_String(self.materials.name) schematicDat.save(self.worldFolder.getFilePath("schematic.dat")) basedir = self.worldFolder.filename assert os.path.isdir(basedir) with closing( zipfile.ZipFile(filename, "w", zipfile.ZIP_STORED, allowZip64=True)) as z: for root, dirs, files in os.walk(basedir): # NOTE: ignore empty directories for fn in files: absfn = os.path.join(root, fn) shutil.move(absfn, absfn.replace("##MCEDIT.TEMP##" + os.sep, "")) absfn = absfn.replace("##MCEDIT.TEMP##" + os.sep, "") zfn = absfn[len(basedir) + len(os.sep):] # XXX: relative path z.write(absfn, zfn)
def _createLevelDat(self, random_seed, last_played): """ Creates a new level.dat root_tag, and puts it in self.root_tag. To write it to the disk, self.save() should be called. :param random_seed: long :param last_played: long :return: None """ with nbt.littleEndianNBT(): root_tag = nbt.TAG_Compound() root_tag["SpawnX"] = nbt.TAG_Int(0) root_tag["SpawnY"] = nbt.TAG_Int(2) root_tag["SpawnZ"] = nbt.TAG_Int(0) if last_played is None: last_played = long(time.time() * 100) if random_seed is None: random_seed = long(numpy.random.random() * 0xffffffffffffffffL) - 0x8000000000000000L self.root_tag = root_tag self.LastPlayed = long(last_played) self.RandomSeed = long(random_seed) self.SizeOnDisk = 0 self.Time = 1 self.LevelName = os.path.basename(self.worldFile.path)
def __init__(self, cmd="", hover="", block="I", d="u", cond=False, redstone=False, time=0, first=False): name = "minecraft:" + self.nameMap[block] dv = self.dMap[d] if cond: dv += 8 nbtData = nbt.TAG_Compound("", []) nbtData.add(nbt.TAG_Byte("auto", int(not redstone))) nbtData.add(nbt.TAG_String("Command", cmd)) nbtData.add(nbt.TAG_String("CustomName", hover)) nbtData.add(nbt.TAG_Byte("powered", int(block == "R" and not redstone))) if time == 0 and not first: nbtData.add(nbt.TAG_Int("Version", 8)) else: nbtData.add(nbt.TAG_Int("Version", 9)) nbtData.add(nbt.TAG_Byte("ExecuteOnFirstTick", int(first))) nbtData.add(nbt.TAG_Int("TickDelay", time)) nbtData.add(nbt.TAG_Byte("conditionMet", 0)) nbtData.add(nbt.TAG_String("id", "CommandBlock")) nbtData.add(nbt.TAG_Byte("isMovable", 1)) nbtData.add(nbt.TAG_Int("LPCommandMode", 0)) # Not sure what these LPModes do. This works. nbtData.add(nbt.TAG_Byte("LPConditionalMode", 0)) nbtData.add(nbt.TAG_Byte("LPRedstoneMode", 0)) nbtData.add(nbt.TAG_Long("LastExecution", 0)) nbtData.add(nbt.TAG_String("LastOutput", "")) nbtData.add(nbt.TAG_List("LastOutputParams", [])) nbtData.add(nbt.TAG_Int("SuccessCount", 0)) nbtData.add(nbt.TAG_Byte("TrackOutput", 1)) super().__init__(name, dv, nbtData)
def chestWithItemID(cls, itemID, count=64, damage=0): """ Creates a chest with a stack of 'itemID' in each slot. Optionally specify the count of items in each stack. Pass a negative value for damage to create unnaturally sturdy tools. """ root_tag = nbt.TAG_Compound() invTag = nbt.TAG_List() root_tag["Inventory"] = invTag for slot in range(9, 36): itemTag = nbt.TAG_Compound() itemTag["Slot"] = nbt.TAG_Byte(slot) itemTag["Count"] = nbt.TAG_Byte(count) itemTag["id"] = nbt.TAG_Short(itemID) itemTag["Damage"] = nbt.TAG_Short(damage) invTag.append(itemTag) chest = INVEditChest(root_tag, "") return chest
def TileEntities(self): chestTag = nbt.TAG_Compound() chestTag["id"] = nbt.TAG_String("Chest") chestTag["Items"] = nbt.TAG_List(self.root_tag["Inventory"]) chestTag["x"] = nbt.TAG_Int(0) chestTag["y"] = nbt.TAG_Int(0) chestTag["z"] = nbt.TAG_Int(0) return nbt.TAG_List([chestTag], name="TileEntities")
def identify(directory): if not (os.path.exists(os.path.join(directory, 'region')) or os.path.exists(os.path.join(directory, 'playerdata'))): return False if not (os.path.exists(os.path.join(directory, 'DIM1')) or os.path.exists(os.path.join(directory, 'DIM-1'))): return False if not (os.path.exists(os.path.join(directory, 'data')) or os.path.exists(os.path.join(directory, 'level.dat'))): return False root = nbt.load(os.path.join(directory, 'level.dat')) if 'FML' in root: return False if root.get('Data', nbt.TAG_Compound()).get('Version', nbt.TAG_Compound()).get( 'Id', nbt.TAG_Int(-1)).value < 1451: return False return True
def Create(cls, tileEntityID, **kw): tileEntityTag = nbt.TAG_Compound() tileEntityTag["id"] = nbt.TAG_String(tileEntityID) base = cls.baseStructures.get(tileEntityID, None) if base: for (name, tag) in base: tileEntityTag[name] = tag() cls.setpos(tileEntityTag, (0, 0, 0)) return tileEntityTag
def toNBT(self): root = nbt.TAG_Compound() root['BlockStates'] = nbt.TAG_Long_Array(self.__old_blockstates) root['Y'] = nbt.TAG_Byte(self._y) root['BlockLight'] = nbt.TAG_Byte_Array(self._block_light) root['SkyLight'] = nbt.TAG_Byte_Array(self._sky_light) palette = nbt.TAG_List() for block in self.palette: palette.append(block.toNBT()) root['Palette'] = self._palette return root
def _savePalette(self, layer): blocks = self.blocks[layer].swapaxes(1, 2).reshape(4096) # Y and Z saved in a inverted order blockIDs = np.empty(4096, dtype=np.uint32) palette = [] mapping = {} for i, block in enumerate(blocks): # Generate the palette nbt for the given block short = (block.name, str(block.properties)) if short not in mapping: if isinstance(block.properties, int): # 1.12 palette.append(nbt.TAG_Compound("", [nbt.TAG_String("name", block.name), nbt.TAG_Short("val", block.properties)])) else: # 1.13 palette.append(nbt.TAG_Compound("", [ nbt.TAG_String("name", block.name), nbt.TAG_Compound("states", block.properties), nbt.TAG_Int("version", 17629200) ])) mapping[short] = len(palette) - 1 blockIDs[i] = mapping[short] return palette, blockIDs
def Create(cls, tileEntityID, pos=(0, 0, 0), **kw): tileEntityTag = nbt.TAG_Compound() tileEntityTag["id"] = nbt.TAG_String(tileEntityID) base = cls.baseStructures.get(tileEntityID, None) if base: for (name, tag) in base: tileEntityTag[name] = tag() if name == "CustomName" and tileEntityID == "Control": tileEntityTag[name] = nbt.TAG_String("@") cls.setpos(tileEntityTag, pos) return tileEntityTag
def TileEntities(self): chestTag = nbt.TAG_Compound() chest_id = "Chest" split_ver = self.gameVersion.split('.') if int(split_ver[0]) >= 1 and int(split[1]) >= 11: chest_id = "minecraft:chest" chestTag["id"] = nbt.TAG_String(chest_id) chestTag["Items"] = nbt.TAG_List(self.root_tag["Inventory"]) chestTag["x"] = nbt.TAG_Int(0) chestTag["y"] = nbt.TAG_Int(0) chestTag["z"] = nbt.TAG_Int(0) return nbt.TAG_List([chestTag], name="TileEntities")
def extractZipSchematicFromIter(sourceLevel, box, zipfilename=None, entities=True): # converts classic blocks to alpha # probably should only apply to alpha levels if zipfilename is None: zipfilename = tempfile.mktemp("zipschematic") p = sourceLevel.adjustExtractionParameters(box) if p is None: return sourceBox, destPoint = p destPoint = (0, 0, 0) tempfolder = tempfile.mktemp("schematic") try: tempSchematic = MCInfdevOldLevel(tempfolder, create=True) tempSchematic.materials = sourceLevel.materials for i in tempSchematic.copyBlocksFromIter(sourceLevel, sourceBox, destPoint, entities=entities, create=True): yield i tempSchematic.saveInPlace( ) # lights not needed for this format - crashes minecraft though schematicDat = nbt.TAG_Compound() schematicDat.name = "Mega Schematic" schematicDat["Width"] = nbt.TAG_Int(sourceBox.size[0]) schematicDat["Height"] = nbt.TAG_Int(sourceBox.size[1]) schematicDat["Length"] = nbt.TAG_Int(sourceBox.size[2]) schematicDat["Materials"] = nbt.TAG_String( tempSchematic.materials.name) schematicDat.save(os.path.join(tempfolder, "schematic.dat")) zipdir(tempfolder, zipfilename) import mclevel yield mclevel.fromFile(zipfilename) finally: # We get here if the generator is GCed also if os.path.exists(tempfolder): shutil.rmtree(tempfolder, False)
def getTAGStructure(self): tag = nbt.TAG_Compound() tag["Name"] = nbt.TAG_String(self.name) tag["DisplayName"] = nbt.TAG_String(self.displayName) tag["Prefix"] = nbt.TAG_String(self.prefix) tag["Suffix"] = nbt.TAG_String(self.suffix) if self.color != None: tag["TeamColor"] = nbt.TAG_String(self.color) tag["NameTagVisibility"] = nbt.TAG_String(self.nametags) tag["DeathMessageVisibility"] = nbt.TAG_String(self.deathMessage) tag["AllowFriendlyFire"] = nbt.TAG_Byte(self.friendlyFire) tag["SeeFriendlyInvisibles"] = nbt.TAG_Byte(self.friendlyInvisibles) players = nbt.TAG_List() for member in self.teamMembers: players.append(nbt.TAG_String(member)) tag["Players"] = players return tag
def Create(cls, tileEntityID, pos=(0, 0, 0), **kw): tileEntityTag = nbt.TAG_Compound() tileEntityTag["id"] = nbt.TAG_String(tileEntityID) base = cls.baseStructures.get(tileEntityID, None) if base: for (name, tag) in base: tileEntityTag[name] = tag() if tileEntityID == "Control": if name == "CustomName": tileEntityTag[name] = nbt.TAG_String("@") elif name == "SuccessCount": tileEntityTag[name] = nbt.TAG_Int(0) elif tileEntityID == "MobSpawner": if name == "EntityId": tileEntityTag[name] = nbt.TAG_String("Pig") cls.setpos(tileEntityTag, pos) return tileEntityTag
def testModify(self): level = self.testCreate() # Most of the value types work as expected. Here, we replace the entire tag with a TAG_String level["About"]["Author"] = nbt.TAG_String("YARRR~!") # Because the tag type usually doesn't change, # we can replace the string tag's value instead of replacing the entire tag. level["About"]["Author"].value = "Stew Pickles" # Remove members of a TAG_Compound using del, similar to a python dict. del (level["About"]) # Replace all of the wood blocks with gold using a boolean index array blocks = level["Map"]["Blocks"].value blocks[blocks == 5] = 41 level["Entities"][0] = nbt.TAG_Compound([ nbt.TAG_String("Creeper", "id"), nbt.TAG_List([nbt.TAG_Double(d) for d in (1, 1, 1)], "Pos") ])
def Create(cls, entityID, **kw): entityTag = nbt.TAG_Compound() entityTag["id"] = nbt.TAG_String(entityID) Entity.setpos(entityTag, (0, 0, 0)) return entityTag
if __name__ == '__main__': #obj = BlockstateRegionFile('C:\\Users\\gotharbg\\Documents\\MC Worlds\\1.13 World\\region\\r.0.0.mca') #obj2 = BlockstateRegionFile('C:\\Users\\gotharbg\\Downloads\\Podshot 1_13 Snapshot\\region\\r.0.0.mca') # world = BlockstateWorld( 'C:\\Users\\gotharbg\\Documents\\Python Projects\\WorldRewriteProto\\tests\\1.13 World' ) save_test = BlockstateRegionFile( world, 'C:\\Users\\gotharbg\\Documents\\Python Projects\\WorldRewriteProto\\tests\\1.13 World\\r.0.0.mca' ) chunk = save_test.getChunk(0, 0) te = nbt.TAG_Compound() te['id'] = nbt.TAG_String('bed') te['x'] = nbt.TAG_Int(1) te['y'] = nbt.TAG_Int(5) te['z'] = nbt.TAG_Int(1) te['color'] = nbt.TAG_Int(15) chunk.TileEntities.append(te) chunk.save() #chunk = obj.getChunk(0,0) #print(chunk.Blocks[0,3,0]) #print(chunk.TileEntities) #chunk.TileEntities.append({'test': 'value'}) #chunk2 = obj2.getChunk(0,0) #print(chunk.TileEntities) #for i in xrange(16):
def save(self, filename=""): structure_tag = nbt.TAG_Compound() blocks_tag = nbt.TAG_List() palette_tag = nbt.TAG_List() entities_tag = nbt.TAG_List() palette = [] if not self._author: self._author = "MCEdit-Unified v{}".format(RELEASE_TAG) structure_tag["author"] = nbt.TAG_String(self._author) if self._version: structure_tag["DataVersion"] = nbt.TAG_Int(self.Version) else: structure_tag["DataVersion"] = nbt.TAG_Int( self.SUPPORTED_VERSIONS[-1]) structure_tag["size"] = nbt.TAG_List([ nbt.TAG_Int(self.Size[0]), nbt.TAG_Int(self.Size[1]), nbt.TAG_Int(self.Size[2]) ]) blockstate_api = BlockstateAPI.material_map.get( self._mat, BlockstateAPI.material_map[alphaMaterials]) for z in xrange( self._blocks.shape[2] ): # For some reason, ndenumerate() didn't work, but this does for x in xrange(self._blocks.shape[0]): for y in xrange(self._blocks.shape[1]): value = self._blocks[x, y, z] name, properties = blockstate_api.idToBlockstate(*value) blockstate = blockstate_api.stringifyBlockstate( name, properties) #if blockstate not in index_table: # index_table[blockstate] = len(index_table) #index = index_table[blockstate] if blockstate not in palette: palette.append(blockstate) index = palette.index(blockstate) block = nbt.TAG_Compound() block["state"] = nbt.TAG_Int(index) block["pos"] = nbt.TAG_List( [nbt.TAG_Int(x), nbt.TAG_Int(y), nbt.TAG_Int(z)]) if self._tile_entities[x, y, z]: block["nbt"] = self._tile_entities[x, y, z] blocks_tag.append(block) structure_tag["blocks"] = blocks_tag for blockstate in palette: name, properties = blockstate_api.deStringifyBlockstate(blockstate) state = nbt.TAG_Compound() state["Name"] = nbt.TAG_String(name) if properties: props = nbt.TAG_Compound() for (key, value) in properties.iteritems(): props[key] = nbt.TAG_String(value) state["Properties"] = props palette_tag.insert(palette.index(blockstate), state) structure_tag["palette"] = palette_tag for e in self._entities: entity = nbt.TAG_Compound() pos = e["Pos"] entity["pos"] = pos entity["nbt"] = e blockPos = nbt.TAG_List() for coord in pos: blockPos.append(nbt.TAG_Int(math.floor(coord.value))) entity["blockPos"] = blockPos entities_tag.append(entity) structure_tag["entities"] = entities_tag structure_tag.save(filename)
def __init__(self, shape=None, root_tag=None, filename=None, mats='Alpha'): """ shape is (x,y,z) for a new level's shape. if none, takes root_tag as a TAG_Compound for an existing schematic file. if none, tries to read the tag from filename. if none, results are undefined. materials can be a MCMaterials instance, or one of "Classic", "Alpha", "Pocket" to indicate allowable blocks. The default is Alpha. block coordinate order in the file is y,z,x to use the same code as classic/indev levels. in hindsight, this was a completely arbitrary decision. the Entities and TileEntities are nbt.TAG_List objects containing TAG_Compounds. this makes it easy to copy entities without knowing about their insides. rotateLeft swaps the axes of the different arrays. because of this, the Width, Height, and Length reflect the current dimensions of the schematic rather than the ones specified in the NBT structure. I'm not sure what happens when I try to re-save a rotated schematic. """ if filename: self.filename = filename if None is root_tag and os.path.exists(filename): root_tag = nbt.load(filename) else: self.filename = None if mats in namedMaterials: self.materials = namedMaterials[mats] else: assert (isinstance(mats, MCMaterials)) self.materials = mats if root_tag: self.root_tag = root_tag if "Materials" in root_tag: self.materials = namedMaterials[self.Materials] else: root_tag["Materials"] = nbt.TAG_String(self.materials.name) w = self.root_tag["Width"].value l = self.root_tag["Length"].value h = self.root_tag["Height"].value self._Blocks = self.root_tag["Blocks"].value.astype('uint16').reshape(h, l, w) # _Blocks is y, z, x del self.root_tag["Blocks"] if "AddBlocks" in self.root_tag: # Use WorldEdit's "AddBlocks" array to load and store the 4 high bits of a block ID. # Unlike Minecraft's NibbleArrays, this array stores the first block's bits in the # 4 high bits of the first byte. size = (h * l * w) # If odd, add one to the size to make sure the adjacent slices line up. add = zeros(size + (size & 1), 'uint16') # Fill the even bytes with data add[::2] = self.root_tag["AddBlocks"].value # Copy the low 4 bits to the odd bytes add[1::2] = add[::2] & 0xf # Shift the even bytes down add[::2] >>= 4 # Shift every byte up before merging it with Blocks add <<= 8 self._Blocks |= add[:size].reshape(h, l, w) del self.root_tag["AddBlocks"] self.root_tag["Data"].value = self.root_tag["Data"].value.reshape(h, l, w) if "Biomes" in self.root_tag: self.root_tag["Biomes"].value.shape = (l, w) else: assert shape is not None root_tag = nbt.TAG_Compound(name="Schematic") root_tag["Height"] = nbt.TAG_Short(shape[1]) root_tag["Length"] = nbt.TAG_Short(shape[2]) root_tag["Width"] = nbt.TAG_Short(shape[0]) root_tag["Entities"] = nbt.TAG_List() root_tag["TileEntities"] = nbt.TAG_List() root_tag["Materials"] = nbt.TAG_String(self.materials.name) self._Blocks = zeros((shape[1], shape[2], shape[0]), 'uint16') root_tag["Data"] = nbt.TAG_Byte_Array(zeros((shape[1], shape[2], shape[0]), uint8)) root_tag["Biomes"] = nbt.TAG_Byte_Array(zeros((shape[2], shape[0]), uint8)) self.root_tag = root_tag self.root_tag["Data"].value &= 0xF # discard high bits
def saveToFile(self, filename=None): if filename is None: filename = self.filename if filename is None: log.warn(u"Attempted to save an unnamed file in place") return # you fool! self.Data <<= 4 self.Data |= (self.BlockLight & 0xf) self.Blocks = swapaxes(self.Blocks, 0, 2) self.Data = swapaxes(self.Data, 0, 2) mapTag = nbt.TAG_Compound() mapTag["Width"] = nbt.TAG_Short(self.Width) mapTag["Height"] = nbt.TAG_Short(self.Height) mapTag["Length"] = nbt.TAG_Short(self.Length) mapTag["Blocks"] = nbt.TAG_Byte_Array(self.Blocks) mapTag["Data"] = nbt.TAG_Byte_Array(self.Data) self.Blocks = swapaxes(self.Blocks, 0, 2) self.Data = swapaxes(self.Data, 0, 2) mapTag[Spawn] = nbt.TAG_List([nbt.TAG_Short(i) for i in self.Spawn]) self.root_tag["Map"] = mapTag self.Entities.append(self.LocalPlayer) # fix up Entities imported from Alpha worlds def numbersToFloats(ent): for attr in "Motion", "Pos": if attr in ent: ent[attr] = nbt.TAG_List([nbt.TAG_Double(t.value) for t in ent[attr]]) for ent in self.Entities: numbersToFloats(ent) # fix up TileEntities imported from Alpha worlds. for ent in self.TileEntities: if "Pos" not in ent and all(c in ent for c in 'xyz'): ent["Pos"] = nbt.TAG_Int(self.encodePos(ent['x'].value, ent['y'].value, ent['z'].value)) # output_file = gzip.open(self.filename, "wb", compresslevel=1) try: os.rename(filename, filename + ".old") except Exception: pass try: self.root_tag.save(filename) except: os.rename(filename + ".old", filename) try: os.remove(filename + ".old") except Exception: pass self.Entities.remove(self.LocalPlayer) self.BlockLight = self.Data & 0xf self.Data >>= 4
def __init__(self, root_tag=None, filename=""): self.Width = 0 self.Height = 0 self.Length = 0 self.Blocks = array([], "uint8") self.Data = array([], "uint8") self.Spawn = (0, 0, 0) self.filename = filename if root_tag: self.root_tag = root_tag mapTag = root_tag["Map"] self.Width = mapTag["Width"].value self.Length = mapTag["Length"].value self.Height = mapTag["Height"].value mapTag["Blocks"].value.shape = (self.Height, self.Length, self.Width) self.Blocks = swapaxes(mapTag["Blocks"].value, 0, 2) mapTag["Data"].value.shape = (self.Height, self.Length, self.Width) self.Data = swapaxes(mapTag["Data"].value, 0, 2) self.BlockLight = self.Data & 0xf self.Data >>= 4 self.Spawn = [mapTag[Spawn][i].value for i in range(3)] if "Entities" not in root_tag: root_tag["Entities"] = nbt.TAG_List() self.Entities = root_tag["Entities"] # xxx fixup Motion and Pos to match infdev format def numbersToDoubles(ent): for attr in "Motion", "Pos": if attr in ent: ent[attr] = nbt.TAG_List([nbt.TAG_Double(t.value) for t in ent[attr]]) for ent in self.Entities: numbersToDoubles(ent) if "TileEntities" not in root_tag: root_tag["TileEntities"] = nbt.TAG_List() self.TileEntities = root_tag["TileEntities"] # xxx fixup TileEntities positions to match infdev format for te in self.TileEntities: pos = te["Pos"].value (x, y, z) = self.decodePos(pos) TileEntity.setpos(te, (x, y, z)) localPlayerList = [tag for tag in root_tag["Entities"] if tag['id'].value == 'LocalPlayer'] if len(localPlayerList) == 0: # omen doesn't make a player entity playerTag = nbt.TAG_Compound() playerTag['id'] = nbt.TAG_String('LocalPlayer') playerTag['Pos'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(64.), nbt.TAG_Float(0.)]) playerTag['Rotation'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(45.)]) self.LocalPlayer = playerTag else: self.LocalPlayer = localPlayerList[0] else: log.info(u"Creating new Indev levels is not yet implemented.!") raise ValueError("Can't do that yet")
def __init__(self, root_tag=None, filename=""): self.Width = 0 self.Height = 0 self.Length = 0 self.Blocks = array([], uint8) self.Data = array([], uint8) self.Spawn = (0, 0, 0) self.filename = filename if root_tag: self.root_tag = root_tag mapTag = root_tag[Map] self.Width = mapTag[Width].value self.Length = mapTag[Length].value self.Height = mapTag[Height].value mapTag[Blocks].value.shape = (self.Height, self.Length, self.Width) self.Blocks = swapaxes(mapTag[Blocks].value, 0, 2) mapTag[Data].value.shape = (self.Height, self.Length, self.Width) self.Data = swapaxes(mapTag[Data].value, 0, 2) self.BlockLight = self.Data & 0xf self.Data >>= 4 self.Spawn = [mapTag[Spawn][i].value for i in range(3)] if not Entities in root_tag: root_tag[Entities] = nbt.TAG_List() self.Entities = root_tag[Entities] # xxx fixup Motion and Pos to match infdev format def numbersToDoubles(ent): for attr in "Motion", "Pos": if attr in ent: ent[attr] = nbt.TAG_List( [nbt.TAG_Double(t.value) for t in ent[attr]]) for ent in self.Entities: numbersToDoubles(ent) if not TileEntities in root_tag: root_tag[TileEntities] = nbt.TAG_List() self.TileEntities = root_tag[TileEntities] # xxx fixup TileEntities positions to match infdev format for te in self.TileEntities: pos = te["Pos"].value (x, y, z) = self.decodePos(pos) TileEntity.setpos(te, (x, y, z)) if len( filter(lambda x: x['id'].value == 'LocalPlayer', root_tag[Entities]) ) == 0: # omen doesn't make a player entity p = nbt.TAG_Compound() p['id'] = nbt.TAG_String('LocalPlayer') p['Pos'] = nbt.TAG_List( [nbt.TAG_Float(0.), nbt.TAG_Float(64.), nbt.TAG_Float(0.)]) p['Rotation'] = nbt.TAG_List( [nbt.TAG_Float(0.), nbt.TAG_Float(45.)]) root_tag[Entities].append(p) # self.saveInPlace() else: info(u"Creating new Indev levels is not yet implemented.!") raise ValueError("Can't do that yet")
def __init__(self, shape=None, root_tag=None, filename=None, mats='Alpha'): """ shape is (x,y,z) for a new level's shape. if none, takes root_tag as a TAG_Compound for an existing schematic file. if none, tries to read the tag from filename. if none, results are undefined. materials can be a MCMaterials instance, or one of "Classic", "Alpha", "Pocket" to indicate allowable blocks. The default is Alpha. block coordinate order in the file is y,z,x to use the same code as classic/indev levels. in hindsight, this was a completely arbitrary decision. the Entities and TileEntities are nbt.TAG_List objects containing TAG_Compounds. this makes it easy to copy entities without knowing about their insides. rotateLeft swaps the axes of the different arrays. because of this, the Width, Height, and Length reflect the current dimensions of the schematic rather than the ones specified in the NBT structure. I'm not sure what happens when I try to re-save a rotated schematic. """ # if(shape != None): # self.setShape(shape) if filename: self.filename = filename if None is root_tag and os.path.exists(filename): root_tag = nbt.load(filename) else: self.filename = None if mats in namedMaterials: self.materials = namedMaterials[mats] else: assert (isinstance(mats, MCMaterials)) self.materials = mats if root_tag: self.root_tag = root_tag if "Materials" in root_tag: self.materials = namedMaterials[self.Materials] else: root_tag["Materials"] = nbt.TAG_String(self.materials.name) self.shapeChunkData() else: assert shape is not None root_tag = nbt.TAG_Compound(name="Schematic") root_tag["Height"] = nbt.TAG_Short(shape[1]) root_tag["Length"] = nbt.TAG_Short(shape[2]) root_tag["Width"] = nbt.TAG_Short(shape[0]) root_tag["Entities"] = nbt.TAG_List() root_tag["TileEntities"] = nbt.TAG_List() root_tag["Materials"] = nbt.TAG_String(self.materials.name) root_tag["Blocks"] = nbt.TAG_Byte_Array( zeros((shape[1], shape[2], shape[0]), uint8)) root_tag["Data"] = nbt.TAG_Byte_Array( zeros((shape[1], shape[2], shape[0]), uint8)) self.root_tag = root_tag self.packUnpack() self.root_tag["Data"].value &= 0xF # discard high bits