Пример #1
0
    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({})
Пример #2
0
  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)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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")
Пример #6
0
    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")
Пример #7
0
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)
Пример #8
0
 def _saveTileEntities(self, db):
   data = nbt.DataWriter()
   for subchunk in self.subchunks:
     if subchunk is None:
       continue
     for x in range(16):
       for y in range(16):
         for z in range(16):
           block = subchunk.getBlock(x, y, z)
           if block.nbt is not None: # Add back the correct position.
             block.nbt.add(nbt.TAG_Int("x", subchunk.x * 16 + x))
             block.nbt.add(nbt.TAG_Int("y", subchunk.y * 16 + y))
             block.nbt.add(nbt.TAG_Int("z", subchunk.z * 16 + z))
             nbt.encode(block.nbt, data)
   ldb.put(db, self.keyBase + b"1", data.get())
Пример #9
0
    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
Пример #10
0
    def savedData(self):
        """
        Returns the data of the chunk to save to the database.
        :return: str of 83200 bytes of chunk data.
        """
        def packData(dataArray):
            """
            Repacks the terrain data to Mojang's leveldb library's format.
            """
            assert dataArray.shape[2] == self.world.Height

            data = numpy.array(dataArray).reshape(16, 16,
                                                  self.world.Height / 2, 2)
            data[..., 1] <<= 4
            data[..., 1] |= data[..., 0]
            return numpy.array(data[:, :, :, 1])

        if self.dirty:
            # elements of DirtyColumns are bitfields. Each bit corresponds to a
            # 16-block segment of the column. We set all of the bits because
            # we only track modifications at the chunk level.
            self.DirtyColumns[:] = 255

        with nbt.littleEndianNBT():
            entityData = ""
            tileEntityData = ""

            for ent in self.TileEntities:
                tileEntityData += ent.save(compressed=False)

            for ent in self.Entities:
                v = ent["id"].value
                #                 ent["id"] = nbt.TAG_Int(entity.PocketEntity.entityList[v])
                id = entity.PocketEntity.getNumId(v)
                #                 print id
                if id >= 1000:
                    print id
                    print type(ent)
                    print ent
                ent['id'] = nbt.TAG_Int(id)
                entityData += ent.save(compressed=False)
                # We have to re-invert after saving otherwise the next save will fail.
                ent["id"] = nbt.TAG_String(v)

        terrain = ''.join([
            self.Blocks.tostring(),
            packData(self.Data).tostring(),
            packData(self.SkyLight).tostring(),
            packData(self.BlockLight).tostring(),
            self.DirtyColumns.tostring(),
            self.GrassColors.tostring(),
        ])

        return terrain, tileEntityData, entityData
Пример #11
0
 def setPlayerSpawnPosition(self, pos, player=None):
     """
     Sets the worlds spawn point to pos. If player is given, sets that players spawn point instead.
     :param pos: tuple int (x, y, z)
     :param player: nbt.TAG_Compound, root tag of the player
     :return: None
     """
     if player is None:
         playerSpawnTag = self.root_tag
     else:
         playerSpawnTag = self.getPlayerTag(player)
     for name, val in zip(("SpawnX", "SpawnY", "SpawnZ"), pos):
         playerSpawnTag[name] = nbt.TAG_Int(val)
Пример #12
0
    def toSchematic(self):
        schem = MCSchematic(shape=self.Size, mats=self._mat)
        for (x, y, z), value in ndenumerate(self._blocks):
            b_id, b_data = value
            schem.Blocks[x, z, y] = b_id
            schem.Data[x, z, y] = b_data

        for (x, y, z), value in ndenumerate(self._tile_entities):
            if not value:
                continue
            tag = value
            tag["x"] = nbt.TAG_Int(x)
            tag["y"] = nbt.TAG_Int(y)
            tag["z"] = nbt.TAG_Int(z)
            schem.addTileEntity(tag)

        entity_list = nbt.TAG_List()
        for e in self._entities:
            entity_list.append(e)
        schem.root_tag["Entities"] = entity_list

        return schem
Пример #13
0
    def copyWithOffset(cls, tileEntity, copyOffset):
        eTag = deepcopy(tileEntity)
        eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0])
        eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1])
        eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2])
        if eTag['id'].value == "Control":
            command = eTag['Command'].value

            # Adjust teleport command coordinates.
            # /tp <playername> <x> <y> <z>
            if command.startswith('/tp'):
                words = command.split(' ')
                if len(words) > 4:
                    x, y, z = words[2:5]

                    # Only adjust non-relative teleport coordinates.
                    # These coordinates can be either ints or floats. If ints, Minecraft adds
                    # 0.5 to the coordinate to center the player in the block.
                    # We need to preserve the int/float status or else the coordinates will shift.
                    # Note that copyOffset is always ints.

                    def num(x):
                        try:
                            return int(x)
                        except ValueError:
                            return float(x)

                    if x[0] != "~":
                        x = str(num(x) + copyOffset[0])
                    if y[0] != "~":
                        y = str(num(y) + copyOffset[1])
                    if z[0] != "~":
                        z = str(num(z) + copyOffset[2])

                    words[2:5] = x, y, z
                    eTag['Command'].value = ' '.join(words)

        return eTag
Пример #14
0
    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)

        cls.setpos(tileEntityTag, pos)
        return tileEntityTag
Пример #15
0
    def setPlayerGameType(self, gametype, player="Player"):
        """
        Sets the game type for player
        :param gametype: int (0=survival, 1=creative, 2=adventure, 3=spectator)
        :param player: string of the name of the player. "Player" for SSP player, player_<client-id> for SMP player.
        :return: None
        """

        # This annoyingly works differently between single- and multi-player.
        if player == "Player":
            self.GameType = gametype
            self.setPlayerAbilities(gametype, player)
        else:
            playerTag = self.getPlayerTag(player)
            playerTag['playerGameType'] = nbt.TAG_Int(gametype)
            self.setPlayerAbilities(gametype, player)
Пример #16
0
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
Пример #17
0
 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
Пример #18
0
    def copyWithOffset(cls, tileEntity, copyOffset, staticCommands, moveSpawnerPos, first, cancelCommandBlockOffset=False):
        # You'll need to use this function twice
        # The first time with first equals to True
        # The second time with first equals to False
        eTag = deepcopy(tileEntity)
        eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0])
        eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1])
        eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2])

        def num(x):
            try:
                return int(x)
            except ValueError:
                return float(x)

        def coordX(x, argument):
            if first:
                x = str(num(x)) + '!' + str(num(x) + copyOffset[0])
            elif argument and x.find("!") >= 0:
                x = x[x.index("!") + 1:]
                x = str(num(x) + copyOffset[0])
            elif not argument and x.find("!") >= 0:
                x = x[:x.index("!")]
            return x

        def coordY(y, argument):
            if first:
                y = str(num(y)) + '!' + str(num(y) + copyOffset[1])
            elif argument and y.find("!") >= 0:
                y = y[y.index("!") + 1:]
                y = str(num(y) + copyOffset[1])
            elif not argument and y.find("!") >= 0:
                y = y[:y.index("!")]
            return y

        def coordZ(z, argument):
            if first:
                z = str(num(z)) + '!' + str(num(z) + copyOffset[2])
            elif argument and z.find("!") >= 0:
                z = z[z.index("!") + 1:]
                z = str(num(z) + copyOffset[2])
            elif not argument and z.find("!") >= 0:
                z = z[:z.index("!")]
            return z

        def coords(x, y, z, argument):
            if x[0] != "~":
                x = coordX(x, argument)
            if y[0] != "~":
                y = coordY(y, argument)
            if z[0] != "~":
                z = coordZ(z, argument)
            return x, y, z

        if eTag['id'].value == 'MobSpawner' or MCEDIT_IDS.get(eTag['id'].value) == 'DEF_BLOCKS_MOB_SPAWNER':
            mobs = []
            if 'SpawnData' in eTag:
                mob = eTag['SpawnData']
                if mob:
                    mobs.append(mob)
            if 'SpawnPotentials' in eTag:
                potentials = eTag['SpawnPotentials']
                for p in potentials:
                    if 'properties' in p:
                        mobs.extend(p["Properties"])
                    elif 'Entity' in p:
                        mobs.extend(p["Entity"])

            for mob in mobs:
                # Why do we get a unicode object as tag 'mob'?
                if "Pos" in mob and mob != "Pos":
                    if first:
                        pos = Entity.pos(mob)
                        x, y, z = [str(part) for part in pos]
                        x, y, z = coords(x, y, z, moveSpawnerPos)
                        mob['Temp1'] = nbt.TAG_String(x)
                        mob['Temp2'] = nbt.TAG_String(y)
                        mob['Temp3'] = nbt.TAG_String(z)
                    elif 'Temp1' in mob and 'Temp2' in mob and 'Temp3' in mob:
                        x = mob['Temp1']
                        y = mob['Temp2']
                        z = mob['Temp3']
                        del mob['Temp1']
                        del mob['Temp2']
                        del mob['Temp3']
                        parts = []
                        for part in (x, y, z):
                            part = str(part)
                            part = part[13:len(part) - 2]
                            parts.append(part)
                        x, y, z = parts
                        pos = [float(p) for p in coords(x, y, z, moveSpawnerPos)]
                        Entity.setpos(mob, pos)

        if (eTag['id'].value == "Control" or MCEDIT_IDS.get(eTag['id'].value) == 'DEF_BLOCKS_COMMAND_BLOCK') and not cancelCommandBlockOffset:
            command = eTag['Command'].value
            oldCommand = command

            def selectorCoords(selector):
                old_selector = selector
                try:
                    char_num = 0
                    new_selector = ""
                    dont_copy = 0
                    if len(selector) > 4:
                        if '0' <= selector[3] <= '9':
                            new_selector = selector[:3]
                            end_char_x = selector.find(',', 4, len(selector) - 1)
                            if end_char_x == -1:
                                end_char_x = len(selector) - 1
                            x = selector[3:end_char_x]
                            x = coordX(x, staticCommands)
                            new_selector += x + ','

                            end_char_y = selector.find(',', end_char_x + 1, len(selector) - 1)
                            if end_char_y == -1:
                                end_char_y = len(selector) - 1
                            y = selector[end_char_x + 1:end_char_y]
                            y = coordY(y, staticCommands)
                            new_selector += y + ','

                            end_char_z = selector.find(',', end_char_y + 1, len(selector) - 1)
                            if end_char_z == -1:
                                end_char_z = len(selector) - 1
                            z = selector[end_char_y + 1:end_char_z]
                            z = coordZ(z, staticCommands)
                            new_selector += z + ',' + selector[end_char_z + 1:]

                        else:
                            for char in selector:
                                if dont_copy != 0:
                                    dont_copy -= 1
                                else:
                                    if (char != 'x' and char != 'y' and char != 'z') or letter:
                                        new_selector += char
                                        if char == '[' or char == ',':
                                            letter = False
                                        else:
                                            letter = True

                                    elif char == 'x' and not letter:
                                        new_selector += selector[char_num:char_num + 2]
                                        char_x = char_num + 2
                                        end_char_x = selector.find(',', char_num + 3, len(selector) - 1)
                                        if end_char_x == -1:
                                            end_char_x = len(selector) - 1
                                        x = selector[char_x:end_char_x]
                                        dont_copy = len(x) + 1
                                        x = coordX(x, staticCommands)
                                        new_selector += x

                                    elif char == 'y' and not letter:
                                        new_selector += selector[char_num:char_num + 2]
                                        char_y = char_num + 2
                                        end_char_y = selector.find(',', char_num + 3, len(selector) - 1)
                                        if end_char_y == -1:
                                            end_char_y = len(selector) - 1
                                        y = selector[char_y:end_char_y]
                                        dont_copy = len(y) + 1
                                        y = coordY(y, staticCommands)
                                        new_selector += y

                                    elif char == 'z' and not letter:
                                        new_selector += selector[char_num:char_num + 2]
                                        char_z = char_num + 2
                                        end_char_z = selector.find(',', char_num + 3, len(selector) - 1)
                                        if end_char_z == -1:
                                            end_char_z = len(selector) - 1
                                        z = selector[char_z:end_char_z]
                                        dont_copy = len(z) + 1
                                        z = coordZ(z, staticCommands)
                                        new_selector += z
                                char_num += 1
                    else:
                        new_selector = old_selector

                except:
                    new_selector = old_selector
                finally:
                    return new_selector

            try:
                execute = False
                Slash = False
                if command[0] == "/":
                    command = command[1:]
                    Slash = True

                # Adjust command coordinates.
                words = command.split(' ')

                i = 0
                for word in words:
                    if word[0] == '@':
                        words[i] = selectorCoords(word)
                    i += 1

                if command.startswith('execute'):
                    stillExecuting = True
                    execute = True
                    saving_command = ""
                    while stillExecuting:
                        if Slash:
                            saving_command += '/'
                        x, y, z = words[2:5]
                        words[2:5] = coords(x, y, z, staticCommands)
                        if words[5] == 'detect':
                            x, y, z = words[6:9]
                            words[6:9] = coords(x, y, z, staticCommands)
                            saving_command += ' '.join(words[:9])
                            words = words[9:]
                        else:
                            saving_command += ' '.join(words[:5])
                            words = words[5:]
                        command = ' '.join(words)
                        saving_command += ' '
                        Slash = False
                        if command[0] == "/":
                            command = command[1:]
                            Slash = True
                        words = command.split(' ')
                        if not command.startswith('execute'):
                            stillExecuting = False

                if (command.startswith('tp') and len(words) == 5) or command.startswith(
                        'particle') or command.startswith('replaceitem block') or (
                            command.startswith('spawnpoint') and len(words) == 5) or command.startswith('stats block') or (
                            command.startswith('summon') and len(words) >= 5):
                    x, y, z = words[2:5]
                    words[2:5] = coords(x, y, z, staticCommands)
                elif command.startswith('blockdata') or command.startswith('setblock') or (
                            command.startswith('setworldspawn') and len(words) == 4):
                    x, y, z = words[1:4]
                    words[1:4] = coords(x, y, z, staticCommands)
                elif command.startswith('playsound') and len(words) >= 6:
                    x, y, z = words[3:6]
                    words[3:6] = coords(x, y, z, staticCommands)
                elif command.startswith('clone'):
                    x1, y1, z1, x2, y2, z2, x, y, z = words[1:10]
                    x1, y1, z1 = coords(x1, y1, z1, staticCommands)
                    x2, y2, z2 = coords(x2, y2, z2, staticCommands)
                    x, y, z = coords(x, y, z, staticCommands)

                    words[1:10] = x1, y1, z1, x2, y2, z2, x, y, z
                elif command.startswith('fill'):
                    x1, y1, z1, x2, y2, z2 = words[1:7]
                    x1, y1, z1 = coords(x1, y1, z1, staticCommands)
                    x2, y2, z2 = coords(x2, y2, z2, staticCommands)

                    words[1:7] = x1, y1, z1, x2, y2, z2
                elif command.startswith('spreadplayers'):
                    x, z = words[1:3]
                    if x[0] != "~":
                        x = coordX(x, staticCommands)
                    if z[0] != "~":
                        z = coordZ(z, staticCommands)

                    words[1:3] = x, z
                elif command.startswith('worldborder center') and len(words) == 4:
                    x, z = words[2:4]
                    if x[0] != "~":
                        x = coordX(x, staticCommands)
                    if z[0] != "~":
                        z = coordZ(z, staticCommands)

                    words[2:4] = x, z
                if Slash:
                    command = '/'
                else:
                    command = ""
                command += ' '.join(words)

                if execute:
                    command = saving_command + command
                eTag['Command'].value = command
            except:
                eTag['Command'].value = oldCommand

        return eTag
Пример #19
0
 def setpos(cls, tag, pos):
     for a, p in zip('xyz', pos):
         tag[a] = nbt.TAG_Int(p)
Пример #20
0
 def testList(self):
     tag = nbt.TAG_List()
     tag.append(nbt.TAG_Int(258))
     del tag[0]
Пример #21
0
    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["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])

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

        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
Пример #22
0
    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
Пример #23
0
    def copyWithOffset(cls, tileEntity, copyOffset, staticCommands,
                       moveSpawnerPos, regenerateUUID, first):
        #You'll need to use this function twice
        #The first time with first equals to True
        #The second time with first equals to False
        eTag = deepcopy(tileEntity)
        eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0])
        eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1])
        eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2])

        if regenerateUUID:
            # Courtesy of SethBling
            eTag["UUIDMost"] = nbt.TAG_Long((random.getrandbits(47) << 16)
                                            | (1 << 12)
                                            | random.getrandbits(12))
            eTag["UUIDLeast"] = nbt.TAG_Long(-(
                (7 << 60) | random.getrandbits(60)))

        def num(x):
            try:
                return int(x)
            except ValueError:
                return float(x)

        def coordX(x, argument):
            if first == True:
                x = str(num(x)) + '!' + str(num(x) + copyOffset[0])
            elif argument == True and x.find("!") >= 0:
                x = x[x.index("!") + 1:]
                x = str(num(x) + copyOffset[0])
            elif argument == False and x.find("!") >= 0:
                x = x[:x.index("!")]
            return x

        def coordY(y, argument):
            if first == True:
                y = str(num(y)) + '!' + str(num(y) + copyOffset[1])
            elif argument == True and y.find("!") >= 0:
                y = y[y.index("!") + 1:]
                y = str(num(y) + copyOffset[1])
            elif argument == False and y.find("!") >= 0:
                y = y[:y.index("!")]
            return y

        def coordZ(z, argument):
            if first == True:
                z = str(num(z)) + '!' + str(num(z) + copyOffset[2])
            elif argument == True and z.find("!") >= 0:
                z = z[z.index("!") + 1:]
                z = str(num(z) + copyOffset[2])
            elif argument == False and z.find("!") >= 0:
                z = z[:z.index("!")]
            return z

        def coords(x, y, z, argument):
            if x[0] != "~":
                x = coordX(x, argument)
            if y[0] != "~":
                y = coordY(y, argument)
            if z[0] != "~":
                z = coordZ(z, argument)
            return x, y, z

        if eTag['id'].value == 'MobSpawner':
            mobs = []
            mob = eTag.get('SpawnData')
            if mob:
                mobs.append(mob)
            potentials = eTag.get('SpawnPotentials')
            if potentials:
                mobs.extend(p["Properties"] for p in potentials)

            for mob in mobs:
                if "Pos" in mob:
                    if first == True:
                        pos = Entity.pos(mob)
                        x, y, z = [str(part) for part in pos]
                        x, y, z = coords(x, y, z, moveSpawnerPos)
                        mob['Temp1'] = nbt.TAG_String(x)
                        mob['Temp2'] = nbt.TAG_String(y)
                        mob['Temp3'] = nbt.TAG_String(z)
                    elif 'Temp1' in mob and 'Temp2' in mob and 'Temp3' in mob:
                        x = mob['Temp1']
                        y = mob['Temp2']
                        z = mob['Temp3']
                        del mob['Temp1']
                        del mob['Temp2']
                        del mob['Temp3']
                        parts = []
                        for part in (x, y, z):
                            part = str(part)
                            part = part[13:len(part) - 2]
                            parts.append(part)
                        x, y, z = parts
                        pos = [
                            float(p) for p in coords(x, y, z, moveSpawnerPos)
                        ]
                        Entity.setpos(mob, pos)

        if eTag['id'].value == "Control":
            command = eTag['Command'].value
            oldCommand = command

            def selectorCoords(selector):
                old_selector = selector
                try:
                    char_num = 0
                    x = ""
                    y = ""
                    z = ""
                    new_selector = ""
                    dont_copy = 0
                    if len(selector) > 4:
                        if selector[3] >= '0' and selector[3] <= '9':
                            new_selector = selector[:3]
                            end_char_x = selector.find(',', 4,
                                                       len(selector) - 1)
                            if end_char_x == -1:
                                end_char_x = len(selector) - 1
                            x = selector[3:end_char_x]
                            x = coordX(x, staticCommands)
                            new_selector += x + ','

                            end_char_y = selector.find(',', end_char_x + 1,
                                                       len(selector) - 1)
                            if end_char_y == -1:
                                end_char_y = len(selector) - 1
                            y = selector[end_char_x + 1:end_char_y]
                            y = coordY(y, staticCommands)
                            new_selector += y + ','

                            end_char_z = selector.find(',', end_char_y + 1,
                                                       len(selector) - 1)
                            if end_char_z == -1:
                                end_char_z = len(selector) - 1
                            z = selector[end_char_y + 1:end_char_z]
                            z = coordZ(z, staticCommands)
                            new_selector += z + ',' + selector[end_char_z + 1:]

                        else:
                            for char in selector:
                                if dont_copy != 0:
                                    dont_copy -= 1
                                else:
                                    if (char != 'x' and char != 'y'
                                            and char != 'z') or letter == True:
                                        new_selector += char
                                        if char == '[' or char == ',':
                                            letter = False
                                        else:
                                            letter = True

                                    elif char == 'x' and letter == False:
                                        new_selector += selector[
                                            char_num:char_num + 2]
                                        char_x = char_num + 2
                                        end_char_x = selector.find(
                                            ',', char_num + 3,
                                            len(selector) - 1)
                                        if end_char_x == -1:
                                            end_char_x = len(selector) - 1
                                        x = selector[char_x:end_char_x]
                                        dont_copy = len(x) + 1
                                        x = coordX(x, staticCommands)
                                        new_selector += x

                                    elif char == 'y' and letter == False:
                                        new_selector += selector[
                                            char_num:char_num + 2]
                                        char_y = char_num + 2
                                        end_char_y = selector.find(
                                            ',', char_num + 3,
                                            len(selector) - 1)
                                        if end_char_y == -1:
                                            end_char_y = len(selector) - 1
                                        y = selector[char_y:end_char_y]
                                        dont_copy = len(y) + 1
                                        y = coordY(y, staticCommands)
                                        new_selector += y

                                    elif char == 'z' and letter == False:
                                        new_selector += selector[
                                            char_num:char_num + 2]
                                        char_z = char_num + 2
                                        end_char_z = selector.find(
                                            ',', char_num + 3,
                                            len(selector) - 1)
                                        if end_char_z == -1:
                                            end_char_z = len(selector) - 1
                                        z = selector[char_z:end_char_z]
                                        dont_copy = len(z) + 1
                                        z = coordZ(z, staticCommands)
                                        new_selector += z
                                char_num += 1
                    else:
                        new_selector = old_selector

                except:
                    new_selector = old_selector
                finally:
                    return new_selector

            try:
                execute = False
                Slash = False
                if command[0] == "/":
                    command = command.replace("/", "", 1)
                    Slash = True

                # Adjust command coordinates.
                words = command.split(' ')

                i = 0
                for word in words:
                    if word[0] == '@':
                        words[i] = selectorCoords(word)
                    i += 1

                if command.startswith('execute'):
                    stillExecuting = True
                    execute = True
                    saving_command = ""
                    while stillExecuting == True:
                        if Slash == True:
                            saving_command += '/'
                        x, y, z = words[2:5]
                        words[2:5] = coords(x, y, z, staticCommands)
                        if words[5] == 'detect':
                            x, y, z = words[6:9]
                            words[6:9] = coords(x, y, z, staticCommands)
                            saving_command += ' '.join(words[:9])
                            words = words[9:]
                        else:
                            saving_command += ' '.join(words[:5])
                            words = words[5:]
                        command = ' '.join(words)
                        saving_command += ' '
                        Slash = False
                        if command[0] == "/":
                            command = command.replace("/", "", 1)
                            Slash = True
                        words = command.split(' ')
                        if not command.startswith('execute'):
                            stillExecuting = False

                if (command.startswith('tp') and len(words) == 5
                    ) or command.startswith('particle') or command.startswith(
                        'replaceitem block') or (
                            command.startswith('spawnpoint') and len(words)
                            == 5) or command.startswith('stats block') or (
                                command.startswith('summon')
                                and len(words) >= 5):
                    x, y, z = words[2:5]
                    words[2:5] = coords(x, y, z, staticCommands)
                elif command.startswith('blockdata') or command.startswith(
                        'setblock') or (command.startswith('setworldspawn')
                                        and len(words) == 4):
                    x, y, z = words[1:4]
                    words[1:4] = coords(x, y, z, staticCommands)
                elif command.startswith('playsound') and len(words) >= 6:
                    x, y, z = words[3:6]
                    words[3:6] = coords(x, y, z, staticCommands)
                elif command.startswith('clone'):
                    x1, y1, z1, x2, y2, z2, x, y, z = words[1:10]
                    x1, y1, z1 = coords(x1, y1, z1, staticCommands)
                    x2, y2, z2 = coords(x2, y2, z2, staticCommands)
                    x, y, z = coords(x, y, z, staticCommands)

                    words[1:10] = x1, y1, z1, x2, y2, z2, x, y, z
                elif command.startswith('fill'):
                    x1, y1, z1, x2, y2, z2 = words[1:7]
                    x1, y1, z1 = coords(x1, y1, z1, staticCommands)
                    x2, y2, z2 = coords(x2, y2, z2, staticCommands)

                    words[1:7] = x1, y1, z1, x2, y2, z2
                elif command.startswith('spreadplayers'):
                    x, z = words[1:3]
                    if x[0] != "~":
                        x = coordX(x, staticCommands)
                    if z[0] != "~":
                        z = coordZ(z, staticCommands)

                    words[1:3] = x, z
                elif command.startswith('worldborder center') and len(
                        words) == 4:
                    x, z = words[2:4]
                    if x[0] != "~":
                        x = coordX(x, staticCommands)
                    if z[0] != "~":
                        z = coordZ(z, staticCommands)

                    words[2:4] = x, z
                if Slash == True:
                    command = '/'
                else:
                    command = ""
                command += ' '.join(words)

                if execute == True:
                    command = saving_command + command
                eTag['Command'].value = command
            except:
                eTag['Command'].value = oldCommand

        return eTag
Пример #24
0
    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)
Пример #25
0
    def __init__(self, filename=''):
        if type(filename) in (str, unicode):
            self.delta_x, self.delta_y, self.delta_z = 0, 0, 0
            self.size_x, self.size_y, self.size_z = 0, 0, 0
            map_block = {}
            not_found = []
            tileentities_list = [
                a.lower() for a in TileEntity.baseStructures.keys()
            ]
            for k, v in materials.block_map.items():
                map_block[v.replace('minecraft:', '')] = k

            def get_delta(x, y, z, debug=False, f_obj=None):
                if x < 0 and abs(x) > self.delta_x:
                    self.delta_x = abs(x)
                if y < 0 and abs(y) > self.delta_y:
                    self.delta_y = abs(y)
                if z < 0 and abs(z) > self.delta_z:
                    self.delta_z = abs(z)
                if x + self.delta_x >= self.size_x:
                    self.size_x = x + self.delta_x + 1
                if y + self.delta_y >= self.size_y:
                    self.size_y = y + self.delta_y + 1
                if z + self.delta_z >= self.size_z:
                    self.size_z = z + self.delta_z + 1
                if debug:
                    output_str = '; '.join(
                        ('get_delta: %s, %s %s' % (x, y, z),
                         'deltas: %s, %s, %s' %
                         (self.delta_x, self.delta_y, self.delta_z),
                         'size: %s, %s %s' %
                         (self.size_x, self.size_y, self.size_z)))
                    print output_str
                    if f_obj != None:
                        f_obj.write(output_str)

            raw_data = open(filename).read()
            lines = re.findall(r'^Block\(.*?\)|^RandomBlock\(.*?\)', raw_data,
                               re.M)
            # Doubling the schematic size calculation avoids missbuilt objects.
            # Rework the get_delta function?
            [
                get_delta(*b) for b in [
                    eval(','.join(
                        a.split('(')[1].split(')')[0].split(',', 3)[:3]))
                    for a in lines
                ]
            ]
            #print 'Size:', self.size_x, self.size_y, self.size_z
            [
                get_delta(*b) for b in [
                    eval(','.join(
                        a.split('(')[1].split(')')[0].split(',', 3)[:3]))
                    for a in lines
                ]
            ]
            #print 'Size:', self.size_x, self.size_y, self.size_z
            self.__schem = schematic.MCSchematic(shape=(self.size_x,
                                                        self.size_y,
                                                        self.size_z))

            def get_block_data(args):
                x, y, z = args[:3]
                b = args[3]
                nbt_data = None
                if len(args) == 5 and args[4] != None:
                    f_name = os.path.join(os.path.dirname(filename),
                                          os.path.normpath(args[4]))
                    if os.path.exists(f_name):
                        nbt_data = nbt.load(f_name)
                    else:
                        print 'Could not find %s' % args[4]
                        print '  Canonical path: %s' % f_name
                x = int(x) + self.delta_x
                y = int(y) + self.delta_y
                z = int(z) + self.delta_z
                if b != None:
                    b_id, b_state = (b + ':0').split(':')[:2]
                else:
                    b_id, b_state = '', None
                if b_state:
                    b_state = int(b_state)
                else:
                    b_state = 0
                return x, y, z, b_id, b_state, nbt_data

            def get_randomblock_data(args):
                x, y, z = args[:3]
                obj = []
                bit_id = False
                bit_path = False
                bit_chance = False
                for arg in args[3:]:
                    if not bit_id:
                        obj.append(arg)
                        bit_id = True
                    elif arg.isdigit():
                        if not bit_path:
                            obj.append(None)
                            bit_path = True
                        obj.append(int(arg))
                        bit_chance = True
                    else:
                        obj.append(arg)
                        bit_path = True
                    if bit_id and bit_path and bit_chance:
                        chance = randint(1, 100)
                        if chance <= obj[2]:
                            break
                        obj = []
                        bit_id, bit_path, bit_chance = False, False, False
                #print 'Selected random object: %s (%s, %s, %s) from %s'%(obj, x, y, z, args[3:])
                # Fallback for chances < 100%
                if not obj:
                    obj = [None, None]
                return get_block_data((x, y, z, obj[0], obj[1]))

            def verify_state(id, state):
                states = corrected_states.get(id, None)
                if states:
                    if type(states) == tuple:
                        if state not in range(*states):
                            state = states[0]
                    elif type(states) == list:
                        if state not in states:
                            state = states[0]
                return state

            for line in lines:
                if line.startswith('Block') or line.startswith('RandomBlock'):
                    #print 'Parsing', line
                    if line.startswith('Block'):
                        x, y, z, b_id, b_state, nbt_data = get_block_data(
                            line.replace("Block(",
                                         "").replace(")",
                                                     "").strip().split(","))
                    else:
                        x, y, z, b_id, b_state, nbt_data = get_randomblock_data(
                            line.replace("RandomBlock(",
                                         "").replace(")",
                                                     "").strip().split(","))

                    b_idn = map_block.get(b_id.lower(),
                                          bo3_blocks.get(b_id, None))
                    if b_idn != None:
                        b_idn = int(b_idn)
                        if b_id.lower() in tileentities_list:
                            if nbt_data == None:
                                nbt_data = nbt.TAG_Compound()
                                nbt_data.add(
                                    nbt.TAG_String(name='id',
                                                   value=b_id.capitalize()))
                            nbt_data.add(nbt.TAG_Int(name='x', value=x))
                            nbt_data.add(nbt.TAG_Int(name='y', value=y))
                            nbt_data.add(nbt.TAG_Int(name='z', value=z))
                            self.__schem.TileEntities.append(nbt_data)
                        try:
                            self.__schem.Blocks[x, z, y] = b_idn
                            self.__schem.Data[x, z,
                                              y] = verify_state(b_id, b_state)
                        except Exception, e:
                            print 'Error while building BO3 data:'
                            print e
                            print 'size', self.size_x, self.size_y, self.size_z
                            print line
                            [
                                get_delta(*b, debug=True) for b in [
                                    eval(','.join(
                                        a.split('(')[1].split(')')[0].split(
                                            ',', 3)[:3])) for a in lines
                                ]
                            ]
                    elif b_id != '':
                        print 'BO3 Block not found: %s' % b_id
Пример #26
0
def main():

    # parse options and get results
    parser = argparse.ArgumentParser(
        description=
        'Converts a single building from a Collada file and pastes into a Minecraft world'
    )
    parser.add_argument('--model', required=True, type=str, \
                           help='relative or absolute path to .kmz file containing Collada model and assets')
    parser.add_argument('--world', required=True, type=str, \
                           help='path to main folder of a target Minecraft world')
    parser.add_argument("-v", "--verbosity", action="count", \
                        help="increase output verbosity")
    parser.add_argument("-q", "--quiet", action="store_true", \
                        help="suppress informational output")
    args = parser.parse_args()

    # set up logging
    log_level = klog_levels.LOG_INFO
    if args.quiet:
        log_level = klog_levels.LOG_ERROR
    if args.verbosity:
        # v=1 is DEBUG 1, v=2 is DEBUG 2, and so on
        log_level += args.verbosity
    log = klogger(log_level)

    # Name of the model that we'll be processing
    filename = args.model
    log.log_info("Converting %s and placing into %s" % \
                 (os.path.basename(filename), os.path.basename(args.world)))

    # Determine where to paste into target world
    zipf = zipfile.ZipFile(args.model, 'r')
    kmldata = minidom.parse(zipf.open('doc.kml'))
    zipf = None

    # Determine location information
    location = kmldata.getElementsByTagName('Location')[0]
    latitude = float(
        location.getElementsByTagName('latitude')[0].childNodes[0].data)
    longitude = float(
        location.getElementsByTagName('longitude')[0].childNodes[0].data)
    altmode = str(
        kmldata.getElementsByTagName('altitudeMode')[0].childNodes[0].data)
    altitude = float(
        location.getElementsByTagName('altitude')[0].childNodes[0].data)

    # Determine orientation information
    orientation = kmldata.getElementsByTagName('Orientation')[0]
    heading = float(
        orientation.getElementsByTagName('heading')[0].childNodes[0].data)
    kmldata = None
    if abs(heading) > 1.0:
        log.log_fatal("Model specifies heading of %f, but this script does" \
                      " not support model rotation" % heading)

    # Get information about the target world
    yamlfile = open(os.path.join(args.world, 'Region.yaml'), 'r')
    yamlfile.readline()  # discard first line
    myRegion = yaml.safe_load(yamlfile)
    yamlfile.close()

    # Check important things
    if myRegion["scale"] != 1 or myRegion["vscale"] != 1:
        log.log_fatal("Currently only scale=1 and vscale=1 are allowed")

    # Compute the world utm (x,y) for this model. Oddly enough, we can use these
    # coordinates directly (for the 1:1 scale case. This script just handles that)
    llextents = myRegion['wgs84extents']['elevation']
    easting, northing, utmzone, utmletter = utmll.from_latlon(
        latitude, longitude)
    northing = (myRegion['tiles']['ymin'] + myRegion['tiles']['ymax']) * myRegion['tilesize'] \
               - northing
    log.log_debug(1, "Base easting = %d, northing = %d in UTM Zone %d%s" % \
                     (easting, northing, utmzone, utmletter))
    modelBaseLoc = [easting, northing, 0]

    log.log_debug(1,"Loc: %.10f,%.10f => %d,%d within %s" % \
                     (latitude, longitude, modelBaseLoc[0], modelBaseLoc[1], str(llextents)))

    # Open the model and determine its extents
    model = collada.Collada(
        filename,
        ignore=[collada.DaeUnsupportedError, collada.DaeBrokenRefError])
    maxs = array([-1e99, -1e99, -1e99])
    mins = array([1e99, 1e99, 1e99])
    mr = ModelRecurse(log)
    mins, maxs = mr.recurse_model(model, "extents", [mins, maxs])
    log.log_info("Computed model extents: [%f, %f, %f,] to [%f, %f, %f]" %
                 (mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]))

    # some sort of scaling information
    scale = [.01, .01, .01]
    if model.assetInfo != None and model.assetInfo.unitmeter != None:
        log.log_debug(1,"This model contains units, %f %s per meter" % \
                            (model.assetInfo.unitmeter, model.assetInfo.unitname))
        scale = model.assetInfo.unitmeter
        scale = [scale, scale, scale]

    t2v = Tri2Voxel(model, log)
    t2v.scale = array(scale)
    t2v.geom_prep(mins, maxs)

    # Use extents and modelBaseLoc to compute the world coordinate that
    # corresponds to the output array's [0,0,0]
    #cornerBase = t2v.tvoffset[0] * t2v.tvscale[0]
    cornerBase = np.multiply(t2v.scale, array([-mins[0], maxs[1], 0]))
    modelBaseLoc -= cornerBase
    modelBaseLoc = [round(x) for x in modelBaseLoc]
    log.log_debug(2,"cornerBase is %s, yielding modelBaseLoc of %s" % \
                  (str(cornerBase), str(modelBaseLoc)))

    # Convert
    mr.recurse_model(model, "convert", t2v)  # Do the conversion!

    # Fix orientation
    t2v.arr3d_id = np.fliplr(t2v.arr3d_id)  # Fix block ID array
    t2v.arr3d_dt = np.fliplr(t2v.arr3d_dt)  # Fix damage val array

    # Print some stats
    ar1 = np.count_nonzero(t2v.arr3d_id)
    ar01 = np.prod(t2v.arrdim)
    log.log_info("%d/%d voxels filled (%.2f%% fill level)" %
                 (ar1, ar01, 100 * ar1 / ar01))
    log.log_info("t2v reports %d voxels changed" % t2v.voxchg)

    # Compute world-scaled altitude information
    # This must be done after the level height is adjusted, otherwise one of the
    # (loaded, cached) chunks will have an incorrect height.
    if altmode == "absolute":
        sealevel = myRegion['sealevel'] if 'sealevel' in myRegion else 64
        modelAltBase = int(altitude * myRegion['vscale'] + sealevel)
    elif altmode == "relativeToGround":
        level = mclevel.fromFile(os.path.join(args.world, "level.dat"))

        xbase = int(round(modelBaseLoc[0] + cornerBase[0]))
        zbase = int(round(modelBaseLoc[1] + cornerBase[1]))
        chunk = level.getChunk(int(xbase / 16.), int(zbase / 16.))
        voxcol = chunk.Blocks[xbase % 16, zbase % 16, :]
        voxtop = [i for i, e in enumerate(voxcol) if e != 0][-1] + 1
        modelAltBase = int(voxtop + modelBaseLoc[2])
        chunk = None
        level.close()
        level = None

    else:
        log.log_fatal("Unknown altitude mode in KML file.")
    log.log_info("Model base altitude is %d meters (voxels)" % modelAltBase)

    # Compute new world height
    worldheight = int(modelAltBase + t2v.arrdim[2])
    worldheight |= worldheight >> 1
    worldheight |= worldheight >> 2
    worldheight |= worldheight >> 4
    worldheight |= worldheight >> 8
    worldheight |= worldheight >> 16
    worldheight += 1

    # Open MC level for computation
    level = mclevel.fromFile(os.path.join(args.world, "level.dat"))

    if worldheight > level.Height:
        log.log_info("World height increased from %d to %d meters" % \
                     (level.Height,worldheight))
        level.Height = worldheight
        level.root_tag["Data"]["worldHeight"] = nbt.TAG_Int(worldheight)
    else:
        log.log_info("World height unmodified at %d meters" % worldheight)

    # Figure out what chunks will be modified
    chunksx = [int(np.floor(modelBaseLoc[0]/16.)), \
               int(np.floor((modelBaseLoc[0]+t2v.arrdim[0])/16.))]
    chunksz = [int(np.floor(modelBaseLoc[1]/16.)), \
               int(np.floor((modelBaseLoc[1]+t2v.arrdim[1])/16.))]

    # Modify the chunks with new building data
    for x in xrange(chunksx[0], 1 + chunksx[1]):
        for z in xrange(chunksz[0], 1 + chunksz[1]):

            # Chunk sub-selection
            chunk = level.getChunk(x, z)
            xmin = max(0, modelBaseLoc[0] - 16 * x)
            xmax = min(16, t2v.arrdim[0] + modelBaseLoc[0] - 16 * x)
            zmin = max(0, modelBaseLoc[1] - 16 * z)
            zmax = min(16, t2v.arrdim[1] + modelBaseLoc[1] - 16 * z)

            # Model sub-selection
            mxmin = (16 * x) + xmin - modelBaseLoc[0]
            mzmin = (16 * z) + zmin - modelBaseLoc[1]

            log.log_debug(2,"Copying region %d,%d,%d to %d,%d,%d" % \
                  (xmin,modelAltBase,zmin,xmax,(modelAltBase+t2v.arrdim[2]),zmax))
            log.log_debug(2,"From model %d,%d,%d to %d,%d,%d" % \
                  (mxmin,0,mzmin,mxmin+(xmax-xmin),t2v.arrdim[2],mzmin+(zmax-zmin)))
            if xmax <= 0 or zmax <= 0:
                log.log_debug(1, "Skipping out-of-bounds copy")
                continue

            # Checking to make sure numpy isn't going to pitch a fit
            shapes = [
                t2v.arrdim[2],
                chunk.Data[xmin, zmin, modelAltBase:(modelAltBase +
                                                     t2v.arrdim[2])].shape[0]
            ]
            if shapes[0] != shapes[1]:
                log.log_fatal("Cannot store resulting model. Chunk (%d,%d) selected height %d does not match " \
                                          "model matrix height %d" % (x, z, shapes[0], shapes[1]))

            inp = chunk.Blocks[xmin:xmax,zmin:zmax, \
                               modelAltBase:(modelAltBase+t2v.arrdim[2])]

            # Data first because Blocks must retain its 0s
            ind = chunk.Data[xmin:xmax,zmin:zmax, \
                             modelAltBase:(modelAltBase+t2v.arrdim[2])]
            chunk.Data[xmin:xmax,zmin:zmax, \
                       modelAltBase:(modelAltBase+t2v.arrdim[2])] = \
            np.where(inp != 0, ind, \
                     t2v.arr3d_dt[mxmin:mxmin + (xmax-xmin), mzmin:mzmin + (zmax-zmin), :])

            # Blocks second.
            chunk.Blocks[xmin:xmax,zmin:zmax, \
                         modelAltBase:(modelAltBase+t2v.arrdim[2])] = \
            np.where(inp != 0, inp, \
                     t2v.arr3d_id[mxmin:mxmin + (xmax-xmin), mzmin:mzmin + (zmax-zmin), :])

            # And mark the chunk.
            chunk.chunkChanged()

    log.log_info("Relighting level...")
    level.generateLights()
    log.log_info("Saving level...")
    level.saveInPlace()
Пример #27
0
    def copyWithOffset(cls, tileEntity, copyOffset, staticCommands, first):
        #You'll need to use this function twice
        #The first time with first equals to True
        #The second time with first equals to False
        eTag = deepcopy(tileEntity)
        eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0])
        eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1])
        eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2])
        if eTag['id'].value == "Control":
            command = eTag['Command'].value
            execute = False
            Slash = False
            if command[0] == "/":
                command = command.replace("/", "", 1)
                Slash = True

            def num(x):
                try:
                    return int(x)
                except ValueError:
                    return float(x)

            def coordX(x):
                if first == True:
                    x = str(num(x)) + '!' + str(num(x) + copyOffset[0])
                elif staticCommands == True:
                    x = x[x.index("!") + 1:]
                    x = str(num(x) + copyOffset[0])
                else:
                    x = x[:x.index("!")]
                return x

            def coordY(y):
                if first == True:
                    y = str(num(y)) + '!' + str(num(y) + copyOffset[1])
                elif staticCommands == True:
                    y = y[y.index("!") + 1:]
                    y = str(num(y) + copyOffset[1])
                else:
                    y = y[:y.index("!")]
                return y

            def coordZ(z):
                if first == True:
                    z = str(num(z)) + '!' + str(num(z) + copyOffset[2])
                elif staticCommands == True:
                    z = z[z.index("!") + 1:]
                    z = str(num(z) + copyOffset[2])
                else:
                    z = z[:z.index("!")]
                return z

            def coords(x, y, z):
                if x[0] != "~":
                    x = coordX(x)
                if y[0] != "~":
                    y = coordY(y)
                if z[0] != "~":
                    z = coordZ(z)
                return x, y, z

            def selectorCoords(selector):
                char_num = 0
                x = ""
                y = ""
                z = ""
                new_selector = ""
                dont_copy = 0
                for char in selector:
                    if dont_copy != 0:
                        dont_copy -= 1
                    else:
                        if char != 'x' and char != 'y' and char != 'z':
                            new_selector += char
                            if char == '[' or char == ',':
                                letter = False
                            else:
                                letter = True
                        elif char == 'x' and letter == False:
                            new_selector += selector[char_num:char_num + 2]
                            char_x = char_num + 2
                            end_char_x = selector.find(',', char_num + 3,
                                                       len(selector) - 1)
                            if end_char_x == -1:
                                end_char_x = len(selector) - 1
                            x = selector[char_x:end_char_x]
                            dont_copy = len(x) + 1
                            x = coordX(x)
                            new_selector += x

                        elif char == 'y' and letter == False:
                            new_selector += selector[char_num:char_num + 2]
                            char_y = char_num + 2
                            end_char_y = selector.find(',', char_num + 3,
                                                       len(selector) - 1)
                            if end_char_y == -1:
                                end_char_y = len(selector) - 1
                            y = selector[char_y:end_char_y]
                            dont_copy = len(y) + 1
                            y = coordY(y)
                            new_selector += y
                        elif char == 'z' and letter == False:
                            new_selector += selector[char_num:char_num + 2]
                            char_z = char_num + 2
                            end_char_z = selector.find(',', char_num + 3,
                                                       len(selector) - 1)
                            if end_char_z == -1:
                                end_char_z = len(selector) - 1
                            z = selector[char_z:end_char_z]
                            dont_copy = len(z) + 1
                            z = coordZ(z)
                            new_selector += z
                    char_num += 1
                return new_selector

            # Adjust command coordinates.
            words = command.split(' ')

            i = 0
            for word in words:
                if word[0] == '@':
                    words[i] = selectorCoords(word)
                i += 1

            if command.startswith('execute'):
                stillExecuting = True
                execute = True
                saving_command = ""
                while stillExecuting == True:
                    if Slash == True:
                        saving_command += '/'
                    x, y, z = words[2:5]
                    words[2:5] = coords(x, y, z)
                    if words[5] == 'detect':
                        x, y, z = words[6:9]
                        words[6:9] = coords(x, y, z)
                        saving_command += ' '.join(words[:9])
                        words = words[9:]
                    else:
                        saving_command += ' '.join(words[:5])
                        words = words[5:]
                    command = ' '.join(words)
                    saving_command += ' '
                    Slash = False
                    if command[0] == "/":
                        command = command.replace("/", "", 1)
                        Slash = True
                    words = command.split(' ')
                    if not command.startswith('execute'):
                        stillExecuting = False

            if (command.startswith('tp') and len(words) == 5
                ) or command.startswith('particle') or command.startswith(
                    'replaceitem block') or (
                        command.startswith('spawnpoint') and len(words)
                        == 5) or command.startswith('stats block') or (
                            command.startswith('summon') and len(words) >= 5):
                x, y, z = words[2:5]
                words[2:5] = coords(x, y, z)
            elif command.startswith('blockdata') or command.startswith(
                    'setblock') or (command.startswith('setworldspawn')
                                    and len(words) == 4):
                x, y, z = words[1:4]
                words[1:4] = coords(x, y, z)
            elif command.startswith('playsound') and len(words) >= 6:
                x, y, z = words[3:6]
                words[3:6] = coords(x, y, z)
            elif command.startswith('clone'):
                x1, y1, z1, x2, y2, z2, x, y, z = words[1:10]
                x1, y1, z1 = coords(x1, y1, z1)
                x2, y2, z2 = coords(x2, y2, z2)
                x, y, z = coords(x, y, z)

                words[1:10] = x1, y1, z1, x2, y2, z2, x, y, z
            elif command.startswith('fill'):
                x1, y1, z1, x2, y2, z2 = words[1:7]
                x1, y1, z1 = coords(x1, y1, z1)
                x2, y2, z2 = coords(x2, y2, z2)

                words[1:7] = x1, y1, z1, x2, y2, z2
            elif command.startswith('spreadplayers'):
                x, z = words[1:3]
                if x[0] != "~":
                    x = coordX(x)
                if z[0] != "~":
                    z = coordZ(z)

                words[1:3] = x, z
            elif command.startswith('worldborder center') and len(words) == 4:
                x, z = words[2:4]
                if x[0] != "~":
                    x = coordX(x)
                if z[0] != "~":
                    z = coordZ(z)

                words[2:4] = x, z
            if Slash == True:
                command = '/'
            else:
                command = ""
            command += ' '.join(words)

            if execute == True:
                command = saving_command + command
            eTag['Command'].value = command

        return eTag
Пример #28
0
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):
    #    print(chunk.Blocks[:,i,1])
Пример #29
0
 def copyWithOffset(cls, tileEntity, copyOffset):
     eTag = deepcopy(tileEntity)
     eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0])
     eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1])
     eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2])
     return eTag