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
STR_List = delimited( pp.delimitedList(STR_TAG).setParseAction(lambda t: tuple(t)), 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(
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