def add_painting(self, painting_file): src = os.path.join(self.painting_path, painting_file + '.dat') painting_file_hash = hashlib.md5(open(src, 'r').read()).digest() # Look up file in hashtable if painting_file_hash in self.maphash: mapid = self.maphash[painting_file_hash] else: # Initialize the map count if it doesn't exist. if 'map' not in self.idcounts: self.idcounts['map'] = nbt.TAG_Short(-1) # Increment and return id self.idcounts['map'].value += 1 mapid = self.idcounts['map'].value # Copy the map to the data dir dest = os.path.join(self.mapstore, 'map_%d.dat' % (mapid)) try: shutil.copy(src, dest) except: sys.exit('Error when placing painting in map directory.') self.maphash[painting_file_hash] = mapid # Update hashtable self.update_mapstore() # Create map item tag item = nbt.TAG_Compound() item['id'] = nbt.TAG_Short(358) item['Damage'] = nbt.TAG_Short(mapid) item['Count'] = nbt.TAG_Byte(1) # Fetch the lore text for this map lorefile = open( os.path.join( self.painting_path, painting_file + '.txt')) loredata = lorefile.read().splitlines() lorefile.close() # Create NBT tag valid_characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ " item['tag'] = nbt.TAG_Compound() item['tag']['display'] = nbt.TAG_Compound() item['tag']['display']['Name'] = nbt.TAG_String( filter( lambda x: x in valid_characters, loredata.pop(0))) item['tag']['display']['Lore'] = nbt.TAG_List() # Slice at 5 lines of 50 chars each for p in loredata[:5]: line = filter(lambda x: x in valid_characters, p) item['tag']['display']['Lore'].append(nbt.TAG_String(line[:50])) return item
def convert(tag): out = None if (tag.type is parse.TAG_Byte): out = nbt.TAG_Byte(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Byte_Array): out = nbt.TAG_Byte_Array(value=fromstring(tag.data), name=tag.name) elif (tag.type is parse.TAG_Double): out = nbt.TAG_Double(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Float): out = nbt.TAG_Float(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Int): out = nbt.TAG_Int(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Int_Array): out = nbt.TAG_Int_Array(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Long): out = nbt.TAG_Long(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_Short): out = nbt.TAG_Short(value=tag.data, name=tag.name) elif (tag.type is parse.TAG_String): out = nbt.TAG_String(value=tag.data, name=tag.name) # Recursives elif (tag.type is parse.TAG_Compound): out = nbt.TAG_Compound(name=tag.name) for item in tag.data: temp = convert(item) if (temp is not None): out[temp.name] = temp elif (tag.type is parse.TAG_List): out = nbt.TAG_List(name=tag.name) for item in tag.data[1]: temp = convert(dummyNBTyaml(tag.data[0], item)) if (temp is not None): out.append(temp) return out
def save(self): ''' Saves all waypoint information to the 'mcedit_waypoints.dat' file in the world directory ''' if DEBUG: current_frame = inspect.currentframe() outerframe = inspect.getouterframes(current_frame, 2)[1] print "Called by '" + str(outerframe[3]) + "()' in '" + str( outerframe[1].split("\\")[-1]) + "' at line " + str( outerframe[2]) del self.nbt_waypoints["Waypoints"] self.nbt_waypoints["Waypoints"] = nbt.TAG_List() for waypoint in self.waypoints.keys(): if waypoint.split()[0] == "Empty": continue way = nbt.TAG_Compound() way["Name"] = nbt.TAG_String(waypoint.split()[0]) way["Dimension"] = nbt.TAG_Int(self.waypoints[waypoint][5]) coords = nbt.TAG_List() coords.append(nbt.TAG_Float(self.waypoints[waypoint][0])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][1])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][2])) rot = nbt.TAG_List() rot.append(nbt.TAG_Float(self.waypoints[waypoint][3])) rot.append(nbt.TAG_Float(self.waypoints[waypoint][4])) way["Coordinates"] = coords way["Rotation"] = rot self.nbt_waypoints["Waypoints"].append(way) self.nbt_waypoints.save( os.path.join(self.worldDirectory, u"mcedit_waypoints.dat"))
def loadrandpainting(self): # No paintings? Give a blank map (ID: 395) if len(self.paintlist) == 0: item = nbt.TAG_Compound() item['id'] = nbt.TAG_String('minecraft:map') return item return self.mapstore.add_painting(random.choice(self.paintlist))
def testModify(self): level = self.testCreate() # Most of the value types work as expected. Here, we replace the entire tag with a TAG_String level["About"]["Author"] = nbt.TAG_String("YARRR~!") # Because the tag type usually doesn't change, # we can replace the string tag's value instead of replacing the entire tag. level["About"]["Author"].value = "Stew Pickles" # Remove members of a TAG_Compound using del, similar to a python dict. del (level["About"]) # Replace all of the wood blocks with gold using a boolean index array blocks = level["Map"]["Blocks"].value blocks[blocks == 5] = 41 level["Entities"][0] = nbt.TAG_Compound([nbt.TAG_String("Creeper", "id"), nbt.TAG_List([nbt.TAG_Double(d) for d in (1, 1, 1)], "Pos")])
def loadrandbooktext(self): item = nbt.TAG_Compound() item['id'] = nbt.TAG_Short(387) # No books? Give a book and quill instead if len(self.booklist) == 0: item['id'] = nbt.TAG_Short(386) return item # Open the book's text file bookfile = open( os.path.join(self.book_path, random.choice(self.booklist))) bookdata = bookfile.read().splitlines() bookfile.close() # Create NBT tag item['tag'] = nbt.TAG_Compound() item['tag']['author'] = nbt.TAG_String( filter(lambda x: x in self.valid_characters, bookdata.pop(0))) # Prevent unusual characters from being used item['tag']['title'] = nbt.TAG_String( filter(lambda x: x in self.valid_characters, bookdata.pop(0))) item['tag']["pages"] = nbt.TAG_List() # Slice the pages at 50 and the page text at 256 to match minecraft # limits for p in bookdata[:50]: page = filter(lambda x: x in self.valid_characters, p) page = self.ConvertEscapeChars(page) # Escape quote charcaters page = page.replace('"', '\\"') item['tag']["pages"].append(nbt.TAG_String('"%s"' % (page[:256]))) # Give the book an edition ed = topheavy_random(0, 9) item['tag']['display'] = nbt.TAG_Compound() item['tag']['display']['Lore'] = nbt.TAG_List() item['tag']['display']['Lore'].append( nbt.TAG_String(self.ed_dict[ed] + ' Edition')) if (ed == 0): item['tag']['generation'] = nbt.TAG_Int(0) elif (ed == 1): item['tag']['generation'] = nbt.TAG_Int(1) else: item['tag']['generation'] = nbt.TAG_Int(2) return item
def placespawners(self, level=0): self.pm.init(self.steps, label='Placing spawners:') count = self.steps for lm in self.landmarks: count -= 1 self.pm.update_left(count) loc = lm.spawnerloc() if loc is None: continue loc = lm.offset + loc self.setblock(loc, materials.Spawner) entity = weighted_choice(cfg.master_landmark_mobs) root_tag = self.getspawnertags(entity) root_tag['id'] = nbt.TAG_String('MobSpawner') root_tag['x'] = nbt.TAG_Int(loc.x ) root_tag['y'] = nbt.TAG_Int(loc.y ) root_tag['z'] = nbt.TAG_Int(loc.z ) root_tag['Delay'] = nbt.TAG_Short(0) SpawnCount = cfg.SpawnCount SpawnMaxNearbyEntities = cfg.SpawnMaxNearbyEntities SpawnMinDelay = cfg.SpawnMinDelay SpawnMaxDelay = cfg.SpawnMaxDelay SpawnRequiredPlayerRange = cfg.SpawnRequiredPlayerRange # But don't overwrite tags from NBT files if (SpawnCount != 0): try: root_tag['SpawnCount'] except: root_tag['SpawnCount'] = nbt.TAG_Short(SpawnCount) if (SpawnMaxNearbyEntities != 0): try: root_tag['MaxNearbyEntities'] except: root_tag['MaxNearbyEntities'] = nbt.TAG_Short( SpawnMaxNearbyEntities) if (SpawnMinDelay != 0): try: root_tag['MinSpawnDelay'] except: root_tag['MinSpawnDelay'] = nbt.TAG_Short(SpawnMinDelay) if (SpawnMaxDelay != 0): try: root_tag['MaxSpawnDelay'] except: root_tag['MaxSpawnDelay'] = nbt.TAG_Short(SpawnMaxDelay) if (SpawnRequiredPlayerRange != 0): try: root_tag['RequiredPlayerRange'] except: root_tag['RequiredPlayerRange'] = nbt.TAG_Short( SpawnRequiredPlayerRange) # Finally give the tag to the entity self.tile_ents[loc] = root_tag self.pm.set_complete()
def tagged_cb(command_block, location, blockspace): """ Translate a command block into a tile mcentity. :param command_block: The command block you want to translate. :param location: the location of the block in the blockspace. :param blockspace: the blockspace at which the command block is located. :return: nbt tag """ command = command_block.command if isinstance(command, str): command = command_factory(command) if hasattr(command, "context"): context = command.context context.executor = command_block context.blockspace = blockspace adjust(command_block, command) command = command.compile() root_tag = nbt.TAG_Compound() root_tag["id"] = nbt.TAG_String("Control") if command_block.custom_name is not None: root_tag["CustomName"] = nbt.TAG_String(command_block.custom_name) if command_block.always_active: root_tag['auto'] = nbt.TAG_Byte(1) root_tag["facing"] = nbt.TAG_String(command_block.facing) # Set the location of the command block. TileEntity.setpos(root_tag, location) # Parse the command of the command block. root_tag["Command"] = nbt.TAG_String(command) root_tag["conditional"] = nbt.TAG_Byte( 1 if command_block.conditional else 0) # Return the tag which represents the mcentity of the command block. return root_tag
def parse_nbt(node, params={}): """Recursivly build nbt datastructure from xml.""" if 'name' in node.attrib: name = node.attrib['name'] else: name = '' if node.text and node.text != '': text = replace_params(node.text, params) else: text = '' if node.tag == 'Compound': values = [] # list of other tags for child in node: values.append(parse_nbt(child, params)) return nbt.TAG_Compound(values, name) if node.tag == 'List': values = [] # list of other tags for child in node: values.append(parse_nbt(child, params)) return nbt.TAG_List(values, name) elif node.tag == 'String': return nbt.TAG_String(text, name) elif node.tag == 'Int': return nbt.TAG_Int(text, name) elif node.tag == 'Byte': return nbt.TAG_Byte(text, name) elif node.tag == 'Short': return nbt.TAG_Short(text, name) elif node.tag == 'Long': return nbt.TAG_Long(text, name) elif node.tag == 'Float': return nbt.TAG_Float(text, name) elif node.tag == 'Double': return nbt.TAG_Double(text, name) else: raise 'Unsupported'
def save(self): del self.nbt_waypoints["Waypoints"] self.nbt_waypoints["Waypoints"] = nbt.TAG_List() for waypoint in self.waypoints.keys(): way = nbt.TAG_Compound() way["Name"] = nbt.TAG_String(waypoint.split()[0]) way["Dimension"] = nbt.TAG_Int(self.waypoints[waypoint][5]) coords = nbt.TAG_List() coords.append(nbt.TAG_Float(self.waypoints[waypoint][0])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][1])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][2])) rot = nbt.TAG_List() rot.append(nbt.TAG_Float(self.waypoints[waypoint][3])) rot.append(nbt.TAG_Float(self.waypoints[waypoint][4])) way["Coordinates"] = coords way["Rotation"] = rot self.nbt_waypoints["Waypoints"].append(way) self.nbt_waypoints.save(os.path.join(self.worldDirectory, u"mcedit_waypoints.dat"))
def render(self): center = self.pos + Vec(8, 0, 8) size = random.randint(6, 10) # Now need to flatten the circle in case it is on a slope # find ground type at centre, and change all heights within circle # to be the same, and the same ground type # center is ground level. self.addclearing(center, size) # Create the circle of skulls p0 = Vec(center.x - size / 2 + 1 - self.parent.position.x, self.parent.position.y - center.y, center.z - size / 2 + 1 - self.parent.position.z) p1 = p0.trans(size - 1, 0, size - 1) skulls = ( (0, 100), # Plain Skull (1, 5), # Wither Skull (3, 1), # Steve Head ) counter = 0 for p in iterate_ellipse(p0, p1): if ((p.x + p.z) % 2 == 0): self.parent.setblock(p.up(1), materials.Fence) # Abort if there is no skull here if (random.randint(0, 100) < 33): continue SkullType = weighted_choice(skulls) self.parent.setblock(p.up(2), materials.MobHead, 1) root_tag = nbt.TAG_Compound() root_tag['id'] = nbt.TAG_String('Skull') root_tag['x'] = nbt.TAG_Int(p.x) root_tag['y'] = nbt.TAG_Int(p.y - 2) root_tag['z'] = nbt.TAG_Int(p.z) root_tag['SkullType'] = nbt.TAG_Byte(SkullType) root_tag['Rot'] = nbt.TAG_Byte(random.randint(0, 15)) self.parent.tile_ents[p.up(2)] = root_tag elif (random.randint(0, 100) < 10): self.parent.setblock(p.up(1), materials.Torch)
def save(self): ''' Saves all waypoint information to the 'mcedit_waypoints.dat' file in the world directory ''' del self.nbt_waypoints["Waypoints"] self.nbt_waypoints["Waypoints"] = nbt.TAG_List() for waypoint in self.waypoints.keys(): if waypoint.split()[0] == "Empty": continue way = nbt.TAG_Compound() way["Name"] = nbt.TAG_String(waypoint.split()[0]) way["Dimension"] = nbt.TAG_Int(self.waypoints[waypoint][5]) coords = nbt.TAG_List() coords.append(nbt.TAG_Float(self.waypoints[waypoint][0])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][1])) coords.append(nbt.TAG_Float(self.waypoints[waypoint][2])) rot = nbt.TAG_List() rot.append(nbt.TAG_Float(self.waypoints[waypoint][3])) rot.append(nbt.TAG_Float(self.waypoints[waypoint][4])) way["Coordinates"] = coords way["Rotation"] = rot self.nbt_waypoints["Waypoints"].append(way) self.nbt_waypoints.save( os.path.join(self.worldDirectory, u"mcedit_waypoints.dat"))
def loadrandbooktext(self): item = nbt.TAG_Compound() item['id'] = nbt.TAG_String('minecraft:written_book') # No books? Give a book and quill instead if len(self.booklist) == 0: item['id'] = nbt.TAG_String('minecraft:writable_book') return item # Open the book's text file bookfile = open(os.path.join(self.book_path, random.choice(self.booklist))) bookdata = bookfile.read().splitlines() bookfile.close() # Create NBT tag item['tag'] = nbt.TAG_Compound() # Prevent unusual characters from being used with filter item['tag']['author'] = nbt.TAG_String( filter( lambda x: x in self.valid_characters, bookdata.pop(0))) title = filter(lambda x: x in self.valid_characters,bookdata.pop(0)) item['tag']['title'] = nbt.TAG_String(title[:32]) item['tag']["pages"] = nbt.TAG_List() # Slice the pages at 50 and the page text at 256 to match minecraft # limits for p in bookdata[:50]: page = filter(lambda x: x in self.valid_characters, p) item['tag']["pages"].append(nbt.TAG_String(encodeJSONtext(page[:256]))) # Give the book an edition ed = topheavy_random(0, 9) item['tag']['display'] = nbt.TAG_Compound() item['tag']['display']['Lore'] = nbt.TAG_List() item['tag']['display']['Lore'].append( nbt.TAG_String( converttoordinal(ed+1) + ' Edition')) if (ed == 0): item['tag']['generation'] = nbt.TAG_Int(0) elif (ed == 1): item['tag']['generation'] = nbt.TAG_Int(1) else: item['tag']['generation'] = nbt.TAG_Int(2) return item
def placechests(self, level=0): # Place chests, create clue books and keys _directions = ( ('Wander {D} til ye find {L}, which be the next step in thy search.', 1), ('Walk as the crow flies {D} without rest until ye find {L}.', 1), ('Travel towards the {D} to {L}, then follow the next step.', 1), ('I hid the next step at {L}, {D} of here.', 1), ('Find {L} to the {D}, and be wary of zombies as ye travel.', 1), ('Now walk ye {D}, and do keep thy eyes peeled for {L}.', 1), ('To the {D} there do lie {L}. Thy next step be to find it.', 1), ('There do lie {L} to the {D}, and that is where ye must needs go next.', 1), ('Turn ye to the {D}, and march forrard \'til ye find {L}.', 1), ) # Iterate through the landmarks from the end back. # Generate a clue book and possible key as we go as extra chest loot. # At each location, randomly either make a chest and store items or # continue one. fromstep = 1 tostep = 1 pages = [] pages.append(self.dungeon_name) # If necessary, we create a key to lock the chests with if cfg.th_locked is True: keyname = self.keyName() print "Creating key: %s" % (keyname) chestkey = nbt.TAG_Compound() chestkey['Count'] = nbt.TAG_Byte(1) chestkey['id'] = nbt.TAG_String('minecraft:stick') # ID 280 chestkey['tag'] = nbt.TAG_Compound() chestkey['tag']['Unbreakable'] = nbt.TAG_Byte(1) chestkey['tag']['display'] = nbt.TAG_Compound() chestkey['tag']['display']['Name'] = nbt.TAG_String(keyname) chestkey['tag']['display']['Lore'] = nbt.TAG_List() chestkey['tag']['display']['Lore'].append( nbt.TAG_String('"Key found with treasure map"')) else: keyname = None # fromstep = step where we're placing the clue chest # tostep = step we are calculating clue for relative to tostep-1 # There are 1-based but the landmarks[] array is 0-based. # If we place an intermediate chest, fromstep is changed else stays as 1 self.pm.init(self.steps, label='Placing chests:') while tostep < self.steps: self.pm.update_left(self.steps - tostep) tostep += 1 if self.args.debug: print 'Processing step %d' % (tostep) if self.landmarks[tostep - 2].pos.z < self.landmarks[tostep - 1].pos.z: direction = 'South' elif self.landmarks[tostep - 2].pos.z > self.landmarks[tostep - 1].pos.z: direction = 'North' else: direction = '' if self.landmarks[tostep - 2].pos.x < self.landmarks[tostep - 1].pos.x: direction = '%sEast' % (direction) elif self.landmarks[tostep - 2].pos.x > self.landmarks[tostep - 1].pos.x: direction = '%sWest' % (direction) landmark_name = self.landmarks[tostep - 1].describe() p = weighted_choice(_directions).format(D=direction, L=landmark_name) if self.args.debug: print "%d: %d, %d, %d\n %s" % ( tostep - 1, self.landmarks[tostep - 1].pos.x, self.landmarks[tostep - 1].pos.y, self.landmarks[tostep - 1].pos.z, p) pages.append(p) if tostep == self.steps: break if random.randint(1, 100) > cfg.th_intermediate: if random.randint(1, 100) < cfg.th_bonus: if self.args.debug: print "Adding an intermediate treasure chest" self.landmarks[tostep - 1].addcluechest( tier=int(tostep / cfg.th_multiplier)) continue # save book and restart self.landmarks[tostep - 1].addchest(name=self.dungeon_name, tier=int(tostep / cfg.th_multiplier), locked=keyname) if self.args.debug: print 'Placed an intermediate chest at step %d!' % (tostep) print 'Location: %s' % (self.landmarks[tostep - 1].chestlocdesc()) pages.append('When ye reach this place, seek ye another clue %s.' % (self.landmarks[tostep - 1].chestlocdesc())) if cfg.th_locked is True: pages.append( 'But take ye heed -- tis only %s as can open the chest.' % (keyname)) cluebook_tag = nbt.TAG_Compound() cluebook_tag['title'] = nbt.TAG_String(self.dungeon_name) cluebook_tag['author'] = nbt.TAG_String(self.owner) cluebook_tag['pages'] = nbt.TAG_List() for p in pages: cluebook_tag['pages'].append(nbt.TAG_String('"%s"' % (p))) cluebook = nbt.TAG_Compound() cluebook['Count'] = nbt.TAG_Byte(1) cluebook['id'] = nbt.TAG_Short( 387) # change to String minecraft:written_book cluebook['Damage'] = nbt.TAG_Short(0) cluebook['tag'] = cluebook_tag # write clue for this stage if fromstep == 1: self.landmarks[fromstep - 1].addcluechest( name=self.dungeon_name, tier=0) self.landmarks[fromstep - 1].addcluechestitem_tag(cluebook) if cfg.th_locked is True: self.landmarks[fromstep - 1].addcluechestitem_tag(chestkey) else: self.landmarks[fromstep - 1].addchestitem_tag(cluebook) if self.args.debug: print 'Placed a clue chest at step %d!' % (fromstep) fromstep = tostep pages = [] pages.append(self.dungeon_name) # write treasure self.landmarks[tostep - 1].addchest(name=self.dungeon_name, tier=int(tostep / cfg.th_multiplier), locked=keyname) if self.args.debug: print 'Placed a treasure chest at step %d, tier %d!' % ( tostep, int(tostep / cfg.th_multiplier)) print 'Location: %s' % (self.landmarks[tostep - 1].chestlocdesc()) pages.append( 'Now that ye have reached thy destination, ye may find the treasure %s.' % (self.landmarks[tostep - 1].chestlocdesc())) if cfg.th_locked is True: pages.append( 'Take heed! For \'tis only %s that can open the chest that holds my treasure.' % (keyname)) cluebook_tag = nbt.TAG_Compound() cluebook_tag['title'] = nbt.TAG_String(self.dungeon_name) cluebook_tag['author'] = nbt.TAG_String(self.owner) cluebook_tag['pages'] = nbt.TAG_List() for p in pages: cluebook_tag['pages'].append(nbt.TAG_String('"%s"' % (p))) cluebook = nbt.TAG_Compound() cluebook['Count'] = nbt.TAG_Byte(1) cluebook['id'] = nbt.TAG_Short(387) cluebook['Damage'] = nbt.TAG_Short(0) cluebook['tag'] = cluebook_tag # write clue for this stage if fromstep == 1: self.landmarks[fromstep - 1].addcluechest(name=self.dungeon_name, tier=0) self.landmarks[fromstep - 1].addcluechestitem_tag(cluebook) if cfg.th_locked is True: self.landmarks[fromstep - 1].addcluechestitem_tag(chestkey) else: self.landmarks[fromstep - 1].addchestitem_tag(cluebook) if self.args.debug: print 'Placed a clue chest at step %d!' % (fromstep) self.pm.set_complete()
def generate_map(self, dungeon, level): '''Generate a new map, save it to disk, flush the cache, and return a map item NBT with the appropriate map ID.''' dungeon_key = '%s,%s' % (dungeon.position.x, dungeon.position.z) if dungeon_key not in self.mapcache['used']: self.mapcache['used'][dungeon_key] = set([]) # Find a map id. Look in the available list for old mcdungeon maps # that can be reused. If not, bump up the idcount and use that. if len(self.mapcache['available']) == 0: # Initialize the map count if it doesn't exist. if 'map' not in self.idcounts: self.idcounts['map'] = nbt.TAG_Short(-1) self.idcounts['map'].value += 1 mapid = self.idcounts['map'].value self.mapcache['used'][dungeon_key].add(mapid) else: mapid = self.mapcache['available'].pop() self.mapcache['used'][dungeon_key].add(mapid) filename = os.path.join(self.mapstore, 'map_%d.dat' % (mapid)) # Setup the defaults. # Offset will be way off somewhere were players are unlikely to go # to avoid the maps from being overwritten. Nothing else really # matters. tags = nbt.TAG_Compound() tags['data'] = nbt.TAG_Compound() tags['data']['scale'] = nbt.TAG_Byte(0) tags['data']['xCenter'] = nbt.TAG_Int(-12500000) tags['data']['zCenter'] = nbt.TAG_Int(-12500000) tags['data']['height'] = nbt.TAG_Short(128) tags['data']['width'] = nbt.TAG_Short(128) tags['data']['dimension'] = nbt.TAG_Byte(0) tags['data']['colors'] = nbt.TAG_Byte_Array(zeros(16384, uint8)) # Generate the map. blocks = dungeon.blocks colors = tags['data']['colors'].value y = level * dungeon.room_height - 3 # Scale the map. We only scale up, not down since scaling # looks terrible. max_dungeon = max(dungeon.xsize * dungeon.room_size, dungeon.zsize * dungeon.room_size) max_dungeon = max(128, max_dungeon) # If the size is less than 8, try to center it. xoffset = 0 zoffset = 0 if dungeon.xsize * dungeon.room_size < 128: xoffset = (128 - dungeon.xsize * dungeon.room_size) / 2 if dungeon.zsize * dungeon.room_size < 128: zoffset = (128 - dungeon.zsize * dungeon.room_size) / 2 # Draw pixels on the map corresponding to blocks just above # floor level. Color chests and spawners. Hide things that should be # hidden. for x in xrange(128): for z in xrange(128): block = Vec(x * max_dungeon / 128 - xoffset, y, z * max_dungeon / 128 - zoffset) if block in blocks: mat = blocks[block].material if mat == materials.StonePressurePlate: colors[x + z * 128] = 10 elif blocks[block].hide is True: colors[x + z * 128] = 0 elif blocks[block].blank is True: colors[x + z * 128] = 0 elif mat == materials.Air: colors[x + z * 128] = 10 elif mat == materials.Spawner: colors[x + z * 128] = 48 elif (mat == materials.Chest or mat == materials.TrappedChest): colors[x + z * 128] = 42 else: colors[x + z * 128] = 54 else: colors[x + z * 128] = 0 # Draw the level number in the corner digits = [[0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1], [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0], [1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1], [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1], [0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1], [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0], [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], [1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1]] sx = 120 if level < 10: sx = 124 sz = 123 for d in str(level): for x in xrange(3): for z in xrange(5): if digits[int(d)][x + z * 3] == 1: colors[x + sx + (z + sz) * 128] = 16 sx += 4 # Save the map file, cache, and idcount.dat tags.save(filename) self.update_mapstore() # Return a map item item = nbt.TAG_Compound() item['id'] = nbt.TAG_String(items.byName('map').id) item['Damage'] = nbt.TAG_Short(mapid) item['Count'] = nbt.TAG_Byte(1) item['tag'] = nbt.TAG_Compound() item['tag']['display'] = nbt.TAG_Compound() name = dungeon.dungeon_name + ' Lv {l}' item['tag']['display']['Name'] = nbt.TAG_String(name.format(l=level)) item['tag']['display']['MapColor'] = nbt.TAG_Int(self.mapcolor) print item['tag']['display']['Name'].value return item
def buildItemTag(self, i): # If it's a binary NBT file, just load it if i.file != '': item_tag = nbt.load(i.file) # Set the slot and count if i.slot != None: item_tag['Slot'] = nbt.TAG_Byte(i.slot) item_tag['Count'] = nbt.TAG_Byte(i.count) return item_tag # Otherwise, we will build the compound item_tag = nbt.TAG_Compound() # Standard stuff item_tag['id'] = nbt.TAG_Short(i.id) item_tag['Damage'] = nbt.TAG_Short(i.damage) # Enchantments if len(i.enchantments) > 0: item_tag['tag'] = nbt.TAG_Compound() if (i.flag == 'ENCH_BOOK'): item_tag['tag']['StoredEnchantments'] = nbt.TAG_List() elist = item_tag['tag']['StoredEnchantments'] else: item_tag['tag']['ench'] = nbt.TAG_List() elist = item_tag['tag']['ench'] for e in i.enchantments: e_tag = nbt.TAG_Compound() e_tag['id'] = nbt.TAG_Short(e['id']) e_tag['lvl'] = nbt.TAG_Short(e['lvl']) elist.append(e_tag) # Custom Potion Effects if i.p_effect != '': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['CustomPotionEffects'] = nbt.TAG_List() elist = item_tag['tag']['CustomPotionEffects'] for e in i.p_effect.split(','): id, amp, dur = e.split('-') e_tag = nbt.TAG_Compound() e_tag['Id'] = nbt.TAG_Byte(id) e_tag['Amplifier'] = nbt.TAG_Byte(amp) e_tag['Duration'] = nbt.TAG_Int(dur) # Flags for hiding potion particles if i.flag == 'HIDE_PARTICLES' or i.flag == 'HIDE_ALL': e_tag['ShowParticles'] = nbt.TAG_Byte(0) elist.append(e_tag) # Flag for hiding additional text if i.flag == 'HIDE_EFFECTS' or i.flag == 'HIDE_ALL': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['HideFlags'] = nbt.TAG_Int( 63) # 63 = Hide everything # Naming if i.customname != '': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['display'] = nbt.TAG_Compound() item_tag['tag']['display']['Name'] = nbt.TAG_String(i.customname) # Lore Text if i.lore != '' or i.flag == 'FORTUNE': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() try: item_tag['tag']['display'] except: item_tag['tag']['display'] = nbt.TAG_Compound() item_tag['tag']['display']['Lore'] = nbt.TAG_List() if i.flag == 'FORTUNE': item_tag['tag']['display']['Name'] = nbt.TAG_String( 'Fortune Cookie') i.lore = self.loadrandfortune() loredata = textwrap.wrap(self.ConvertEscapeChars(i.lore), 30) for loretext in loredata[:10]: item_tag['tag']['display']['Lore'].append( nbt.TAG_String(loretext)) else: loredata = i.lore.split(':') for loretext in loredata[:10]: item_tag['tag']['display']['Lore'].append( nbt.TAG_String(self.ConvertEscapeChars(loretext[:50]))) # Dyed if (i.flag == 'DYED'): try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() try: item_tag['tag']['display'] except: item_tag['tag']['display'] = nbt.TAG_Compound() if i.flagparam == '': item_tag['tag']['display']['color'] = nbt.TAG_Int( random.randint(0, 16777215)) else: item_tag['tag']['display']['color'] = nbt.TAG_Int(i.flagparam) # special cases for written books and paintings if (i.flag == 'WRITTEN'): item_tag = self.loadrandbooktext() if (i.flag == 'PAINT'): item_tag = self.loadrandpainting() # Set the slot and count if i.slot != None: item_tag['Slot'] = nbt.TAG_Byte(i.slot) item_tag['Count'] = nbt.TAG_Byte(i.count) return item_tag
def buildItemTag(self,i): # If it's a binary NBT file, just load it if i.file != '': item_tag = tagsfromfile(i.file) # Set the slot and count if i.slot != None: item_tag['Slot'] = nbt.TAG_Byte(i.slot) item_tag['Count'] = nbt.TAG_Byte(i.count) return item_tag # Otherwise, we will build the compound item_tag = nbt.TAG_Compound() # Standard stuff item_tag['id'] = nbt.TAG_String(i.id) item_tag['Damage'] = nbt.TAG_Short(i.damage) # Enchantments if len(i.enchantments) > 0: item_tag['tag'] = nbt.TAG_Compound() if (i.flag == 'ENCH_BOOK'): item_tag['tag']['StoredEnchantments'] = nbt.TAG_List() elist = item_tag['tag']['StoredEnchantments'] else: item_tag['tag']['ench'] = nbt.TAG_List() elist = item_tag['tag']['ench'] for e in i.enchantments: e_tag = nbt.TAG_Compound() e_tag['id'] = nbt.TAG_Short(e['id']) e_tag['lvl'] = nbt.TAG_Short(e['lvl']) elist.append(e_tag) # Custom Potion Effects if i.p_effect != '': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() # Is this a 'basic' potion i.e. no custom effects list if (i.p_effect.replace(',','').replace('-','').isdigit()): item_tag['tag']['CustomPotionEffects'] = nbt.TAG_List() elist = item_tag['tag']['CustomPotionEffects'] for e in i.p_effect.split(','): id, amp, dur = e.split('-') e_tag = nbt.TAG_Compound() e_tag['Id'] = nbt.TAG_Byte(id) e_tag['Amplifier'] = nbt.TAG_Byte(amp) e_tag['Duration'] = nbt.TAG_Int(dur) # Flags for hiding potion particles if i.flag == 'HIDE_PARTICLES' or i.flag == 'HIDE_ALL': e_tag['ShowParticles'] = nbt.TAG_Byte(0) elist.append(e_tag) # If we have a flagparam, use it for the potion's colour if i.flagparam != '': item_tag['tag']['CustomPotionColor'] = nbt.TAG_Int(i.flagparam) else: item_tag['tag']['Potion'] = nbt.TAG_String(i.p_effect) # For basic potions there is no need for a custom name i.customname = '' # Flag for hiding additional text if i.flag == 'HIDE_EFFECTS' or i.flag == 'HIDE_ALL': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['HideFlags'] = nbt.TAG_Int(63) # 63 = Hide everything # Naming if i.customname != '': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['display'] = nbt.TAG_Compound() item_tag['tag']['display']['Name'] = nbt.TAG_String(i.customname) # Lore Text if i.lore != '' or i.flag == 'FORTUNE': try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() try: item_tag['tag']['display'] except: item_tag['tag']['display'] = nbt.TAG_Compound() item_tag['tag']['display']['Lore'] = nbt.TAG_List() if i.flag == 'FORTUNE': item_tag['tag']['display'][ 'Name'] = nbt.TAG_String('Fortune Cookie') i.lore = random_line_from_file(cfg.file_fortunes, "...in bed") loredata = textwrap.wrap(self.ConvertEscapeChars(i.lore), 30) for loretext in loredata[:10]: item_tag['tag']['display']['Lore'].append( nbt.TAG_String(loretext)) else: loredata = i.lore.split(':') for loretext in loredata[:10]: item_tag['tag']['display']['Lore'].append( nbt.TAG_String(self.ConvertEscapeChars(loretext[:50]))) # Flag: Dyed item if (i.flag == 'DYED'): try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() try: item_tag['tag']['display'] except: item_tag['tag']['display'] = nbt.TAG_Compound() if i.flagparam == '': item_tag['tag']['display']['color'] = nbt.TAG_Int( random.randint( 0, 16777215)) else: item_tag['tag']['display']['color'] = nbt.TAG_Int(i.flagparam) # Flags: Random Book or Painting elif (i.flag == 'WRITTEN'): item_tag = self.loadrandbooktext() elif (i.flag == 'PAINT'): item_tag = self.loadrandpainting() # Flag: Paint banner or shield with dungeon flag design elif (i.flag == 'DUNGEON_FLAG'): try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['BlockEntityTag'] = nbt.TAG_Compound() item_tag['tag']['BlockEntityTag']['Base'] = nbt.TAG_Int(self.flag['Base']) item_tag['tag']['BlockEntityTag']['Patterns'] = nbt.TAG_List() for p in self.flag['Patterns']: q = nbt.TAG_Compound() q['Color'] = nbt.TAG_Int(p[0]) q['Pattern'] = nbt.TAG_String(p[1]) item_tag['tag']['BlockEntityTag']['Patterns'].append(q) # Set the damage to match the base colour. This is a special case for # banner items in chests if i.id == 'minecraft:banner': item_tag['Damage'] = nbt.TAG_Short(self.flag['Base']) # Flag: Give item mob entity tag (spawn eggs) elif (i.flag.startswith('ENTITYTAG:')): try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['EntityTag'] = nbt.TAG_Compound() # ENTITYTAG: is 10 characters, we want everything afterwards item_tag['tag']['EntityTag']['id'] = nbt.TAG_String(i.flag[10:]) # Flag: Give random recipie from recipes.txt elif (i.flag == 'RECIPE'): try: item_tag['tag'] except: item_tag['tag'] = nbt.TAG_Compound() item_tag['tag']['Recipes'] = nbt.TAG_List() r = random_line_from_file(cfg.file_recipes, "minecraft:crafting_table") item_tag['tag']['Recipes'].append(nbt.TAG_String(r)) # Set the slot and count if i.slot != None: item_tag['Slot'] = nbt.TAG_Byte(i.slot) item_tag['Count'] = nbt.TAG_Byte(i.count) return item_tag
def testCreate(): "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