Пример #1
0
    def update_server_address(self, ip, name='AWScraft'):
        '''
        Updates the server named <name> with new IP address <ip> in servers.dat.
        Otherwise creates a new server entry named <name> with <ip>
        '''
        server_file = os.path.join(self.data_directory, 'servers.dat')
        if not os.path.isfile(server_file):
            return False  # Check Server File Exists

        with open(server_file, 'rb') as binary:
            server = nbt.NBTFile(buffer=binary)

        updated = False
        for entry in server['servers']:
            if entry['name'] == name:
                entry['ip'] = ip
                updated = True

        if not updated:
            new_server = nbt.TAG_Compound()
            new_server.tags.append(nbt.TAG_String(name='name', value=name))
            new_server.tags.append(nbt.TAG_String(name='ip', value=ip))

            server['servers'].append(new_server)

        os.remove(server_file)
        with open(server_file, 'wb') as new_binary:
            server.write_file(buffer=new_binary)

        return True
Пример #2
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
Пример #3
0
    def __init__(
        self,
        namespace: str,
        block_id: str = None,
        properties: dict = None,
        states: dict = None,
    ):
        """
        Parameters
        ----------
        namespace
            Namespace of the block. If no block_id is given, assume this is ``block_id`` and set namespace to ``"minecraft"``
        block_id
            ID of the block
        properties
            Block properties
        states
            Block properties in simple form
        """
        # Transform block properties from a simple dict to a dict containing
        # the weird NBT value TAG thingys.
        if states:
            properties = {k: nbt.TAG_String(v, k) for k, v in states.items()}

        if block_id is None:
            self.namespace = "minecraft"
            self.id = namespace
        else:
            self.namespace = namespace
            self.id = block_id
        self.properties = properties or {}
Пример #4
0
 def toNbt(self, slotIdx=None) -> Optional[nbt.TAG_Compound]:
     if self.isEmpty():
         return None
     else:
         result = nbt.TAG_Compound()
         result.tags.append(nbt.TAG_String(f'minecraft:{self.item}', 'id'))
         result.tags.append(nbt.TAG_Byte(self.amount, 'Count'))
         if slotIdx is not None:
             result.tags.append(nbt.TAG_Byte(slotIdx, 'Slot'))
         return result
Пример #5
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
Пример #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
Пример #7
0
    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
Пример #8
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
Пример #9
0
    start='[',
    end=']')
STR_Compound = matchDict(STR_String, STR_TAG)

STR_TAG << (STR_Number | STR_String | STR_Byte_Array | STR_Int_Array
            | STR_Long_Array | STR_List | STR_Compound)

# ----------------------------------------------------------------------

STR_Byte.addParseAction(lambda t: nbt.TAG_Byte(t[0]))
STR_Short.addParseAction(lambda t: nbt.TAG_Short(t[0]))
STR_Int.addParseAction(lambda t: nbt.TAG_Int(t[0]))
STR_Long.addParseAction(lambda t: nbt.TAG_Long(t[0]))
STR_Float.addParseAction(lambda t: nbt.TAG_Float(t[0]))
STR_Double.addParseAction(lambda t: nbt.TAG_Double(t[0]))
STR_String.addParseAction(lambda t: nbt.TAG_String(t[0]))


def make_tag_array(vals, tag_type, value_constructor=list):
    tag = tag_type()
    tag.value = value_constructor(vals)
    return tag


STR_Byte_Array.addParseAction(lambda t: make_tag_array(
    t[0], nbt.TAG_Byte_Array, value_constructor=bytearray))
STR_Int_Array.addParseAction(lambda t: make_tag_array(t[0], nbt.TAG_Int_Array))
STR_Long_Array.addParseAction(
    lambda t: make_tag_array(t[0], nbt.TAG_Long_Array))

Пример #10
0
                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))
Пример #11
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
Пример #12
0
def convert(path):
    if not os.path.isdir(path):
        sys.stderr.write('Path is not directory or does not exist:' + path)
        return False
    max_payload_size = 50
    retry_delay = 3
    profile_url = 'https://api.mojang.com/profiles/minecraft'
    #profile_url = 'http://api.goender.net/api/profiles/minecraft'
    player_data_path = os.path.join(path, 'players')
    target_data_path = os.path.join(path, 'playerdata')
    missing_data_path = os.path.join(path, 'players.missing')
    converted_data_path = os.path.join(path, 'players.converted')
    invalid_data_path = os.path.join(path, 'players.invalid')
    player_files = {}
    if not os.path.isdir(missing_data_path):
        os.mkdir(missing_data_path)
    if not os.path.isdir(converted_data_path):
        os.mkdir(converted_data_path)
    if not os.path.isdir(invalid_data_path):
        os.mkdir(invalid_data_path)
    for player_file in os.listdir(player_data_path):
        if os.path.isfile(
                os.path.join(player_data_path,
                             player_file)) and player_file.endswith('.dat'):
            name = os.path.splitext(os.path.basename(player_file))[0].lower()
            player_files[name] = os.path.join(player_data_path, player_file)
    if not player_files:
        sys.stderr.write('No player data found!\n')
        return False
    if not os.path.isdir(target_data_path):
        os.mkdir(target_data_path)
    payload = []
    current = 0
    for name in player_files.keys():
        current = current + 1
        payload.append(name)
        if (float(current) %
                max_payload_size) != 0 and current != len(player_files):
            continue
        request = urllib2.Request(profile_url, json.dumps(payload),
                                  {'Content-Type': 'application/json'})
        retry = False
        retry_count = 0
        while True:
            try:
                response = urllib2.urlopen(request)
                if retry:
                    sys.stderr.write('Retry successful! Number of retries: ' +
                                     str(retry_count) + '\n')
                    retry = False
                retry_count = 0
                break
            except Exception as e:
                sys.stderr.write(
                    str(e) + " (don't worry, we'll retry until it works!)\n")
                retry = True
                time.sleep(retry_delay)
            retry_count = retry_count + 1
        profiles = json.loads(response.read())
        if isinstance(profiles,
                      dict):  # http://api.goender.net/api/profiles/minecraft
            data = profiles
            profiles = []
            for name in data.keys():
                profiles.append({'id': data[name], 'name': name})
        if len(profiles) != len(payload):
            payload_names = set([name.lower() for name in payload])
            response_names = set(
                [profile['name'].lower() for profile in profiles])
            missing_names = list(payload_names - response_names)
            for name in missing_names:
                try:
                    src = player_files[name]
                    shutil.move(
                        src,
                        os.path.join(missing_data_path, os.path.basename(src)))
                except Exception as e:
                    sys.stderr.write('Error moving file file: ' + src + ' (' +
                                     str(e) + ')\n')
            sys.stderr.write('Missing profiles from API response: ' +
                             repr(missing_names) + '\n')
        payload = []
        for profile in profiles:
            name = profile['name'].lower()
            if name not in player_files:
                continue
            src = player_files[name]
            dst = os.path.join(target_data_path,
                               str(uuid.UUID(profile['id'])) + '.dat')
            try:
                nbtfile = nbt.NBTFile(src, 'rb')
            except Exception as e:
                sys.stderr.write('Error reading NBT file: ' + src + ' (' +
                                 str(e) + ')\n')
                try:
                    shutil.move(
                        src,
                        os.path.join(invalid_data_path, os.path.basename(src)))
                except:
                    pass
                continue
            try:
                bukkit = nbtfile['bukkit']
            except KeyError:
                bukkit = nbt.TAG_Compound()
                bukkit.name = 'bukkit'
                nbtfile.tags.append(bukkit)
            try:
                lastKnownName = bukkit['lastKnownName']
            except KeyError:
                lastKnownName = nbt.TAG_String(name='lastKnownName')
                bukkit.tags.append(lastKnownName)
            lastKnownName.value = profile['name']
            nbtfile.write_file(dst)
            try:
                shutil.move(
                    src,
                    os.path.join(converted_data_path, os.path.basename(src)))
            except Exception as e:
                sys.stderr.write('Error moving file file: ' + src + ' (' +
                                 str(e) + ')\n')
    return True