Exemplo n.º 1
0
def Load():
    print 'Reading loot tables...'
    global _maxtier

    while (cfg.parser.has_section('tier%d' % (_maxtier + 1))):
        _maxtier += 1
        tiername = 'tier%d' % (_maxtier)
        # print 'Reading loot table for:',tiername
        loots = cfg.parser.items(tiername)
        _master_loot[tiername] = {}
        thistable = _master_loot[tiername]
        num = 0
        for line in loots:
            try:
                chance, minmax, enchant = [
                    x.strip() for x in line[1].split(',')
                ]
                minimum = minmax.split('-')[0]
                maximum = minmax.split('-')[-1]
            except:
                print 'WARNING: Cannot parse loot table entry around line:'
                print '  {}: {} (skipping...)'.format(line[0], line[1])
                continue

            ilist = []
            for i in line[0].split(','):
                thisitem = items.byName(i.strip())
                if thisitem is None:
                    print 'ERROR: Tried to reference loot that does not exist.'
                    sys.exit()
                ilist.append(items.byName(i.strip()))
            thistable[num] = dict([('item', ilist), ('chance', int(chance)),
                                   ('min', int(minimum)),
                                   ('max', int(maximum)), ('ench', enchant)])
            num += 1
Exemplo n.º 2
0
 def stringToLoot(self, inloot):
     if inloot == None:
         return None
     loot = inloot.lower().split(',')
     i = random.choice(loot[0].split('/'))
     item = items.byName(i)
     if item == None:
         sys.exit('%s not found' % i)
     if len(loot) < 2:
         count = 1
     else:
         count = int(loot[1])
     if len(loot) < 3:
         enchantments = []
         if item.name.startswith('magic_'):
             ench_level = 0
             if len(item.ench) > 0:
                 for e in item.ench.split(','):
                     k = int(e.split('-')[0])
                     v = int(e.split('-')[-1])
                     enchantments.append(dict({'id': k, 'lvl': v}))
     else:
         enchantments = list(loottable.enchant(item.name, int(loot[2])))
     return loottable.Loot(0, count, item.value, item.data, enchantments,
                           item.p_effect, item.customname, item.flag,
                           item.flagparam, item.lore, item.file)
Exemplo n.º 3
0
 def stringToLoot(self,inloot):
     if inloot == None:
         return None
     loot = inloot.lower().split(',')
     i = random.choice(loot[0].split('/'))
     item = items.byName(i)
     if item == None:
         sys.exit('%s not found'% i)
     if len(loot) < 2:
         count = 1
     else:
         count = int(loot[1])
     if len(loot) < 3:
         enchantments = []
         if item.name.startswith('magic_'):
             ench_level = 0
             if len(item.ench) > 0:
                 for e in item.ench.split(','):
                     k = int(e.split('-')[0])
                     v = int(e.split('-')[-1])
                     enchantments.append(dict({'id': k, 'lvl': v}))
     else:
         enchantments = list(loottable.enchant(item.name, int(loot[2])))
     return loottable.Loot(0,
                           count,
                           item.value,
                           item.data,
                           enchantments,
                           item.p_effect,
                           item.customname,
                           item.flag,
                           item.flagparam,
                           item.lore,
                           item.file)
Exemplo n.º 4
0
def Load ():
    print 'Reading loot tables...'
    global _maxtier

    while (cfg.parser.has_section('tier%d'%(_maxtier+1))):
        _maxtier += 1
        tiername = 'tier%d'%(_maxtier)
        #print 'Reading loot table for:',tiername
        loots = cfg.parser.items(tiername)
        _master_loot[tiername] = {}
        thistable =  _master_loot[tiername]
        num = 0
        for line in loots:
            chance, minmax, enchant = [x.strip() for x in line[1].split(',')]
            minimum = minmax.split('-')[0]
            maximum = minmax.split('-')[-1]

            ilist = []
            for i in line[0].split(','):
                ilist.append(items.byName(i.strip()))
            thistable[num] = dict([
                ('item', ilist),
                ('chance', int(chance)),
                ('min', int(minimum)),
                ('max', int(maximum)),
                ('ench', enchant)
            ])
            num += 1
Exemplo n.º 5
0
def Load():
    print "Reading loot tables..."
    global _maxtier

    while cfg.parser.has_section("tier%d" % (_maxtier + 1)):
        _maxtier += 1
        tiername = "tier%d" % (_maxtier)
        # print 'Reading loot table for:',tiername
        loots = cfg.parser.items(tiername)
        _master_loot[tiername] = {}
        thistable = _master_loot[tiername]
        num = 0
        for line in loots:
            chance, minmax, enchant = [x.strip() for x in line[1].split(",")]
            minimum = minmax.split("-")[0]
            maximum = minmax.split("-")[-1]

            ilist = []
            for i in line[0].split(","):
                ilist.append(items.byName(i.strip()))
            thistable[num] = dict(
                [
                    ("item", ilist),
                    ("chance", int(chance)),
                    ("min", int(minimum)),
                    ("max", int(maximum)),
                    ("ench", enchant),
                ]
            )
            num += 1
Exemplo n.º 6
0
 def buildFrameItemTag(self, i, ench=(), customname=''):
     item = items.byName(i)
     if customname == '':
         customname = item.customname
     thisloot = loottable.Loot(None, 1, item.value, item.data, ench,
                               item.p_effect, customname, item.flag,
                               item.flagparam, item.lore, item.file)
     return self.buildItemTag(thisloot)
Exemplo n.º 7
0
def Load():
    print 'Reading loot tables...'
    global _maxtier

    while (cfg.parser.has_section('tier%d' % (_maxtier + 1))):
        _maxtier += 1
        tiername = 'tier%d' % (_maxtier)
        # print 'Reading loot table for:',tiername
        loots = cfg.parser.items(tiername)
        _master_loot[tiername] = {}
        thistable = _master_loot[tiername]
        num = 0
        for line in loots:
            try:
                chance, minmax, enchant = [x.strip()
                                           for x in line[1].split(',')]
                minimum = minmax.split('-')[0]
                maximum = minmax.split('-')[-1]
            except:
                print 'WARNING: Cannot parse loot table entry around line:'
                print '  {}: {} (skipping...)'.format(
                    line[0],
                    line[1]
                )
                continue

            ilist = []
            for i in line[0].split(','):
                thisitem = items.byName(i.strip())
                if thisitem is None:
                    print 'ERROR: Tried to reference loot that does not exist.'
                    sys.exit()
                ilist.append(items.byName(i.strip()))
            thistable[num] = dict([
                ('item', ilist),
                ('chance', int(chance)),
                ('min', int(minimum)),
                ('max', int(maximum)),
                ('ench', enchant)
            ])
            num += 1
Exemplo n.º 8
0
    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_String(items.byName('map').id)
        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 display tags
        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]))
        item['tag']['display']['MapColor'] = nbt.TAG_Int(self.paintingcolor)

        return item
Exemplo n.º 9
0
 def buildFrameItemTag(self,i,ench=(),customname=''):
     item = items.byName(i)
     if customname == '':
         customname = item.customname
     thisloot = loottable.Loot(  None,
                                 1,
                                 item.value,
                                 item.data,
                                 ench,
                                 item.p_effect,
                                 customname,
                                 item.flag,
                                 item.flagparam,
                                 item.lore,
                                 item.file)
     return self.buildItemTag(thisloot)
Exemplo n.º 10
0
    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_String(items.byName('map').id)
        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 display tags
        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]))
        item['tag']['display']['MapColor'] = nbt.TAG_Int(self.paintingcolor)

        return item
Exemplo n.º 11
0
    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
Exemplo n.º 12
0
    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))
        print item['tag']['display']['Name'].value

        return item
Exemplo n.º 13
0
 def updateData(self):
     self.val = items.byName(self.name).value
     self.data = items.byName(self.name).data
Exemplo n.º 14
0
    def render(self):
        o = self.parent.loc.trans(2,0,2)
        sb = self.parent.parent.setblock

        roomtype = random.choice(('study', 'sepulchure'))

        if roomtype == 'study':
            wmat = materials._wall
            fmat = materials._floor
            cmat = materials._ceiling
        else:
            wmat = materials.meta_mossystonebrick
            fmat = materials.meta_mossystonebrick
            cmat = materials._ceiling

        # Reform the room.
        # Air space
        for p in iterate_cube(o.trans(1,1,1), o.trans(10,3,10)):
            sb(p, materials.Air)
        # Walls
        for p in iterate_four_walls(o, o.trans(11,0,11),-4):
            sb(p, wmat)
        # Ceiling
        for p in iterate_cube(o, o.trans(11,0,11)):
            sb(p, cmat)
        # Floor
        for p in iterate_cube(o.trans(0,4,0), o.trans(11,4,11)):
            sb(p, fmat)

        # Pick random contents. Right now there are two possibilities. 
        if roomtype == 'study':
            # A secret study
            # Book cases
            for p in iterate_four_walls(o.trans(1,1,1), o.trans(10,1,10),-2):
                sb(p, materials.Bookshelf)
            for p in (Vec(1,1,3), Vec(1,1,8),
                      Vec(3,1,1), Vec(3,1,10),
                      Vec(8,1,1), Vec(8,1,10),
                      Vec(10,1,3), Vec(10,1,8)):
                for q in iterate_cube(o+p, o+p.down(2)):
                    sb(q, materials.Air)
            # Torches
            for p in (Vec(2,3,2), Vec(2,3,9),
                      Vec(9,3,2), Vec(9,3,9)):
                sb(o+p, materials.Fence)
                sb(o+p.up(1), materials.Torch, 5)

            # Desk
            mats = [
                materials.Air,          # 0
                materials.WoodPlanks,   # 1
                materials.Chest,        # 2
                materials.CraftingTable,# 3
                materials.WallSign,     # 4
                materials.WoodenStairs  # 5
            ]
            template = [
                [3,1,1,2],
                [0,4,5,4]
            ]
            oo = o.trans(5,3,4)
            for x in xrange(2):
                for z in xrange(4):
                    p = oo.trans(x,0,z)
                    sb(p, mats[template[x][z]])
            self.parent.parent.blocks[o+Vec(6,3,5)].data = 2
            self.parent.parent.blocks[o+Vec(6,3,6)].data = 0
            self.parent.parent.blocks[o+Vec(6,3,7)].data = 3
            sb(o.trans(5,2,5), materials.Torch)
            self.parent.parent.addchest(o.trans(5,3,7))
        else:
            # a small sepulchure
            # Torches
            for p in (Vec(2,3,2), Vec(2,3,9),
                      Vec(9,3,2), Vec(9,3,9)):
                sb(o+p, materials.Fence)
                sb(o+p.up(1), materials.Torch, 5)
            # Sarcophagus
            for p in iterate_cube(o.trans(3,3,4), o.trans(8,3,6)):
                sb(p, materials.EndStone)
            sb(o+Vec(3,3,4), materials.SandstoneSlab)
            sb(o+Vec(3,3,6), materials.SandstoneSlab)
            sb(o+Vec(8,3,4), materials.SandstoneSlab)
            sb(o+Vec(8,3,6), materials.SandstoneSlab)
            sb(o+Vec(4,2,5), materials.StoneBrick)
            sb(o+Vec(5,2,5), materials.StoneBrickSlab)
            sb(o+Vec(6,2,5), materials.StoneBrickSlab)
            sb(o+Vec(7,2,5), materials.StoneBrickStairs, 0)

            # Loot for the sarcophagus.
            loota = []
            lootb = []
            bone = items.byName('bone')
            for slot in xrange(11,15,1):
                loota.append(loottable.Loot(slot,1,bone.value,bone.data,''))
                lootb.append(loottable.Loot(slot,1,bone.value,bone.data,''))
            for slot in xrange(18,27,1):
                loota.append(loottable.Loot(slot,1,bone.value,bone.data,''))
            for slot in xrange(0,9,1):
                lootb.append(loottable.Loot(slot,1,bone.value,bone.data,''))

            # Random stuff to be buried with. Like Crypt, but not as good.
            lootc = [(items.byName('iron ingot'), 5),
                     (items.byName('book'), 10),
                     (items.byName('bow'), 10),
                     (items.byName('diamond'), 5),
                     (items.byName('gold ingot'), 5),
                     (items.byName('bowl'), 10),
                     (items.byName('feather'), 10),
                     (items.byName('golden apple'), 5),
                     (items.byName('paper'), 10),
                     (items.byName('arrow'), 10),
                     (items.byName('clock'), 10),
                     (items.byName('compass'), 10),
                     (items.byName('gold nugget'), 10),
                     (items.byName('ghast tear'), 1),
                     (items.byName('glass bottle'), 10)]

            i = weighted_choice(lootc)
            loota[7].id = i.value
            loota[7].data = i.data
            sb(o+Vec(5,3,5), materials.Chest)
            self.parent.parent.addchest(o+Vec(5,3,5), loot=loota)

            i = weighted_choice(lootc)
            lootb[7].id = i.value
            lootb[7].data = i.data
            sb(o+Vec(6,3,5), materials.Chest)
            self.parent.parent.addchest(o+Vec(6,3,5), loot=lootb)

            # Vines
            for p in iterate_cube(o, o.trans(11,3,11)):
                if random.randint(1,100) <= 20:
                    self.parent.parent.vines(p, grow=True)


        # Hallway
        # Find the direction, room, and connecting room.
        # room = this room
        # d = direction out of this room
        # offset = offset of the hallways
        # oroom = connecting room
        # od = direction out of the connecting room
        # length = legth of the opposite hall

        # hall positions to grid direction
        dirs = {3: Vec(-1,0,0),
                1: Vec(1,0,0),
                2: Vec(0,0,1),
                0: Vec(0,0,-1)}

        room = self.parent
        d = 0
        for x in xrange(4):
            if room.halls[x]._name != 'blank':
                d = x
        offset = room.halls[d].offset
        oroom = self.parent.parent.rooms[room.pos+dirs[d]]
        od = (d+2)%4
        length = oroom.hallLength[od]-2

        # Figure our out deltas. There are 8 possibilities based on direction
        # and offset. Offset will basically mirror across width. 
        # dw = delta width
        # dl = delta length
        # spos = start pos for the mechanism

        # d = 0 (West)
        if d == 0:
            dw = Vec(1,0,0)
            dl = Vec(0,0,-1)
            spos = o.trans(offset,0,0)
        # d = 1 (South)
        elif d == 1:
            dw = Vec(0,0,1)
            dl = Vec(1,0,0)
            spos = o.trans(11,0,offset)
        # d = 2 (East)
        elif d == 2:
            dw = Vec(1,0,0)
            dl = Vec(0,0,1)
            spos = o.trans(offset,0,11)
        # d = 3 (North)
        else:
            dw = Vec(0,0,1)
            dl = Vec(-1,0,0)
            spos = o.trans(0,0,offset)
        if offset >= 7:
            dw = dw*-1
            if (d == 0 or d == 2):
                spos = spos.trans(-2,0,0)
            elif (d == 1 or d == 3):
                spos = spos.trans(0,0,-2)

        # Position the start block for the mechanism
        spos = spos + dl*length - dw

        if self.parent.parent.args.debug:
            print
            print 'room:', room.pos
            print 'dir:', d
            print 'offset:', offset
            print 'dl:', dl
            print 'dw:', dw
            print

        mats = [
            [materials.Air,0],          # 0 (ignore these)
            [materials.Air,0],          # 1
            [materials.Bookshelf,0],    # 2
            [materials.Stone,0],        # 3
            [materials._wall,0],        # 4
            [materials.RedStoneWire,0], # 5
            [materials.StickyPiston,3], # 6 - toggle piston
            [materials.RedStoneTorchOn,2],# 7
            [materials._ceiling, 0],    # 8
            [materials.StickyPiston, 4],# 9 - pusher piston
            [materials.RedStoneRepeaterOff, 3],# 10 - piston repeater
            [materials.RedStoneRepeaterOff, 7],# 11 - toggle repeater
            [materials.Torch, 0],       # 12
            [materials._secret_door, 0],# 13
            [materials._floor, 0],      # 14
            [materials._subfloor, 0]    # 15
        ]
        if roomtype == 'sepulchure':
            mats[2] = [materials.meta_mossystonebrick, 0]

        template = [
           [[ 8, 8, 8, 8, 8],
            [ 8, 8, 8, 8, 8],
            [ 8, 8, 8, 8, 8],
            [ 8, 8, 8, 8, 8],
            [ 8, 8, 8, 8, 8]],
           [[ 1, 1, 1,12, 4],
            [ 2, 4, 4, 4, 4],
            [ 2, 1, 1, 1, 4],
            [ 2, 1, 1, 1, 4],
            [ 2, 1, 1, 1, 4]],
           [[ 1, 7, 1 ,1,13],
            [ 2, 4, 6, 1, 4],
            [ 2,11, 9, 9, 4],
            [ 2, 5,10,10, 4],
            [ 2, 5, 5, 5, 4]],
           [[ 1, 1, 1, 1,13],
            [ 2, 4, 6, 1, 4],
            [ 2, 3, 9, 9, 4],
            [ 2, 3, 3, 3, 4],
            [ 2, 3, 3, 3, 4]],
           [[14,14,14,14,14],
            [14,14,14,14,14],
            [14,14,14,14,14],
            [14,14,14,14,14],
            [14,14,14,14,14]],
           [[15,15,15,15,15],
            [15,15,15,15,15],
            [15,15,15,15,15],
            [15,15,15,15,15],
            [15,15,15,15,15]],
        ]
        bdata = 3

        # Data adjustments for directions. There are 8, but the defaults are
        # for East, low offset. 

        # West
        if d == 0:
            bdata = 4
            if offset >= 7:
                mats[6][1] = 2
                mats[7][1] = 1
                mats[9][1] = 5
                mats[10][1] = 1
                mats[11][1] = 5
            else:
                mats[6][1] = 2

        # South
        if d == 1:
            bdata = 1
            if offset >= 7:
                mats[6][1] = 5
                mats[7][1] = 3
                mats[9][1] = 3
                mats[10][1] = 2
                mats[11][1] = 6
            else:
                mats[6][1] = 5
                mats[7][1] = 4
                mats[9][1] = 2
                mats[10][1] = 0
                mats[11][1] = 4

        # East, flipped
        if (d == 2 and offset >= 7):
            # flip the pusher piston
            mats[7][1] = 1
            mats[9][1] = 5
            mats[10][1] = 1
            mats[11][1] = 5

        # North
        if d == 3:
            bdata = 2
            if offset >= 7:
                mats[6][1] = 4
                mats[7][1] = 3
                mats[9][1] = 3
                mats[10][1] = 2
                mats[11][1] = 6
            else:
                mats[6][1] = 4
                mats[7][1] = 4
                mats[9][1] = 2
                mats[10][1] = 0
                mats[11][1] = 4

        # Draw the mechanism
        for y in xrange(6):
            for w in xrange(5):
                for l in xrange(5):
                    p = spos+dl*l+dw*w+Vec(0,1,0)*y
                    sb(p, mats[template[y][w][l]][0],
                          mats[template[y][w][l]][1])

        # The button.
        p = spos+dl*3+dw*4+Vec(0,1,0)*2
        blocks = self.parent.parent.blocks
        while blocks[p+dl].material != materials.Air:
            sb(p.up(1), materials.Air)
            sb(p, materials.RedStoneWire)
            sb(p.down(1), materials.Stone)
            p = p + dl
        sb(p+dl, materials.StoneButton, bdata)

        # Clear out extra space inside the room
        p = spos.down(1)
        for q in iterate_cube(p, p-dl*2+Vec(0,2,0)):
            sb(q, materials.Air)

        # Clear out any doors or extra torches in this room
        for p in iterate_cube(o, o.trans(11,4,11)):
            if p in self.parent.parent.doors:
                del(self.parent.parent.doors[p])
            if p in self.parent.parent.torches:
                del(self.parent.parent.torches[p])

        # Clear doors and torches from the entry way
        p = spos+dl*4
        for q in iterate_cube(p.trans(-1,0,-1), p.trans(1,4,1)):
            if q in self.parent.parent.doors:
                del(self.parent.parent.doors[q])
            if q in self.parent.parent.torches:
                del(self.parent.parent.torches[q])

        # Kill the canvas to prevent spawners and chests from appearing
        self.parent.canvas = (
            Vec(0,0,0),
            Vec(0,0,0),
            Vec(0,0,0))

        # Cobwebs
        webs = {}
        for p in iterate_cube(o, o.trans(11,3,11)):
            count = 0
            perc = 80 - (p.y - o.y) * (70/5)
            if (p not in blocks or
                blocks[p].material != materials.Air):
                continue
            for q in (Vec(1,0,0), Vec(-1,0,0),
                      Vec(0,1,0), Vec(0,-1,0),
                      Vec(0,0,1), Vec(0,0,-1)):
                if (p+q in blocks and
                    blocks[p+q].material != materials.Air and
                    random.randint(1,100) <= perc):
                    count += 1
            if count >= 3:
                webs[p] = True
        for p, q in webs.items():
            sb(p, materials.Cobweb)