Exemple #1
0
    def toNbt(self) -> nbt.TAG_Compound:
        data = nbt.TAG_Compound()

        motion = nbt.TAG_List(name="Motion", type=nbt.TAG_Double)
        motion.append(nbt.TAG_Double(self.velocity[0]))
        motion.append(nbt.TAG_Double(self.velocity[1]))
        motion.append(nbt.TAG_Double(self.velocity[2]))
        data.tags.append(motion)

        pos = nbt.TAG_List(name="Pos", type=nbt.TAG_Double)
        pos.append(nbt.TAG_Double(self.pos[0]))
        pos.append(nbt.TAG_Double(self.pos[1]))
        pos.append(nbt.TAG_Double(self.pos[2]))
        data.tags.append(pos)

        data.tags.append(
            nbt.TAG_String(name="id", value=f"minecraft:{self.kind.name}"))

        data.tags.append(nbt.TAG_Float(name="Health", value=self.health))

        data.tags.append(nbt.TAG_Byte(name="OnGround", value=self.onGround))

        data.tags.append(
            nbt.TAG_Int(name="PortalCooldown", value=self.portalCooldown))

        if self.extra is not None:
            extra = self.extra.toNbt()
            data.tags += extra.tags

        return data
Exemple #2
0
def norbert_parse_line(line, sep=DEFAULT_SEP):
    line = line.strip()
    name, tagtype, value = norbert_split_line(line, sep[2])

    # validate user input
    if tagtype is None:
        err("Invalid or missing tag type: " + line)
        raise IOError(exceptions.INVALID_TYPE, "Not a norbert file")
    elif tagtype != nbt.TAG_COMPOUND and value is None:
        err("Tag value not found: " + line)
        raise IOError(exceptions.INVALID_VALUE, "Not a norbert file")

    # get the list of names/indexes
    names = norbert_split_name(name, sep)

    # create the tag
    if tagtype == nbt.TAG_LIST:
        listtype = tag_types[value]
        tag = nbt.TAG_List(type=nbt.TAGLIST[listtype])
    elif tagtype == nbt.TAG_COMPOUND:
        tag = nbt.TAG_Compound()
    else:
        tag = nbt.TAGLIST[tagtype]()
        retval = set_tag(tag, value)
        if retval != 0:
            err("Invalid tag value: " + line)
            raise IOError(retval, "Not a norbert file")

    return names, tag
Exemple #3
0
def norbert_add_tag(nbtfile, names, newtag):
    # give the root TAG_Compound the right name
    nbtfile.name = names[0]
    names.pop(0)

    tag = nbtfile
    for i, name in enumerate(names):
        testtag = get_tag(tag, str(name))
        # tag already exists
        if testtag is not None:
            tag = testtag

        # add leaf node
        elif i + 1 == len(names):
            tag = norbert_add_child(tag, name, newtag)

        # add a list
        elif isinstance(names[i + 1], int):
            # list of basic tags
            if i + 2 == len(names):
                listtype = newtag.id
            # list of lists
            elif isinstance(names[i + 2], int):
                listtype = nbt.TAG_LIST
            # list of compounds
            else:
                listtype = nbt.TAG_COMPOUND

            tag = norbert_add_child(tag, name, \
                                    nbt.TAG_List(type=nbt.TAGLIST[listtype])
            )

        # add a compound
        else:
            tag = norbert_add_child(tag, name, nbt.TAG_Compound())
Exemple #4
0
def toNbt(entities: List[Entity]) -> nbt.TAG_List:
    result = nbt.TAG_List(type=nbt.TAG_Compound, name="Entities")

    for entity in entities:
        result.append(entity.toNbt())

    return result
Exemple #5
0
def template_village_file(tick):
    """
    Creates a template villages.dat file that i can modify later on
    """
    cat = nbt.NBTFile()
    cat2 = cat['data'] = nbt.TAG_Compound()
    cat2["Villages"] = nbt.TAG_List(Banana)
    cat2['Tick'] = nbt.TAG_Int(tick)
    return cat
Exemple #6
0
    def _as_schematic(self):
        nbtfile = nbt.NBTFile()
        nbtfile.name = "Schematic"
        nbtfile.tags.append(nbt.TAG_Short(name="Height", value=self.height))
        nbtfile.tags.append(nbt.TAG_Short(name="Width", value=self.width))
        nbtfile.tags.append(nbt.TAG_Short(name="Length", value=self.depth))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOffsetX", value=-1))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOffsetY", value=0))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOffsetZ", value=-1))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOriginX", value=0))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOriginY", value=0))
        nbtfile.tags.append(nbt.TAG_Int(name="WEOriginZ", value=0))
        
        # YZX ordering
       
        data = bytearray()
        blocks = bytearray()
      
        for y in range(self.height):
            for z in range(self.depth):
                for x in range(self.width):
                    block_id, block_data = self.reader.get(x, y, z)
                    blocks.append(block_id)
                    data.append(block_data)
           
        blocks_tag = nbt.TAG_Byte_Array()
        blocks_tag.value = blocks

        data_tag = nbt.TAG_Byte_Array()
        data_tag.value = data
        
        nbtfile["Blocks"] = blocks_tag
        nbtfile["Data"] = data_tag
        
        nbtfile.tags.append(nbt.TAG_String(name="Materials", value=u"Alpha"))
        nbtfile["Entities"] = nbt.TAG_List(type=nbt.TAG_Compound)
        nbtfile["TileEntities"] = nbt.TAG_List(type=nbt.TAG_Compound)
        
        output = BytesIO()
        nbtfile.write_file(fileobj=output)
        as_nbt = output.getvalue()
        output.close()
        return as_nbt
Exemple #7
0
def check_region_file(region_file, delete_entities=False, entity_limit=500):
    """ Takes a RegionFile obj and returns a list of corrupted 
    chunks where each element represents a corrupted chunk and
    contains a tuple:
     (region file, coord x, coord y) 
     and returns also the total number of chunks (including corrupted ones)
     """

    total_chunks = 0
    bad_chunks = []
    wrong_located_chunks = []
    try:
        for x in range(32):
            for z in range(32):
                #~ print "In chunk ({0},{1})".format(x,z)
                chunk = check_chunk(region_file, x, z)
                if isinstance(chunk, nbt.TAG_Compound):
                    total_chunks += 1
                    total_entities = len(chunk['Level']['Entities'].tags)
                    # deleting entities is here because to parse a chunk with thousands of wrong entities
                    # takes a long time, and once detected is better to fix it at once.
                    if delete_entities == True and total_entities > entity_limit:

                        #~ print len(chunk['Level']['Entities'].tags)
                        empty_tag_list = nbt.TAG_List(nbt.TAG_Byte, '',
                                                      'Entities')

                        chunk['Level']['Entities'] = empty_tag_list
                        #~ print len(chunk['Level']['Entities'].tags)
                        print "Deleted {0} entities in chunk ({1},{2}).".format(
                            total_entities, x, z)
                        region_file.write_chunk(x, z, chunk)

                    elif total_entities > entity_limit:
                        print "[WARNING!]: The chunk ({0},{1}) in region file {2} has {3} entities, and this may be too much. This may be a problem!".format(
                            x, z, region_file, total_entities)

                elif chunk == -1:
                    total_chunks += 1
                    bad_chunks.append((region_file.filename, x, z))
                elif chunk == -2:
                    total_chunks += 1
                    wrong_located_chunks.append((region_file.filename, x, z))
                # if None do nothing
                del chunk  # unload chunk from memory

        filename = split(region_file.filename)[1]

        del region_file

    except KeyboardInterrupt:
        print "\nInterrupted by user\n"
        sys.exit(1)

    return filename, bad_chunks, wrong_located_chunks, total_chunks
def delete_entities(region_file, x, z):
    """ This function is used while scanning the world in scan.py! Takes
        a region file obj and a local chunks coords and deletes all the
        entities in that chunk. """
    chunk = region_file.get_chunk(x, z)
    counter = len(chunk['Level']['Entities'])
    empty_tag_list = nbt.TAG_List(nbt.TAG_Byte, '', 'Entities')
    chunk['Level']['Entities'] = empty_tag_list
    region_file.write_chunk(x, z, chunk)

    return counter
    def remove_chunk_entities(self, x, z):
        """ Takes a chunk coordinates, opens the chunk and removes all
            the entities in it. Return an integer with the number of
            entities removed"""
        region_file = region.RegionFile(self.path)
        chunk = region_file.get_chunk(x, z)
        counter = len(chunk['Level']['Entities'])
        empty_tag_list = nbt.TAG_List(nbt.TAG_Byte, '', 'Entities')
        chunk['Level']['Entities'] = empty_tag_list
        region_file.write_chunk(x, z, chunk)

        return counter
    def save(self) -> nbt.NBTFile:
        """
        Saves the chunk data to a :class:`NBTFile`

        Notes
        -----
        Does not contain most data a regular chunk would have,
        but minecraft stills accept it.
        """
        root = nbt.NBTFile()
        root.tags.append(nbt.TAG_Int(name='DataVersion', value=self.version))
        level = nbt.TAG_Compound()
        # Needs to be in a separate line because it just gets
        # ignored if you pass it as a kwarg in the constructor
        level.name = 'Level'
        level.tags.extend([
            nbt.TAG_List(name='Entities', type=nbt.TAG_Compound),
            nbt.TAG_List(name='TileEntities', type=nbt.TAG_Compound),
            nbt.TAG_List(name='LiquidTicks', type=nbt.TAG_Compound),
            nbt.TAG_Int(name='xPos', value=self.x),
            nbt.TAG_Int(name='zPos', value=self.z),
            nbt.TAG_Long(name='LastUpdate', value=0),
            nbt.TAG_Long(name='InhabitedTime', value=0),
            nbt.TAG_Byte(name='isLightOn', value=1),
            nbt.TAG_String(name='Status', value='full')
        ])
        sections = nbt.TAG_List(name='Sections', type=nbt.TAG_Compound)
        for s in self.sections:
            if s:
                p = s.palette()
                # Minecraft does not save sections that are just air
                # So we can just skip them
                if len(p) == 1 and p[0].name() == 'minecraft:air':
                    continue
                sections.tags.append(s.save())
        level.tags.append(sections)
        root.tags.append(level)
        return root
Exemple #11
0
    def create_village(tick):
        """
        Creates a template village
        """
        village_template = nbt.TAG_Compound()

        village_template['Doors'] = nbt.TAG_List(Banana)
        village_template['Players'] = nbt.TAG_List(Banana)
        village_template['ACX'] = nbt.TAG_Int(0)
        village_template['ACY'] = nbt.TAG_Int(0)
        village_template['ACZ'] = nbt.TAG_Int(0)

        village_template['CX'] = nbt.TAG_Int(0)
        village_template['CY'] = nbt.TAG_Int(0)
        village_template['CZ'] = nbt.TAG_Int(0)

        village_template['Golems'] = nbt.TAG_Int(0)
        village_template['MTick'] = nbt.TAG_Int(0)
        village_template['PopSize'] = nbt.TAG_Int(1)
        village_template['Radius'] = nbt.TAG_Int(32)
        village_template['Stable'] = nbt.TAG_Int(tick)
        village_template['Tick'] = nbt.TAG_Int(tick)
        return Village(village_template)
def create_nbt_from_entry(
        entry: Union[NBTEntry, NBTListEntry, NBTCompoundEntry]) -> nbt.TAG:
    tag = None
    entry_type = entry.tag_type
    if entry_type in _entry_to_tag_map:
        tag = _entry_to_tag_map[entry_type](value=entry.value)
    elif isinstance(entry, NBTCompoundEntry):
        tag = nbt.TAG_Compound()
        for name, child_entry in entry.items():
            tag[name] = create_nbt_from_entry(child_entry)
    elif isinstance(entry, NBTListEntry):
        tag = nbt.TAG_List()
        for child_entry in entry:
            tag.append(create_nbt_from_entry(child_entry))
    return tag
Exemple #13
0
    def place_chests(self, region, new_region, x, y, z, direction):
        # add_x = 1
        # add_z = 0
        chest = anvil.Block("minecraft", "chest")
        chest.properties["waterlogged"] = "false"
        chest.properties["facing"] = "east"
        chest.properties["type"] = "single"

        # if direction == cfg.M_DIR_Z:
        #     add_x = 0
        #     add_z = 1
        #     chest.properties["shape"] = "east_west"

        i = 0
        chest_x = x
        chest_y = y - 1
        chest_z = z

        for item_type in self.item_dict:
            amount = self.item_dict[item_type]

            while amount > 0:
                if direction == cfg.M_DIR_Z:
                    chest_x = x + 1
                    chest_z = z + i
                else:
                    chest_x = x + i
                    chest_z = z + 1

                new_region.set_block(chest, chest_x, chest_y, chest_z)

                item = "minecraft:" + str(item_type)
                block_entity, amount = self.create_chest_block_entity(
                    chest_x, chest_y, chest_z, item, amount)

                chunk_idx_x = chest_x // cfg.CHUNK_B_X
                chunk_idx_z = chest_z // cfg.CHUNK_B_Z
                chunk = region.get_chunk(chunk_idx_x, chunk_idx_z)

                if chunk.data["TileEntities"].tagID != nbt.TAG_Compound.id:
                    chunk.data["TileEntities"] = nbt.TAG_List(
                        name="TileEntities", type=nbt.TAG_Compound)
                chunk.data["TileEntities"].tags.append(block_entity)
                i += 1
Exemple #14
0
    def get_chunk(self, chunk_x, chunk_z):
        key = (chunk_x, chunk_z)
        if not key in self.chunks:
            try:
                self.chunks[key] = self.region.get_chunk(chunk_x, chunk_z)
            except region.InconceivedChunk:
                # create the chunk
                new_chunk = nbt.NBTFile()
                level_tag = nbt.TAG_Compound()
                level_tag.name = "Level"
                level_tag.tags.append(
                    nbt.TAG_Int(name="xPos", value=chunk_x * 32))
                level_tag.tags.append(
                    nbt.TAG_Int(name="zPos", value=chunk_z * 32))
                level_tag.tags.append(
                    nbt.TAG_List(name="Sections", type=nbt.TAG_Compound))
                new_chunk.tags.append(level_tag)
                self.chunks[key] = new_chunk

        return self.chunks[key]
Exemple #15
0
    def create_chest_block_entity(self, chest_x, chest_y, chest_z, b_type,
                                  amount):
        items = nbt.TAG_List(name="Items", type=nbt.TAG_Compound)

        # TODO make this variable by using the config file
        stacks = min(amount // 64, 27)
        remainder = amount % 64 if stacks < 27 else 0

        for i in range(stacks):
            chest_entry = nbt.TAG_Compound()
            chest_entry.tags.extend([
                nbt.TAG_Byte(name="Count", value=64),
                nbt.TAG_Byte(name="Slot", value=i),
                nbt.TAG_String(name="id", value=b_type),
            ])
            items.tags.append(chest_entry)

        if stacks < 27:
            chest_entry = nbt.TAG_Compound()
            chest_entry.tags.extend([
                nbt.TAG_Byte(name="Count", value=amount % 64),
                nbt.TAG_Byte(name="Slot", value=stacks),
                nbt.TAG_String(name="id", value=b_type),
            ])
            items.tags.append(chest_entry)

        block_entity = nbt.TAG_Compound()
        block_entity.tags.extend([
            nbt.TAG_String(name="id", value="minecraft:chest"),
            nbt.TAG_Int(name="x", value=chest_x),
            nbt.TAG_Int(name="y", value=chest_y),
            nbt.TAG_Int(name="z", value=chest_z),
            nbt.TAG_Byte(name="keepPacked", value=0),
        ])
        block_entity.tags.append(items)

        new_amount = amount - (stacks * 64 + remainder)
        return block_entity, new_amount
Exemple #16
0
    def toNbt(self) -> nbt.TAG_Compound:
        tag = super().toNbt()

        inventory = nbt.TAG_List(type=nbt.TAG_Compound, name='Inventory')
        for (slotIdx, item) in enumerate(self.inventory):
            stackTag = item.stack.toNbt(slotIdx)
            if stackTag is not None:
                inventory.append(stackTag)

        tag.tags.append(inventory)

        gameMode = 1 if self.creative else 0
        tag.tags.append(nbt.TAG_Int(gameMode, 'playerGameType'))

        abilities = nbt.TAG_Compound()
        abilities.name = 'abilities'
        abilities.tags.append(nbt.TAG_Byte(int(self.flying), 'flying'))

        tag.tags.append(abilities)

        tag.tags.append(nbt.TAG_String(self.dimension, 'dimension'))

        return tag
Exemple #17
0
def save_chunk(self, data) -> nbt.NBTFile:
    """
    Saves the chunk data to a :class:`NBTFile`

    Notes
    -----
    Does not contain most data a regular chunk would have,
    but minecraft stills accept it.
    """
    root = nbt.NBTFile()
    root.tags.append(nbt.TAG_Int(name="DataVersion", value=self.version))
    level = nbt.TAG_Compound()
    # Needs to be in a separate line because it just gets
    # ignored if you pass it as a kwarg in the constructor
    level.name = "Level"

    if data:
        if data.get("Biomes") is not None:
            level.tags.append(data["Biomes"])
        if data.get("Heightmaps") is not None:
            level.tags.append(data["Heightmaps"])
        # level.tags.append(data["CarvingMasks"])
        if data.get("Entities") is not None:
            level.tags.append(data["Entities"])
        if data.get("TileEntities") is not None:
            level.tags.append(data["TileEntities"])

        # if data.get("TileTicks") is not None:
        #     level.tags.append(data["TileTicks"])
        if data.get("LiquidTicks") is not None:
            level.tags.append(data["LiquidTicks"])
        ########
        if data.get("Lights") is not None:
            level.tags.append(data["Lights"])
        if data.get("LiquidsToBeTicked") is not None:
            level.tags.append(data["LiquidsToBeTicked"])
        if data.get("ToBeTicked") is not None:
            level.tags.append(data["ToBeTicked"])
        if data.get("CarvingMasks") is not None:
            level.tags.append(data["CarvingMasks"])

        ##########
        if data.get("PostProcessing") is not None:
            level.tags.append(data["PostProcessing"])
        if data.get("Structures") is not None:
            level.tags.append(data["Structures"])

        level.tags.extend([
            # nbt.TAG_List(name="Entities", type=nbt.TAG_Compound),
            # nbt.TAG_List(name="TileEntities", type=nbt.TAG_Compound),
            # nbt.TAG_List(name="LiquidTicks", type=nbt.TAG_Compound),
            nbt.TAG_Int(name="xPos", value=self.x),
            nbt.TAG_Int(name="zPos", value=self.z),
            # nbt.TAG_Long(name="LastUpdate", value=data["LastUpdate"]),
            nbt.TAG_Long(name="LastUpdate", value=0),
            # nbt.TAG_Long(name="InhabitedTime", value=data["InhabitedTime"]),
            nbt.TAG_Long(name="InhabitedTime", value=0),
            nbt.TAG_Byte(name="isLightOn", value=1),
            nbt.TAG_String(name="Status", value="full"),
        ])

        # entities = self.add_entities(data["Entities"])
        # level.tags.append(entities)
        # nbt.TAG_List(name="Entities", type=nbt.TAG_Compound)
    else:
        level.tags.extend([
            # nbt.TAG_List(name="Entities", type=nbt.TAG_Compound),
            nbt.TAG_List(name="TileEntities", type=nbt.TAG_Compound),
            nbt.TAG_List(name="LiquidTicks", type=nbt.TAG_Compound),
            nbt.TAG_Int(name="xPos", value=self.x),
            nbt.TAG_Int(name="zPos", value=self.z),
            nbt.TAG_Long(name="LastUpdate", value=0),
            nbt.TAG_Long(name="InhabitedTime", value=0),
            nbt.TAG_Byte(name="isLightOn", value=1),
            nbt.TAG_String(name="Status", value="full"),
        ])

    sections = nbt.TAG_List(name="Sections", type=nbt.TAG_Compound)
    for s in self.sections:
        if s:
            p = s.palette()
            # Minecraft does not save sections that are just air
            # So we can just skip them
            if len(p) == 1 and p[0].name() == "minecraft:air":
                continue
            sections.tags.append(s.save())
    level.tags.append(sections)
    root.tags.append(level)
    return root
                return template.default_value
            return NBTListEntry()
        else:
            return template.create_entry_from_template()

    template = loader.load_template(entity_id)
    entry = NBTCompoundEntry(convert_template(template))
    return entry


if __name__ == "__main__":
    print(create_entry_from_nbt(nbt.TAG_Byte(value=4)))

    compound = nbt.TAG_Compound()
    compound["test1"] = nbt.TAG_Int(value=-100)
    compound["test2"] = nbt.TAG_String(value="hello!")

    test1 = create_entry_from_nbt(compound)
    print(test1)
    print(create_nbt_from_entry(test1))
    print("=" * 16)

    test2 = create_entry_from_nbt(
        nbt.TAG_List(value=[
            nbt.TAG_String(value="test1"),
            nbt.TAG_String(value="test2"),
            nbt.TAG_String(value="test3"),
        ]))
    print(test2)
    print(create_nbt_from_entry(test2))
Exemple #19
0
def make_tag_list(vals):
    tag = nbt.TAG_List(type=vals[0])
    tag.tags = list(vals)
    return tag
Exemple #20
0
def scan_mcr_file(region_file_path):
    """ Scans a region file reporting problems.
    
    Takes a RegionFile obj and returns a list of corrupted 
    chunks where each element represents a corrupted chunk and
    is a tuple containing:

    (region file, (coord x, coord y), problem) 

    This function is used from scan_all_mcr_files and uses a
    multiprocessing queue to return in real time info about the process.
    """

    delete_entities = scan_mcr_file.options.delete_entities
    entity_limit = scan_mcr_file.options.entity_limit
    region_file = region.RegionFile(region_file_path)
    w = scan_mcr_file.w
    chunks = 0
    problems = []
    corrupted = 0
    wrong = 0
    entities_prob = 0
    filename = split(region_file.filename)[1]
    try:
        for x in range(32):
            for z in range(32):
                chunk, status, error_msg = scan_chunk(region_file, x, z)
                if status == 0:
                    chunks += 1
                    total_entities = len(chunk['Level']['Entities'].tags)
                    # deleting entities is in here because to parse a chunk with thousands of wrong entities
                    # takes a long time, and once detected is better to fix it at once.
                    if total_entities >= entity_limit:
                        if delete_entities == True:
                            empty_tag_list = nbt.TAG_List(nbt.TAG_Byte,'','Entities')
                            chunk['Level']['Entities'] = empty_tag_list
                            print "Deleted {0} entities in chunk ({1},{2}).".format(total_entities, x, z)
                            region_file.write_chunk(x, z, chunk)

                        else:
                            problems.append((region_file.filename,(x,z),w.TOO_MUCH_ENTITIES))
                            entities_prob += 1
                            print "[WARNING!]: The chunk ({0},{1}) in region file {2} has {3} entities, and this may be too much. This may be a problem!".format(x,z,split(region_file.filename)[1],total_entities)

                            # This stores all the entities in a file,
                            # comes handy sometimes.
                            #~ pretty_tree = chunk['Level']['Entities'].pretty_tree()
                            #~ name = "{2}.chunk.{0}.{1}.txt".format(x,z,split(region_file.filename)[1])
                            #~ archivo = open(name,'w')
                            #~ archivo.write(pretty_tree)

                elif status == -1:
                    chunks += 1
                    problems.append((region_file.filename,(x,z),w.CORRUPTED))
                    corrupted += 1
                elif status == -2:
                    chunks += 1
                    problems.append((region_file.filename,(x,z),w.WRONG_LOCATED))
                    wrong += 1
                # if None do nothing

                del chunk # unload chunk from memory

        del region_file

    except KeyboardInterrupt:
        print "\nInterrupted by user\n"
        sys.exit(1)

    scan_mcr_file.q.put((filename, corrupted, wrong, entities_prob, chunks))

    return problems