예제 #1
0
    def _createMetadataTag(self, random_seed=None):
        """
        Create a level.dat for a newly created world or a world found with damaged level.dat/.dat_old (xxx repair in
        WorldEditor?)
        :param random_seed:
        :type random_seed:
        :return:
        :rtype:
        """
        metadataTag = nbt.TAG_Compound()
        metadataTag["Data"] = nbt.TAG_Compound()
        metadataTag["Data"]["SpawnX"] = nbt.TAG_Int(0)
        metadataTag["Data"]["SpawnY"] = nbt.TAG_Int(2)
        metadataTag["Data"]["SpawnZ"] = nbt.TAG_Int(0)

        last_played = long(time.time() * 1000)
        if random_seed is None:
            random_seed = long(random.random() * 0xffffffffffffffffL) - 0x8000000000000000L

        metadataTag["Data"]['version'] = nbt.TAG_Int(VERSION_ANVIL)

        self.metadata = AnvilWorldMetadata(metadataTag)

        self.metadata.LastPlayed = long(last_played)
        self.metadata.RandomSeed = long(random_seed)
        self.metadata.SizeOnDisk = 0
        self.metadata.Time = 1
        self.metadata.LevelName = os.path.basename(self.filename)
예제 #2
0
    def createPlayer(self, playerUUID=""):
        """
        Create a new player with the given name and return the PlayerRef. Raises some kind of IOError if the player
         could not be created.

        :param playerUUID:
        :type playerUUID: str
        :return:
        :rtype: PCPlayer
        """
        if self.readonly:
            raise IOError("World is opened read only.")

        playerFilePath = "playerdata/%s.dat" % playerUUID

        if playerUUID == "":
            if "Player" in self.metadata.rootTag["Data"]:
                raise IOError("Single-player player already exists.")
            playerTag = nbt.TAG_Compound()
            self.metadata.rootTag["Data"]["Player"] = playerTag
        else:
            if self.selectedRevision.containsFile(playerFilePath):
                raise ValueError("Cannot create player %s: already exists.")

            playerTag = nbt.TAG_Compound()

        player = AnvilPlayerRef(playerTag, self)
        nbtattr.SetNBTDefaults(player)

        if playerUUID != "Player":
            self.checkSessionLock()
            self.selectedRevision.writeFile(playerFilePath, playerTag.save())

        return self.getPlayer(playerUUID)
예제 #3
0
 def create(cls, mapID, adapter, width=128, height=128):
     mapTag = nbt.TAG_Compound()
     mapDataTag = nbt.TAG_Compound()
     mapTag["data"] = mapDataTag
     mapDataTag["colors"] = nbt.TAG_Byte_Array(numpy.zeros((width * height,), dtype=numpy.uint8))
     mapData = cls(mapTag, mapID, adapter)
     mapData.dimension = 0
     mapData.width = width
     mapData.height = height
     mapData.scale = 1
     mapData.xCenter = -1 << 30
     mapData.zCenter = -1 << 30
     return mapData
예제 #4
0
    def readChunk(self, cx, cz, dimName, create=False):
        """
        Creates a FakeChunkData object representing the chunk at the given
        position. Subclasses may choose to override
        fakeBlocksForChunk and fakeDataForChunk to provide block and blockdata arrays.
        They may instead override getChunk and return a ChunkBase subclass.

        By default, returns a chunk whose ``Blocks`` is made from slices of self.Blocks (and
        ``Data`` from self.Data if present)
        """
        if not self.bounds.containsChunk(cx, cz):
            raise ChunkNotPresent((cx, cz))
        chunk = self.ChunkDataClass()
        chunk.dimension = self
        chunk.cx = cx
        chunk.cz = cz
        chunk.dimName = dimName

        chunk.Blocks = self.fakeBlocksForChunk(cx, cz)

        chunk.Data = self.fakeDataForChunk(cx, cz)

        whiteLight = zeros_like(chunk.Blocks)
        whiteLight[:] = 15

        chunk.BlockLight = whiteLight
        chunk.SkyLight = whiteLight

        chunk.Entities, chunk.TileEntities = self.fakeEntitiesForChunk(cx, cz)

        chunk.rootTag = nbt.TAG_Compound()

        return chunk
예제 #5
0
    def _create(self):
        shape = 16, 16, 16
        self.Y = 0

        self.Blocks = numpy.zeros(shape, 'uint16')
        self.Data = numpy.zeros(shape, 'uint8')
        self.SkyLight = numpy.zeros(shape, 'uint8')
        self.BlockLight = numpy.zeros(shape, 'uint8')
        self.old_section_tag = nbt.TAG_Compound()
예제 #6
0
    def TileEntities(self):
        chestTag = nbt.TAG_Compound()
        chestTag["id"] = nbt.TAG_String("Chest")
        chestTag["Items"] = nbt.TAG_List(self.rootTag["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")
예제 #7
0
    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. """
        rootTag = nbt.TAG_Compound()
        invTag = nbt.TAG_List()
        rootTag["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(rootTag, "")

        return chest
예제 #8
0
    def _create(self):
        chunkTag = nbt.TAG_Compound()
        chunkTag.name = ""

        levelTag = nbt.TAG_Compound()
        chunkTag["Level"] = levelTag

        levelTag["HeightMap"] = nbt.TAG_Int_Array(numpy.zeros((16, 16), 'uint32').newbyteorder())
        levelTag["TerrainPopulated"] = nbt.TAG_Byte(1)
        levelTag["xPos"] = nbt.TAG_Int(self.cx)
        levelTag["zPos"] = nbt.TAG_Int(self.cz)

        levelTag["LastUpdate"] = nbt.TAG_Long(0)

        levelTag["Entities"] = nbt.TAG_List()
        levelTag["TileEntities"] = nbt.TAG_List()

        self.rootTag = chunkTag

        self.dirty = True
예제 #9
0
def SetNBTDefaults(ref):
    """
    Given an object whose class has several members of type `NBT[*]Attr`,
    sets those attributes to their default values.
    """
    cls = ref.__class__
    for k, v in cls.__dict__.iteritems():
        if isinstance(v, NBTCompoundAttr):
            ref.rootTag[k] = nbt.TAG_Compound()
            SetNBTDefaults(getattr(ref, k))
        elif isinstance(v, (NBTAttr, NBTListAttr)):
            if v.default is not None:
                setattr(ref, k, v.default)
예제 #10
0
    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")])
예제 #11
0
    def createMap(self):
        # idcounts.dat should hold the ID number of the last created map
        # but we can't trust it because of bugs in the old map import filters
        mapIDs = list(self.listMaps())
        if len(mapIDs):
            maximumID = max(mapIDs)
            mapID = maximumID + 1
        else:
            mapID = 0

        idcountsTag = nbt.TAG_Compound()
        idcountsTag["map"] = nbt.TAG_Short(mapID)

        # idcounts.dat is not compressed.
        self.selectedRevision.writeFile("data/idcounts.dat", idcountsTag.save(compressed=False))

        mapData = AnvilMapData.create(mapID, self)

        mapData.save()
        return mapData
예제 #12
0
    def saveToFile(self, filename):
        super(ZipSchematic, self).saveChanges()
        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.blocktypes.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)) as z:
            for root, dirs, files in os.walk(basedir):
                # NOTE: ignore empty directories
                for fn in files:
                    absfn = os.path.join(root, fn)
                    zfn = absfn[len(basedir) +
                                len(os.sep):]  # XXX: relative path
                    z.write(absfn, zfn)
예제 #13
0
 def create(cls):
     rootTag = nbt.TAG_Compound()
     ref = cls(rootTag)
     nbtattr.SetNBTDefaults(ref)
     return ref
예제 #14
0
def itemIDMapping(blocktypes):
    mapping = nbt.TAG_Compound()
    for name, ID in blocktypes.itemTypes.IDsByInternalName.iteritems():
        mapping[str(ID)] = nbt.TAG_String(name)
    return mapping
예제 #15
0
    def __init__(self,
                 shape=None,
                 filename=None,
                 blocktypes='Alpha',
                 readonly=False,
                 resume=False):
        """
        Creates an object which stores a section of a Minecraft world as an
        NBT structure. The order of the coordinates for the block arrays in
        the file is y,z,x. This is the same order used in Minecraft 1.4's
        chunk sections.

        :type shape: tuple
        :param shape: The shape of the schematic as (x, y, z)
        :type filename: basestring
        :param filename: Path to a file to load a saved schematic from.
        :type blocktypes: basestring or BlockTypeSet
        :param blocktypes: The name of a builtin blocktypes set (one of
            "Classic", "Alpha", "Pocket") to indicate allowable blocks. The default
            is Alpha. An instance of BlockTypeSet may be passed instead.
        :rtype: SchematicFileAdapter

        """
        if filename is None and shape is None:
            raise ValueError("shape or filename required to create %s" %
                             self.__class__.__name__)

        if filename:
            self.filename = filename
            if os.path.exists(filename):
                rootTag = nbt.load(filename)
            else:
                rootTag = None
        else:
            self.filename = None
            rootTag = None

        if blocktypes in blocktypes_named:
            self.blocktypes = blocktypes_named[blocktypes]
        else:
            assert (isinstance(blocktypes, BlockTypeSet))
            self.blocktypes = blocktypes

        if rootTag:
            self.rootTag = rootTag
            if "Materials" in rootTag:
                self.blocktypes = blocktypes_named[self.Materials]
            else:
                rootTag["Materials"] = nbt.TAG_String(self.blocktypes.name)

            w = self.rootTag["Width"].value
            l = self.rootTag["Length"].value
            h = self.rootTag["Height"].value

            assert self.rootTag["Blocks"].value.size == w * l * h
            self._Blocks = self.rootTag["Blocks"].value.astype(
                'uint16').reshape(h, l, w)  # _Blocks is y, z, x

            del self.rootTag["Blocks"]
            if "AddBlocks" in self.rootTag:
                # 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 = numpy.empty(size + (size & 1), 'uint16')

                # Fill the even bytes with data
                add[::2] = self.rootTag["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.rootTag["AddBlocks"]

            self.rootTag["Data"].value = self.rootTag["Data"].value.reshape(
                h, l, w)

            if "Biomes" in self.rootTag:
                self.rootTag["Biomes"].value.shape = (l, w)

        else:
            rootTag = nbt.TAG_Compound(name="Schematic")
            rootTag["Height"] = nbt.TAG_Short(shape[1])
            rootTag["Length"] = nbt.TAG_Short(shape[2])
            rootTag["Width"] = nbt.TAG_Short(shape[0])

            rootTag["Entities"] = nbt.TAG_List()
            rootTag["TileEntities"] = nbt.TAG_List()
            rootTag["Materials"] = nbt.TAG_String(self.blocktypes.name)

            self._Blocks = zeros((shape[1], shape[2], shape[0]), 'uint16')
            rootTag["Data"] = nbt.TAG_Byte_Array(
                zeros((shape[1], shape[2], shape[0]), uint8))

            rootTag["Biomes"] = nbt.TAG_Byte_Array(
                zeros((shape[2], shape[0]), uint8))

            self.rootTag = rootTag

        #expand blocks and data to chunk edges
        h16 = (self.Height + 15) & ~0xf
        l16 = (self.Length + 15) & ~0xf
        w16 = (self.Width + 15) & ~0xf

        blocks = self._Blocks
        self._Blocks = numpy.zeros((h16, l16, w16), blocks.dtype)
        self._Blocks[:blocks.shape[0], :blocks.shape[1], :blocks.
                     shape[2]] = blocks

        data = self.rootTag["Data"].value
        self.rootTag["Data"].value = numpy.zeros((h16, l16, w16), data.dtype)
        self.rootTag["Data"].value[:data.shape[0], :data.shape[1], :data.
                                   shape[2]] = data

        self.rootTag["Data"].value &= 0xF  # discard high bits

        self.Entities = [
            self.EntityRef(tag) for tag in self.rootTag["Entities"]
        ]
        self.TileEntities = [
            self.EntityRef(tag) for tag in self.rootTag["TileEntities"]
        ]
예제 #16
0
    def __init__(self,
                 shape=None,
                 filename=None,
                 blocktypes='Alpha',
                 readonly=False,
                 resume=False):
        """
        Creates an object which stores a section of a Minecraft world as an
        NBT structure. The order of the coordinates for the block arrays in
        the file is y,z,x. This is the same order used in Minecraft 1.4's
        chunk sections.

        :type shape: tuple
        :param shape: The shape of the schematic as (x, y, z)
        :type filename: basestring
        :param filename: Path to a file to load a saved schematic from.
        :type blocktypes: basestring or BlockTypeSet
        :param blocktypes: The name of a builtin blocktypes set (one of
            "Classic", "Alpha", "Pocket") to indicate allowable blocks. The default
            is Alpha. An instance of BlockTypeSet may be passed instead.
        :rtype: SchematicFileAdapter

        """
        self.EntityRef = PCEntityRef
        self.TileEntityRef = PCTileEntityRef

        if filename is None and shape is None:
            raise ValueError("shape or filename required to create %s" %
                             self.__class__.__name__)

        if filename:
            self.filename = filename
            if os.path.exists(filename):
                rootTag = nbt.load(filename)
            else:
                rootTag = None
        else:
            self.filename = None
            rootTag = None

        if blocktypes in blocktypeClassesByName:
            self.blocktypes = blocktypeClassesByName[blocktypes]()
        else:
            assert (isinstance(blocktypes, BlockTypeSet))
            self.blocktypes = blocktypes

        if rootTag:
            self.rootTag = rootTag
            if "Materials" in rootTag:
                self.blocktypes = blocktypeClassesByName[self.Materials]()
            else:
                rootTag["Materials"] = nbt.TAG_String(self.blocktypes.name)

            w = self.rootTag["Width"].value
            l = self.rootTag["Length"].value
            h = self.rootTag["Height"].value

            assert self.rootTag["Blocks"].value.size == w * l * h
            self._Blocks = self.rootTag["Blocks"].value.astype(
                'uint16').reshape(h, l, w)  # _Blocks is y, z, x

            del self.rootTag["Blocks"]
            if "AddBlocks" in self.rootTag:
                # 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 = numpy.empty(size + (size & 1), 'uint16')

                # Fill the even bytes with data
                add[::2] = self.rootTag["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.rootTag["AddBlocks"]

            self.rootTag["Data"].value = self.rootTag["Data"].value.reshape(
                h, l, w)

            if "Biomes" in self.rootTag:
                self.rootTag["Biomes"].value.shape = (l, w)

            # If BlockIDs is present, it contains an ID->internalName mapping
            # from the source level's FML tag.

            if "BlockIDs" in self.rootTag:
                self.blocktypes.addBlockIDsFromSchematicTag(
                    self.rootTag["BlockIDs"])

            # If itemStackVersion is present, it was exported from MCEdit 2.0.
            # Its value is either 17 or 18, the values of the version constants.
            # ItemIDs will also be present.

            # If itemStackVersion is not present, this schematic was exported from
            # WorldEdit or MCEdit 1.0. The itemStackVersion cannot be determined
            # without searching the entities for an itemStack and checking
            # the type of its `id` tag. If no itemStacks are found, the
            # version defaults to 1.8 which does not need an ItemIDs tag.

            if "itemStackVersion" in self.rootTag:
                itemStackVersion = self.rootTag["itemStackVersion"].value
                if itemStackVersion not in (VERSION_1_7, VERSION_1_8):
                    raise LevelFormatError("Unknown item stack version %d" %
                                           itemStackVersion)
                if itemStackVersion == VERSION_1_7:
                    itemIDs = self.rootTag.get("ItemIDs")
                    if itemIDs is not None:
                        self.blocktypes.addItemIDsFromSchematicTag(itemIDs)

                self.blocktypes.itemStackVersion = itemStackVersion
            else:
                self.blocktypes.itemStackVersion = self.getItemStackVersionFromEntities(
                )

        else:
            rootTag = nbt.TAG_Compound(name="Schematic")
            rootTag["Height"] = nbt.TAG_Short(shape[1])
            rootTag["Length"] = nbt.TAG_Short(shape[2])
            rootTag["Width"] = nbt.TAG_Short(shape[0])

            rootTag["Entities"] = nbt.TAG_List()
            rootTag["TileEntities"] = nbt.TAG_List()
            rootTag["Materials"] = nbt.TAG_String(self.blocktypes.name)
            rootTag["itemStackVersion"] = nbt.TAG_Byte(
                self.blocktypes.itemStackVersion)

            self._Blocks = zeros((shape[1], shape[2], shape[0]), 'uint16')
            rootTag["Data"] = nbt.TAG_Byte_Array(
                zeros((shape[1], shape[2], shape[0]), uint8))

            rootTag["Biomes"] = nbt.TAG_Byte_Array(
                zeros((shape[2], shape[0]), uint8))

            self.rootTag = rootTag

            self.rootTag["BlockIDs"] = blockIDMapping(blocktypes)
            itemMapping = itemIDMapping(blocktypes)
            if itemMapping is not None:
                self.rootTag[
                    "ItemIDs"] = itemMapping  # Only present for Forge 1.7

        # Expand blocks and data to chunk edges
        h16 = (self.Height + 15) & ~0xf
        l16 = (self.Length + 15) & ~0xf
        w16 = (self.Width + 15) & ~0xf

        blocks = self._Blocks
        self._Blocks = numpy.zeros((h16, l16, w16), blocks.dtype)
        self._Blocks[:blocks.shape[0], :blocks.shape[1], :blocks.
                     shape[2]] = blocks

        data = self.rootTag["Data"].value
        self.rootTag["Data"].value = numpy.zeros((h16, l16, w16), data.dtype)
        self.rootTag["Data"].value[:data.shape[0], :data.shape[1], :data.
                                   shape[2]] = data

        self.rootTag["Data"].value &= 0xF  # discard high bits

        self.entitiesByChunk = defaultdict(list)
        for tag in self.rootTag["Entities"]:
            ref = self.EntityRef(tag)
            pos = ref.Position
            cx, cy, cz = pos.chunkPos()
            self.entitiesByChunk[cx, cz].append(tag)

        self.tileEntitiesByChunk = defaultdict(list)
        for tag in self.rootTag["TileEntities"]:
            ref = self.TileEntityRef(tag)
            pos = ref.Position
            cx, cy, cz = pos.chunkPos()
            self.tileEntitiesByChunk[cx, cz].append(tag)
예제 #17
0
def created_nbt():

    # 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["About"]["CreatedOn"] = nbt.TAG_Long(time.time())

    level["Environment"] = nbt.TAG_Compound()
    level["Environment"]["SkyBrightness"] = nbt.TAG_Byte(16)
    level["Environment"]["SurroundingWaterHeight"] = nbt.TAG_Short(32)
    level["Environment"]["FogColor"] = nbt.TAG_Int(0xcccccc)

    entity = nbt.TAG_Compound()
    entity["id"] = nbt.TAG_String("Creeper")
    entity["Pos"] = nbt.TAG_List(
        [nbt.TAG_Float(d) for d in (32.5, 64.0, 33.3)])

    level["Entities"] = nbt.TAG_List([entity])

    spawn = nbt.TAG_List(
        (nbt.TAG_Short(100), nbt.TAG_Short(45), nbt.TAG_Short(55)))

    mapTag = nbt.TAG_Compound()
    mapTag["Spawn"] = spawn
    level["Map"] = mapTag

    mapTag2 = nbt.TAG_Compound([spawn])
    mapTag2.name = "Map"

    # 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)

    # Save a few more tag types for completeness

    level["ShortArray"] = nbt.TAG_Short_Array(
        numpy.zeros((16, 16), dtype='uint16'))
    level["IntArray"] = nbt.TAG_Int_Array(numpy.zeros((16, 16),
                                                      dtype='uint32'))
    level["Float"] = nbt.TAG_Float(0.3)

    return level
예제 #18
0
def exportStructure(filename,
                    dim,
                    selection,
                    author=None,
                    excludedBlocks=None):
    """

    Parameters
    ----------
    filename : unicode
    dim : mceditlib.worldeditor.WorldEditorDimension
    selection : mceditlib.selection.SelectionBox

    Returns
    -------

    """

    excludedBlocks = set(excludedBlocks or [])

    rootTag = nbt.TAG_Compound()
    rootTag['author'] = nbt.TAG_String(author or "Anonymous")
    rootTag['version'] = nbt.TAG_Int(1)
    rootTag['size'] = nbt.TAG_List([nbt.TAG_Int(s) for s in selection.size])
    entities = rootTag['entities'] = nbt.TAG_List(list_type=nbt.ID_COMPOUND)
    blocks = rootTag['blocks'] = nbt.TAG_List(list_type=nbt.ID_COMPOUND)
    palette = rootTag['palette'] = nbt.TAG_List(list_type=nbt.ID_COMPOUND)

    ox, oy, oz = selection.origin

    paletteIDs = {}
    for x, y, z in selection.positions:
        block = dim.getBlock(x, y, z)
        if block in excludedBlocks:
            continue

        paletteIdx = paletteIDs.get(block.nameAndState, None)
        if paletteIdx is None:
            paletteTag = nbt.TAG_Compound()
            paletteTag['Name'] = nbt.TAG_String(block.internalName)
            if len(block.stateDict):
                paletteTag['Properties'] = nbt.TAG_Compound()
                for k, v in block.stateDict.iteritems():
                    paletteTag['Properties'][k] = nbt.TAG_String(v)

            paletteIdx = paletteIDs[block.nameAndState] = len(palette)
            palette.append(paletteTag)

        blockTag = nbt.TAG_Compound()
        blockTag['state'] = nbt.TAG_Int(paletteIdx)
        blockTag['pos'] = nbt.TAG_List(
            [nbt.TAG_Int(a) for a in x - ox, y - oy, z - oz])

        tileEntity = dim.getTileEntity((x, y, z))
        if tileEntity:
            tileEntity = tileEntity.copyWithOffset(-selection.origin)
            blockTag['nbt'] = tileEntity.rootTag
        blocks.append(blockTag)

    for entity in dim.getEntities(selection):
        entity = entity.copyWithOffset(-selection.origin)
        entityTag = nbt.TAG_Compound()
        entityTag['pos'] = nbt.TAG_List(
            [nbt.TAG_Double(a) for a in entity.Position])
        entityTag['blockPos'] = nbt.TAG_List(
            [nbt.TAG_Int(int(floor(a))) for a in entity.Position])
        entityTag['nbt'] = entity.rootTag
        entities.append(entityTag)

    rootTag.save(filename)
예제 #19
0
 def __init__(self, rootTag=None, parent=None):
     if rootTag is None:
         rootTag = nbt.TAG_Compound()
         nbtattr.SetNBTDefaults(self)
     super(DrawerItemStackRef, self).__init__(rootTag, parent)
예제 #20
0
def itemIDMapping(blocktypes):
    return nbt.TAG_Compound()