├── .gitignore ├── README.md ├── docs ├── Block_IDs.md ├── Level.md ├── Tile.md ├── is-leaky.png └── y.gif └── examples ├── BlockMap.py ├── ConversionTools.py ├── Get_Block_IDs_and_Data_Values.py ├── JavaWorldReader.py ├── ResourcesPackUtils.py ├── Set_Block_IDs_and_Data_Values.py ├── SimpleTileViewer.py ├── Tile.py ├── docs └── Using_ConversionTools.md ├── level_template.dat └── pretty_compact_json.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /examples/__pycache__/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minecraft Dungeons Level Format 2 | 3 | The goal of this repo is to document the Minecraft Dungeons level and tile formats and to give examples of how to manipulate them. 4 | 5 | ## Overview 6 | 7 | To get an idea of how levels and tiles work, here is a brief summary: 8 | 9 | *Levels* in Dungeons are stored as [JSON](https://www.json.org/json-en.html) files that tell the game how to put the world together from *tiles*. They also have information about what types of monsters should spawn, what mission objectives and challenges players need to get through, what resource packs should be enabled, and more. 10 | 11 | Tiles are stored as JSON objects in *object groups*, and are cuboid shapes made up of blocks. Tiles also store information about things like invisible barriers, the minimap, what areas of the tile players can walk through, how they can be connected to other tiles, and more. 12 | 13 | Object groups are simply collections of tiles, stored as JSON files. Levels needs to specify which object groups they need tiles from, so a good way to group your tiles is by putting tiles that are used in the same level in the same group. 14 | 15 | These JSON files are *not* Unreal assets, and does not need to be cooked before being packaged. 16 | 17 | ## Documentation 18 | 19 | :warning: This section is still under construction! 20 | 21 | Note that this documentation is not official in any way and has been put together by doing a lot of tests, so it can contain errors or be missing some information. 22 | 23 | - [Level](/docs/Level.md) 24 | - [List of block IDs](/docs/Block_IDs.md) 25 | - [Tile](/docs/Tile.md) 26 | 27 | ## Examples 28 | 29 | :warning: This section is still under construction! 30 | 31 | The examples in this repo are written in Python. Some are not necessarily the most optimized way to do things, they are just examples. 32 | 33 | - [Converting a Java world to a Dungeons object group or vice versa](/examples/docs/Using_ConversionTools.md) 34 | - [How to get the ID and data value of a block in a tile](/examples/Get_Block_IDs_and_Data_Values.py) 35 | - [How to set the ID and data value of a block in a tile](/examples/Set_Block_IDs_and_Data_Values.py) 36 | - [Simple Tile Viewer](/examples/SimpleTileViewer.py) using the Tile module, NumPy, Pillow, and PySimpleGUI 37 | - [Tile module](/examples/Tile.py) -------------------------------------------------------------------------------- /docs/Block_IDs.md: -------------------------------------------------------------------------------- 1 | # Block IDs 2 | 3 | Below is a list of known block IDs in game and what block names they represent. 4 | 5 | ID | Hex | Block Name 6 | -- | --- | ---------- 7 | 0 | 00 | `air` 8 | 1 | 01 | `stone` 9 | 2 | 02 | `grass` 10 | 3 | 03 | `dirt` 11 | 4 | 04 | `cobblestone` 12 | 5 | 05 | `planks` 13 | 6 | 06 | `sapling` 14 | 7 | 07 | `bedrock` 15 | 8 | 08 | `flowing_water` 16 | 9 | 09 | `water` 17 | 10 | 0a | `flowing_lava` 18 | 11 | 0b | `lava` 19 | 12 | 0c | `sand` 20 | 13 | 0d | `gravel` 21 | 14 | 0e | `gold_ore` 22 | 15 | 0f | `iron_ore` 23 | 16 | 10 | `coal_ore` 24 | 17 | 11 | `log` 25 | 18 | 12 | `leaves` 26 | 19 | 13 | `sponge` / `sponge.dry` 27 | 20 | 14 | `glass` 28 | 21 | 15 | `lapis_ore` 29 | 22 | 16 | `lapis_block` 30 | 23 | 17 | `dispenser` 31 | 24 | 18 | `sandstone` 32 | 25 | 19 | `noteblock` 33 | 26 | 1a | `bed` 34 | 27 | 1b | `golden_rail` 35 | 28 | 1a | `detector_rail` 36 | 29 | 1d | `sticky_piston` 37 | 30 | 1e | `web` 38 | 31 | 1f | `tallgrass` 39 | 32 | 20 | `deadbush` 40 | 35 | 23 | `wool` 41 | 37 | 25 | `yellow_flower` 42 | 38 | 26 | `red_flower` 43 | 40 | 28 | `red_mushroom` 44 | 41 | 29 | `gold_block` 45 | 42 | 2a | `iron_block` 46 | 43 | 2b | `double_stone_slab` 47 | 44 | 2c | `stone_slab` 48 | 45 | 2d | `brick_block` 49 | 46 | 2e | `tnt` 50 | 47 | 2f | `bookshelf` 51 | 48 | 30 | `mossy_cobblestone` 52 | 49 | 31 | `obsidian` 53 | 50 | 32 | `torch` 54 | 51 | 33 | `fire` 55 | 52 | 34 | `mob_spawner` 56 | 53 | 35 | `oak_stairs` 57 | 54 | 36 | `chest` 58 | 55 | 37 | `redstone_wire` 59 | 56 | 38 | `diamond_ore` 60 | 57 | 39 | `diamond_block` 61 | 58 | 3a | `crafting_table` 62 | 59 | 3b | `wheat` 63 | 60 | 3c | `farmland` 64 | 61 | 3d | `furnace` 65 | 63 | 3f | `standing_sign` 66 | 65 | 41 | `ladder` 67 | 66 | 42 | `rail` 68 | 67 | 43 | `stone_stairs` 69 | 68 | 44 | `wall_sign` 70 | 70 | 46 | `stone_pressure_plate` 71 | 71 | 47 | `iron_door` 72 | 73 | 49 | `redstone_ore` 73 | 74 | 4a | `lit_redstone_ore` 74 | 76 | 4c | `redstone_torch` 75 | 77 | 4d | `stone_button` 76 | 78 | 4e | `snow_layer` 77 | 79 | 4f | `ice` 78 | 80 | 50 | `snow` 79 | 81 | 51 | `cactus` 80 | 82 | 52 | `clay` 81 | 83 | 53 | `reeds` 82 | 85 | 55 | `fence` 83 | 86 | 56 | `pumpkin` 84 | 87 | 57 | `netherrack` 85 | 88 | 58 | `soul_sand` 86 | 89 | 59 | `glowstone` 87 | 91 | 5b | `lit_pumpkin` 88 | 93 | 5d | `unpowered_repeater` 89 | 94 | 5e | `powered_repeater` 90 | 96 | 60 | `trapdoor` 91 | 98 | 62 | `stonebrick` 92 | 99 | 63 | `brown_mushroom_block` 93 | 100 | 64 | `red_mushroom_block` 94 | 101 | 65 | `iron_bars` 95 | 102 | 66 | `glass_pane` 96 | 103 | 67 | `melon_block` 97 | 104 | 68 | `pumpkin_stem` 98 | 105 | 69 | `melon_stem` 99 | 106 | 6a | `vine` 100 | 108 | 6c | `brick_stairs` 101 | 109 | 6d | `stone_brick_stairs` 102 | 110 | 6e | `mycelium` 103 | 111 | 6f | `waterlily` 104 | 112 | 70 | `nether_brick` 105 | 113 | 71 | `nether_brick_fence` 106 | 114 | 72 | `nether_brick_stairs` 107 | 116 | 74 | `enchanting_table` 108 | 117 | 75 | `brewing_stand` 109 | 118 | 76 | `cauldron` 110 | 123 | 7b | `redstone_lamp` 111 | 125 | 7d | `dropper` 112 | 127 | 7f | `cocoa` 113 | 128 | 80 | `sandstone_stairs` 114 | 129 | 81 | `emerald_ore` 115 | 133 | 85 | `emerald_block` 116 | 134 | 86 | `spruce_stairs` 117 | 135 | 87 | `birch_stairs` 118 | 136 | 88 | `jungle_stairs` 119 | 137 | 89 | `stonefloor_slab` 120 | 139 | 8b | `cobblestone_wall` 121 | 140 | 8c | `flower_pot` 122 | 141 | 8d | `carrots` 123 | 144 | 90 | `skull` 124 | 145 | 91 | `anvil` 125 | 149 | 95 | `unpowered_comparator` 126 | 150 | 96 | `powered_comparator` 127 | 152 | 98 | `redstone_block` 128 | 153 | 99 | `quartz_ore` 129 | 155 | 9b | `quartz_block` 130 | 156 | 9c | `quartz_stairs` 131 | 157 | 9d | `double_wooden_slab` 132 | 158 | 9e | `wooden_slab` 133 | 159 | 9f | `stained_hardened_clay` 134 | 161 | a1 | `leaves2` 135 | 162 | a2 | `log2` 136 | 163 | a3 | `acacia_stairs` 137 | 164 | a4 | `dark_oak_stairs` 138 | 167 | a7 | `iron_trapdoor` 139 | 170 | aa | `hay_block` 140 | 171 | ab | `carpet` 141 | 172 | ac | `hardened_clay` 142 | 173 | ad | `coal_block` 143 | 174 | ae | `packed_ice` 144 | 175 | af | `double_plant` 145 | 179 | b3 | `red_sandstone` 146 | 180 | b4 | `red_sandstone_stairs` 147 | 181 | b5 | `double_stone_slab2` 148 | 182 | b6 | `stone_slab2` 149 | 183 | b7 | `spruce_fence_gate` 150 | 184 | b8 | `birch_fence_gate` 151 | 185 | b9 | `jungle_fence_gate` 152 | 186 | ba | `dark_oak_fence_gate` 153 | 187 | bb | `acacia_fence_gate` 154 | 193 | c1 | `spruce_door` 155 | 194 | c2 | `birch_door` 156 | 195 | c3 | `jungle_door` 157 | 196 | c4 | `acacia_door` 158 | 197 | c5 | `dark_oak_door` 159 | 198 | c6 | `grass_path` 160 | 199 | c7 | `frame` 161 | 224 | e0 | `custom_0` 162 | 225 | e1 | `custom_1` 163 | 226 | e2 | `custom_2` 164 | 227 | e3 | `custom_3` 165 | 228 | e4 | `custom_4` 166 | 229 | e5 | `custom_5` 167 | 230 | e6 | `custom_6` 168 | 231 | e7 | `custom_7` 169 | 232 | e8 | `custom_8` 170 | 233 | e9 | `custom_9` 171 | 234 | ea | `custom_10` 172 | 235 | eb | `custom_11` 173 | 236 | ec | `custom_12` 174 | 237 | ed | `custom_13` 175 | 238 | ee | `custom_14` 176 | 239 | ef | `custom_15` 177 | 243 | f3 | `podzol` 178 | 244 | f4 | `beetroot` 179 | 245 | f5 | `stonecutter` 180 | 246 | f6 | `glowingobsidian` 181 | 247 | f7 | `netherreactor` 182 | 248 | f8 | `info_update` 183 | 249 | f9 | `info_update2` 184 | 250 | fa | `movingblock` 185 | 251 | fb | `observer` 186 | 255 | ff | `reserved6` -------------------------------------------------------------------------------- /docs/Level.md: -------------------------------------------------------------------------------- 1 | # Level 2 | 3 | Level files use [tiles](/docs/Tile.md) from object groups to create the worlds you can play in. They also store information about the mission objectives, what types of mobs can spawn, what props are used, and more. 4 | 5 | Levels are stored as JSON files in the `Dungeons/Content/data/lovika/levels` directory. 6 | 7 | ## Table of contents 8 | 9 | - [death-outside](#death-outside) 10 | - [fill](#fill) 11 | - [id](#id) 12 | - [object-groups](#object-groups) 13 | - [objectives](#objectives) 14 | - [play-intro](#play-intro) 15 | - [resource-packs](#resource-packs) 16 | - [stretches](#stretches) 17 | 18 | ## Properties 19 | 20 | :warning: This section is still under construction! More properties and information will be added over time. 21 | 22 | 23 | ### death-outside 24 | 25 | - Type: `boolean` 26 | 27 | By default, if the player walks off the edge of the level, they will respawn at their last checkpoint. Setting this property to `false` will create a "soft" barrier around the level that players can't walk through. It is still possible to roll through this barrier, however. It works just like the `2` and `4` values of the `region-plane` in tiles. 28 | 29 | If this property is set to `false` and the level has "fill", rolling through the barrier will allow you to walk around on the fill freely. 30 | 31 | #### See also... 32 | - [Tile "region-plane" property](/docs/Tile.md#region-plane) 33 | - [fill](#fill) 34 | 35 | 36 | ### fill 37 | 38 | - Type: `object` or `string` 39 | 40 | This property controls the level "fill", which is a layer of blocks automatically placed by the game around the outside of tiles. The fill is made up of up to 17 bands of "gradient" blocks. 41 | 42 | It can have a `world` property, which can have a `gradient` property, which is an array numbers. The first number controls the average width of the first band of blocks. The second number controls the width of the second band, and so on. Because there are only 16 different gradient blocks in the game, all bands beyond 16 will use the first gradient block, creating a 17th band with an average width equal to the sum of all numbers in the array after the 16th. 43 | 44 | The `y` tile property has some sort of effect on the level fill, but it is not fully understood yet. 45 | 46 | ![y property affecting the level fill](/docs/y.gif) 47 | 48 | The `fill` property may also instead be set to a string, like `"only-doors"`. This value has not been tested yet, but may be the default value, where the fill only covers doors that aren't connected to anything. In that case, the fill uses the blocks adjacent to the door horizontally to fill the door's space. No other string values has been found for the fill property yet. 49 | 50 | #### See also... 51 | - [Tile "y" property](/docs/Tile.md#y) 52 | 53 | 54 | ### id 55 | 56 | - Type: `string` 57 | 58 | The ID of the level. This is used to set the environment of the level. For example, setting it to `creeperwoods` will make it night-time. 59 | 60 | It also controls what into sequence is played at the start of the level. 61 | 62 | It might control more than just these two things, more testing is required. 63 | 64 | 65 | ### object-groups 66 | 67 | - Type: `array` of `string` 68 | 69 | A list of object groups that the level uses tiles from. Each object group is represented by the object group's file path relative to the `Dungeons/Content/data/lovika/objectgroups` directory, without the file extension. 70 | 71 | 72 | ### objectives 73 | 74 | - Type: `array` of `object` 75 | 76 | A list of mission objectives that the players need to complete in order to finish the level. 77 | 78 | ~~For more information about objectives, see [the page about them here.](/docs/Objective.md)~~ 79 | 80 | 81 | ### play-intro 82 | 83 | - Type: `boolean` 84 | 85 | By default, levels that have an intro sequence will play it after loading into the level. This property can be set to `false` to disable the intro. 86 | 87 | 88 | ### resource-packs 89 | 90 | - Type: `array` of `string` 91 | 92 | A list of resource packs to use for this level. Each resource pack is represented by its directory name in the `Dungeons/Content/data/resourcepacks` directory. 93 | 94 | Some testing is still required to find out how multiple resource packs work together, but it is most likely similar to how they work in Minecraft Bedrock Edition. 95 | 96 | 97 | ### stretches 98 | 99 | - Type: `array` of `object` 100 | 101 | A list of "stretches", which are distinct parts of the level that are made up of tiles and potential side-paths. 102 | 103 | ~~For more information about stretches, see [the page about them here.](/docs/Stretch.md)~~ -------------------------------------------------------------------------------- /docs/Tile.md: -------------------------------------------------------------------------------- 1 | # Tile 2 | 3 | A tile is essentially a chunk of Minecraft blocks. They can be pretty much any size, but they are always shaped like a cuboid. They are stored as JSON objects in object groups. 4 | 5 | ## Table of contents 6 | 7 | - [blocks](#blocks) 8 | - [boundaries](#boundaries) 9 | - [doors](#doors) 10 | - [height-plane](#height-plane) 11 | - [id](#id) 12 | - [is-leaky](#is-leaky) 13 | - [locked](#locked) 14 | - [pos](#pos) 15 | - [region-plane](#region-plane) 16 | - [region-y-plane](#region-y-plane) 17 | - [regions](#regions) 18 | - [size](#size) 19 | - [tags](#tags) 20 | - [walkable-plane](#walkable-plane) 21 | - [y](#y) 22 | 23 | ## Properties 24 | 25 | :warning: This section is still under construction! 26 | 27 | 28 | ### blocks 29 | 30 | - Type: `string` 31 | - Encoding/compression: Base64 encoded zlib compressed 32 | 33 | The blocks in the tile, stored as block IDs and data values. This is split into two parts: 34 | 35 | #### Block IDs 36 | 37 | The first part is the same size as the volume of the tile in bytes. Each byte in this section is a block ID. The order is YZX, meaning if you have a point `(x, y, z)` in a tile with a size `(w, h, d)`, the index of the block at that point is `(y * d + z) * w + x`. 38 | 39 | In 1.8.0.0+, the block IDs can also be 16-bit integers, meaning this part can be twice as big. The old single byte format is still used for tiles that don't use block IDs above 255. To check if a tile is using the new 16-bit format, just check if the number of bytes in this `blocks` string is more than twice the volume of the tile. 40 | 41 | #### Block data values 42 | 43 | The second part is similar to the first one, but each data value is only 4 bits instead of a byte/two bytes, meaning this part is half or a quarter of the size of the first. 44 | 45 | The total size of the `blocks` property of a tile with a size `(w, h, d)` is either `ceil(w * h * d * 1.5)` or `ceil(w * h * d * 3)` bytes, depending on the format. 46 | 47 | #### See also... 48 | - [List of block IDs](/docs/Block_IDs.md) 49 | - [Example: How to get the ID and data value of a block in a tile](/examples/Get_Block_IDs_and_Data_Values.py) 50 | - [Example: How to set the ID and data value of a block in a tile](/examples/Set_Block_IDs_and_Data_Values.py) 51 | 52 | 53 | ### boundaries 54 | 55 | - Type: `string` **or** `array` of `array` of `number` 56 | - Encoding/compression: If it is a `string`, base64 encoded zlib compressed 57 | 58 | A list of boundaries in the tile. A boundary is a vertical stack of invisible blocks that players and monsters can't get through. The top and bottom of a boundary are not solid, only the sides are, meaning it's not possible to walk on top of them. 59 | 60 | Each boundary is defined by 4 16-bit integers that represent a point in space and a height. The point is the position of the bottom of the boundary and the height is how many blocks tall it should be. 61 | 62 | The order of the 4 integers is: x, y, z, height. 63 | 64 | Most tiles in the game uses the more compact encoded string format for this property. In this format, each boundary is simply the 4 16-bit integers packed together into 8 bytes. The boundaries are then packed together without anything separating them to form the list, so that every 8 bytes is a boundary. 65 | 66 | The array format is, as of version 1.3.2.0, only found in the `GenericCaves/objectgroup.json.oldold` file. In this format, each boundary is an array containing the 4 integers, and the list is simply an array of these boundary arrays. This format is much easier to understand for most people, but it is far less compact. 67 | 68 | 69 | ### doors 70 | 71 | - Type: `array` of `object` 72 | 73 | A list of doors in the tile. A door can be a tile connection point or an object players can interact with to teleport somewhere else in the level. Tile connection points does not need to be the same size to be able to connect, however it is recommended that they are, to have full control over exactly how they connect. 74 | 75 | ~~For more information about doors, see [the page about them here.]()~~ 76 | 77 | 78 | ### height-plane 79 | 80 | - Type: `string` 81 | - Encoding/compression: Base64 encoded zlib compressed 82 | 83 | A heightmap of the tile. This is similar to the block IDs in the `blocks` property, except there is only one layer. The values represent the Y coordinate of the top non-air block. 84 | 85 | This property is often a copy of the `region-y-plane` property, but not always, and they function differently. 86 | 87 | What this property actually affects is currently unknown and requires more testing. 88 | 89 | #### See also... 90 | - [blocks](#blocks) 91 | - [region-y-plane](#region-y-plane) 92 | 93 | 94 | ### id 95 | 96 | - Type: `string` 97 | 98 | A unique identifier/name for the tile. This is used to reference the tile in the level files. 99 | 100 | 101 | ### is-leaky 102 | 103 | - Type: `boolean` 104 | 105 | ["It's an internal thing to determine if you can escape tiles."](/docs/is-leaky.png) 106 | 107 | Possibly just something Mojang's editor uses to show if a tile needs more boundaries. After a lot of testing, it doesn't seem to affect anything in-game. 108 | 109 | 110 | ### locked 111 | 112 | - Type: `boolean` 113 | 114 | What this does is currently unknown. The property first appreared in version 1.2.1.0, and as of 1.3.2.0, no tiles have it set to `true`. 115 | 116 | 117 | ### pos 118 | 119 | - Type: `array` of `number` 120 | 121 | This is not actually the position of the tile in the level and changing it has seemingly no effect. It is most likely the position of the tile in the world where it was built in Minecraft, before importing the tile to Dungeons. 122 | 123 | 124 | ### region-plane 125 | 126 | - Type: `string` 127 | - Encoding/compression: Base64 encoded zlib compressed 128 | 129 | Information about how the tile should be displayed on the minimap and what areas of the tile players can walk through. It is very similar to the block IDs in the `blocks` property, except there is only one layer and the values range from 0 to 4, each with a different meaning: 130 | 131 | Value | Walkable | Minimap 132 | ----- | -------- | ------- 133 | 0 | Yes | Yes 134 | 1 | Yes | No 135 | 2 | Only if below `region-y-plane` | No 136 | 3 | Yes | Yes 137 | 4 | Only if below `region-y-plane` | No 138 | 139 | Unwalkable areas stop players from simply walking into them, but does not stop them from rolling or using artifacts that causes the player to move. The `region-plane` is what stops players from just walking off most cliffs. 140 | 141 | Note that `0` and `3`, and `2` and `4` have the same properties. This could mean that the `region-plane` controls more than just thse two things, however what that could be is still unknown. 142 | 143 | One difference between `0` and `3` is how they are used in the vanilla game. `0` is used for most areas where players can walk, while `3` is used for roofed areas, like tunnels or overhangs. 144 | 145 | There are also some differences in how `2` and `4` are used. `2` is mostly used for big falls, while `4` is usually used for high walls. 146 | 147 | Values greater than 4 work just like `0`. 148 | 149 | #### See also... 150 | - [blocks](#blocks) 151 | - [region-y-plane](#region-y-plane) 152 | 153 | 154 | ### region-y-plane 155 | 156 | - Type: `string` 157 | - Encoding/compression: Base64 encoded zlib compressed 158 | 159 | This is similar to the `height-plane` property and, for a lot of the tiles in the game, these two properties are identical. However, they don't function the same way. The values here represent the Y coordinate of where some `region-plane` values change properties: 160 | 161 | `region-plane` Value | Effect 162 | -------------------- | ------ 163 | 0 | None? 164 | 1 | None? 165 | 2 | If the player is below the `region-y-plane`, they can move through the area freely. If they are above, they can not walk into the area, but can still roll/jump into it. 166 | 3 | None? 167 | 4 | If the player is below the `region-y-plane`, they can move through the area freely. If they are above, they can not walk into the area, but can still roll/jump into it. 168 | 169 | More testing is required to find out more about this property. It might be related to what separates the `0` and `3`, and/or the `2` and `4` values of the `region-plane`, but that is just speculation for now. 170 | 171 | #### See also... 172 | - [height-plane](#height-plane) 173 | - [region-plane](#region-plane) 174 | 175 | 176 | ### regions 177 | 178 | - Type: `array` of `object` 179 | 180 | A list of regions in the tile. Regions are areas in a tile that can either trigger something, or be used to spawn objects or monsters, or set the spawn point for players. 181 | 182 | ~~For more information about regions, see [the page about them here.]()~~ 183 | 184 | 185 | ### size 186 | 187 | - Type: `array` of `number` 188 | 189 | The size of the tile. 190 | 191 | 192 | ### tags 193 | 194 | - Type: `string` 195 | 196 | Currently unknown. 197 | 198 | Possibly used by level files to reference multiple tiles at once, for example `"*.*.tile_tag_goes_here"`, but this hasn't been tested yet. 199 | 200 | 201 | ### walkable-plane 202 | 203 | - Type: `string` 204 | - Encoding/compression: Base64 encoded zlib compressed 205 | 206 | Like the other `*-plane` properties, this is similar to the block IDs in the `blocks` property, except there is only one layer. What the values in this property actually represents and what changing them does is currently unknown. One pattern of this property that the vanilla files seems to follow is having the values be the Y coordinate of the top *solid* block + 1 in areas where the players can walk, and `0` for out-of-bounds areas. 207 | 208 | #### See also... 209 | - [blocks](#blocks) 210 | 211 | 212 | ### y 213 | 214 | - Type: `number` 215 | 216 | This seems to have something to do with height and the level "fill", but it is not fully understood yet. 217 | 218 | ![y property affecting the level fill](/docs/y.gif) 219 | 220 | #### See also... 221 | - [Level "fill" property](/docs/Level.md#fill) -------------------------------------------------------------------------------- /docs/is-leaky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dokucraft/Dungeons-Level-Format/9eb650235d65d506eaa17ac9de4c6a71e34ee18a/docs/is-leaky.png -------------------------------------------------------------------------------- /docs/y.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dokucraft/Dungeons-Level-Format/9eb650235d65d506eaa17ac9de4c6a71e34ee18a/docs/y.gif -------------------------------------------------------------------------------- /examples/BlockMap.py: -------------------------------------------------------------------------------- 1 | blocks = [ 2 | # Dungeons Format: 3 | # 0: Block ID 4 | # 1: Block Data 5 | # 2: Block Data Mask 6 | 7 | # Java Format: 8 | # 0: Block ID 9 | # 1: Block Properties 10 | 11 | { 'dungeons': [ 0x0000 ], 'java': [ 'minecraft:air' ] }, 12 | { 'dungeons': [ 0x0001, 0b0000 ], 'java': [ 'minecraft:stone' ] }, 13 | { 'dungeons': [ 0x0001, 0b0001 ], 'java': [ 'minecraft:granite' ] }, 14 | { 'dungeons': [ 0x0001, 0b0010 ], 'java': [ 'minecraft:polished_granite' ] }, 15 | { 'dungeons': [ 0x0001, 0b0011 ], 'java': [ 'minecraft:diorite' ] }, 16 | { 'dungeons': [ 0x0001, 0b0100 ], 'java': [ 'minecraft:polished_diorite' ] }, 17 | { 'dungeons': [ 0x0001, 0b0101 ], 'java': [ 'minecraft:andesite' ] }, 18 | { 'dungeons': [ 0x0001, 0b0110 ], 'java': [ 'minecraft:polished_andesite' ] }, 19 | { 'dungeons': [ 0x0001, 0b0111 ], 'java': [ 'minecraft:blackstone' ] }, # stonefloor1 20 | { 'dungeons': [ 0x0001, 0b1000 ], 'java': [ 'minecraft:chiseled_polished_blackstone' ] }, # stonefloor2 21 | { 'dungeons': [ 0x0001, 0b1001 ], 'java': [ 'minecraft:polished_blackstone' ] }, # stonefloor3 22 | { 'dungeons': [ 0x0001, 0b1010 ], 'java': [ 'minecraft:polished_blackstone_bricks' ] }, # stonefloor4 23 | { 'dungeons': [ 0x0001, 0b1011 ], 'java': [ 'minecraft:gilded_blackstone' ] }, # stonefloor5 24 | { 'dungeons': [ 0x0001, 0b1100 ], 'java': [ 'minecraft:cracked_polished_blackstone_bricks' ] }, # stonefloor6 25 | { 'dungeons': [ 0x0001, 0b1101 ], 'java': [ 'minecraft:lodestone' ] }, # stonefloor7 26 | { 'dungeons': [ 0x0001, 0b1110 ], 'java': [ 'minecraft:ancient_debris' ] }, # stonefloor8 27 | { 'dungeons': [ 0x0001, 0b1111 ], 'java': [ 'minecraft:infested_chiseled_stone_bricks' ] }, # stonefloor9 28 | { 'dungeons': [ 0x0002, 0b0000 ], 'java': [ 'minecraft:grass_block' ] }, 29 | { 'dungeons': [ 0x0003, 0b0000 ], 'java': [ 'minecraft:dirt' ] }, 30 | { 'dungeons': [ 0x0003, 0b0001 ], 'java': [ 'minecraft:coarse_dirt' ] }, 31 | { 'dungeons': [ 0x0004, 0b0000 ], 'java': [ 'minecraft:cobblestone' ] }, 32 | { 'dungeons': [ 0x0005, 0b0000 ], 'java': [ 'minecraft:oak_planks' ] }, 33 | { 'dungeons': [ 0x0005, 0b0001 ], 'java': [ 'minecraft:spruce_planks' ] }, 34 | { 'dungeons': [ 0x0005, 0b0010 ], 'java': [ 'minecraft:birch_planks' ] }, 35 | { 'dungeons': [ 0x0005, 0b0011 ], 'java': [ 'minecraft:jungle_planks' ] }, 36 | { 'dungeons': [ 0x0005, 0b0100 ], 'java': [ 'minecraft:acacia_planks' ] }, 37 | { 'dungeons': [ 0x0005, 0b0101 ], 'java': [ 'minecraft:dark_oak_planks' ] }, 38 | { 'dungeons': [ 0x0006, 0b0000 ], 'java': [ 'minecraft:oak_sapling', { 'stage': '0' } ] }, 39 | { 'dungeons': [ 0x0006, 0b0001 ], 'java': [ 'minecraft:spruce_sapling', { 'stage': '0' } ] }, 40 | { 'dungeons': [ 0x0006, 0b0010 ], 'java': [ 'minecraft:birch_sapling', { 'stage': '0' } ] }, 41 | { 'dungeons': [ 0x0006, 0b0011 ], 'java': [ 'minecraft:jungle_sapling', { 'stage': '0' } ] }, 42 | { 'dungeons': [ 0x0006, 0b0100 ], 'java': [ 'minecraft:acacia_sapling', { 'stage': '0' } ] }, 43 | { 'dungeons': [ 0x0006, 0b0101 ], 'java': [ 'minecraft:dark_oak_sapling', { 'stage': '0' } ] }, 44 | { 'dungeons': [ 0x0006, 0b1000 ], 'java': [ 'minecraft:oak_sapling', { 'stage': '1' } ] }, 45 | { 'dungeons': [ 0x0006, 0b1001 ], 'java': [ 'minecraft:spruce_sapling', { 'stage': '1' } ] }, 46 | { 'dungeons': [ 0x0006, 0b1010 ], 'java': [ 'minecraft:birch_sapling', { 'stage': '1' } ] }, 47 | { 'dungeons': [ 0x0006, 0b1011 ], 'java': [ 'minecraft:jungle_sapling', { 'stage': '1' } ] }, 48 | { 'dungeons': [ 0x0006, 0b1100 ], 'java': [ 'minecraft:acacia_sapling', { 'stage': '1' } ] }, 49 | { 'dungeons': [ 0x0006, 0b1101 ], 'java': [ 'minecraft:dark_oak_sapling', { 'stage': '1' } ] }, 50 | { 'dungeons': [ 0x0007, 0b0000 ], 'java': [ 'minecraft:bedrock' ] }, 51 | { 'dungeons': [ 0x0008, 0b0000 ], 'java': [ 'minecraft:water', { 'level': '1' } ] }, 52 | { 'dungeons': [ 0x0008, 0b0001 ], 'java': [ 'minecraft:water', { 'level': '2' } ] }, 53 | { 'dungeons': [ 0x0008, 0b0010 ], 'java': [ 'minecraft:water', { 'level': '3' } ] }, 54 | { 'dungeons': [ 0x0008, 0b0011 ], 'java': [ 'minecraft:water', { 'level': '4' } ] }, 55 | { 'dungeons': [ 0x0008, 0b0100 ], 'java': [ 'minecraft:water', { 'level': '5' } ] }, 56 | { 'dungeons': [ 0x0008, 0b0101 ], 'java': [ 'minecraft:water', { 'level': '6' } ] }, 57 | { 'dungeons': [ 0x0008, 0b0110 ], 'java': [ 'minecraft:water', { 'level': '7' } ] }, 58 | { 'dungeons': [ 0x0008, 0b0111 ], 'java': [ 'minecraft:water', { 'level': '8' } ] }, 59 | { 'dungeons': [ 0x0008, 0b1000 ], 'java': [ 'minecraft:water', { 'level': '9' } ] }, 60 | { 'dungeons': [ 0x0008, 0b1001 ], 'java': [ 'minecraft:water', { 'level': '10' } ] }, 61 | { 'dungeons': [ 0x0008, 0b1010 ], 'java': [ 'minecraft:water', { 'level': '11' } ] }, 62 | { 'dungeons': [ 0x0008, 0b1011 ], 'java': [ 'minecraft:water', { 'level': '12' } ] }, 63 | { 'dungeons': [ 0x0008, 0b1100 ], 'java': [ 'minecraft:water', { 'level': '13' } ] }, 64 | { 'dungeons': [ 0x0008, 0b1101 ], 'java': [ 'minecraft:water', { 'level': '14' } ] }, 65 | { 'dungeons': [ 0x0008, 0b1110 ], 'java': [ 'minecraft:water', { 'level': '15' } ] }, 66 | { 'dungeons': [ 0x0009 ], 'java': [ 'minecraft:water', { 'level': '0' } ] }, 67 | { 'dungeons': [ 0x000a, 0b0000 ], 'java': [ 'minecraft:lava', { 'level': '1' } ] }, 68 | { 'dungeons': [ 0x000a, 0b0001 ], 'java': [ 'minecraft:lava', { 'level': '2' } ] }, 69 | { 'dungeons': [ 0x000a, 0b0010 ], 'java': [ 'minecraft:lava', { 'level': '3' } ] }, 70 | { 'dungeons': [ 0x000a, 0b0011 ], 'java': [ 'minecraft:lava', { 'level': '4' } ] }, 71 | { 'dungeons': [ 0x000a, 0b0100 ], 'java': [ 'minecraft:lava', { 'level': '5' } ] }, 72 | { 'dungeons': [ 0x000a, 0b0101 ], 'java': [ 'minecraft:lava', { 'level': '6' } ] }, 73 | { 'dungeons': [ 0x000a, 0b0110 ], 'java': [ 'minecraft:lava', { 'level': '7' } ] }, 74 | { 'dungeons': [ 0x000a, 0b0111 ], 'java': [ 'minecraft:lava', { 'level': '8' } ] }, 75 | { 'dungeons': [ 0x000a, 0b1000 ], 'java': [ 'minecraft:lava', { 'level': '9' } ] }, 76 | { 'dungeons': [ 0x000a, 0b1001 ], 'java': [ 'minecraft:lava', { 'level': '10' } ] }, 77 | { 'dungeons': [ 0x000a, 0b1010 ], 'java': [ 'minecraft:lava', { 'level': '11' } ] }, 78 | { 'dungeons': [ 0x000a, 0b1011 ], 'java': [ 'minecraft:lava', { 'level': '12' } ] }, 79 | { 'dungeons': [ 0x000a, 0b1100 ], 'java': [ 'minecraft:lava', { 'level': '13' } ] }, 80 | { 'dungeons': [ 0x000a, 0b1101 ], 'java': [ 'minecraft:lava', { 'level': '14' } ] }, 81 | { 'dungeons': [ 0x000a, 0b1110 ], 'java': [ 'minecraft:lava', { 'level': '15' } ] }, 82 | { 'dungeons': [ 0x000b ], 'java': [ 'minecraft:lava', { 'level': '0' } ] }, 83 | { 'dungeons': [ 0x000c, 0b0000 ], 'java': [ 'minecraft:sand' ] }, 84 | { 'dungeons': [ 0x000c, 0b0001 ], 'java': [ 'minecraft:red_sand' ] }, 85 | { 'dungeons': [ 0x000d, 0b0000 ], 'java': [ 'minecraft:gravel' ] }, 86 | { 'dungeons': [ 0x000e, 0b0000 ], 'java': [ 'minecraft:gold_ore' ] }, 87 | { 'dungeons': [ 0x000f, 0b0000 ], 'java': [ 'minecraft:iron_ore' ] }, 88 | { 'dungeons': [ 0x0010, 0b0000 ], 'java': [ 'minecraft:coal_ore' ] }, 89 | { 'dungeons': [ 0x0011, 0b0000 ], 'java': [ 'minecraft:oak_log', { 'axis': 'y' } ] }, 90 | { 'dungeons': [ 0x0011, 0b0001 ], 'java': [ 'minecraft:spruce_log', { 'axis': 'y' } ] }, 91 | { 'dungeons': [ 0x0011, 0b0010 ], 'java': [ 'minecraft:birch_log', { 'axis': 'y' } ] }, 92 | { 'dungeons': [ 0x0011, 0b0011 ], 'java': [ 'minecraft:jungle_log', { 'axis': 'y' } ] }, 93 | { 'dungeons': [ 0x0011, 0b0100 ], 'java': [ 'minecraft:oak_log', { 'axis': 'x' } ] }, 94 | { 'dungeons': [ 0x0011, 0b0101 ], 'java': [ 'minecraft:spruce_log', { 'axis': 'x' } ] }, 95 | { 'dungeons': [ 0x0011, 0b0110 ], 'java': [ 'minecraft:birch_log', { 'axis': 'x' } ] }, 96 | { 'dungeons': [ 0x0011, 0b0111 ], 'java': [ 'minecraft:jungle_log', { 'axis': 'x' } ] }, 97 | { 'dungeons': [ 0x0011, 0b1000 ], 'java': [ 'minecraft:oak_log', { 'axis': 'z' } ] }, 98 | { 'dungeons': [ 0x0011, 0b1001 ], 'java': [ 'minecraft:spruce_log', { 'axis': 'z' } ] }, 99 | { 'dungeons': [ 0x0011, 0b1010 ], 'java': [ 'minecraft:birch_log', { 'axis': 'z' } ] }, 100 | { 'dungeons': [ 0x0011, 0b1011 ], 'java': [ 'minecraft:jungle_log', { 'axis': 'z' } ] }, 101 | { 'dungeons': [ 0x0011, 0b1100 ], 'java': [ 'minecraft:oak_wood' ] }, 102 | { 'dungeons': [ 0x0011, 0b1101 ], 'java': [ 'minecraft:spruce_wood' ] }, 103 | { 'dungeons': [ 0x0011, 0b1110 ], 'java': [ 'minecraft:birch_wood' ] }, 104 | { 'dungeons': [ 0x0011, 0b1111 ], 'java': [ 'minecraft:jungle_wood' ] }, 105 | { 'dungeons': [ 0x0012, 0b0000, 0b0111 ], 'java': [ 'minecraft:oak_leaves', { 'persistent': 'false' } ] }, 106 | { 'dungeons': [ 0x0012, 0b0001, 0b0111 ], 'java': [ 'minecraft:spruce_leaves', { 'persistent': 'false' } ] }, 107 | { 'dungeons': [ 0x0012, 0b0010, 0b0111 ], 'java': [ 'minecraft:birch_leaves', { 'persistent': 'false' } ] }, 108 | { 'dungeons': [ 0x0012, 0b0011, 0b0111 ], 'java': [ 'minecraft:jungle_leaves', { 'persistent': 'false' } ] }, 109 | { 'dungeons': [ 0x0012, 0b0100, 0b0111 ], 'java': [ 'minecraft:oak_leaves', { 'persistent': 'true' } ] }, 110 | { 'dungeons': [ 0x0012, 0b0101, 0b0111 ], 'java': [ 'minecraft:spruce_leaves', { 'persistent': 'true' } ] }, 111 | { 'dungeons': [ 0x0012, 0b0110, 0b0111 ], 'java': [ 'minecraft:birch_leaves', { 'persistent': 'true' } ] }, 112 | { 'dungeons': [ 0x0012, 0b0111, 0b0111 ], 'java': [ 'minecraft:jungle_leaves', { 'persistent': 'true' } ] }, 113 | { 'dungeons': [ 0x0013, 0b0000 ], 'java': [ 'minecraft:sponge' ] }, 114 | { 'dungeons': [ 0x0014, 0b0000 ], 'java': [ 'minecraft:glass' ] }, 115 | { 'dungeons': [ 0x0015, 0b0000 ], 'java': [ 'minecraft:lapis_ore' ] }, 116 | { 'dungeons': [ 0x0016, 0b0000 ], 'java': [ 'minecraft:lapis_block' ] }, 117 | { 'dungeons': [ 0x0017, 0b0000 ], 'java': [ 'minecraft:dispenser', { 'facing': 'down' } ] }, 118 | { 'dungeons': [ 0x0017, 0b0001 ], 'java': [ 'minecraft:dispenser', { 'facing': 'up' } ] }, 119 | { 'dungeons': [ 0x0017, 0b0010 ], 'java': [ 'minecraft:dispenser', { 'facing': 'north' } ] }, 120 | { 'dungeons': [ 0x0017, 0b0011 ], 'java': [ 'minecraft:dispenser', { 'facing': 'south' } ] }, 121 | { 'dungeons': [ 0x0017, 0b0100 ], 'java': [ 'minecraft:dispenser', { 'facing': 'west' } ] }, 122 | { 'dungeons': [ 0x0017, 0b0101 ], 'java': [ 'minecraft:dispenser', { 'facing': 'east' } ] }, 123 | { 'dungeons': [ 0x0017, 0b1000 ], 'java': [ 'minecraft:dispenser', { 'facing': 'down' } ] }, 124 | { 'dungeons': [ 0x0017, 0b1001 ], 'java': [ 'minecraft:dispenser', { 'facing': 'up' } ] }, 125 | { 'dungeons': [ 0x0017, 0b1010 ], 'java': [ 'minecraft:dispenser', { 'facing': 'north' } ] }, 126 | { 'dungeons': [ 0x0017, 0b1011 ], 'java': [ 'minecraft:dispenser', { 'facing': 'south' } ] }, 127 | { 'dungeons': [ 0x0017, 0b1100 ], 'java': [ 'minecraft:dispenser', { 'facing': 'west' } ] }, 128 | { 'dungeons': [ 0x0017, 0b1101 ], 'java': [ 'minecraft:dispenser', { 'facing': 'east' } ] }, 129 | { 'dungeons': [ 0x0018, 0b0000 ], 'java': [ 'minecraft:sandstone' ] }, 130 | { 'dungeons': [ 0x0018, 0b0001 ], 'java': [ 'minecraft:chiseled_sandstone' ] }, 131 | { 'dungeons': [ 0x0018, 0b0010 ], 'java': [ 'minecraft:cut_sandstone' ] }, 132 | { 'dungeons': [ 0x0018, 0b0011 ], 'java': [ 'minecraft:smooth_sandstone' ] }, 133 | { 'dungeons': [ 0x0019, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '0' } ] }, 134 | { 'dungeons': [ 0x001a, 0b0000 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'false', 'facing': 'south' } ] }, 135 | { 'dungeons': [ 0x001a, 0b0001 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'false', 'facing': 'west' } ] }, 136 | { 'dungeons': [ 0x001a, 0b0010 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'false', 'facing': 'north' } ] }, 137 | { 'dungeons': [ 0x001a, 0b0011 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'false', 'facing': 'east' } ] }, 138 | { 'dungeons': [ 0x001a, 0b0100 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'true', 'facing': 'south' } ] }, 139 | { 'dungeons': [ 0x001a, 0b0101 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'true', 'facing': 'west' } ] }, 140 | { 'dungeons': [ 0x001a, 0b0110 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'true', 'facing': 'north' } ] }, 141 | { 'dungeons': [ 0x001a, 0b0111 ], 'java': [ 'minecraft:red_bed', { 'part': 'foot', 'occupied': 'true', 'facing': 'east' } ] }, 142 | { 'dungeons': [ 0x001a, 0b1000 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'false', 'facing': 'south' } ] }, 143 | { 'dungeons': [ 0x001a, 0b1001 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'false', 'facing': 'west' } ] }, 144 | { 'dungeons': [ 0x001a, 0b1010 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'false', 'facing': 'north' } ] }, 145 | { 'dungeons': [ 0x001a, 0b1011 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'false', 'facing': 'east' } ] }, 146 | { 'dungeons': [ 0x001a, 0b1100 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'true', 'facing': 'south' } ] }, 147 | { 'dungeons': [ 0x001a, 0b1101 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'true', 'facing': 'west' } ] }, 148 | { 'dungeons': [ 0x001a, 0b1110 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'true', 'facing': 'north' } ] }, 149 | { 'dungeons': [ 0x001a, 0b1111 ], 'java': [ 'minecraft:red_bed', { 'part': 'head', 'occupied': 'true', 'facing': 'east' } ] }, 150 | { 'dungeons': [ 0x001b, 0b0000 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'north_south' } ] }, 151 | { 'dungeons': [ 0x001b, 0b0001 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'east_west' } ] }, 152 | { 'dungeons': [ 0x001b, 0b0010 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'ascending_east' } ] }, 153 | { 'dungeons': [ 0x001b, 0b0011 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'ascending_west' } ] }, 154 | { 'dungeons': [ 0x001b, 0b0100 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'ascending_north' } ] }, 155 | { 'dungeons': [ 0x001b, 0b0101 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'false', 'shape': 'ascending_south' } ] }, 156 | { 'dungeons': [ 0x001b, 0b1000 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'north_south' } ] }, 157 | { 'dungeons': [ 0x001b, 0b1001 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'east_west' } ] }, 158 | { 'dungeons': [ 0x001b, 0b1010 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'ascending_east' } ] }, 159 | { 'dungeons': [ 0x001b, 0b1011 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'ascending_west' } ] }, 160 | { 'dungeons': [ 0x001b, 0b1100 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'ascending_north' } ] }, 161 | { 'dungeons': [ 0x001b, 0b1101 ], 'java': [ 'minecraft:powered_rail', { 'powered': 'true', 'shape': 'ascending_south' } ] }, 162 | { 'dungeons': [ 0x001c, 0b0000 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'north_south' } ] }, 163 | { 'dungeons': [ 0x001c, 0b0001 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'east_west' } ] }, 164 | { 'dungeons': [ 0x001c, 0b0010 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'ascending_east' } ] }, 165 | { 'dungeons': [ 0x001c, 0b0011 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'ascending_west' } ] }, 166 | { 'dungeons': [ 0x001c, 0b0100 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'ascending_north' } ] }, 167 | { 'dungeons': [ 0x001c, 0b0101 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'false', 'shape': 'ascending_south' } ] }, 168 | { 'dungeons': [ 0x001c, 0b1000 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'north_south' } ] }, 169 | { 'dungeons': [ 0x001c, 0b1001 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'east_west' } ] }, 170 | { 'dungeons': [ 0x001c, 0b1010 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'ascending_east' } ] }, 171 | { 'dungeons': [ 0x001c, 0b1011 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'ascending_west' } ] }, 172 | { 'dungeons': [ 0x001c, 0b1100 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'ascending_north' } ] }, 173 | { 'dungeons': [ 0x001c, 0b1101 ], 'java': [ 'minecraft:detector_rail', { 'powered': 'true', 'shape': 'ascending_south' } ] }, 174 | { 'dungeons': [ 0x001d, 0b0000 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'down' } ] }, 175 | { 'dungeons': [ 0x001d, 0b0001 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'up' } ] }, 176 | { 'dungeons': [ 0x001d, 0b0010 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'north' } ] }, 177 | { 'dungeons': [ 0x001d, 0b0011 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'south' } ] }, 178 | { 'dungeons': [ 0x001d, 0b0100 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'west' } ] }, 179 | { 'dungeons': [ 0x001d, 0b0101 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'false', 'facing': 'east' } ] }, 180 | { 'dungeons': [ 0x001d, 0b1000 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'down' } ] }, 181 | { 'dungeons': [ 0x001d, 0b1001 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'up' } ] }, 182 | { 'dungeons': [ 0x001d, 0b1010 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'north' } ] }, 183 | { 'dungeons': [ 0x001d, 0b1011 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'south' } ] }, 184 | { 'dungeons': [ 0x001d, 0b1100 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'west' } ] }, 185 | { 'dungeons': [ 0x001d, 0b1101 ], 'java': [ 'minecraft:sticky_piston', { 'extended': 'true', 'facing': 'east' } ] }, 186 | { 'dungeons': [ 0x001e, 0b0000 ], 'java': [ 'minecraft:cobweb' ] }, 187 | { 'dungeons': [ 0x001f, 0b0001 ], 'java': [ 'minecraft:grass' ] }, 188 | { 'dungeons': [ 0x001f, 0b0010 ], 'java': [ 'minecraft:fern' ] }, 189 | { 'dungeons': [ 0x0023, 0b0000 ], 'java': [ 'minecraft:white_wool' ] }, 190 | { 'dungeons': [ 0x0023, 0b0001 ], 'java': [ 'minecraft:orange_wool' ] }, 191 | { 'dungeons': [ 0x0023, 0b0010 ], 'java': [ 'minecraft:magenta_wool' ] }, 192 | { 'dungeons': [ 0x0023, 0b0011 ], 'java': [ 'minecraft:light_blue_wool' ] }, 193 | { 'dungeons': [ 0x0023, 0b0100 ], 'java': [ 'minecraft:yellow_wool' ] }, 194 | { 'dungeons': [ 0x0023, 0b0101 ], 'java': [ 'minecraft:lime_wool' ] }, 195 | { 'dungeons': [ 0x0023, 0b0110 ], 'java': [ 'minecraft:pink_wool' ] }, 196 | { 'dungeons': [ 0x0023, 0b0111 ], 'java': [ 'minecraft:gray_wool' ] }, 197 | { 'dungeons': [ 0x0023, 0b1000 ], 'java': [ 'minecraft:light_gray_wool' ] }, 198 | { 'dungeons': [ 0x0023, 0b1001 ], 'java': [ 'minecraft:cyan_wool' ] }, 199 | { 'dungeons': [ 0x0023, 0b1010 ], 'java': [ 'minecraft:purple_wool' ] }, 200 | { 'dungeons': [ 0x0023, 0b1011 ], 'java': [ 'minecraft:blue_wool' ] }, 201 | { 'dungeons': [ 0x0023, 0b1100 ], 'java': [ 'minecraft:brown_wool' ] }, 202 | { 'dungeons': [ 0x0023, 0b1101 ], 'java': [ 'minecraft:green_wool' ] }, 203 | { 'dungeons': [ 0x0023, 0b1110 ], 'java': [ 'minecraft:red_wool' ] }, 204 | { 'dungeons': [ 0x0023, 0b1111 ], 'java': [ 'minecraft:black_wool' ] }, 205 | { 'dungeons': [ 0x0025, 0b0000 ], 'java': [ 'minecraft:dandelion' ] }, 206 | { 'dungeons': [ 0x0026, 0b0000 ], 'java': [ 'minecraft:poppy' ] }, 207 | { 'dungeons': [ 0x0026, 0b0001 ], 'java': [ 'minecraft:blue_orchid' ] }, 208 | { 'dungeons': [ 0x0026, 0b0010 ], 'java': [ 'minecraft:allium' ] }, 209 | { 'dungeons': [ 0x0026, 0b0011 ], 'java': [ 'minecraft:azure_bluet' ] }, 210 | { 'dungeons': [ 0x0026, 0b0100 ], 'java': [ 'minecraft:red_tulip' ] }, 211 | { 'dungeons': [ 0x0026, 0b0101 ], 'java': [ 'minecraft:orange_tulip' ] }, 212 | { 'dungeons': [ 0x0026, 0b0110 ], 'java': [ 'minecraft:white_tulip' ] }, 213 | { 'dungeons': [ 0x0026, 0b0111 ], 'java': [ 'minecraft:pink_tulip' ] }, 214 | { 'dungeons': [ 0x0026, 0b1000 ], 'java': [ 'minecraft:oxeye_daisy' ] }, 215 | { 'dungeons': [ 0x0026, 0b1001 ], 'java': [ 'minecraft:cornflower' ] }, 216 | { 'dungeons': [ 0x0026, 0b1010 ], 'java': [ 'minecraft:lily_of_the_valley' ] }, 217 | { 'dungeons': [ 0x0027, 0b0000 ], 'java': [ 'minecraft:brown_mushroom' ] }, 218 | { 'dungeons': [ 0x0028, 0b0000 ], 'java': [ 'minecraft:red_mushroom' ] }, 219 | { 'dungeons': [ 0x0029, 0b0000 ], 'java': [ 'minecraft:gold_block' ] }, 220 | { 'dungeons': [ 0x002a, 0b0000 ], 'java': [ 'minecraft:iron_block' ] }, 221 | { 'dungeons': [ 0x002b, 0b0000 ], 'java': [ 'minecraft:smooth_stone_slab', { 'type': 'double' } ] }, 222 | { 'dungeons': [ 0x002b, 0b0001 ], 'java': [ 'minecraft:sandstone_slab', { 'type': 'double' } ] }, 223 | { 'dungeons': [ 0x002b, 0b0010 ], 'java': [ 'minecraft:petrified_oak_slab', { 'type': 'double' } ] }, 224 | { 'dungeons': [ 0x002b, 0b0011 ], 'java': [ 'minecraft:cobblestone_slab', { 'type': 'double' } ] }, 225 | { 'dungeons': [ 0x002b, 0b0100 ], 'java': [ 'minecraft:brick_slab', { 'type': 'double' } ] }, 226 | { 'dungeons': [ 0x002b, 0b0101 ], 'java': [ 'minecraft:stone_brick_slab', { 'type': 'double' } ] }, 227 | { 'dungeons': [ 0x002b, 0b0110 ], 'java': [ 'minecraft:quartz_slab', { 'type': 'double' } ] }, 228 | { 'dungeons': [ 0x002b, 0b0111 ], 'java': [ 'minecraft:nether_brick_slab', { 'type': 'double' } ] }, 229 | { 'dungeons': [ 0x002c, 0b0000 ], 'java': [ 'minecraft:smooth_stone_slab', { 'type': 'bottom' } ] }, 230 | { 'dungeons': [ 0x002c, 0b0001 ], 'java': [ 'minecraft:sandstone_slab', { 'type': 'bottom' } ] }, 231 | { 'dungeons': [ 0x002c, 0b0010 ], 'java': [ 'minecraft:petrified_oak_slab', { 'type': 'bottom' } ] }, 232 | { 'dungeons': [ 0x002c, 0b0011 ], 'java': [ 'minecraft:cobblestone_slab', { 'type': 'bottom' } ] }, 233 | { 'dungeons': [ 0x002c, 0b0100 ], 'java': [ 'minecraft:brick_slab', { 'type': 'bottom' } ] }, 234 | { 'dungeons': [ 0x002c, 0b0101 ], 'java': [ 'minecraft:stone_brick_slab', { 'type': 'bottom' } ] }, 235 | { 'dungeons': [ 0x002c, 0b0110 ], 'java': [ 'minecraft:quartz_slab', { 'type': 'bottom' } ] }, 236 | { 'dungeons': [ 0x002c, 0b0111 ], 'java': [ 'minecraft:nether_brick_slab', { 'type': 'bottom' } ] }, 237 | { 'dungeons': [ 0x002c, 0b1000 ], 'java': [ 'minecraft:smooth_stone_slab', { 'type': 'top' } ] }, 238 | { 'dungeons': [ 0x002c, 0b1001 ], 'java': [ 'minecraft:sandstone_slab', { 'type': 'top' } ] }, 239 | { 'dungeons': [ 0x002c, 0b1010 ], 'java': [ 'minecraft:petrified_oak_slab', { 'type': 'top' } ] }, 240 | { 'dungeons': [ 0x002c, 0b1011 ], 'java': [ 'minecraft:cobblestone_slab', { 'type': 'top' } ] }, 241 | { 'dungeons': [ 0x002c, 0b1100 ], 'java': [ 'minecraft:brick_slab', { 'type': 'top' } ] }, 242 | { 'dungeons': [ 0x002c, 0b1101 ], 'java': [ 'minecraft:stone_brick_slab', { 'type': 'top' } ] }, 243 | { 'dungeons': [ 0x002c, 0b1110 ], 'java': [ 'minecraft:quartz_slab', { 'type': 'top' } ] }, 244 | { 'dungeons': [ 0x002c, 0b1111 ], 'java': [ 'minecraft:nether_brick_slab', { 'type': 'top' } ] }, 245 | { 'dungeons': [ 0x002d, 0b0000 ], 'java': [ 'minecraft:bricks' ] }, 246 | { 'dungeons': [ 0x002e, 0b0000 ], 'java': [ 'minecraft:tnt' ] }, 247 | { 'dungeons': [ 0x002f, 0b0000 ], 'java': [ 'minecraft:bookshelf' ] }, 248 | { 'dungeons': [ 0x0030, 0b0000 ], 'java': [ 'minecraft:mossy_cobblestone' ] }, 249 | { 'dungeons': [ 0x0031, 0b0000 ], 'java': [ 'minecraft:obsidian' ] }, 250 | { 'dungeons': [ 0x0032, 0b0001 ], 'java': [ 'minecraft:wall_torch', { 'facing': 'east' } ] }, 251 | { 'dungeons': [ 0x0032, 0b0010 ], 'java': [ 'minecraft:wall_torch', { 'facing': 'west' } ] }, 252 | { 'dungeons': [ 0x0032, 0b0011 ], 'java': [ 'minecraft:wall_torch', { 'facing': 'south' } ] }, 253 | { 'dungeons': [ 0x0032, 0b0100 ], 'java': [ 'minecraft:wall_torch', { 'facing': 'north' } ] }, 254 | { 'dungeons': [ 0x0032, 0b0101 ], 'java': [ 'minecraft:torch' ] }, 255 | { 'dungeons': [ 0x0033, 0b0000 ], 'java': [ 'minecraft:fire' ] }, 256 | { 'dungeons': [ 0x0034, 0b0000 ], 'java': [ 'minecraft:spawner' ] }, 257 | { 'dungeons': [ 0x0035, 0b0000 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 258 | { 'dungeons': [ 0x0035, 0b0001 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 259 | { 'dungeons': [ 0x0035, 0b0010 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 260 | { 'dungeons': [ 0x0035, 0b0011 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 261 | { 'dungeons': [ 0x0035, 0b0100 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'east', 'half': 'top' } ] }, 262 | { 'dungeons': [ 0x0035, 0b0101 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'west', 'half': 'top' } ] }, 263 | { 'dungeons': [ 0x0035, 0b0110 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'south', 'half': 'top' } ] }, 264 | { 'dungeons': [ 0x0035, 0b0111 ], 'java': [ 'minecraft:oak_stairs', { 'facing': 'north', 'half': 'top' } ] }, 265 | { 'dungeons': [ 0x0036, 0b0010 ], 'java': [ 'minecraft:chest', { 'facing': 'north' } ] }, 266 | { 'dungeons': [ 0x0036, 0b0011 ], 'java': [ 'minecraft:chest', { 'facing': 'south' } ] }, 267 | { 'dungeons': [ 0x0036, 0b0100 ], 'java': [ 'minecraft:chest', { 'facing': 'west' } ] }, 268 | { 'dungeons': [ 0x0036, 0b0101 ], 'java': [ 'minecraft:chest', { 'facing': 'east' } ] }, 269 | { 'dungeons': [ 0x0037, 0b0000 ], 'java': [ 'minecraft:redstone_wire', { 'power': '0' } ] }, 270 | { 'dungeons': [ 0x0037, 0b0001 ], 'java': [ 'minecraft:redstone_wire', { 'power': '1' } ] }, 271 | { 'dungeons': [ 0x0037, 0b0010 ], 'java': [ 'minecraft:redstone_wire', { 'power': '2' } ] }, 272 | { 'dungeons': [ 0x0037, 0b0011 ], 'java': [ 'minecraft:redstone_wire', { 'power': '3' } ] }, 273 | { 'dungeons': [ 0x0037, 0b0100 ], 'java': [ 'minecraft:redstone_wire', { 'power': '4' } ] }, 274 | { 'dungeons': [ 0x0037, 0b0101 ], 'java': [ 'minecraft:redstone_wire', { 'power': '5' } ] }, 275 | { 'dungeons': [ 0x0037, 0b0110 ], 'java': [ 'minecraft:redstone_wire', { 'power': '6' } ] }, 276 | { 'dungeons': [ 0x0037, 0b0111 ], 'java': [ 'minecraft:redstone_wire', { 'power': '7' } ] }, 277 | { 'dungeons': [ 0x0037, 0b1000 ], 'java': [ 'minecraft:redstone_wire', { 'power': '8' } ] }, 278 | { 'dungeons': [ 0x0037, 0b1001 ], 'java': [ 'minecraft:redstone_wire', { 'power': '9' } ] }, 279 | { 'dungeons': [ 0x0037, 0b1010 ], 'java': [ 'minecraft:redstone_wire', { 'power': '10' } ] }, 280 | { 'dungeons': [ 0x0037, 0b1011 ], 'java': [ 'minecraft:redstone_wire', { 'power': '11' } ] }, 281 | { 'dungeons': [ 0x0037, 0b1100 ], 'java': [ 'minecraft:redstone_wire', { 'power': '12' } ] }, 282 | { 'dungeons': [ 0x0037, 0b1101 ], 'java': [ 'minecraft:redstone_wire', { 'power': '13' } ] }, 283 | { 'dungeons': [ 0x0037, 0b1110 ], 'java': [ 'minecraft:redstone_wire', { 'power': '14' } ] }, 284 | { 'dungeons': [ 0x0037, 0b1111 ], 'java': [ 'minecraft:redstone_wire', { 'power': '15' } ] }, 285 | { 'dungeons': [ 0x0038, 0b0000 ], 'java': [ 'minecraft:diamond_ore' ] }, 286 | { 'dungeons': [ 0x0039, 0b0000 ], 'java': [ 'minecraft:diamond_block' ] }, 287 | { 'dungeons': [ 0x003a, 0b0000 ], 'java': [ 'minecraft:crafting_table' ] }, 288 | { 'dungeons': [ 0x003b, 0b0000 ], 'java': [ 'minecraft:wheat', { 'age': '0' } ] }, 289 | { 'dungeons': [ 0x003b, 0b0001 ], 'java': [ 'minecraft:wheat', { 'age': '1' } ] }, 290 | { 'dungeons': [ 0x003b, 0b0010 ], 'java': [ 'minecraft:wheat', { 'age': '2' } ] }, 291 | { 'dungeons': [ 0x003b, 0b0011 ], 'java': [ 'minecraft:wheat', { 'age': '3' } ] }, 292 | { 'dungeons': [ 0x003b, 0b0100 ], 'java': [ 'minecraft:wheat', { 'age': '4' } ] }, 293 | { 'dungeons': [ 0x003b, 0b0101 ], 'java': [ 'minecraft:wheat', { 'age': '5' } ] }, 294 | { 'dungeons': [ 0x003b, 0b0110 ], 'java': [ 'minecraft:wheat', { 'age': '6' } ] }, 295 | { 'dungeons': [ 0x003b, 0b0111 ], 'java': [ 'minecraft:wheat', { 'age': '7' } ] }, 296 | { 'dungeons': [ 0x003c, 0b0000 ], 'java': [ 'minecraft:farmland', { 'moisture': '0' } ] }, 297 | { 'dungeons': [ 0x003c, 0b0111 ], 'java': [ 'minecraft:farmland', { 'moisture': '7' } ] }, 298 | { 'dungeons': [ 0x003d, 0b0010 ], 'java': [ 'minecraft:furnace', { 'facing': 'north' } ] }, 299 | { 'dungeons': [ 0x003d, 0b0011 ], 'java': [ 'minecraft:furnace', { 'facing': 'south' } ] }, 300 | { 'dungeons': [ 0x003d, 0b0100 ], 'java': [ 'minecraft:furnace', { 'facing': 'west' } ] }, 301 | { 'dungeons': [ 0x003d, 0b0101 ], 'java': [ 'minecraft:furnace', { 'facing': 'east' } ] }, 302 | { 'dungeons': [ 0x003f, 0b0000 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '0' } ] }, 303 | { 'dungeons': [ 0x003f, 0b0001 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '1' } ] }, 304 | { 'dungeons': [ 0x003f, 0b0010 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '2' } ] }, 305 | { 'dungeons': [ 0x003f, 0b0011 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '3' } ] }, 306 | { 'dungeons': [ 0x003f, 0b0100 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '4' } ] }, 307 | { 'dungeons': [ 0x003f, 0b0101 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '5' } ] }, 308 | { 'dungeons': [ 0x003f, 0b0110 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '6' } ] }, 309 | { 'dungeons': [ 0x003f, 0b0111 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '7' } ] }, 310 | { 'dungeons': [ 0x003f, 0b1000 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '8' } ] }, 311 | { 'dungeons': [ 0x003f, 0b1001 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '9' } ] }, 312 | { 'dungeons': [ 0x003f, 0b1010 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '10' } ] }, 313 | { 'dungeons': [ 0x003f, 0b1011 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '11' } ] }, 314 | { 'dungeons': [ 0x003f, 0b1100 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '12' } ] }, 315 | { 'dungeons': [ 0x003f, 0b1101 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '13' } ] }, 316 | { 'dungeons': [ 0x003f, 0b1110 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '14' } ] }, 317 | { 'dungeons': [ 0x003f, 0b1111 ], 'java': [ 'minecraft:oak_sign', { 'rotation': '15' } ] }, 318 | { 'dungeons': [ 0x0040, 0b0000 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'east' } ] }, 319 | { 'dungeons': [ 0x0040, 0b0001 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'south' } ] }, 320 | { 'dungeons': [ 0x0040, 0b0010 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'west' } ] }, 321 | { 'dungeons': [ 0x0040, 0b0011 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'north' } ] }, 322 | { 'dungeons': [ 0x0040, 0b0100 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'east' } ] }, 323 | { 'dungeons': [ 0x0040, 0b0101 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'south' } ] }, 324 | { 'dungeons': [ 0x0040, 0b0110 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'west' } ] }, 325 | { 'dungeons': [ 0x0040, 0b0111 ], 'java': [ 'minecraft:oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'north' } ] }, 326 | { 'dungeons': [ 0x0040, 0b1000 ], 'java': [ 'minecraft:oak_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'left' } ] }, 327 | { 'dungeons': [ 0x0040, 0b1001 ], 'java': [ 'minecraft:oak_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'right' } ] }, 328 | { 'dungeons': [ 0x0040, 0b1010 ], 'java': [ 'minecraft:oak_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'left' } ] }, 329 | { 'dungeons': [ 0x0040, 0b1011 ], 'java': [ 'minecraft:oak_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'right' } ] }, 330 | { 'dungeons': [ 0x0041, 0b0010, 0b0111 ], 'java': [ 'minecraft:ladder', { 'facing': 'north' } ] }, 331 | { 'dungeons': [ 0x0041, 0b0011, 0b0111 ], 'java': [ 'minecraft:ladder', { 'facing': 'south' } ] }, 332 | { 'dungeons': [ 0x0041, 0b0100, 0b0111 ], 'java': [ 'minecraft:ladder', { 'facing': 'west' } ] }, 333 | { 'dungeons': [ 0x0041, 0b0101, 0b0111 ], 'java': [ 'minecraft:ladder', { 'facing': 'east' } ] }, 334 | { 'dungeons': [ 0x0042, 0b0000 ], 'java': [ 'minecraft:rail', { 'shape': 'north_south' } ] }, 335 | { 'dungeons': [ 0x0042, 0b0001 ], 'java': [ 'minecraft:rail', { 'shape': 'east_west' } ] }, 336 | { 'dungeons': [ 0x0042, 0b0010 ], 'java': [ 'minecraft:rail', { 'shape': 'ascending_east' } ] }, 337 | { 'dungeons': [ 0x0042, 0b0011 ], 'java': [ 'minecraft:rail', { 'shape': 'ascending_west' } ] }, 338 | { 'dungeons': [ 0x0042, 0b0100 ], 'java': [ 'minecraft:rail', { 'shape': 'ascending_north' } ] }, 339 | { 'dungeons': [ 0x0042, 0b0101 ], 'java': [ 'minecraft:rail', { 'shape': 'ascending_south' } ] }, 340 | { 'dungeons': [ 0x0042, 0b0110 ], 'java': [ 'minecraft:rail', { 'shape': 'south_east' } ] }, 341 | { 'dungeons': [ 0x0042, 0b0111 ], 'java': [ 'minecraft:rail', { 'shape': 'south_west' } ] }, 342 | { 'dungeons': [ 0x0042, 0b1000 ], 'java': [ 'minecraft:rail', { 'shape': 'north_west' } ] }, 343 | { 'dungeons': [ 0x0042, 0b1001 ], 'java': [ 'minecraft:rail', { 'shape': 'north_east' } ] }, 344 | { 'dungeons': [ 0x0043, 0b0000 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 345 | { 'dungeons': [ 0x0043, 0b0001 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 346 | { 'dungeons': [ 0x0043, 0b0010 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 347 | { 'dungeons': [ 0x0043, 0b0011 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 348 | { 'dungeons': [ 0x0043, 0b0100 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'east', 'half': 'top' } ] }, 349 | { 'dungeons': [ 0x0043, 0b0101 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'west', 'half': 'top' } ] }, 350 | { 'dungeons': [ 0x0043, 0b0110 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'south', 'half': 'top' } ] }, 351 | { 'dungeons': [ 0x0043, 0b0111 ], 'java': [ 'minecraft:cobblestone_stairs', { 'facing': 'north', 'half': 'top' } ] }, 352 | { 'dungeons': [ 0x0044, 0b0010 ], 'java': [ 'minecraft:oak_wall_sign', { 'facing': 'north' } ] }, 353 | { 'dungeons': [ 0x0044, 0b0011 ], 'java': [ 'minecraft:oak_wall_sign', { 'facing': 'south' } ] }, 354 | { 'dungeons': [ 0x0044, 0b0100 ], 'java': [ 'minecraft:oak_wall_sign', { 'facing': 'west' } ] }, 355 | { 'dungeons': [ 0x0044, 0b0101 ], 'java': [ 'minecraft:oak_wall_sign', { 'facing': 'east' } ] }, 356 | { 'dungeons': [ 0x0046, 0b0000 ], 'java': [ 'minecraft:stone_pressure_plate', { 'powered': 'false' } ] }, 357 | { 'dungeons': [ 0x0046, 0b0001 ], 'java': [ 'minecraft:stone_pressure_plate', { 'powered': 'true' } ] }, 358 | { 'dungeons': [ 0x0049, 0b0000 ], 'java': [ 'minecraft:redstone_ore', { 'lit': 'false' } ] }, 359 | { 'dungeons': [ 0x004a, 0b0000 ], 'java': [ 'minecraft:redstone_ore', { 'lit': 'true' } ] }, 360 | { 'dungeons': [ 0x004e, 0b0000, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '1' } ] }, 361 | { 'dungeons': [ 0x004e, 0b0001, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '2' } ] }, 362 | { 'dungeons': [ 0x004e, 0b0010, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '3' } ] }, 363 | { 'dungeons': [ 0x004e, 0b0011, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '4' } ] }, 364 | { 'dungeons': [ 0x004e, 0b0100, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '5' } ] }, 365 | { 'dungeons': [ 0x004e, 0b0101, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '6' } ] }, 366 | { 'dungeons': [ 0x004e, 0b0110, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '7' } ] }, 367 | { 'dungeons': [ 0x004e, 0b0111, 0b0111 ], 'java': [ 'minecraft:snow', { 'layers': '8' } ] }, 368 | { 'dungeons': [ 0x004b, 0b0001 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'false', 'facing': 'east' } ] }, 369 | { 'dungeons': [ 0x004b, 0b0010 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'false', 'facing': 'west' } ] }, 370 | { 'dungeons': [ 0x004b, 0b0011 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'false', 'facing': 'south' } ] }, 371 | { 'dungeons': [ 0x004b, 0b0100 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'false', 'facing': 'north' } ] }, 372 | { 'dungeons': [ 0x004b, 0b0101 ], 'java': [ 'minecraft:redstone_torch', { 'lit': 'false' } ] }, 373 | { 'dungeons': [ 0x004c, 0b0001 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'true', 'facing': 'east' } ] }, 374 | { 'dungeons': [ 0x004c, 0b0010 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'true', 'facing': 'west' } ] }, 375 | { 'dungeons': [ 0x004c, 0b0011 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'true', 'facing': 'south' } ] }, 376 | { 'dungeons': [ 0x004c, 0b0100 ], 'java': [ 'minecraft:redstone_wall_torch', { 'lit': 'true', 'facing': 'north' } ] }, 377 | { 'dungeons': [ 0x004c, 0b0101 ], 'java': [ 'minecraft:redstone_torch', { 'lit': 'true' } ] }, 378 | { 'dungeons': [ 0x004d, 0b0000 ], 'java': [ 'minecraft:stone_button', { 'face': 'ceiling' } ] }, 379 | { 'dungeons': [ 0x004d, 0b0001 ], 'java': [ 'minecraft:stone_button', { 'face': 'floor' } ] }, 380 | { 'dungeons': [ 0x004d, 0b0010 ], 'java': [ 'minecraft:stone_button', { 'face': 'wall', 'facing': 'north' } ] }, 381 | { 'dungeons': [ 0x004d, 0b0011 ], 'java': [ 'minecraft:stone_button', { 'face': 'wall', 'facing': 'south' } ] }, 382 | { 'dungeons': [ 0x004d, 0b0100 ], 'java': [ 'minecraft:stone_button', { 'face': 'wall', 'facing': 'west' } ] }, 383 | { 'dungeons': [ 0x004d, 0b0101 ], 'java': [ 'minecraft:stone_button', { 'face': 'wall', 'facing': 'east' } ] }, 384 | { 'dungeons': [ 0x004f, 0b0000 ], 'java': [ 'minecraft:ice' ] }, 385 | { 'dungeons': [ 0x0050, 0b0000 ], 'java': [ 'minecraft:snow_block' ] }, 386 | { 'dungeons': [ 0x0051, 0b0000 ], 'java': [ 'minecraft:cactus', { 'age': '0' } ] }, 387 | { 'dungeons': [ 0x0051, 0b0001 ], 'java': [ 'minecraft:cactus', { 'age': '1' } ] }, 388 | { 'dungeons': [ 0x0051, 0b0010 ], 'java': [ 'minecraft:cactus', { 'age': '2' } ] }, 389 | { 'dungeons': [ 0x0051, 0b0011 ], 'java': [ 'minecraft:cactus', { 'age': '3' } ] }, 390 | { 'dungeons': [ 0x0051, 0b0100 ], 'java': [ 'minecraft:cactus', { 'age': '4' } ] }, 391 | { 'dungeons': [ 0x0051, 0b0101 ], 'java': [ 'minecraft:cactus', { 'age': '5' } ] }, 392 | { 'dungeons': [ 0x0051, 0b0110 ], 'java': [ 'minecraft:cactus', { 'age': '6' } ] }, 393 | { 'dungeons': [ 0x0051, 0b0111 ], 'java': [ 'minecraft:cactus', { 'age': '7' } ] }, 394 | { 'dungeons': [ 0x0051, 0b1000 ], 'java': [ 'minecraft:cactus', { 'age': '8' } ] }, 395 | { 'dungeons': [ 0x0051, 0b1001 ], 'java': [ 'minecraft:cactus', { 'age': '9' } ] }, 396 | { 'dungeons': [ 0x0051, 0b1010 ], 'java': [ 'minecraft:cactus', { 'age': '10' } ] }, 397 | { 'dungeons': [ 0x0051, 0b1011 ], 'java': [ 'minecraft:cactus', { 'age': '11' } ] }, 398 | { 'dungeons': [ 0x0051, 0b1100 ], 'java': [ 'minecraft:cactus', { 'age': '12' } ] }, 399 | { 'dungeons': [ 0x0051, 0b1101 ], 'java': [ 'minecraft:cactus', { 'age': '13' } ] }, 400 | { 'dungeons': [ 0x0051, 0b1110 ], 'java': [ 'minecraft:cactus', { 'age': '14' } ] }, 401 | { 'dungeons': [ 0x0051, 0b1111 ], 'java': [ 'minecraft:cactus', { 'age': '15' } ] }, 402 | { 'dungeons': [ 0x0052, 0b0000 ], 'java': [ 'minecraft:clay' ] }, 403 | { 'dungeons': [ 0x0053, 0b0000 ], 'java': [ 'minecraft:sugar_cane', { 'age': '0' } ] }, 404 | { 'dungeons': [ 0x0053, 0b0001 ], 'java': [ 'minecraft:sugar_cane', { 'age': '1' } ] }, 405 | { 'dungeons': [ 0x0053, 0b0010 ], 'java': [ 'minecraft:sugar_cane', { 'age': '2' } ] }, 406 | { 'dungeons': [ 0x0053, 0b0011 ], 'java': [ 'minecraft:sugar_cane', { 'age': '3' } ] }, 407 | { 'dungeons': [ 0x0053, 0b0100 ], 'java': [ 'minecraft:sugar_cane', { 'age': '4' } ] }, 408 | { 'dungeons': [ 0x0053, 0b0101 ], 'java': [ 'minecraft:sugar_cane', { 'age': '5' } ] }, 409 | { 'dungeons': [ 0x0053, 0b0110 ], 'java': [ 'minecraft:sugar_cane', { 'age': '6' } ] }, 410 | { 'dungeons': [ 0x0053, 0b0111 ], 'java': [ 'minecraft:sugar_cane', { 'age': '7' } ] }, 411 | { 'dungeons': [ 0x0053, 0b1000 ], 'java': [ 'minecraft:sugar_cane', { 'age': '8' } ] }, 412 | { 'dungeons': [ 0x0053, 0b1001 ], 'java': [ 'minecraft:sugar_cane', { 'age': '9' } ] }, 413 | { 'dungeons': [ 0x0053, 0b1010 ], 'java': [ 'minecraft:sugar_cane', { 'age': '10' } ] }, 414 | { 'dungeons': [ 0x0053, 0b1011 ], 'java': [ 'minecraft:sugar_cane', { 'age': '11' } ] }, 415 | { 'dungeons': [ 0x0053, 0b1100 ], 'java': [ 'minecraft:sugar_cane', { 'age': '12' } ] }, 416 | { 'dungeons': [ 0x0053, 0b1101 ], 'java': [ 'minecraft:sugar_cane', { 'age': '13' } ] }, 417 | { 'dungeons': [ 0x0053, 0b1110 ], 'java': [ 'minecraft:sugar_cane', { 'age': '14' } ] }, 418 | { 'dungeons': [ 0x0053, 0b1111 ], 'java': [ 'minecraft:sugar_cane', { 'age': '15' } ] }, 419 | { 'dungeons': [ 0x0055, 0b0000 ], 'java': [ 'minecraft:oak_fence' ] }, 420 | { 'dungeons': [ 0x0055, 0b0001 ], 'java': [ 'minecraft:spruce_fence' ] }, 421 | { 'dungeons': [ 0x0055, 0b0010 ], 'java': [ 'minecraft:birch_fence' ] }, 422 | { 'dungeons': [ 0x0055, 0b0011 ], 'java': [ 'minecraft:jungle_fence' ] }, 423 | { 'dungeons': [ 0x0055, 0b0100 ], 'java': [ 'minecraft:acacia_fence' ] }, 424 | { 'dungeons': [ 0x0055, 0b0101 ], 'java': [ 'minecraft:dark_oak_fence' ] }, 425 | { 'dungeons': [ 0x0056, 0b0000 ], 'java': [ 'minecraft:carved_pumpkin', { 'facing': 'east' } ] }, 426 | { 'dungeons': [ 0x0056, 0b0001 ], 'java': [ 'minecraft:carved_pumpkin', { 'facing': 'west' } ] }, 427 | { 'dungeons': [ 0x0056, 0b0010 ], 'java': [ 'minecraft:carved_pumpkin', { 'facing': 'north' } ] }, 428 | { 'dungeons': [ 0x0056, 0b0011 ], 'java': [ 'minecraft:carved_pumpkin', { 'facing': 'south' } ] }, 429 | { 'dungeons': [ 0x0057, 0b0000 ], 'java': [ 'minecraft:netherrack' ] }, 430 | { 'dungeons': [ 0x0058, 0b0000 ], 'java': [ 'minecraft:soul_sand' ] }, 431 | { 'dungeons': [ 0x0059, 0b0000 ], 'java': [ 'minecraft:glowstone' ] }, 432 | { 'dungeons': [ 0x005b, 0b0000 ], 'java': [ 'minecraft:jack_o_lantern', { 'facing': 'south' } ] }, 433 | { 'dungeons': [ 0x005b, 0b0001 ], 'java': [ 'minecraft:jack_o_lantern', { 'facing': 'west' } ] }, 434 | { 'dungeons': [ 0x005b, 0b0010 ], 'java': [ 'minecraft:jack_o_lantern', { 'facing': 'north' } ] }, 435 | { 'dungeons': [ 0x005b, 0b0011 ], 'java': [ 'minecraft:jack_o_lantern', { 'facing': 'east' } ] }, 436 | { 'dungeons': [ 0x005d, 0b0000 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '1', 'powered': 'false' } ] }, 437 | { 'dungeons': [ 0x005d, 0b0001 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '1', 'powered': 'false' } ] }, 438 | { 'dungeons': [ 0x005d, 0b0010 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '1', 'powered': 'false' } ] }, 439 | { 'dungeons': [ 0x005d, 0b0011 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '1', 'powered': 'false' } ] }, 440 | { 'dungeons': [ 0x005d, 0b0100 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '2', 'powered': 'false' } ] }, 441 | { 'dungeons': [ 0x005d, 0b0101 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '2', 'powered': 'false' } ] }, 442 | { 'dungeons': [ 0x005d, 0b0110 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '2', 'powered': 'false' } ] }, 443 | { 'dungeons': [ 0x005d, 0b0111 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '2', 'powered': 'false' } ] }, 444 | { 'dungeons': [ 0x005d, 0b1000 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '3', 'powered': 'false' } ] }, 445 | { 'dungeons': [ 0x005d, 0b1001 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '3', 'powered': 'false' } ] }, 446 | { 'dungeons': [ 0x005d, 0b1010 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '3', 'powered': 'false' } ] }, 447 | { 'dungeons': [ 0x005d, 0b1011 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '3', 'powered': 'false' } ] }, 448 | { 'dungeons': [ 0x005d, 0b1100 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '4', 'powered': 'false' } ] }, 449 | { 'dungeons': [ 0x005d, 0b1101 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '4', 'powered': 'false' } ] }, 450 | { 'dungeons': [ 0x005d, 0b1110 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '4', 'powered': 'false' } ] }, 451 | { 'dungeons': [ 0x005d, 0b1111 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '4', 'powered': 'false' } ] }, 452 | { 'dungeons': [ 0x005e, 0b0000 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '1', 'powered': 'true' } ] }, 453 | { 'dungeons': [ 0x005e, 0b0001 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '1', 'powered': 'true' } ] }, 454 | { 'dungeons': [ 0x005e, 0b0010 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '1', 'powered': 'true' } ] }, 455 | { 'dungeons': [ 0x005e, 0b0011 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '1', 'powered': 'true' } ] }, 456 | { 'dungeons': [ 0x005e, 0b0100 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '2', 'powered': 'true' } ] }, 457 | { 'dungeons': [ 0x005e, 0b0101 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '2', 'powered': 'true' } ] }, 458 | { 'dungeons': [ 0x005e, 0b0110 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '2', 'powered': 'true' } ] }, 459 | { 'dungeons': [ 0x005e, 0b0111 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '2', 'powered': 'true' } ] }, 460 | { 'dungeons': [ 0x005e, 0b1000 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '3', 'powered': 'true' } ] }, 461 | { 'dungeons': [ 0x005e, 0b1001 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '3', 'powered': 'true' } ] }, 462 | { 'dungeons': [ 0x005e, 0b1010 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '3', 'powered': 'true' } ] }, 463 | { 'dungeons': [ 0x005e, 0b1011 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '3', 'powered': 'true' } ] }, 464 | { 'dungeons': [ 0x005e, 0b1100 ], 'java': [ 'minecraft:repeater', { 'facing': 'north', 'delay': '4', 'powered': 'true' } ] }, 465 | { 'dungeons': [ 0x005e, 0b1101 ], 'java': [ 'minecraft:repeater', { 'facing': 'east', 'delay': '4', 'powered': 'true' } ] }, 466 | { 'dungeons': [ 0x005e, 0b1110 ], 'java': [ 'minecraft:repeater', { 'facing': 'south', 'delay': '4', 'powered': 'true' } ] }, 467 | { 'dungeons': [ 0x005e, 0b1111 ], 'java': [ 'minecraft:repeater', { 'facing': 'west', 'delay': '4', 'powered': 'true' } ] }, 468 | { 'dungeons': [ 0x0060, 0b0000 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'east' } ] }, 469 | { 'dungeons': [ 0x0060, 0b0001 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'west' } ] }, 470 | { 'dungeons': [ 0x0060, 0b0010 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'south' } ] }, 471 | { 'dungeons': [ 0x0060, 0b0011 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'north' } ] }, 472 | { 'dungeons': [ 0x0060, 0b0100 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'east' } ] }, 473 | { 'dungeons': [ 0x0060, 0b0101 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'west' } ] }, 474 | { 'dungeons': [ 0x0060, 0b0110 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'south' } ] }, 475 | { 'dungeons': [ 0x0060, 0b0111 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'north' } ] }, 476 | { 'dungeons': [ 0x0060, 0b1000 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'east' } ] }, 477 | { 'dungeons': [ 0x0060, 0b1001 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'west' } ] }, 478 | { 'dungeons': [ 0x0060, 0b1010 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'south' } ] }, 479 | { 'dungeons': [ 0x0060, 0b1011 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'north' } ] }, 480 | { 'dungeons': [ 0x0060, 0b1100 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'east' } ] }, 481 | { 'dungeons': [ 0x0060, 0b1101 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'west' } ] }, 482 | { 'dungeons': [ 0x0060, 0b1110 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'south' } ] }, 483 | { 'dungeons': [ 0x0060, 0b1111 ], 'java': [ 'minecraft:oak_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'north' } ] }, 484 | { 'dungeons': [ 0x0062, 0b0000 ], 'java': [ 'minecraft:stone_bricks' ] }, 485 | { 'dungeons': [ 0x0062, 0b0001 ], 'java': [ 'minecraft:mossy_stone_bricks' ] }, 486 | { 'dungeons': [ 0x0062, 0b0010 ], 'java': [ 'minecraft:cracked_stone_bricks' ] }, 487 | { 'dungeons': [ 0x0062, 0b0011 ], 'java': [ 'minecraft:chiseled_stone_bricks' ] }, 488 | { 'dungeons': [ 0x0062, 0b0100 ], 'java': [ 'minecraft:netherite_block' ] }, 489 | { 'dungeons': [ 0x0063, 0b0000 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 490 | { 'dungeons': [ 0x0063, 0b0001 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 491 | { 'dungeons': [ 0x0063, 0b0010 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 492 | { 'dungeons': [ 0x0063, 0b0011 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 493 | { 'dungeons': [ 0x0063, 0b0100 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 494 | { 'dungeons': [ 0x0063, 0b0101 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 495 | { 'dungeons': [ 0x0063, 0b0110 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 496 | { 'dungeons': [ 0x0063, 0b0111 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 497 | { 'dungeons': [ 0x0063, 0b1000 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'true', 'up': 'true', 'down': 'false' } ] }, 498 | { 'dungeons': [ 0x0063, 0b1001 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'false', 'south': 'true', 'up': 'true', 'down': 'false' } ] }, 499 | { 'dungeons': [ 0x0063, 0b1010 ], 'java': [ 'minecraft:mushroom_stem', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'false', 'down': 'false' } ] }, 500 | { 'dungeons': [ 0x0063, 0b1011 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 501 | { 'dungeons': [ 0x0063, 0b1100 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 502 | { 'dungeons': [ 0x0063, 0b1101 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 503 | { 'dungeons': [ 0x0063, 0b1110 ], 'java': [ 'minecraft:brown_mushroom_block', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'true', 'down': 'true' } ] }, 504 | { 'dungeons': [ 0x0063, 0b1111 ], 'java': [ 'minecraft:mushroom_stem', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'true', 'down': 'true' } ] }, 505 | { 'dungeons': [ 0x0064, 0b0000 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 506 | { 'dungeons': [ 0x0064, 0b0001 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 507 | { 'dungeons': [ 0x0064, 0b0010 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 508 | { 'dungeons': [ 0x0064, 0b0011 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'true', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 509 | { 'dungeons': [ 0x0064, 0b0100 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 510 | { 'dungeons': [ 0x0064, 0b0101 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 511 | { 'dungeons': [ 0x0064, 0b0110 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 512 | { 'dungeons': [ 0x0064, 0b0111 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'true', 'north': 'false', 'south': 'false', 'up': 'true', 'down': 'false' } ] }, 513 | { 'dungeons': [ 0x0064, 0b1000 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'true', 'up': 'true', 'down': 'false' } ] }, 514 | { 'dungeons': [ 0x0064, 0b1001 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'true', 'west': 'false', 'north': 'false', 'south': 'true', 'up': 'true', 'down': 'false' } ] }, 515 | { 'dungeons': [ 0x0064, 0b1010 ], 'java': [ 'minecraft:mushroom_stem', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'false', 'down': 'false' } ] }, 516 | { 'dungeons': [ 0x0064, 0b1011 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 517 | { 'dungeons': [ 0x0064, 0b1100 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 518 | { 'dungeons': [ 0x0064, 0b1101 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'false', 'west': 'false', 'north': 'false', 'south': 'false', 'up': 'false', 'down': 'false' } ] }, 519 | { 'dungeons': [ 0x0064, 0b1110 ], 'java': [ 'minecraft:red_mushroom_block', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'true', 'down': 'true' } ] }, 520 | { 'dungeons': [ 0x0064, 0b1111 ], 'java': [ 'minecraft:mushroom_stem', { 'east': 'true', 'west': 'true', 'north': 'true', 'south': 'true', 'up': 'true', 'down': 'true' } ] }, 521 | { 'dungeons': [ 0x0065, 0b0000 ], 'java': [ 'minecraft:iron_bars' ] }, 522 | { 'dungeons': [ 0x0066, 0b0000 ], 'java': [ 'minecraft:glass_pane' ] }, 523 | { 'dungeons': [ 0x0067, 0b0000 ], 'java': [ 'minecraft:melon' ] }, 524 | { 'dungeons': [ 0x0068, 0b0000 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '0' } ] }, 525 | { 'dungeons': [ 0x0068, 0b0001 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '1' } ] }, 526 | { 'dungeons': [ 0x0068, 0b0010 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '2' } ] }, 527 | { 'dungeons': [ 0x0068, 0b0011 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '3' } ] }, 528 | { 'dungeons': [ 0x0068, 0b0100 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '4' } ] }, 529 | { 'dungeons': [ 0x0068, 0b0101 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '5' } ] }, 530 | { 'dungeons': [ 0x0068, 0b0110 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '6' } ] }, 531 | { 'dungeons': [ 0x0068, 0b0111 ], 'java': [ 'minecraft:pumpkin_stem', { 'age': '7' } ] }, 532 | { 'dungeons': [ 0x0069, 0b0000 ], 'java': [ 'minecraft:melon_stem', { 'age': '0' } ] }, 533 | { 'dungeons': [ 0x0069, 0b0001 ], 'java': [ 'minecraft:melon_stem', { 'age': '1' } ] }, 534 | { 'dungeons': [ 0x0069, 0b0010 ], 'java': [ 'minecraft:melon_stem', { 'age': '2' } ] }, 535 | { 'dungeons': [ 0x0069, 0b0011 ], 'java': [ 'minecraft:melon_stem', { 'age': '3' } ] }, 536 | { 'dungeons': [ 0x0069, 0b0100 ], 'java': [ 'minecraft:melon_stem', { 'age': '4' } ] }, 537 | { 'dungeons': [ 0x0069, 0b0101 ], 'java': [ 'minecraft:melon_stem', { 'age': '5' } ] }, 538 | { 'dungeons': [ 0x0069, 0b0110 ], 'java': [ 'minecraft:melon_stem', { 'age': '6' } ] }, 539 | { 'dungeons': [ 0x0069, 0b0111 ], 'java': [ 'minecraft:melon_stem', { 'age': '7' } ] }, 540 | { 'dungeons': [ 0x006a, 0b0000 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'false', 'west': 'false', 'south': 'false' } ] }, 541 | { 'dungeons': [ 0x006a, 0b0001 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'false', 'west': 'false', 'south': 'true' } ] }, 542 | { 'dungeons': [ 0x006a, 0b0010 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'false', 'west': 'true', 'south': 'false' } ] }, 543 | { 'dungeons': [ 0x006a, 0b0011 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'false', 'west': 'true', 'south': 'true' } ] }, 544 | { 'dungeons': [ 0x006a, 0b0100 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'true', 'west': 'false', 'south': 'false' } ] }, 545 | { 'dungeons': [ 0x006a, 0b0101 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'true', 'west': 'false', 'south': 'true' } ] }, 546 | { 'dungeons': [ 0x006a, 0b0110 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'true', 'west': 'true', 'south': 'false' } ] }, 547 | { 'dungeons': [ 0x006a, 0b0111 ], 'java': [ 'minecraft:vine', { 'east': 'false', 'north': 'true', 'west': 'true', 'south': 'true' } ] }, 548 | { 'dungeons': [ 0x006a, 0b1000 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'false', 'west': 'false', 'south': 'false' } ] }, 549 | { 'dungeons': [ 0x006a, 0b1001 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'false', 'west': 'false', 'south': 'true' } ] }, 550 | { 'dungeons': [ 0x006a, 0b1010 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'false', 'west': 'true', 'south': 'false' } ] }, 551 | { 'dungeons': [ 0x006a, 0b1011 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'false', 'west': 'true', 'south': 'true' } ] }, 552 | { 'dungeons': [ 0x006a, 0b1100 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'true', 'west': 'false', 'south': 'false' } ] }, 553 | { 'dungeons': [ 0x006a, 0b1101 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'true', 'west': 'false', 'south': 'true' } ] }, 554 | { 'dungeons': [ 0x006a, 0b1110 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'true', 'west': 'true', 'south': 'false' } ] }, 555 | { 'dungeons': [ 0x006a, 0b1111 ], 'java': [ 'minecraft:vine', { 'east': 'true', 'north': 'true', 'west': 'true', 'south': 'true' } ] }, 556 | { 'dungeons': [ 0x006c, 0b0000 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 557 | { 'dungeons': [ 0x006c, 0b0001 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 558 | { 'dungeons': [ 0x006c, 0b0010 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 559 | { 'dungeons': [ 0x006c, 0b0011 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 560 | { 'dungeons': [ 0x006c, 0b0100 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'east', 'half': 'top' } ] }, 561 | { 'dungeons': [ 0x006c, 0b0101 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'west', 'half': 'top' } ] }, 562 | { 'dungeons': [ 0x006c, 0b0110 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'south', 'half': 'top' } ] }, 563 | { 'dungeons': [ 0x006c, 0b0111 ], 'java': [ 'minecraft:brick_stairs', { 'facing': 'north', 'half': 'top' } ] }, 564 | { 'dungeons': [ 0x006d, 0b0000 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 565 | { 'dungeons': [ 0x006d, 0b0001 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 566 | { 'dungeons': [ 0x006d, 0b0010 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 567 | { 'dungeons': [ 0x006d, 0b0011 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 568 | { 'dungeons': [ 0x006d, 0b0100 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'east', 'half': 'top' } ] }, 569 | { 'dungeons': [ 0x006d, 0b0101 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'west', 'half': 'top' } ] }, 570 | { 'dungeons': [ 0x006d, 0b0110 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'south', 'half': 'top' } ] }, 571 | { 'dungeons': [ 0x006d, 0b0111 ], 'java': [ 'minecraft:stone_brick_stairs', { 'facing': 'north', 'half': 'top' } ] }, 572 | { 'dungeons': [ 0x006e, 0b0000 ], 'java': [ 'minecraft:podzol' ] }, # Out of bounds grass 573 | { 'dungeons': [ 0x006f, 0b0000 ], 'java': [ 'minecraft:lily_pad' ] }, 574 | { 'dungeons': [ 0x0070, 0b0000 ], 'java': [ 'minecraft:nether_bricks' ] }, 575 | { 'dungeons': [ 0x0071, 0b0000 ], 'java': [ 'minecraft:nether_brick_fence' ] }, 576 | { 'dungeons': [ 0x0072, 0b0000 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 577 | { 'dungeons': [ 0x0072, 0b0001 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 578 | { 'dungeons': [ 0x0072, 0b0010 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 579 | { 'dungeons': [ 0x0072, 0b0011 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 580 | { 'dungeons': [ 0x0072, 0b0100 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'east', 'half': 'top' } ] }, 581 | { 'dungeons': [ 0x0072, 0b0101 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'west', 'half': 'top' } ] }, 582 | { 'dungeons': [ 0x0072, 0b0110 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'south', 'half': 'top' } ] }, 583 | { 'dungeons': [ 0x0072, 0b0111 ], 'java': [ 'minecraft:nether_brick_stairs', { 'facing': 'north', 'half': 'top' } ] }, 584 | { 'dungeons': [ 0x0074, 0b0000 ], 'java': [ 'minecraft:enchanting_table' ] }, 585 | { 'dungeons': [ 0x0075, 0b0000 ], 'java': [ 'minecraft:brewing_stand' ] }, 586 | { 'dungeons': [ 0x0076, 0b0000 ], 'java': [ 'minecraft:cauldron', { 'level': '0' } ] }, 587 | { 'dungeons': [ 0x0076, 0b0001 ], 'java': [ 'minecraft:cauldron', { 'level': '0' } ] }, 588 | { 'dungeons': [ 0x0076, 0b0010 ], 'java': [ 'minecraft:cauldron', { 'level': '1' } ] }, 589 | { 'dungeons': [ 0x0076, 0b0011 ], 'java': [ 'minecraft:cauldron', { 'level': '1' } ] }, 590 | { 'dungeons': [ 0x0076, 0b0100 ], 'java': [ 'minecraft:cauldron', { 'level': '2' } ] }, 591 | { 'dungeons': [ 0x0076, 0b0101 ], 'java': [ 'minecraft:cauldron', { 'level': '2' } ] }, 592 | { 'dungeons': [ 0x0076, 0b0110 ], 'java': [ 'minecraft:cauldron', { 'level': '3' } ] }, 593 | { 'dungeons': [ 0x0078, 0b0000 ], 'java': [ 'minecraft:end_portal_frame' ] }, 594 | { 'dungeons': [ 0x007b, 0b0000 ], 'java': [ 'minecraft:redstone_lamp' ] }, 595 | { 'dungeons': [ 0x007d, 0b0000 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'down' } ] }, 596 | { 'dungeons': [ 0x007d, 0b0001 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'up' } ] }, 597 | { 'dungeons': [ 0x007d, 0b0010 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'north' } ] }, 598 | { 'dungeons': [ 0x007d, 0b0011 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'south' } ] }, 599 | { 'dungeons': [ 0x007d, 0b0100 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'west' } ] }, 600 | { 'dungeons': [ 0x007d, 0b0101 ], 'java': [ 'minecraft:dropper', { 'triggered': 'false', 'facing': 'east' } ] }, 601 | { 'dungeons': [ 0x007d, 0b1000 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'down' } ] }, 602 | { 'dungeons': [ 0x007d, 0b1001 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'up' } ] }, 603 | { 'dungeons': [ 0x007d, 0b1010 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'north' } ] }, 604 | { 'dungeons': [ 0x007d, 0b1011 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'south' } ] }, 605 | { 'dungeons': [ 0x007d, 0b1100 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'west' } ] }, 606 | { 'dungeons': [ 0x007d, 0b1101 ], 'java': [ 'minecraft:dropper', { 'triggered': 'true', 'facing': 'east' } ] }, 607 | { 'dungeons': [ 0x007f, 0b0000 ], 'java': [ 'minecraft:cocoa', { 'age': '0', 'facing': 'north' } ] }, 608 | { 'dungeons': [ 0x007f, 0b0001 ], 'java': [ 'minecraft:cocoa', { 'age': '0', 'facing': 'east' } ] }, 609 | { 'dungeons': [ 0x007f, 0b0010 ], 'java': [ 'minecraft:cocoa', { 'age': '0', 'facing': 'south' } ] }, 610 | { 'dungeons': [ 0x007f, 0b0011 ], 'java': [ 'minecraft:cocoa', { 'age': '0', 'facing': 'west' } ] }, 611 | { 'dungeons': [ 0x007f, 0b0100 ], 'java': [ 'minecraft:cocoa', { 'age': '1', 'facing': 'north' } ] }, 612 | { 'dungeons': [ 0x007f, 0b0101 ], 'java': [ 'minecraft:cocoa', { 'age': '1', 'facing': 'east' } ] }, 613 | { 'dungeons': [ 0x007f, 0b0110 ], 'java': [ 'minecraft:cocoa', { 'age': '1', 'facing': 'south' } ] }, 614 | { 'dungeons': [ 0x007f, 0b0111 ], 'java': [ 'minecraft:cocoa', { 'age': '1', 'facing': 'west' } ] }, 615 | { 'dungeons': [ 0x007f, 0b1000 ], 'java': [ 'minecraft:cocoa', { 'age': '2', 'facing': 'north' } ] }, 616 | { 'dungeons': [ 0x007f, 0b1001 ], 'java': [ 'minecraft:cocoa', { 'age': '2', 'facing': 'east' } ] }, 617 | { 'dungeons': [ 0x007f, 0b1010 ], 'java': [ 'minecraft:cocoa', { 'age': '2', 'facing': 'south' } ] }, 618 | { 'dungeons': [ 0x007f, 0b1011 ], 'java': [ 'minecraft:cocoa', { 'age': '2', 'facing': 'west' } ] }, 619 | { 'dungeons': [ 0x0080, 0b0000 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 620 | { 'dungeons': [ 0x0080, 0b0001 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 621 | { 'dungeons': [ 0x0080, 0b0010 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 622 | { 'dungeons': [ 0x0080, 0b0011 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 623 | { 'dungeons': [ 0x0080, 0b0100 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'east', 'half': 'top' } ] }, 624 | { 'dungeons': [ 0x0080, 0b0101 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'west', 'half': 'top' } ] }, 625 | { 'dungeons': [ 0x0080, 0b0110 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'south', 'half': 'top' } ] }, 626 | { 'dungeons': [ 0x0080, 0b0111 ], 'java': [ 'minecraft:sandstone_stairs', { 'facing': 'north', 'half': 'top' } ] }, 627 | { 'dungeons': [ 0x0081, 0b0000 ], 'java': [ 'minecraft:emerald_ore' ] }, 628 | { 'dungeons': [ 0x0085, 0b0000 ], 'java': [ 'minecraft:emerald_block' ] }, 629 | { 'dungeons': [ 0x0086, 0b0000 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 630 | { 'dungeons': [ 0x0086, 0b0001 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 631 | { 'dungeons': [ 0x0086, 0b0010 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 632 | { 'dungeons': [ 0x0086, 0b0011 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 633 | { 'dungeons': [ 0x0086, 0b0100 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'east', 'half': 'top' } ] }, 634 | { 'dungeons': [ 0x0086, 0b0101 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'west', 'half': 'top' } ] }, 635 | { 'dungeons': [ 0x0086, 0b0110 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'south', 'half': 'top' } ] }, 636 | { 'dungeons': [ 0x0086, 0b0111 ], 'java': [ 'minecraft:spruce_stairs', { 'facing': 'north', 'half': 'top' } ] }, 637 | { 'dungeons': [ 0x0087, 0b0000 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 638 | { 'dungeons': [ 0x0087, 0b0001 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 639 | { 'dungeons': [ 0x0087, 0b0010 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 640 | { 'dungeons': [ 0x0087, 0b0011 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 641 | { 'dungeons': [ 0x0087, 0b0100 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'east', 'half': 'top' } ] }, 642 | { 'dungeons': [ 0x0087, 0b0101 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'west', 'half': 'top' } ] }, 643 | { 'dungeons': [ 0x0087, 0b0110 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'south', 'half': 'top' } ] }, 644 | { 'dungeons': [ 0x0087, 0b0111 ], 'java': [ 'minecraft:birch_stairs', { 'facing': 'north', 'half': 'top' } ] }, 645 | { 'dungeons': [ 0x0088, 0b0000 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 646 | { 'dungeons': [ 0x0088, 0b0001 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 647 | { 'dungeons': [ 0x0088, 0b0010 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 648 | { 'dungeons': [ 0x0088, 0b0011 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 649 | { 'dungeons': [ 0x0088, 0b0100 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'east', 'half': 'top' } ] }, 650 | { 'dungeons': [ 0x0088, 0b0101 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'west', 'half': 'top' } ] }, 651 | { 'dungeons': [ 0x0088, 0b0110 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'south', 'half': 'top' } ] }, 652 | { 'dungeons': [ 0x0088, 0b0111 ], 'java': [ 'minecraft:jungle_stairs', { 'facing': 'north', 'half': 'top' } ] }, 653 | { 'dungeons': [ 0x0089, 0b0000 ], 'java': [ 'minecraft:blackstone_slab', { 'type': 'bottom' } ] }, # stonefloor1 slab 654 | { 'dungeons': [ 0x0089, 0b0001 ], 'java': [ 'minecraft:crimson_slab', { 'type': 'bottom' } ] }, # stonefloor2 slab 655 | { 'dungeons': [ 0x0089, 0b0010 ], 'java': [ 'minecraft:polished_blackstone_slab', { 'type': 'bottom' } ] }, # stonefloor3 slab 656 | { 'dungeons': [ 0x0089, 0b0011 ], 'java': [ 'minecraft:polished_blackstone_brick_slab', { 'type': 'bottom' } ] }, # stonefloor4 slab 657 | { 'dungeons': [ 0x0089, 0b0100 ], 'java': [ 'minecraft:smooth_quartz_slab', { 'type': 'bottom' } ] }, # stonefloor5 slab 658 | { 'dungeons': [ 0x0089, 0b0101 ], 'java': [ 'minecraft:stone_slab', { 'type': 'bottom' } ] }, # stonefloor6 slab 659 | { 'dungeons': [ 0x0089, 0b0110 ], 'java': [ 'minecraft:smooth_sandstone_slab', { 'type': 'bottom' } ] }, # stonefloor7 slab 660 | { 'dungeons': [ 0x0089, 0b0111 ], 'java': [ 'minecraft:cut_sandstone_slab', { 'type': 'bottom' } ] }, # stonefloor8 slab 661 | { 'dungeons': [ 0x0089, 0b1000 ], 'java': [ 'minecraft:blackstone_slab', { 'type': 'top' } ] }, 662 | { 'dungeons': [ 0x0089, 0b1001 ], 'java': [ 'minecraft:crimson_slab', { 'type': 'top' } ] }, 663 | { 'dungeons': [ 0x0089, 0b1010 ], 'java': [ 'minecraft:polished_blackstone_slab', { 'type': 'top' } ] }, 664 | { 'dungeons': [ 0x0089, 0b1011 ], 'java': [ 'minecraft:polished_blackstone_brick_slab', { 'type': 'top' } ] }, 665 | { 'dungeons': [ 0x0089, 0b1100 ], 'java': [ 'minecraft:smooth_quartz_slab', { 'type': 'top' } ] }, 666 | { 'dungeons': [ 0x0089, 0b1101 ], 'java': [ 'minecraft:stone_slab', { 'type': 'top' } ] }, 667 | { 'dungeons': [ 0x0089, 0b1110 ], 'java': [ 'minecraft:smooth_sandstone_slab', { 'type': 'top' } ] }, 668 | { 'dungeons': [ 0x0089, 0b1111 ], 'java': [ 'minecraft:cut_sandstone_slab', { 'type': 'top' } ] }, 669 | { 'dungeons': [ 0x008b, 0b0000 ], 'java': [ 'minecraft:cobblestone_wall' ] }, 670 | { 'dungeons': [ 0x008b, 0b0001 ], 'java': [ 'minecraft:mossy_cobblestone_wall' ] }, 671 | { 'dungeons': [ 0x008b, 0b0010 ], 'java': [ 'minecraft:granite_wall' ] }, 672 | { 'dungeons': [ 0x008b, 0b0011 ], 'java': [ 'minecraft:diorite_wall' ] }, 673 | { 'dungeons': [ 0x008b, 0b0100 ], 'java': [ 'minecraft:andesite_wall' ] }, 674 | { 'dungeons': [ 0x008b, 0b0101 ], 'java': [ 'minecraft:sandstone_wall' ] }, 675 | { 'dungeons': [ 0x008b, 0b0110 ], 'java': [ 'minecraft:brick_wall' ] }, 676 | { 'dungeons': [ 0x008b, 0b0111 ], 'java': [ 'minecraft:stone_brick_wall' ] }, 677 | { 'dungeons': [ 0x008b, 0b1000 ], 'java': [ 'minecraft:mossy_stone_brick_wall' ] }, 678 | { 'dungeons': [ 0x008b, 0b1001 ], 'java': [ 'minecraft:end_stone_brick_wall' ] }, 679 | { 'dungeons': [ 0x008b, 0b1010 ], 'java': [ 'minecraft:nether_brick_wall' ] }, 680 | { 'dungeons': [ 0x008b, 0b1011 ], 'java': [ 'minecraft:prismarine_wall' ] }, 681 | { 'dungeons': [ 0x008b, 0b1100 ], 'java': [ 'minecraft:red_sandstone_wall' ] }, 682 | { 'dungeons': [ 0x008b, 0b1101 ], 'java': [ 'minecraft:red_nether_brick_wall' ] }, 683 | { 'dungeons': [ 0x008d, 0b0000 ], 'java': [ 'minecraft:carrots', { 'age': '0' } ] }, 684 | { 'dungeons': [ 0x008d, 0b0001 ], 'java': [ 'minecraft:carrots', { 'age': '1' } ] }, 685 | { 'dungeons': [ 0x008d, 0b0010 ], 'java': [ 'minecraft:carrots', { 'age': '2' } ] }, 686 | { 'dungeons': [ 0x008d, 0b0011 ], 'java': [ 'minecraft:carrots', { 'age': '3' } ] }, 687 | { 'dungeons': [ 0x008d, 0b0100 ], 'java': [ 'minecraft:carrots', { 'age': '4' } ] }, 688 | { 'dungeons': [ 0x008d, 0b0101 ], 'java': [ 'minecraft:carrots', { 'age': '5' } ] }, 689 | { 'dungeons': [ 0x008d, 0b0110 ], 'java': [ 'minecraft:carrots', { 'age': '6' } ] }, 690 | { 'dungeons': [ 0x008d, 0b0111 ], 'java': [ 'minecraft:carrots', { 'age': '7' } ] }, 691 | { 'dungeons': [ 0x0090, 0b0001 ], 'java': [ 'minecraft:skeleton_skull' ] }, 692 | { 'dungeons': [ 0x0090, 0b0010 ], 'java': [ 'minecraft:skeleton_wall_skull', { 'facing': 'north' } ] }, 693 | { 'dungeons': [ 0x0090, 0b0011 ], 'java': [ 'minecraft:skeleton_wall_skull', { 'facing': 'south' } ] }, 694 | { 'dungeons': [ 0x0090, 0b0100 ], 'java': [ 'minecraft:skeleton_wall_skull', { 'facing': 'east' } ] }, 695 | { 'dungeons': [ 0x0090, 0b0101 ], 'java': [ 'minecraft:skeleton_wall_skull', { 'facing': 'west' } ] }, 696 | { 'dungeons': [ 0x0091, 0b0000 ], 'java': [ 'minecraft:anvil', { 'facing': 'west' } ] }, 697 | { 'dungeons': [ 0x0091, 0b0001 ], 'java': [ 'minecraft:anvil', { 'facing': 'north' } ] }, 698 | { 'dungeons': [ 0x0091, 0b0010 ], 'java': [ 'minecraft:anvil', { 'facing': 'east' } ] }, 699 | { 'dungeons': [ 0x0091, 0b0011 ], 'java': [ 'minecraft:anvil', { 'facing': 'south' } ] }, 700 | { 'dungeons': [ 0x0091, 0b0100 ], 'java': [ 'minecraft:chipped_anvil', { 'facing': 'west' } ] }, 701 | { 'dungeons': [ 0x0091, 0b0101 ], 'java': [ 'minecraft:chipped_anvil', { 'facing': 'north' } ] }, 702 | { 'dungeons': [ 0x0091, 0b0110 ], 'java': [ 'minecraft:chipped_anvil', { 'facing': 'east' } ] }, 703 | { 'dungeons': [ 0x0091, 0b0111 ], 'java': [ 'minecraft:chipped_anvil', { 'facing': 'south' } ] }, 704 | { 'dungeons': [ 0x0091, 0b1000 ], 'java': [ 'minecraft:damaged_anvil', { 'facing': 'west' } ] }, 705 | { 'dungeons': [ 0x0091, 0b1001 ], 'java': [ 'minecraft:damaged_anvil', { 'facing': 'north' } ] }, 706 | { 'dungeons': [ 0x0091, 0b1010 ], 'java': [ 'minecraft:damaged_anvil', { 'facing': 'east' } ] }, 707 | { 'dungeons': [ 0x0091, 0b1011 ], 'java': [ 'minecraft:damaged_anvil', { 'facing': 'south' } ] }, 708 | { 'dungeons': [ 0x0095, 0b0000, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'north', 'mode': 'compare', 'powered': 'false' } ] }, 709 | { 'dungeons': [ 0x0095, 0b0001, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'east', 'mode': 'compare', 'powered': 'false' } ] }, 710 | { 'dungeons': [ 0x0095, 0b0010, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'south', 'mode': 'compare', 'powered': 'false' } ] }, 711 | { 'dungeons': [ 0x0095, 0b0011, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'west', 'mode': 'compare', 'powered': 'false' } ] }, 712 | { 'dungeons': [ 0x0095, 0b0100, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'north', 'mode': 'subtract', 'powered': 'false' } ] }, 713 | { 'dungeons': [ 0x0095, 0b0101, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'east', 'mode': 'subtract', 'powered': 'false' } ] }, 714 | { 'dungeons': [ 0x0095, 0b0110, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'south', 'mode': 'subtract', 'powered': 'false' } ] }, 715 | { 'dungeons': [ 0x0095, 0b0111, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'west', 'mode': 'subtract', 'powered': 'false' } ] }, 716 | { 'dungeons': [ 0x0096, 0b0000, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'north', 'mode': 'compare', 'powered': 'true' } ] }, 717 | { 'dungeons': [ 0x0096, 0b0001, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'east', 'mode': 'compare', 'powered': 'true' } ] }, 718 | { 'dungeons': [ 0x0096, 0b0010, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'south', 'mode': 'compare', 'powered': 'true' } ] }, 719 | { 'dungeons': [ 0x0096, 0b0011, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'west', 'mode': 'compare', 'powered': 'true' } ] }, 720 | { 'dungeons': [ 0x0096, 0b0100, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'north', 'mode': 'subtract', 'powered': 'true' } ] }, 721 | { 'dungeons': [ 0x0096, 0b0101, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'east', 'mode': 'subtract', 'powered': 'true' } ] }, 722 | { 'dungeons': [ 0x0096, 0b0110, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'south', 'mode': 'subtract', 'powered': 'true' } ] }, 723 | { 'dungeons': [ 0x0096, 0b0111, 0b0111 ], 'java': [ 'minecraft:comparator', { 'facing': 'west', 'mode': 'subtract', 'powered': 'true' } ] }, 724 | { 'dungeons': [ 0x0098, 0b0000 ], 'java': [ 'minecraft:redstone_block' ] }, 725 | { 'dungeons': [ 0x0099, 0b0000 ], 'java': [ 'minecraft:quartz_ore' ] }, 726 | { 'dungeons': [ 0x009b, 0b0000 ], 'java': [ 'minecraft:quartz_block' ] }, 727 | { 'dungeons': [ 0x009b, 0b0001 ], 'java': [ 'minecraft:chiseled_quartz_block' ] }, 728 | { 'dungeons': [ 0x009b, 0b0010 ], 'java': [ 'minecraft:quartz_pillar', { 'axis': 'y' } ] }, 729 | { 'dungeons': [ 0x009b, 0b0011 ], 'java': [ 'minecraft:smooth_quartz' ] }, 730 | { 'dungeons': [ 0x009b, 0b0100 ], 'java': [ 'minecraft:dead_fire_coral_block' ] }, 731 | { 'dungeons': [ 0x009b, 0b0101 ], 'java': [ 'minecraft:dead_brain_coral_block' ] }, 732 | { 'dungeons': [ 0x009b, 0b0110 ], 'java': [ 'minecraft:quartz_pillar', { 'axis': 'x' } ] }, 733 | { 'dungeons': [ 0x009b, 0b1001 ], 'java': [ 'minecraft:dead_bubble_coral_block' ] }, 734 | { 'dungeons': [ 0x009b, 0b1010 ], 'java': [ 'minecraft:quartz_pillar', { 'axis': 'z' } ] }, 735 | { 'dungeons': [ 0x009c, 0b0000 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 736 | { 'dungeons': [ 0x009c, 0b0001 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 737 | { 'dungeons': [ 0x009c, 0b0010 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 738 | { 'dungeons': [ 0x009c, 0b0011 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 739 | { 'dungeons': [ 0x009c, 0b0100 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'east', 'half': 'top' } ] }, 740 | { 'dungeons': [ 0x009c, 0b0101 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'west', 'half': 'top' } ] }, 741 | { 'dungeons': [ 0x009c, 0b0110 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'south', 'half': 'top' } ] }, 742 | { 'dungeons': [ 0x009c, 0b0111 ], 'java': [ 'minecraft:quartz_stairs', { 'facing': 'north', 'half': 'top' } ] }, 743 | { 'dungeons': [ 0x009d, 0b0000, 0b0111 ], 'java': [ 'minecraft:oak_slab', { 'type': 'double' } ] }, 744 | { 'dungeons': [ 0x009d, 0b0001, 0b0111 ], 'java': [ 'minecraft:spruce_slab', { 'type': 'double' } ] }, 745 | { 'dungeons': [ 0x009d, 0b0010, 0b0111 ], 'java': [ 'minecraft:birch_slab', { 'type': 'double' } ] }, 746 | { 'dungeons': [ 0x009d, 0b0011, 0b0111 ], 'java': [ 'minecraft:jungle_slab', { 'type': 'double' } ] }, 747 | { 'dungeons': [ 0x009d, 0b0100, 0b0111 ], 'java': [ 'minecraft:acacia_slab', { 'type': 'double' } ] }, 748 | { 'dungeons': [ 0x009d, 0b0101, 0b0111 ], 'java': [ 'minecraft:dark_oak_slab', { 'type': 'double' } ] }, 749 | { 'dungeons': [ 0x009e, 0b0000 ], 'java': [ 'minecraft:oak_slab', { 'type': 'bottom' } ] }, 750 | { 'dungeons': [ 0x009e, 0b0001 ], 'java': [ 'minecraft:spruce_slab', { 'type': 'bottom' } ] }, 751 | { 'dungeons': [ 0x009e, 0b0010 ], 'java': [ 'minecraft:birch_slab', { 'type': 'bottom' } ] }, 752 | { 'dungeons': [ 0x009e, 0b0011 ], 'java': [ 'minecraft:jungle_slab', { 'type': 'bottom' } ] }, 753 | { 'dungeons': [ 0x009e, 0b0100 ], 'java': [ 'minecraft:acacia_slab', { 'type': 'bottom' } ] }, 754 | { 'dungeons': [ 0x009e, 0b0101 ], 'java': [ 'minecraft:dark_oak_slab', { 'type': 'bottom' } ] }, 755 | { 'dungeons': [ 0x009e, 0b1000 ], 'java': [ 'minecraft:oak_slab', { 'type': 'top' } ] }, 756 | { 'dungeons': [ 0x009e, 0b1001 ], 'java': [ 'minecraft:spruce_slab', { 'type': 'top' } ] }, 757 | { 'dungeons': [ 0x009e, 0b1010 ], 'java': [ 'minecraft:birch_slab', { 'type': 'top' } ] }, 758 | { 'dungeons': [ 0x009e, 0b1011 ], 'java': [ 'minecraft:jungle_slab', { 'type': 'top' } ] }, 759 | { 'dungeons': [ 0x009e, 0b1100 ], 'java': [ 'minecraft:acacia_slab', { 'type': 'top' } ] }, 760 | { 'dungeons': [ 0x009e, 0b1101 ], 'java': [ 'minecraft:dark_oak_slab', { 'type': 'top' } ] }, 761 | { 'dungeons': [ 0x009f, 0b0000 ], 'java': [ 'minecraft:white_terracotta' ] }, 762 | { 'dungeons': [ 0x009f, 0b0001 ], 'java': [ 'minecraft:orange_terracotta' ] }, 763 | { 'dungeons': [ 0x009f, 0b0010 ], 'java': [ 'minecraft:magenta_terracotta' ] }, 764 | { 'dungeons': [ 0x009f, 0b0011 ], 'java': [ 'minecraft:light_blue_terracotta' ] }, 765 | { 'dungeons': [ 0x009f, 0b0100 ], 'java': [ 'minecraft:yellow_terracotta' ] }, 766 | { 'dungeons': [ 0x009f, 0b0101 ], 'java': [ 'minecraft:lime_terracotta' ] }, 767 | { 'dungeons': [ 0x009f, 0b0110 ], 'java': [ 'minecraft:pink_terracotta' ] }, 768 | { 'dungeons': [ 0x009f, 0b0111 ], 'java': [ 'minecraft:gray_terracotta' ] }, 769 | { 'dungeons': [ 0x009f, 0b1000 ], 'java': [ 'minecraft:light_gray_terracotta' ] }, 770 | { 'dungeons': [ 0x009f, 0b1001 ], 'java': [ 'minecraft:cyan_terracotta' ] }, 771 | { 'dungeons': [ 0x009f, 0b1010 ], 'java': [ 'minecraft:purple_terracotta' ] }, 772 | { 'dungeons': [ 0x009f, 0b1011 ], 'java': [ 'minecraft:blue_terracotta' ] }, 773 | { 'dungeons': [ 0x009f, 0b1100 ], 'java': [ 'minecraft:brown_terracotta' ] }, 774 | { 'dungeons': [ 0x009f, 0b1101 ], 'java': [ 'minecraft:green_terracotta' ] }, 775 | { 'dungeons': [ 0x009f, 0b1110 ], 'java': [ 'minecraft:red_terracotta' ] }, 776 | { 'dungeons': [ 0x009f, 0b1111 ], 'java': [ 'minecraft:black_terracotta' ] }, 777 | { 'dungeons': [ 0x00a1, 0b0000, 0b0111 ], 'java': [ 'minecraft:acacia_leaves', { 'persistent': 'false' } ] }, 778 | { 'dungeons': [ 0x00a1, 0b0001, 0b0111 ], 'java': [ 'minecraft:dark_oak_leaves', { 'persistent': 'false' } ] }, 779 | { 'dungeons': [ 0x00a1, 0b0100, 0b0111 ], 'java': [ 'minecraft:acacia_leaves', { 'persistent': 'true' } ] }, 780 | { 'dungeons': [ 0x00a1, 0b0101, 0b0111 ], 'java': [ 'minecraft:dark_oak_leaves', { 'persistent': 'true' } ] }, 781 | { 'dungeons': [ 0x00a2, 0b0000 ], 'java': [ 'minecraft:acacia_log', { 'axis': 'y' } ] }, 782 | { 'dungeons': [ 0x00a2, 0b0001 ], 'java': [ 'minecraft:dark_oak_log', { 'axis': 'y' } ] }, 783 | { 'dungeons': [ 0x00a2, 0b0100 ], 'java': [ 'minecraft:acacia_log', { 'axis': 'x' } ] }, 784 | { 'dungeons': [ 0x00a2, 0b0101 ], 'java': [ 'minecraft:dark_oak_log', { 'axis': 'x' } ] }, 785 | { 'dungeons': [ 0x00a2, 0b1000 ], 'java': [ 'minecraft:acacia_log', { 'axis': 'z' } ] }, 786 | { 'dungeons': [ 0x00a2, 0b1001 ], 'java': [ 'minecraft:dark_oak_log', { 'axis': 'z' } ] }, 787 | { 'dungeons': [ 0x00a2, 0b1100 ], 'java': [ 'minecraft:acacia_wood' ] }, 788 | { 'dungeons': [ 0x00a2, 0b1101 ], 'java': [ 'minecraft:dark_oak_wood' ] }, 789 | { 'dungeons': [ 0x00a3, 0b0000 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 790 | { 'dungeons': [ 0x00a3, 0b0001 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 791 | { 'dungeons': [ 0x00a3, 0b0010 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 792 | { 'dungeons': [ 0x00a3, 0b0011 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 793 | { 'dungeons': [ 0x00a3, 0b0100 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'east', 'half': 'top' } ] }, 794 | { 'dungeons': [ 0x00a3, 0b0101 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'west', 'half': 'top' } ] }, 795 | { 'dungeons': [ 0x00a3, 0b0110 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'south', 'half': 'top' } ] }, 796 | { 'dungeons': [ 0x00a3, 0b0111 ], 'java': [ 'minecraft:acacia_stairs', { 'facing': 'north', 'half': 'top' } ] }, 797 | { 'dungeons': [ 0x00a4, 0b0000 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 798 | { 'dungeons': [ 0x00a4, 0b0001 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 799 | { 'dungeons': [ 0x00a4, 0b0010 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 800 | { 'dungeons': [ 0x00a4, 0b0011 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 801 | { 'dungeons': [ 0x00a4, 0b0100 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'east', 'half': 'top' } ] }, 802 | { 'dungeons': [ 0x00a4, 0b0101 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'west', 'half': 'top' } ] }, 803 | { 'dungeons': [ 0x00a4, 0b0110 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'south', 'half': 'top' } ] }, 804 | { 'dungeons': [ 0x00a4, 0b0111 ], 'java': [ 'minecraft:dark_oak_stairs', { 'facing': 'north', 'half': 'top' } ] }, 805 | { 'dungeons': [ 0x00a7, 0b0000 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'east' } ] }, 806 | { 'dungeons': [ 0x00a7, 0b0001 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'west' } ] }, 807 | { 'dungeons': [ 0x00a7, 0b0010 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'south' } ] }, 808 | { 'dungeons': [ 0x00a7, 0b0011 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'bottom', 'facing': 'north' } ] }, 809 | { 'dungeons': [ 0x00a7, 0b0100 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'east' } ] }, 810 | { 'dungeons': [ 0x00a7, 0b0101 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'west' } ] }, 811 | { 'dungeons': [ 0x00a7, 0b0110 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'south' } ] }, 812 | { 'dungeons': [ 0x00a7, 0b0111 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'false', 'half': 'top', 'facing': 'north' } ] }, 813 | { 'dungeons': [ 0x00a7, 0b1000 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'east' } ] }, 814 | { 'dungeons': [ 0x00a7, 0b1001 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'west' } ] }, 815 | { 'dungeons': [ 0x00a7, 0b1010 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'south' } ] }, 816 | { 'dungeons': [ 0x00a7, 0b1011 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'bottom', 'facing': 'north' } ] }, 817 | { 'dungeons': [ 0x00a7, 0b1100 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'east' } ] }, 818 | { 'dungeons': [ 0x00a7, 0b1101 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'west' } ] }, 819 | { 'dungeons': [ 0x00a7, 0b1110 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'south' } ] }, 820 | { 'dungeons': [ 0x00a7, 0b1111 ], 'java': [ 'minecraft:iron_trapdoor', { 'open': 'true', 'half': 'top', 'facing': 'north' } ] }, 821 | { 'dungeons': [ 0x00aa, 0b0000 ], 'java': [ 'minecraft:hay_block', { 'axis': 'y' } ] }, 822 | { 'dungeons': [ 0x00aa, 0b0100 ], 'java': [ 'minecraft:hay_block', { 'axis': 'x' } ] }, 823 | { 'dungeons': [ 0x00aa, 0b1000 ], 'java': [ 'minecraft:hay_block', { 'axis': 'z' } ] }, 824 | { 'dungeons': [ 0x00ab, 0b0000 ], 'java': [ 'minecraft:white_carpet' ] }, 825 | { 'dungeons': [ 0x00ab, 0b0001 ], 'java': [ 'minecraft:orange_carpet' ] }, 826 | { 'dungeons': [ 0x00ab, 0b0010 ], 'java': [ 'minecraft:magenta_carpet' ] }, 827 | { 'dungeons': [ 0x00ab, 0b0011 ], 'java': [ 'minecraft:light_blue_carpet' ] }, 828 | { 'dungeons': [ 0x00ab, 0b0100 ], 'java': [ 'minecraft:yellow_carpet' ] }, 829 | { 'dungeons': [ 0x00ab, 0b0101 ], 'java': [ 'minecraft:lime_carpet' ] }, 830 | { 'dungeons': [ 0x00ab, 0b0110 ], 'java': [ 'minecraft:pink_carpet' ] }, 831 | { 'dungeons': [ 0x00ab, 0b0111 ], 'java': [ 'minecraft:gray_carpet' ] }, 832 | { 'dungeons': [ 0x00ab, 0b1000 ], 'java': [ 'minecraft:light_gray_carpet' ] }, 833 | { 'dungeons': [ 0x00ab, 0b1001 ], 'java': [ 'minecraft:cyan_carpet' ] }, 834 | { 'dungeons': [ 0x00ab, 0b1010 ], 'java': [ 'minecraft:purple_carpet' ] }, 835 | { 'dungeons': [ 0x00ab, 0b1011 ], 'java': [ 'minecraft:blue_carpet' ] }, 836 | { 'dungeons': [ 0x00ab, 0b1100 ], 'java': [ 'minecraft:brown_carpet' ] }, 837 | { 'dungeons': [ 0x00ab, 0b1101 ], 'java': [ 'minecraft:green_carpet' ] }, 838 | { 'dungeons': [ 0x00ab, 0b1110 ], 'java': [ 'minecraft:red_carpet' ] }, 839 | { 'dungeons': [ 0x00ab, 0b1111 ], 'java': [ 'minecraft:black_carpet' ] }, 840 | { 'dungeons': [ 0x00ac, 0b0000 ], 'java': [ 'minecraft:terracotta' ] }, 841 | { 'dungeons': [ 0x00ad, 0b0000 ], 'java': [ 'minecraft:coal_block' ] }, 842 | { 'dungeons': [ 0x00ae, 0b0000 ], 'java': [ 'minecraft:packed_ice' ] }, 843 | { 'dungeons': [ 0x00af, 0b0000 ], 'java': [ 'minecraft:sunflower', { 'half': 'lower' } ] }, 844 | { 'dungeons': [ 0x00af, 0b0001 ], 'java': [ 'minecraft:lilac', { 'half': 'lower' } ] }, 845 | { 'dungeons': [ 0x00af, 0b0010 ], 'java': [ 'minecraft:tall_grass', { 'half': 'lower' } ] }, 846 | { 'dungeons': [ 0x00af, 0b0011 ], 'java': [ 'minecraft:large_fern', { 'half': 'lower' } ] }, 847 | { 'dungeons': [ 0x00af, 0b0100 ], 'java': [ 'minecraft:rose_bush', { 'half': 'lower' } ] }, 848 | { 'dungeons': [ 0x00af, 0b0101 ], 'java': [ 'minecraft:peony', { 'half': 'lower' } ] }, 849 | { 'dungeons': [ 0x00af, 0b1000 ], 'java': [ 'minecraft:sunflower', { 'half': 'upper' } ] }, 850 | { 'dungeons': [ 0x00af, 0b1001 ], 'java': [ 'minecraft:lilac', { 'half': 'upper' } ] }, 851 | { 'dungeons': [ 0x00af, 0b1010 ], 'java': [ 'minecraft:tall_grass', { 'half': 'upper' } ] }, 852 | { 'dungeons': [ 0x00af, 0b1011 ], 'java': [ 'minecraft:large_fern', { 'half': 'upper' } ] }, 853 | { 'dungeons': [ 0x00af, 0b1100 ], 'java': [ 'minecraft:rose_bush', { 'half': 'upper' } ] }, 854 | { 'dungeons': [ 0x00af, 0b1101 ], 'java': [ 'minecraft:peony', { 'half': 'upper' } ] }, 855 | { 'dungeons': [ 0x00b3, 0b0000 ], 'java': [ 'minecraft:red_sandstone' ] }, 856 | { 'dungeons': [ 0x00b3, 0b0001 ], 'java': [ 'minecraft:chiseled_red_sandstone' ] }, 857 | { 'dungeons': [ 0x00b3, 0b0010 ], 'java': [ 'minecraft:cut_red_sandstone' ] }, 858 | { 'dungeons': [ 0x00b3, 0b0011 ], 'java': [ 'minecraft:smooth_red_sandstone' ] }, 859 | { 'dungeons': [ 0x00b4, 0b0000 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'east', 'half': 'bottom' } ] }, 860 | { 'dungeons': [ 0x00b4, 0b0001 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'west', 'half': 'bottom' } ] }, 861 | { 'dungeons': [ 0x00b4, 0b0010 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'south', 'half': 'bottom' } ] }, 862 | { 'dungeons': [ 0x00b4, 0b0011 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'north', 'half': 'bottom' } ] }, 863 | { 'dungeons': [ 0x00b4, 0b0100 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'east', 'half': 'top' } ] }, 864 | { 'dungeons': [ 0x00b4, 0b0101 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'west', 'half': 'top' } ] }, 865 | { 'dungeons': [ 0x00b4, 0b0110 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'south', 'half': 'top' } ] }, 866 | { 'dungeons': [ 0x00b4, 0b0111 ], 'java': [ 'minecraft:red_sandstone_stairs', { 'facing': 'north', 'half': 'top' } ] }, 867 | { 'dungeons': [ 0x00b5, 0b0000 ], 'java': [ 'minecraft:red_sandstone_slab', { 'type': 'double' } ] }, 868 | { 'dungeons': [ 0x00b5, 0b0001 ], 'java': [ 'minecraft:purpur_slab', { 'type': 'double' } ] }, 869 | { 'dungeons': [ 0x00b5, 0b0010 ], 'java': [ 'minecraft:prismarine_slab', { 'type': 'double' } ] }, 870 | { 'dungeons': [ 0x00b5, 0b0011 ], 'java': [ 'minecraft:prismarine_brick_slab', { 'type': 'double' } ] }, 871 | { 'dungeons': [ 0x00b5, 0b0100 ], 'java': [ 'minecraft:dark_prismarine_slab', { 'type': 'double' } ] }, 872 | { 'dungeons': [ 0x00b5, 0b0101 ], 'java': [ 'minecraft:mossy_cobblestone_slab', { 'type': 'double' } ] }, 873 | { 'dungeons': [ 0x00b5, 0b0110 ], 'java': [ 'minecraft:smooth_sandstone_slab', { 'type': 'double' } ] }, 874 | { 'dungeons': [ 0x00b5, 0b0111 ], 'java': [ 'minecraft:red_nether_brick_slab', { 'type': 'double' } ] }, 875 | { 'dungeons': [ 0x00b6, 0b0000 ], 'java': [ 'minecraft:red_sandstone_slab', { 'type': 'bottom' } ] }, 876 | { 'dungeons': [ 0x00b6, 0b0001 ], 'java': [ 'minecraft:purpur_slab', { 'type': 'bottom' } ] }, 877 | { 'dungeons': [ 0x00b6, 0b0010 ], 'java': [ 'minecraft:prismarine_slab', { 'type': 'bottom' } ] }, 878 | { 'dungeons': [ 0x00b6, 0b0011 ], 'java': [ 'minecraft:prismarine_brick_slab', { 'type': 'bottom' } ] }, 879 | { 'dungeons': [ 0x00b6, 0b0100 ], 'java': [ 'minecraft:dark_prismarine_slab', { 'type': 'bottom' } ] }, 880 | { 'dungeons': [ 0x00b6, 0b0101 ], 'java': [ 'minecraft:mossy_cobblestone_slab', { 'type': 'bottom' } ] }, 881 | { 'dungeons': [ 0x00b6, 0b0110 ], 'java': [ 'minecraft:smooth_sandstone_slab', { 'type': 'bottom' } ] }, 882 | { 'dungeons': [ 0x00b6, 0b0111 ], 'java': [ 'minecraft:red_nether_brick_slab', { 'type': 'bottom' } ] }, 883 | { 'dungeons': [ 0x00b6, 0b1000 ], 'java': [ 'minecraft:red_sandstone_slab', { 'type': 'top' } ] }, 884 | { 'dungeons': [ 0x00b6, 0b1001 ], 'java': [ 'minecraft:purpur_slab', { 'type': 'top' } ] }, 885 | { 'dungeons': [ 0x00b6, 0b1010 ], 'java': [ 'minecraft:prismarine_slab', { 'type': 'top' } ] }, 886 | { 'dungeons': [ 0x00b6, 0b1011 ], 'java': [ 'minecraft:prismarine_brick_slab', { 'type': 'top' } ] }, 887 | { 'dungeons': [ 0x00b6, 0b1100 ], 'java': [ 'minecraft:dark_prismarine_slab', { 'type': 'top' } ] }, 888 | { 'dungeons': [ 0x00b6, 0b1101 ], 'java': [ 'minecraft:mossy_cobblestone_slab', { 'type': 'top' } ] }, 889 | { 'dungeons': [ 0x00b6, 0b1110 ], 'java': [ 'minecraft:smooth_sandstone_slab', { 'type': 'top' } ] }, 890 | { 'dungeons': [ 0x00b6, 0b1111 ], 'java': [ 'minecraft:red_nether_brick_slab', { 'type': 'top' } ] }, 891 | { 'dungeons': [ 0x00b7, 0b0000 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'south' } ] }, 892 | { 'dungeons': [ 0x00b7, 0b0001 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'west' } ] }, 893 | { 'dungeons': [ 0x00b7, 0b0010 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'north' } ] }, 894 | { 'dungeons': [ 0x00b7, 0b0011 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'east' } ] }, 895 | { 'dungeons': [ 0x00b7, 0b0100 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'south' } ] }, 896 | { 'dungeons': [ 0x00b7, 0b0101 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'west' } ] }, 897 | { 'dungeons': [ 0x00b7, 0b0110 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'north' } ] }, 898 | { 'dungeons': [ 0x00b7, 0b0111 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'east' } ] }, 899 | { 'dungeons': [ 0x00b7, 0b1000 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'south' } ] }, 900 | { 'dungeons': [ 0x00b7, 0b1001 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'west' } ] }, 901 | { 'dungeons': [ 0x00b7, 0b1010 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'north' } ] }, 902 | { 'dungeons': [ 0x00b7, 0b1011 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'east' } ] }, 903 | { 'dungeons': [ 0x00b7, 0b1100 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'south' } ] }, 904 | { 'dungeons': [ 0x00b7, 0b1101 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'west' } ] }, 905 | { 'dungeons': [ 0x00b7, 0b1110 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'north' } ] }, 906 | { 'dungeons': [ 0x00b7, 0b1111 ], 'java': [ 'minecraft:spruce_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'east' } ] }, 907 | { 'dungeons': [ 0x00b8, 0b0000 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'south' } ] }, 908 | { 'dungeons': [ 0x00b8, 0b0001 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'west' } ] }, 909 | { 'dungeons': [ 0x00b8, 0b0010 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'north' } ] }, 910 | { 'dungeons': [ 0x00b8, 0b0011 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'east' } ] }, 911 | { 'dungeons': [ 0x00b8, 0b0100 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'south' } ] }, 912 | { 'dungeons': [ 0x00b8, 0b0101 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'west' } ] }, 913 | { 'dungeons': [ 0x00b8, 0b0110 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'north' } ] }, 914 | { 'dungeons': [ 0x00b8, 0b0111 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'east' } ] }, 915 | { 'dungeons': [ 0x00b8, 0b1000 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'south' } ] }, 916 | { 'dungeons': [ 0x00b8, 0b1001 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'west' } ] }, 917 | { 'dungeons': [ 0x00b8, 0b1010 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'north' } ] }, 918 | { 'dungeons': [ 0x00b8, 0b1011 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'east' } ] }, 919 | { 'dungeons': [ 0x00b8, 0b1100 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'south' } ] }, 920 | { 'dungeons': [ 0x00b8, 0b1101 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'west' } ] }, 921 | { 'dungeons': [ 0x00b8, 0b1110 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'north' } ] }, 922 | { 'dungeons': [ 0x00b8, 0b1111 ], 'java': [ 'minecraft:birch_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'east' } ] }, 923 | { 'dungeons': [ 0x00bb, 0b0000 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'south' } ] }, 924 | { 'dungeons': [ 0x00bb, 0b0001 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'west' } ] }, 925 | { 'dungeons': [ 0x00bb, 0b0010 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'north' } ] }, 926 | { 'dungeons': [ 0x00bb, 0b0011 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'false', 'facing': 'east' } ] }, 927 | { 'dungeons': [ 0x00bb, 0b0100 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'south' } ] }, 928 | { 'dungeons': [ 0x00bb, 0b0101 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'west' } ] }, 929 | { 'dungeons': [ 0x00bb, 0b0110 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'north' } ] }, 930 | { 'dungeons': [ 0x00bb, 0b0111 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'false', 'open': 'true', 'facing': 'east' } ] }, 931 | { 'dungeons': [ 0x00bb, 0b1000 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'south' } ] }, 932 | { 'dungeons': [ 0x00bb, 0b1001 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'west' } ] }, 933 | { 'dungeons': [ 0x00bb, 0b1010 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'north' } ] }, 934 | { 'dungeons': [ 0x00bb, 0b1011 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'false', 'facing': 'east' } ] }, 935 | { 'dungeons': [ 0x00bb, 0b1100 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'south' } ] }, 936 | { 'dungeons': [ 0x00bb, 0b1101 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'west' } ] }, 937 | { 'dungeons': [ 0x00bb, 0b1110 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'north' } ] }, 938 | { 'dungeons': [ 0x00bb, 0b1111 ], 'java': [ 'minecraft:acacia_fence_gate', { 'in_wall': 'true', 'open': 'true', 'facing': 'east' } ] }, 939 | { 'dungeons': [ 0x00c1, 0b0000 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'false', 'facing': 'east' } ] }, 940 | { 'dungeons': [ 0x00c1, 0b0001 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'false', 'facing': 'south' } ] }, 941 | { 'dungeons': [ 0x00c1, 0b0010 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'false', 'facing': 'west' } ] }, 942 | { 'dungeons': [ 0x00c1, 0b0011 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'false', 'facing': 'north' } ] }, 943 | { 'dungeons': [ 0x00c1, 0b0100 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'true', 'facing': 'east' } ] }, 944 | { 'dungeons': [ 0x00c1, 0b0101 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'true', 'facing': 'south' } ] }, 945 | { 'dungeons': [ 0x00c1, 0b0110 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'true', 'facing': 'west' } ] }, 946 | { 'dungeons': [ 0x00c1, 0b0111 ], 'java': [ 'minecraft:spruce_door', { 'half': 'lower', 'open': 'true', 'facing': 'north' } ] }, 947 | { 'dungeons': [ 0x00c1, 0b1000 ], 'java': [ 'minecraft:spruce_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'left' } ] }, 948 | { 'dungeons': [ 0x00c1, 0b1001 ], 'java': [ 'minecraft:spruce_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'right' } ] }, 949 | { 'dungeons': [ 0x00c1, 0b1010 ], 'java': [ 'minecraft:spruce_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'left' } ] }, 950 | { 'dungeons': [ 0x00c1, 0b1011 ], 'java': [ 'minecraft:spruce_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'right' } ] }, 951 | { 'dungeons': [ 0x00c3, 0b0000 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'false', 'facing': 'east' } ] }, 952 | { 'dungeons': [ 0x00c3, 0b0001 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'false', 'facing': 'south' } ] }, 953 | { 'dungeons': [ 0x00c3, 0b0010 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'false', 'facing': 'west' } ] }, 954 | { 'dungeons': [ 0x00c3, 0b0011 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'false', 'facing': 'north' } ] }, 955 | { 'dungeons': [ 0x00c3, 0b0100 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'true', 'facing': 'east' } ] }, 956 | { 'dungeons': [ 0x00c3, 0b0101 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'true', 'facing': 'south' } ] }, 957 | { 'dungeons': [ 0x00c3, 0b0110 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'true', 'facing': 'west' } ] }, 958 | { 'dungeons': [ 0x00c3, 0b0111 ], 'java': [ 'minecraft:jungle_door', { 'half': 'lower', 'open': 'true', 'facing': 'north' } ] }, 959 | { 'dungeons': [ 0x00c3, 0b1000 ], 'java': [ 'minecraft:jungle_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'left' } ] }, 960 | { 'dungeons': [ 0x00c3, 0b1001 ], 'java': [ 'minecraft:jungle_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'right' } ] }, 961 | { 'dungeons': [ 0x00c3, 0b1010 ], 'java': [ 'minecraft:jungle_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'left' } ] }, 962 | { 'dungeons': [ 0x00c3, 0b1011 ], 'java': [ 'minecraft:jungle_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'right' } ] }, 963 | { 'dungeons': [ 0x00c5, 0b0000 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'east' } ] }, 964 | { 'dungeons': [ 0x00c5, 0b0001 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'south' } ] }, 965 | { 'dungeons': [ 0x00c5, 0b0010 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'west' } ] }, 966 | { 'dungeons': [ 0x00c5, 0b0011 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'false', 'facing': 'north' } ] }, 967 | { 'dungeons': [ 0x00c5, 0b0100 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'east' } ] }, 968 | { 'dungeons': [ 0x00c5, 0b0101 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'south' } ] }, 969 | { 'dungeons': [ 0x00c5, 0b0110 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'west' } ] }, 970 | { 'dungeons': [ 0x00c5, 0b0111 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'lower', 'open': 'true', 'facing': 'north' } ] }, 971 | { 'dungeons': [ 0x00c5, 0b1000 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'left' } ] }, 972 | { 'dungeons': [ 0x00c5, 0b1001 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'upper', 'powered': 'false', 'hinge': 'right' } ] }, 973 | { 'dungeons': [ 0x00c5, 0b1010 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'left' } ] }, 974 | { 'dungeons': [ 0x00c5, 0b1011 ], 'java': [ 'minecraft:dark_oak_door', { 'half': 'upper', 'powered': 'true', 'hinge': 'right' } ] }, 975 | { 'dungeons': [ 0x00c6, 0b0000 ], 'java': [ 'minecraft:dirt_path' ] }, 976 | { 'dungeons': [ 0x00c6, 0b0001 ], 'java': [ 'minecraft:farmland', { 'moisture': '1' } ] }, # dirt_path 977 | { 'dungeons': [ 0x00c6, 0b0010 ], 'java': [ 'minecraft:farmland', { 'moisture': '2' } ] }, # stone_path 978 | { 'dungeons': [ 0x00c6, 0b0011 ], 'java': [ 'minecraft:farmland', { 'moisture': '3' } ] }, # skull_path 979 | { 'dungeons': [ 0x00c6, 0b0100 ], 'java': [ 'minecraft:farmland', { 'moisture': '4' } ] }, # gravel_path 980 | { 'dungeons': [ 0x00c7, 0b0011 ], 'java': [ 'minecraft:dead_tube_coral_block' ] }, 981 | { 'dungeons': [ 0x00e0, 0b0000 ], 'java': [ 'minecraft:white_concrete' ] }, # custom_0 982 | { 'dungeons': [ 0x00e1, 0b0000 ], 'java': [ 'minecraft:orange_concrete' ] }, # custom_1 983 | { 'dungeons': [ 0x00e2, 0b0000 ], 'java': [ 'minecraft:magenta_concrete' ] }, # custom_2 984 | { 'dungeons': [ 0x00e3, 0b0000 ], 'java': [ 'minecraft:light_blue_concrete' ] }, # custom_3 985 | { 'dungeons': [ 0x00e4, 0b0000 ], 'java': [ 'minecraft:yellow_concrete' ] }, # custom_4 986 | { 'dungeons': [ 0x00e5, 0b0000 ], 'java': [ 'minecraft:lime_concrete' ] }, # custom_5 987 | { 'dungeons': [ 0x00e6, 0b0000 ], 'java': [ 'minecraft:pink_concrete' ] }, # custom_6 988 | { 'dungeons': [ 0x00e7, 0b0000 ], 'java': [ 'minecraft:gray_concrete' ] }, # custom_7 989 | { 'dungeons': [ 0x00e8, 0b0000 ], 'java': [ 'minecraft:light_gray_concrete' ] }, # custom_8 990 | { 'dungeons': [ 0x00e9, 0b0000 ], 'java': [ 'minecraft:cyan_concrete' ] }, # custom_9 991 | { 'dungeons': [ 0x00ea, 0b0000 ], 'java': [ 'minecraft:blue_concrete' ] }, # custom_10 992 | { 'dungeons': [ 0x00eb, 0b0000 ], 'java': [ 'minecraft:purple_concrete' ] }, # custom_11 993 | { 'dungeons': [ 0x00ec, 0b0000 ], 'java': [ 'minecraft:brown_concrete' ] }, # custom_12 994 | { 'dungeons': [ 0x00ed, 0b0000 ], 'java': [ 'minecraft:green_concrete' ] }, # custom_13 995 | { 'dungeons': [ 0x00ee, 0b0000 ], 'java': [ 'minecraft:red_concrete' ] }, # custom_14 996 | { 'dungeons': [ 0x00ef, 0b0000 ], 'java': [ 'minecraft:black_concrete' ] }, # custom_15 997 | { 'dungeons': [ 0x00f3, 0b0000 ], 'java': [ 'minecraft:mycelium' ] }, 998 | { 'dungeons': [ 0x00f5, 0b0000 ], 'java': [ 'minecraft:stonecutter' ] }, 999 | { 'dungeons': [ 0x00fb, 0b0000 ], 'java': [ 'minecraft:observer', { 'facing': 'down', 'powered': 'false' } ] }, 1000 | { 'dungeons': [ 0x00fb, 0b0001 ], 'java': [ 'minecraft:observer', { 'facing': 'up', 'powered': 'false' } ] }, 1001 | { 'dungeons': [ 0x00fb, 0b0010 ], 'java': [ 'minecraft:observer', { 'facing': 'north', 'powered': 'false' } ] }, 1002 | { 'dungeons': [ 0x00fb, 0b0011 ], 'java': [ 'minecraft:observer', { 'facing': 'south', 'powered': 'false' } ] }, 1003 | { 'dungeons': [ 0x00fb, 0b0100 ], 'java': [ 'minecraft:observer', { 'facing': 'west', 'powered': 'false' } ] }, 1004 | { 'dungeons': [ 0x00fb, 0b0101 ], 'java': [ 'minecraft:observer', { 'facing': 'east', 'powered': 'false' } ] }, 1005 | { 'dungeons': [ 0x00fb, 0b1000 ], 'java': [ 'minecraft:observer', { 'facing': 'down', 'powered': 'true' } ] }, 1006 | { 'dungeons': [ 0x00fb, 0b1001 ], 'java': [ 'minecraft:observer', { 'facing': 'up', 'powered': 'true' } ] }, 1007 | { 'dungeons': [ 0x00fb, 0b1010 ], 'java': [ 'minecraft:observer', { 'facing': 'north', 'powered': 'true' } ] }, 1008 | { 'dungeons': [ 0x00fb, 0b1011 ], 'java': [ 'minecraft:observer', { 'facing': 'south', 'powered': 'true' } ] }, 1009 | { 'dungeons': [ 0x00fb, 0b1100 ], 'java': [ 'minecraft:observer', { 'facing': 'west', 'powered': 'true' } ] }, 1010 | { 'dungeons': [ 0x00fb, 0b1101 ], 'java': [ 'minecraft:observer', { 'facing': 'east', 'powered': 'true' } ] }, 1011 | { 'dungeons': [ 0x010c, 0b0000 ], 'java': [ 'minecraft:warped_planks' ] }, 1012 | { 'dungeons': [ 0x010d, 0b0000 ], 'java': [ 'minecraft:crimson_nylium' ] }, 1013 | { 'dungeons': [ 0x010e, 0b0000 ], 'java': [ 'minecraft:warped_nylium' ] }, 1014 | { 'dungeons': [ 0x0110, 0b0000 ], 'java': [ 'minecraft:honeycomb_block' ] }, 1015 | { 'dungeons': [ 0x0111, 0b0000 ], 'java': [ 'minecraft:lodestone' ] }, 1016 | { 'dungeons': [ 0x0112, 0b0000 ], 'java': [ 'minecraft:warped_wart_block' ] }, 1017 | { 'dungeons': [ 0x0114, 0b0000 ], 'java': [ 'minecraft:crimson_planks' ] }, 1018 | { 'dungeons': [ 0x0130, 0b0000 ], 'java': [ 'minecraft:quartz_bricks' ] }, 1019 | { 'dungeons': [ 0x0131, 0b0000 ], 'java': [ 'minecraft:basalt', { 'axis': 'x' } ] }, 1020 | { 'dungeons': [ 0x0132, 0b0000 ], 'java': [ 'minecraft:basalt', { 'axis': 'y' } ] }, 1021 | { 'dungeons': [ 0x0133, 0b0000 ], 'java': [ 'minecraft:basalt', { 'axis': 'z' } ] }, 1022 | { 'dungeons': [ 0x015b, 0b0000 ], 'java': [ 'minecraft:crying_obsidian' ] }, 1023 | { 'dungeons': [ 0x015c, 0b0000 ], 'java': [ 'minecraft:dried_kelp_block' ] }, 1024 | { 'dungeons': [ 0x015d, 0b0000 ], 'java': [ 'minecraft:nether_gold_ore' ] }, 1025 | { 'dungeons': [ 0x0162, 0b0000 ], 'java': [ 'minecraft:polished_basalt', { 'axis': 'x' } ] }, 1026 | { 'dungeons': [ 0x0163, 0b0000 ], 'java': [ 'minecraft:polished_basalt', { 'axis': 'y' } ] }, 1027 | { 'dungeons': [ 0x0164, 0b0000 ], 'java': [ 'minecraft:polished_basalt', { 'axis': 'z' } ] }, 1028 | { 'dungeons': [ 0x0165, 0b0000 ], 'java': [ 'minecraft:crimson_stem', { 'axis': 'x' } ] }, 1029 | { 'dungeons': [ 0x0207, 0b0000 ], 'java': [ 'minecraft:crimson_slab', { 'type': 'bottom' } ] }, 1030 | { 'dungeons': [ 0x0208, 0b0000 ], 'java': [ 'minecraft:warped_slab', { 'type': 'bottom' } ] }, 1031 | { 'dungeons': [ 0x010b, 0b0000 ], 'java': [ 'minecraft:sea_lantern' ] }, 1032 | { 'dungeons': [ 0x0168, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '1' } ] }, 1033 | { 'dungeons': [ 0x0158, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '2' } ] }, 1034 | { 'dungeons': [ 0x0154, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '3' } ] }, 1035 | { 'dungeons': [ 0x0155, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '4' } ] }, 1036 | { 'dungeons': [ 0x0157, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '5' } ] }, 1037 | { 'dungeons': [ 0x0156, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '6' } ] }, 1038 | { 'dungeons': [ 0x015a, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '7' } ] }, 1039 | { 'dungeons': [ 0x0160, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '8' } ] }, 1040 | { 'dungeons': [ 0x0127, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '9' } ] }, 1041 | { 'dungeons': [ 0x0128, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '10' } ] }, 1042 | { 'dungeons': [ 0x012f, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '11' } ] }, 1043 | { 'dungeons': [ 0x014b, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '12' } ] }, 1044 | { 'dungeons': [ 0x012e, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '13' } ] }, 1045 | { 'dungeons': [ 0x0156, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '14' } ] }, 1046 | { 'dungeons': [ 0x0161, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '15' } ] }, 1047 | { 'dungeons': [ 0x015f, 0b0000 ], 'java': [ 'minecraft:note_block', { 'instrument': 'harp', 'note': '16' } ] }, 1048 | { 'dungeons': [ 0x01ea, 0b0000 ], 'java': [ 'minecraft:stripped_oak_log', { 'axis': 'y' } ] }, 1049 | { 'dungeons': [ 0x01ea, 0b0100 ], 'java': [ 'minecraft:stripped_oak_log', { 'axis': 'x' } ] }, 1050 | { 'dungeons': [ 0x01ea, 0b1000 ], 'java': [ 'minecraft:stripped_oak_log', { 'axis': 'z' } ] } 1051 | ] 1052 | 1053 | blocks_by_java_id = {} 1054 | blocks_by_dungeons_id = {} 1055 | 1056 | for i, b in enumerate(blocks): 1057 | if b['java'][0] in blocks_by_java_id: 1058 | blocks_by_java_id[b['java'][0]].append(b) 1059 | else: 1060 | blocks_by_java_id[b['java'][0]] = [b] 1061 | 1062 | if len(b['dungeons']) > 1: 1063 | if len(b['dungeons']) > 2: 1064 | for m in range(16): 1065 | if m & b['dungeons'][2] == b['dungeons'][1]: 1066 | blocks_by_dungeons_id[b['dungeons'][0] << 4 | m] = b 1067 | else: 1068 | blocks_by_dungeons_id[b['dungeons'][0] << 4 | b['dungeons'][1]] = b 1069 | else: 1070 | for m in range(16): 1071 | blocks_by_dungeons_id[b['dungeons'][0] << 4 | m] = b 1072 | 1073 | def find_java_block(block): 1074 | namespaced_id = block.namespace + ':' + block.id 1075 | if not namespaced_id in blocks_by_java_id: 1076 | return None 1077 | 1078 | if len(block.properties) > 0: 1079 | for b in blocks_by_java_id[namespaced_id]: 1080 | if len(b['java']) > 1: 1081 | matches = True 1082 | for prop in b['java'][1]: 1083 | if not prop in block.properties or b['java'][1][prop] != block.properties[prop].value: 1084 | matches = False 1085 | break 1086 | if matches: 1087 | return b 1088 | else: 1089 | return b 1090 | else: 1091 | return blocks_by_java_id[namespaced_id][0] 1092 | 1093 | return None 1094 | 1095 | def find_dungeons_block(block_id, block_data=0): 1096 | k = block_id << 4 | block_data 1097 | if k in blocks_by_dungeons_id: 1098 | return blocks_by_dungeons_id[k] 1099 | else: 1100 | return None -------------------------------------------------------------------------------- /examples/ConversionTools.py: -------------------------------------------------------------------------------- 1 | """A collection of tools that convert Dungeons tiles to other formats and vice versa.""" 2 | 3 | import os 4 | import time 5 | import json 6 | import re 7 | 8 | import anvil 9 | from nbt.nbt import * 10 | from PIL import Image 11 | 12 | from pretty_compact_json import stringify 13 | from JavaWorldReader import JavaWorldReader 14 | from Tile import Tile, Boundary, Door, Region 15 | from BlockMap import find_java_block, find_dungeons_block 16 | from ResourcesPackUtils import DungeonToJavaResourcesPack 17 | def find_tile_entity(chunk, x, y, z): 18 | for te in chunk.tile_entities: 19 | if te['x'].value == x and te['y'].value == y and te['z'].value == z: 20 | return te 21 | return None 22 | 23 | def structure_block_entity(x, y, z, mode='DATA', name='', metadata='', px=0, py=0, pz=0, sx=0, sy=0, sz=0): 24 | tile_entity = TAG_Compound() 25 | tile_entity.tags.extend([ 26 | TAG_String(name='author', value='?'), 27 | TAG_String(name='id', value='minecraft:structure_block'), 28 | TAG_Byte(name='ignoreEntities', value=1), 29 | TAG_Float(name='integrity', value=1), 30 | TAG_Byte(name='keepPacked', value=0), 31 | TAG_String(name='metadata', value=metadata), 32 | TAG_String(name='mirror', value='NONE'), 33 | TAG_String(name='mode', value=mode), 34 | TAG_String(name='name', value=name), 35 | TAG_Int(name='posX', value=px), 36 | TAG_Int(name='posY', value=py), 37 | TAG_Int(name='posZ', value=pz), 38 | TAG_Byte(name='powered', value=0), 39 | TAG_String(name='rotation', value='NONE'), 40 | TAG_Long(name='seed', value=0), 41 | TAG_Byte(name='showair', value=0), 42 | TAG_Byte(name='showboundingbox', value=0), 43 | TAG_Int(name='sizeX', value=sx), 44 | TAG_Int(name='sizeY', value=sy), 45 | TAG_Int(name='sizeZ', value=sz), 46 | TAG_Int(name='x', value=x), 47 | TAG_Int(name='y', value=y), 48 | TAG_Int(name='z', value=z) 49 | ]) 50 | return tile_entity 51 | 52 | # Colors for the plane images 53 | region_plane_colors = [ 54 | ( 98, 188, 50), # Walkable, minimap 55 | (237, 214, 59), # Walkable, no minimap 56 | ( 0, 0, 0), # Unwalkable, no minimap, used for big falls 57 | ( 25, 155, 216), # Walkable, minimap, used for overhangs/tunnels 58 | (244, 38, 16), # Unwalkable, no minimap, used for walls 59 | ] 60 | region_plane_color_names = [ 61 | 'Walkable, minimap, used for most playable areas', 62 | 'Walkable, no minimap, used for playable areas that are not on the minimap', 63 | 'Unwalkable, no minimap, used for big falls', 64 | 'Walkable, minimap, used for overhangs/tunnels', 65 | 'Unwalkable, no minimap, used for walls', 66 | ] 67 | 68 | def closest_color(rgb, palette): 69 | r, g, b = rgb 70 | color_diffs = [] 71 | for color in palette: 72 | cr, cg, cb = color 73 | color_diff = sqrt(abs(r - cr)**2 + abs(g - cg)**2 + abs(b - cb)**2) 74 | color_diffs.append((color_diff, color)) 75 | return min(color_diffs)[1] 76 | 77 | class JavaWorldToObjectGroup: 78 | """Converter that takes a Java Edition world and creates a Dungeons object group.""" 79 | def __init__(self, world_dir): 80 | self.world_dir = world_dir 81 | self.boundary_block = 'minecraft:barrier' 82 | 83 | def convert(self, dict_format=True): 84 | """Returns a Dungeons object group, or a list of tiles, based on the Java Edition world.""" 85 | with open(self.world_dir + '/objectgroup.json') as json_file: 86 | tiles = [Tile.from_dict(t) for t in json.load(json_file)['objects']] 87 | 88 | world = JavaWorldReader(self.world_dir) 89 | 90 | air_blocks = [ 91 | 'minecraft:air', 92 | 'minecraft:cave_air' 93 | ] 94 | 95 | player_heads = [ 96 | 'minecraft:player_head', 97 | 'minecraft:player_wall_head' 98 | ] 99 | 100 | # Apologies for the confusing variable names below. Let me explain what they mean: 101 | # ax, ay, az are absolute coordinates. These are the world coordinates of the block in Java edition. 102 | # tx, ty, tz are block coordinates relative to the tile's position. 103 | # cx and cz are chunk coordinates. Chunks hold 16x256x16 blocks. 104 | # yi and zi are iterable ranges for the Y and Z axes. 105 | 106 | for tile in tiles: 107 | # Creating these ranges here is faster than doing it for each slice/column of the tile 108 | zi = range(tile.size[2]) 109 | yi = range(min(256, tile.size[1])) 110 | 111 | doors = [] 112 | 113 | # For each slice of the tile along the X axis... 114 | for tx in range(tile.size[0]): 115 | ax = tx + tile.pos[0] 116 | cx = ax // 16 117 | 118 | # For each column of the slice along the Z axis... 119 | for tz in zi: 120 | az = tz + tile.pos[2] 121 | cz = az // 16 122 | chunk = world.chunk(cx, cz) 123 | if chunk is None: 124 | print(f'Warning: Missing chunk at {cx},{cz}. Blocks in this chunk will be ignored.') 125 | continue 126 | 127 | # TODO: Handle boundaries differently. With the current implemenation, 128 | # boundaries that go outside of the tile (most of the vanilla ones do...) 129 | # will lose the parts that are outside of the tile. 130 | current_boundary = None 131 | 132 | # For each block in the column along the Y axis... 133 | for ty in yi: 134 | ay = ty + tile.pos[1] 135 | 136 | # Get the block from the Java world chunk 137 | java_block = chunk.get_block(ax % 16, ay, az % 16) 138 | namespaced_id = java_block.namespace + ':' + java_block.id 139 | 140 | # There's no reason to keep going if the block is just air 141 | if namespaced_id in air_blocks: 142 | continue 143 | 144 | # Handle blocks that are used for special things in this converter, like tile doors and boundaries 145 | if namespaced_id == 'minecraft:structure_block': 146 | entity = find_tile_entity(chunk, ax, ay, az) 147 | if entity is None: 148 | continue 149 | 150 | if entity['name'].value.startswith('door:'): 151 | door = Door( 152 | pos = [tx + entity['posX'].value, ty + entity['posY'].value, tz + entity['posZ'].value], 153 | size = [entity['sizeX'].value, entity['sizeY'].value, entity['sizeZ'].value]) 154 | if len(entity['name'].value) > 5: 155 | door.name = entity['name'].value[5:] 156 | if len(entity['metadata'].value) > 2: 157 | try: 158 | door_info = json.loads(entity['metadata'].value) 159 | if 'tags' in door_info: 160 | door.tags = door_info['tags'] 161 | except: 162 | print(f'Warning: Invalid JSON in structure block metadata at {ax},{ay},{az}') 163 | tile.doors.append(door) 164 | 165 | elif entity['name'].value.startswith('region:'): 166 | tile_region = Region( # Note: This is a Tile.Region, not an anvil.Region 167 | pos = [tx + entity['posX'].value, ty + entity['posY'].value, tz + entity['posZ'].value], 168 | size = [entity['sizeX'].value, entity['sizeY'].value, entity['sizeZ'].value]) 169 | if len(entity['name'].value) > 7: 170 | tile_region.name = entity['name'].value[7:] 171 | if len(entity['metadata'].value) > 2: 172 | try: 173 | region_info = json.loads(entity['metadata'].value) 174 | if 'tags' in region_info: 175 | tile_region.tags = region_info['tags'] 176 | if 'type' in region_info: 177 | tile_region.type = region_info['type'] 178 | except: 179 | print(f'Warning: Invalid JSON in structure block metadata at {ax},{ay},{az}') 180 | tile.regions.append(tile_region) 181 | continue 182 | 183 | if namespaced_id in player_heads: 184 | tile_region = Region([tx, ty, tz]) # Note: This is a Tile.Region, not an anvil.Region 185 | tile_region.name = 'playerstart' 186 | tile_region.tags = 'playerstart' 187 | tile_region.type = 'trigger' 188 | tile.regions.append(tile_region) 189 | continue 190 | 191 | if namespaced_id == self.boundary_block: 192 | # Check if this block is connected to the last boundary found in this column 193 | if current_boundary is None or current_boundary.y + current_boundary.h != ty: 194 | current_boundary = Boundary(tx, ty, tz, 1) 195 | tile.boundaries.append(current_boundary) 196 | else: 197 | current_boundary.h += 1 198 | continue 199 | 200 | # Mapped blocks have both a Java namespaced ID + state and a Dungeons ID + data value 201 | mapped_block = find_java_block(java_block) 202 | 203 | if mapped_block is None: 204 | props = {} 205 | for prop in java_block.properties: 206 | props[prop] = java_block.properties[prop].value 207 | print(f'Warning: {java_block}{json.dumps(props)} is not mapped to anything. It will be replaced by air.') 208 | continue 209 | 210 | # Check if the block has a data value 211 | if len(mapped_block['dungeons']) > 1: 212 | tile.set_block(tx, ty, tz, block_id = mapped_block['dungeons'][0], block_data = mapped_block['dungeons'][1]) 213 | else: 214 | tile.set_block(tx, ty, tz, block_id = mapped_block['dungeons'][0]) 215 | 216 | # Convert plane images to tile planes 217 | if os.path.isfile(os.path.join(self.world_dir, 'region_plane', tile.id + '.png')): 218 | img = Image.open(os.path.join(self.world_dir, 'region_plane', tile.id + '.png')).convert('RGB') 219 | for x in range(tile.size[0]): 220 | for z in zi: 221 | pixel = img.getpixel((x, z)) 222 | idx = tile.get_block_index(x, 0, z) 223 | if pixel in region_plane_colors: 224 | tile.region_plane[idx] = region_plane_colors.index(pixel) 225 | else: 226 | tile.region_plane[idx] = region_plane_colors.index(closest_color(pixel, region_plane_colors)) 227 | 228 | if os.path.isfile(os.path.join(self.world_dir, 'region_y_plane', tile.id + '.png')): 229 | tile.region_y_plane_copy_height = False 230 | img = Image.open(os.path.join(self.world_dir, 'region_y_plane', tile.id + '.png')).convert('L') 231 | for x in range(tile.size[0]): 232 | for z in zi: 233 | idx = tile.get_block_index(x, 0, z) 234 | tile.region_y_plane[idx] = img.getpixel((x, z)) 235 | 236 | if os.path.isfile(os.path.join(self.world_dir, 'walkable_plane', tile.id + '.png')): 237 | tile.write_walkable_plane = True 238 | img = Image.open(os.path.join(self.world_dir, 'walkable_plane', tile.id + '.png')).convert('L') 239 | for x in range(tile.size[0]): 240 | for z in zi: 241 | idx = tile.get_block_index(x, 0, z) 242 | tile.walkable_plane[idx] = img.getpixel((x, z)) 243 | 244 | if dict_format: 245 | return {'objects':[t.dict() for t in tiles]} 246 | else: 247 | return {'objects':tiles} 248 | 249 | 250 | class ObjectGroupToJavaWorld: 251 | """Converter that takes a Dungeons object group and creates a Java Edition world.""" 252 | def __init__(self, objectgroup, world_dir, resources_pack_path=None): 253 | self.objectgroup = objectgroup 254 | self.world_dir = world_dir 255 | self.level_name = 'Converted Object Group' 256 | self.boundary_block = anvil.Block('minecraft', 'barrier') 257 | 258 | # If Not None, it will convert a MC Dungeon resources pack to a MC resources pack 259 | self.resources_pack_path = resources_pack_path 260 | 261 | # If True, convert regions that are small enough to structure blocks 262 | self.region_structure_blocks = True 263 | 264 | # If True, use player heads as playerstart regions instead of structure blocks 265 | self.playerstart_to_player_head = True 266 | 267 | def convert(self): 268 | """Creates a Java Edition world in the world directory from the object group.""" 269 | # TODO: Converting to a Java world should be done one region or maybe even 270 | # one sub-region at a time. Right now, all regions are kept 271 | # in memory until the conversion process is done, which means the memory 272 | # usage can be massive for bigger object groups. 273 | 274 | # anvil-parser doesn't actually support loading a region from a file and 275 | # then editing it and writing it to a file again. Regions loaded from a 276 | # file are read-only, and the regions that can be edited start out empty. 277 | 278 | region_cache = {} 279 | block_cache = {} 280 | 281 | def get_region(rx, rz): 282 | if f'{rx}x{rz}' in region_cache: 283 | return region_cache[f'{rx}x{rz}'] 284 | else: 285 | region_cache[f'{rx}x{rz}'] = anvil.EmptyRegion(rx, rz) 286 | return region_cache[f'{rx}x{rz}'] 287 | 288 | structure_block = anvil.Block('minecraft', 'structure_block') 289 | player_head = anvil.Block('minecraft', 'player_head') 290 | 291 | def find_room_for_structure_block(area, get_block): 292 | xi = range(area[0]) 293 | zi = range(area[1]) 294 | 295 | # Blocks that will break if a stucture block is placed on top of them 296 | breakable_blocks = [0x3c, 0xc6] 297 | 298 | # Check the area and blocks above it 299 | for y in range(49): 300 | for x in xi: 301 | for z in zi: 302 | if get_block(x, y, z) == 0 and not get_block(x, y - 1, z) in breakable_blocks: 303 | return (x, y, z) 304 | 305 | # Check blocks below the area 306 | for y in range(-1, -49, -1): 307 | for x in xi: 308 | for z in zi: 309 | if get_block(x, y, z) == 0 and not get_block(x, y - 1, z) in breakable_blocks: 310 | return (x, y, z) 311 | 312 | # No room found :( 313 | return None 314 | 315 | if isinstance(self.objectgroup, dict): 316 | og = self.objectgroup 317 | 318 | else: # If objectgroup is a file path, parse the json file 319 | with open(self.objectgroup) as json_file: 320 | og = json.load(json_file) 321 | 322 | os.makedirs(os.path.join(self.world_dir, 'region_plane'), exist_ok=True) 323 | os.makedirs(os.path.join(self.world_dir, 'region_y_plane'), exist_ok=True) 324 | os.makedirs(os.path.join(self.world_dir, 'walkable_plane'), exist_ok=True) 325 | 326 | for tile_dict in og['objects']: 327 | if isinstance(tile_dict, Tile): 328 | tile = tile_dict 329 | else: 330 | tile = Tile.from_dict(tile_dict) 331 | 332 | zi = range(tile.size[2]) 333 | yi = range(min(256, tile.size[1])) 334 | 335 | # For each slice of the tile along the X axis... 336 | for tx in range(tile.size[0]): 337 | ax = tx + tile.pos[0] 338 | rx = ax // 512 339 | 340 | # For each column of the slice along the Z axis... 341 | for tz in zi: 342 | az = tz + tile.pos[2] 343 | rz = az // 512 344 | region = get_region(rx, rz) 345 | 346 | # For each block in the column along the Y axis... 347 | for ty in yi: 348 | ay = ty + tile.pos[1] 349 | 350 | # Skip this block if it's outside of the world bounds 351 | if ay < 0 or ay >= 256: 352 | continue 353 | 354 | bidx = tile.get_block_index(tx, ty, tz) 355 | 356 | # If the block is just air, we don't need to do anything 357 | if tile.blocks[bidx] == 0: 358 | continue 359 | 360 | # Get the Java block from the cache if it's there 361 | bcid = tile.blocks[bidx] << 4 | tile.block_data[bidx] 362 | if bcid in block_cache: 363 | java_block = block_cache[bcid] 364 | 365 | else: # If not, find it and add it to the cache to speed things up later 366 | mapped_block = find_dungeons_block(tile.blocks[bidx], tile.block_data[bidx]) 367 | 368 | if mapped_block is None: 369 | print(f'Warning: {tile.blocks[bidx]}:{tile.block_data[bidx]} is not mapped to anything. It will be replaced by air.') 370 | continue 371 | 372 | if len(mapped_block['java']) > 1: 373 | java_block = anvil.Block(*mapped_block['java'][0].split(':', 1), mapped_block['java'][1]) 374 | else: 375 | java_block = anvil.Block(*mapped_block['java'][0].split(':', 1)) 376 | 377 | block_cache[bcid] = java_block 378 | 379 | # Once we have the Java block, add it to the region 380 | region.set_block(java_block, ax, ay, az) 381 | 382 | # TODO: Block post-processing to fix fences, walls, stairs, and more 383 | 384 | converter_blocks = [] 385 | 386 | # Add the tile doors to the world 387 | for door in tile.doors: 388 | def get_block(x, y, z): 389 | tx = x + door.pos[0] 390 | ty = y + door.pos[1] 391 | tz = z + door.pos[2] 392 | if f'{tx},{ty},{tz}' in converter_blocks: 393 | return -1 394 | if tx >= 0 and tx < tile.size[0] and ty >= 0 and ty < tile.size[1] and tz >= 0 and tz < tile.size[2]: 395 | return tile.get_block_id(tx, ty, tz) 396 | else: 397 | return 0 398 | pos = find_room_for_structure_block(door.size[::2], get_block) 399 | 400 | if pos is None: 401 | if hasattr(door, 'name'): 402 | print(f'Warning: No room to place structure block for door: {door.name}') 403 | else: 404 | print(f'Warning: No room to place structure block for unnamed door.') 405 | 406 | else: 407 | tpos = [p + d for p, d in zip(pos, door.pos)] 408 | if tpos[0] >= 0 and tpos[0] < tile.size[0] and tpos[1] >= 0 and tpos[1] < tile.size[1] and tpos[2] >= 0 and tpos[2] < tile.size[2]: 409 | apos = [p + t for p, t in zip(tpos, tile.pos)] 410 | region = get_region(apos[0] // 512, apos[2] // 512) 411 | region.set_block(structure_block, *apos) 412 | metadata = door.dict() 413 | metadata.pop('name', None) 414 | metadata.pop('pos', None) 415 | metadata.pop('size', None) 416 | if hasattr(door, 'name'): 417 | tile_entity = structure_block_entity(*apos, 'SAVE', f'door:{door.name}', json.dumps(metadata), *[-v for v in pos], *door.size) 418 | else: 419 | tile_entity = structure_block_entity(*apos, 'SAVE', 'door:', json.dumps(metadata), *[-v for v in pos], *door.size) 420 | region.chunks[apos[2] // 16 % 32 * 32 + apos[0] // 16 % 32].tile_entities.append(tile_entity) 421 | converter_blocks.append(f'{tpos[0]},{tpos[1]},{tpos[2]}') 422 | 423 | if self.region_structure_blocks: 424 | # Add the tile regions to the world 425 | for tile_region in tile.regions: 426 | # playerstart regions just use a player head instead of a structure block 427 | if self.playerstart_to_player_head and hasattr(tile_region, 'tags') and tile_region.tags == 'playerstart': 428 | ax = tile.pos[0] + tile_region.pos[0] 429 | ay = tile.pos[1] + tile_region.pos[1] 430 | az = tile.pos[2] + tile_region.pos[2] 431 | rx = ax // 512 432 | rz = az // 512 433 | region = get_region(rx, rz) 434 | region.set_block(player_head, ax, ay, az) 435 | tile_entity = TAG_Compound() 436 | tile_entity.tags.extend([ 437 | TAG_String(name='id', value='minecraft:skull'), 438 | TAG_Byte(name='keepPacked', value=0), 439 | TAG_Int(name='x', value=ax), 440 | TAG_Int(name='y', value=ay), 441 | TAG_Int(name='z', value=az) 442 | ]) 443 | region.chunks[az // 16 % 32 * 32 + ax // 16 % 32].tile_entities.append(tile_entity) 444 | converter_blocks.append(f'{tile_region.pos[0]},{tile_region.pos[1]},{tile_region.pos[2]}') 445 | 446 | elif tile_region.size[0] <= 48 and tile_region.size[1] <= 48 and tile_region.size[2] <= 48: 447 | def get_block(x, y, z): 448 | tx = x + tile_region.pos[0] 449 | ty = y + tile_region.pos[1] 450 | tz = z + tile_region.pos[2] 451 | if f'{tx},{ty},{tz}' in converter_blocks: 452 | return -1 453 | if tx >= 0 and tx < tile.size[0] and ty >= 0 and ty < tile.size[1] and tz >= 0 and tz < tile.size[2]: 454 | return tile.get_block_id(tx, ty, tz) 455 | else: 456 | return 0 457 | pos = find_room_for_structure_block(tile_region.size[::2], get_block) 458 | 459 | if pos is None: 460 | if hasattr(tile_region, 'name'): 461 | print(f'Warning: No room to place structure block for region: {tile_region.name}') 462 | else: 463 | print(f'Warning: No room to place structure block for unnamed region.') 464 | 465 | else: 466 | tpos = [p + d for p, d in zip(pos, tile_region.pos)] 467 | if tpos[0] >= 0 and tpos[0] < tile.size[0] and tpos[1] >= 0 and tpos[1] < tile.size[1] and tpos[2] >= 0 and tpos[2] < tile.size[2]: 468 | apos = [p + t for p, t in zip(tpos, tile.pos)] 469 | region = get_region(apos[0] // 512, apos[2] // 512) 470 | region.set_block(structure_block, *apos) 471 | metadata = tile_region.dict() 472 | metadata.pop('name', None) 473 | metadata.pop('pos', None) 474 | metadata.pop('size', None) 475 | if hasattr(tile_region, 'name'): 476 | tile_entity = structure_block_entity(*apos, 'SAVE', f'region:{tile_region.name}', json.dumps(metadata), *[-v for v in pos], *tile_region.size) 477 | else: 478 | tile_entity = structure_block_entity(*apos, 'SAVE', 'region:', json.dumps(metadata), *[-v for v in pos], *tile_region.size) 479 | region.chunks[apos[2] // 16 % 32 * 32 + apos[0] // 16 % 32].tile_entities.append(tile_entity) 480 | converter_blocks.append(f'{tpos[0]},{tpos[1]},{tpos[2]}') 481 | 482 | # Add the tile boundaries to the world 483 | for boundary in tile.boundaries: 484 | ax = tile.pos[0] + boundary.x 485 | az = tile.pos[2] + boundary.z 486 | rx = ax // 512 487 | rz = az // 512 488 | region = get_region(rx, rz) 489 | 490 | for by in range(boundary.h): 491 | ay = tile.pos[1] + boundary.y + by 492 | 493 | region.set_block(self.boundary_block, ax, ay, az) 494 | 495 | # Convert the planes to images, so they can be edited easily 496 | region_plane_img = Image.new('RGB', (tile.size[0], tile.size[2])) 497 | region_y_plane_img = Image.new('L', (tile.size[0], tile.size[2])) 498 | walkable_plane_img = Image.new('L', (tile.size[0], tile.size[2])) 499 | for x in range(tile.size[0]): 500 | for z in zi: 501 | idx = tile.get_block_index(x, 0, z) 502 | region_plane_img.putpixel((x, z), region_plane_colors[tile.region_plane[idx]]) 503 | region_y_plane_img.putpixel((x, z), tile.region_y_plane[idx]) 504 | walkable_plane_img.putpixel((x, z), tile.walkable_plane[idx]) 505 | 506 | region_plane_img.save(os.path.join(self.world_dir, 'region_plane', tile.id + '.png')) 507 | region_y_plane_img.save(os.path.join(self.world_dir, 'region_y_plane', tile.id + '.png')) 508 | walkable_plane_img.save(os.path.join(self.world_dir, 'walkable_plane', tile.id + '.png')) 509 | 510 | with open(os.path.join(self.world_dir, 'region_plane', '_README.txt'), 'w') as region_plane_readme: 511 | region_plane_readme.write('Region plane colors:\n\n') 512 | region_plane_readme.write('\n'.join([('#%02x%02x%02x' % c) + f': {n}' for c, n in zip(region_plane_colors, region_plane_color_names)])) 513 | 514 | # Write regions to files 515 | os.makedirs(os.path.join(self.world_dir, 'region'), exist_ok=True) 516 | for k in region_cache: 517 | region_cache[k].save(os.path.join(self.world_dir, f'region/r.{region_cache[k].x}.{region_cache[k].z}.mca')) 518 | 519 | # For convenience, write the object group to objectgroup.json in the world 520 | # directory, so JavaWorldToObjectGroup can convert the world back to an 521 | # object group without any changes. 522 | og_copy = json.loads(json.dumps(og)) # faster than copy.deepcopy 523 | for tile in og_copy['objects']: 524 | tile.pop('blocks', None) 525 | tile.pop('boundaries', None) 526 | tile.pop('doors', None) 527 | tile.pop('height-plane', None) 528 | tile.pop('region-plane', None) 529 | tile.pop('region-y-plane', None) 530 | tile.pop('walkable-plane', None) 531 | if self.region_structure_blocks and 'regions' in tile: 532 | # Keep only regions that are too big turn into structure blocks 533 | tile['regions'] = [r for r in tile['regions'] if r['size'][0] > 48 or r['size'][1] > 48 or r['size'][2] > 48] 534 | with open(os.path.join(self.world_dir, 'objectgroup.json'), 'w') as out_file: 535 | out_file.write(stringify(og_copy)) 536 | 537 | # Create level.dat file 538 | level = NBTFile('level_template.dat', 'rb') 539 | level['Data']['LevelName'].value = self.level_name 540 | level['Data']['LastPlayed'].value = int(time.time()*1000) 541 | 542 | # Place the player spawn above the center of the first tile. 543 | # This could probably be made a bit smarter, since the center of the tile 544 | # might still be above the void. For now, this faster solution will have to do. 545 | level['Data']['SpawnX'].value = int(og['objects'][0]['pos'][0] + og['objects'][0]['size'][0] * 0.5) 546 | level['Data']['SpawnY'].value = min(255, og['objects'][0]['pos'][1] + og['objects'][0]['size'][1]) 547 | level['Data']['SpawnZ'].value = int(og['objects'][0]['pos'][2] + og['objects'][0]['size'][2] * 0.5) 548 | 549 | level.write_file(os.path.join(self.world_dir, 'level.dat')) 550 | 551 | if self.resources_pack_path is not None: 552 | print("Resource pack") 553 | DungeonToJavaResourcesPack(resource_pack_path=self.resources_pack_path, 554 | dest_path=os.path.join(self.world_dir, "resources"), 555 | verbose=False).convert() 556 | -------------------------------------------------------------------------------- /examples/Get_Block_IDs_and_Data_Values.py: -------------------------------------------------------------------------------- 1 | import zlib 2 | import base64 3 | import math 4 | 5 | # Function for getting the ID and data value of a block at x,y,z 6 | def get_block(blocks, tile_size, x, y, z): 7 | tile_volume = tile_size[0] * tile_size[1] * tile_size[2] 8 | block_id_index = (y * tile_size[2] + z) * tile_size[0] + x 9 | 10 | # To get the data value of the block, we need to check if the block index is 11 | # even or odd to know if we need to take the first or latter half of the 12 | # byte. 13 | if block_id_index % 2 == 0: 14 | return { 15 | 'id': blocks[block_id_index], 16 | 'data': blocks[math.floor(block_id_index / 2) + tile_volume] >> 4 17 | } 18 | else: 19 | return { 20 | 'id': blocks[block_id_index], 21 | 'data': blocks[math.floor(block_id_index / 2) + tile_volume] & 0xf 22 | } 23 | 24 | 25 | # Example tile. 26 | # It would be better to read this from an object group file, but it will do for 27 | # this example script. 28 | tile = { 29 | "id": "example_tile_01", 30 | "pos": [36, 12, 46], 31 | "size": [7, 3, 7], 32 | "blocks": "eNpTViYVMIAALan28vKO8vIKTIqBgaOBgYF4qgEAohseFg==", 33 | "region-plane": "eNpjYCARAAAAMQAB", 34 | "doors": [ 35 | {"pos": [1, 1, 0], "size": [5, 1, 1]}, 36 | {"pos": [1, 1, 6], "size": [5, 1, 1]} 37 | ] 38 | } 39 | 40 | # Decode and decompress the blocks property. 41 | block_bytes = zlib.decompress(base64.b64decode(tile['blocks'])) 42 | 43 | # Using the function to get a block. 44 | block = get_block(block_bytes, tile['size'], x = 0, y = 2, z = 4) 45 | 46 | # Should be 35 and 8 for the example tile. 47 | print('Block ID: ' + str(block['id'])) 48 | print('Block Data Value: ' + str(block['data'])) -------------------------------------------------------------------------------- /examples/JavaWorldReader.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | import anvil 3 | 4 | """Module for optimized reading of Minecraft Java Edition worlds. 5 | 6 | Handles caching automatically. 7 | """ 8 | 9 | class JavaWorldReader: 10 | def __init__(self, world_dir): 11 | self.dir = world_dir 12 | 13 | self.region_cache_max = 4 14 | self.__region_cache = OrderedDict() 15 | 16 | self.chunk_cache_max = 64 17 | self.__chunk_cache = OrderedDict() 18 | 19 | def chunk(self, cx, cz): 20 | try: 21 | if f'{cx}x{cz}' in self.__chunk_cache: 22 | return self.__chunk_cache[f'{cx}x{cz}'] 23 | 24 | else: 25 | rx = cx // 32 26 | rz = cz // 32 27 | 28 | if not f'{rx}x{rz}' in self.__region_cache: 29 | self.__region_cache[f'{rx}x{rz}'] = anvil.Region.from_file(f'{self.dir}/region/r.{rx}.{rz}.mca') 30 | if len(self.__region_cache) > self.region_cache_max: 31 | self.__region_cache.popitem(last=False) 32 | 33 | self.__chunk_cache[f'{cx}x{cz}'] = anvil.Chunk.from_region(self.__region_cache[f'{rx}x{rz}'], cx, cz) 34 | if len(self.__chunk_cache) > self.chunk_cache_max: 35 | self.__chunk_cache.popitem(last=False) 36 | return self.__chunk_cache[f'{cx}x{cz}'] 37 | 38 | except: 39 | return None -------------------------------------------------------------------------------- /examples/ResourcesPackUtils.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | from shutil import copy2, make_archive 3 | from pathlib import Path 4 | import BlockMap as BlockMap 5 | from os import makedirs, path 6 | 7 | """ 8 | MCD = MineCraft Dungeon 9 | MCJ = MineCraft Java 10 | """ 11 | 12 | MCD_PACK_ICON = "pack_icon.png" 13 | MCJ_PACK_ICON = "pack.png" 14 | MCJ_PACK_META = "pack.mcmeta" 15 | 16 | MCD_BLOCK_FOLDER = path.join("images", "blocks") 17 | MCJ_BLOCK_FOLDER = path.join("assets", "minecraft", "textures", "block") 18 | 19 | additional_dict = { 20 | 'stonebrick': 'stone_bricks', 21 | 'stonebrick_mossy': 'mossy_stone_bricks', 22 | 'stonebrick_cracked': 'cracked_stone_bricks', 23 | 'stonebrick_carved': 'chiseled_stone_bricks', 24 | 'stonefloor1': 'blackstone', 25 | 'stonefloor2': 'chiseled_polished_blackstone', 26 | 'stonefloor3': 'polished_blackstone', 27 | 'stonefloor4': 'polished_blackstone_bricks', 28 | 'stonefloor5': 'gilded_blackstone', 29 | 'stonefloor6': 'cracked_polished_blackstone_bricks', 30 | 'stonefloor7': 'lodestone', 31 | 'stonefloor8': 'ancient_debris', 32 | 'stonefloor9': 'infested_chiseled_stone_bricks', 33 | 'stone_andesite': 'andesite', 34 | 'stone_andesite_smooth': 'polished_andesite', 35 | 'stone_diorite': 'diorite', 36 | 'stone_diorite_smooth': 'polished_diorite', 37 | 'stone_slab_side': 'smooth_stone_slab_side', # Not sure 38 | 'tallgrass': 'grass', 39 | 'tnt_bottom': 'tnt_bottom', 40 | 'tnt_top': 'tnt_top', 41 | 'tnt_side': 'tnt_side', 42 | 'torch_on': 'torch', 43 | 'redstone_torch_on': 'redstone_torch', 44 | 'trapdoor': 'oak_trapdoor', 45 | 'waterlily': 'lily_pad', 46 | 'wheat_stage_0': 'wheat_stage0', 47 | 'wheat_stage_1': 'wheat_stage1', 48 | 'wheat_stage_2': 'wheat_stage2', 49 | 'wheat_stage_3': 'wheat_stage3', 50 | 'wheat_stage_4': 'wheat_stage4', 51 | 'wheat_stage_5': 'wheat_stage5', 52 | 'wheat_stage_6': 'wheat_stage6', 53 | 'wheat_stage_7': 'wheat_stage7', 54 | 'wool_colored_white': 'white_wool', 55 | 'wool_colored_yellow': 'yellow_wool', 56 | 'wool_colored_red': 'red_wool', 57 | 'wool_colored_purple': 'purple_wool', 58 | 'wool_colored_pink': 'pink_wool', 59 | 'wool_colored_orange': 'orange_wool', 60 | 'wool_colored_magenta': 'magenta_wool', 61 | 'wool_colored_lime': 'lime_wool', 62 | 'wool_colored_green': 'green_wool', 63 | 'wool_colored_light_blue': 'light_blue_wool', 64 | 'wool_colored_gray': 'gray_wool', 65 | 'wool_colored_cyan': 'cyan_wool', 66 | 'wool_colored_brown': 'brown_wool', 67 | 'wool_colored_blue': 'blue_wool', 68 | 'wool_colored_black': 'black_wool', 69 | 'anvil_base': 'anvil', 70 | 'anvil_top_damaged_0': 'anvil_top', 71 | 'anvil_top_damaged_1': 'chipped_anvil_top', 72 | 'anvil_top_damaged_2': 'damaged_anvil_top', 73 | 'beacon': 'beacon', 74 | 'beetroot_stage_0': 'beetroot_stage_0', 75 | 'beetroot_stage_1': 'beetroot_stage_1', 76 | 'beetroot_stage_2': 'beetroot_stage_2', 77 | 'beetroot_stage_3': 'beetroot_stage_3', 78 | 'brewing_stand_base': 'brewing_stand_base', 79 | 'brick': 'bricks', 80 | 'cactus_bottom': 'cactus_bottom', 81 | 'cactus_top': 'cactus_top', 82 | 'cactus_side': 'cactus_side', 83 | 'cake_bottom': 'cake_bottom', 84 | 'cake_inner': 'cake_inner', 85 | 'cake_side': 'cake_side', 86 | 'cake_top': 'cake_top', 87 | 'carrots_stage_0': 'carrots_stage0', 88 | 'carrots_stage_1': 'carrots_stage1', 89 | 'carrots_stage_2': 'carrots_stage2', 90 | 'carrots_stage_3': 'carrots_stage3', 91 | 'cauldron_bottom': 'cauldron_bottom', 92 | 'cauldron_inner': 'cauldron_inner', 93 | 'cauldron_side': 'cauldron_side', 94 | 'cauldron_top': 'cauldron_top', 95 | 'cobblestone_mossy': 'mossy_cobblestone', 96 | 'cocoa_stage_0': 'cocoa_stage0', 97 | 'cocoa_stage_1': 'cocoa_stage1', 98 | 'cocoa_stage_2': 'cocoa_stage2', 99 | 'comparator_on': 'comparator_on', 100 | 'comparator_off': 'comparator', 101 | 'crafting_table_front': 'crafting_table_front', 102 | 'crafting_table_side': 'crafting_table_side', 103 | 'crafting_table_top': 'crafting_table_top', 104 | 'custom_0': 'white_concrete', 105 | 'custom_1': 'orange_concrete', 106 | 'custom_2': 'magenta_concrete', 107 | 'custom_3': 'light_blue_concrete', 108 | 'custom_4': 'yellow_concrete', 109 | 'custom_5': 'lime_concrete', 110 | 'custom_6': 'pink_concrete', 111 | 'custom_7': 'gray_concrete', 112 | 'custom_8': 'light_gray_concrete', 113 | 'custom_9': 'cyan_concrete', 114 | 'custom_10': 'blue_concrete', 115 | 'custom_11': 'purple_concrete', 116 | 'custom_12': 'brown_concrete', 117 | 'custom_13': 'green_concrete', 118 | 'custom_14': 'red_concrete', 119 | 'custom_15': 'black_concrete', 120 | 'daylight_detector_inverted_top': 'daylight_detector_inverted_top', 121 | 'daylight_detector_side': 'daylight_detector_side', 122 | 'daylight_detector_top': 'daylight_detector_top', 123 | 'deadbush': 'dead_bush', 124 | 'destroy_stage_0': 'destroy_stage_0', 125 | 'destroy_stage_1': 'destroy_stage_1', 126 | 'destroy_stage_2': 'destroy_stage_2', 127 | 'destroy_stage_3': 'destroy_stage_3', 128 | 'destroy_stage_4': 'destroy_stage_4', 129 | 'destroy_stage_5': 'destroy_stage_5', 130 | 'destroy_stage_6': 'destroy_stage_6', 131 | 'destroy_stage_7': 'destroy_stage_7', 132 | 'destroy_stage_8': 'destroy_stage_8', 133 | 'destroy_stage_9': 'destroy_stage_9', 134 | 'dirt_path_side': 'grass_path_side', 135 | 'dirt_path_top': 'grass_path_top', 136 | 'dispenser_front_horizontal': 'dispenser_front', 137 | 'dispenser_front_vertical': 'dispenser_front_vertical', 138 | 'door_acacia_lower': 'acacia_door_bottom', 139 | 'door_acacia_upper': 'acacia_door_top', 140 | 'door_birch_lower': 'birch_door_bottom', 141 | 'door_birch_upper': 'birch_door_top', 142 | 'door_dark_oak_lower': 'dark_oak_door_bottom', 143 | 'door_dark_oak_upper': 'dark_oak_door_top', 144 | 'door_iron_lower': 'iron_door_bottom', 145 | 'door_iron_upper': 'iron_door_top', 146 | 'door_jungle_lower': 'jungle_door_bottom', 147 | 'door_jungle_upper': 'jungle_door_top', 148 | 'door_spruce_lower': 'spruce_door_bottom', 149 | 'door_spruce_upper': 'spruce_door_top', 150 | 'door_wood_lower': 'oak_door_bottom', 151 | 'door_wood_upper': 'oak_door_top', 152 | 'grass_top': 'grass_block_top', 153 | 'grass_side': 'grass_block_side', 154 | 'grass_path_top': 'grass_path_top', 155 | 'grass_path_side': 'grass_path_side', 156 | 'dirt_podzol_top': 'podzol_top', 157 | 'dirt_podzol_side': 'podzol_side', 158 | 'mycelium_side': 'mycelium_side', 159 | 'mycelium_top': 'mycelium_top', 160 | 'log_big_oak': 'oak_log', 161 | 'log_big_oak_top': 'oak_log_top', 162 | 'leaves_oak': 'oak_leaves', 163 | # TODO: finish the list (A lot more to do) 164 | } 165 | 166 | """ 167 | Ignored: 168 | stonecutter_top (size not matching) 169 | stonecutter_side (size not matching) 170 | stonecutter_other_side (size not matching) 171 | stonecutter_bottom (size not matching) 172 | stone_gradient_{0..15} 173 | stone_path_side 174 | stone_path_top 175 | stone_slab_top 176 | tallgrass 177 | torch_on_emissive 178 | transparent 179 | trip_wire 180 | trip_wire_source 181 | wool_colored_silver 182 | _end_stone 183 | bed_feet_end 184 | bed_feet_side 185 | bed_feet_top 186 | bed_head_end 187 | bed_head_side 188 | bed_head_top 189 | build_allow 190 | build_deny 191 | camera_back 192 | camera_front 193 | camera_side 194 | camera_top 195 | carried_waterlily 196 | cauldron_water 197 | chest_front 198 | chest_side 199 | chest_top 200 | command_block 201 | diamond_ore_emissive 202 | dirt_podzol_side 203 | dirt_podzol_top 204 | grass_and_leaves_27 205 | _grass_side 206 | """ 207 | 208 | 209 | class DungeonToJavaResourcesPack: 210 | 211 | def __init__(self, resource_pack_path, dest_path, verbose=False): 212 | self.dest_path = dest_path 213 | self.verbose = verbose 214 | self.path = resource_pack_path 215 | if verbose: 216 | print("from ", self.path, " to ", self.dest_path) 217 | 218 | def convert(self): 219 | # Creating temp folder to store the resources 220 | f = tempfile.TemporaryDirectory() 221 | 222 | if self.verbose: 223 | print("Temp directory created ", f.name) 224 | 225 | # Creating directory to store blocks textures 226 | makedirs(path.join(f.name, MCJ_BLOCK_FOLDER)) 227 | 228 | # Copying icon pack 229 | copy2(path.join(self.path, MCD_PACK_ICON), path.join(f.name, MCJ_PACK_ICON)) 230 | 231 | # Creating meta description file 232 | meta = open(path.join(f.name, MCJ_PACK_META), "w") 233 | meta.write('{ "pack": { "pack_format": 5, "description": "auto generated resources pack" } }') 234 | meta.close() 235 | 236 | # Take all textures (.png) from the directory give. TODO: convert TGA 237 | blocks_path = Path(path.join(self.path, MCD_BLOCK_FOLDER)).glob('*.png') 238 | 239 | # Iterate though all blocs 240 | for block in blocks_path: 241 | # Try to found the id 242 | java_block = BlockMap.blocks_by_java_id.get("minecraft:" + block.stem) 243 | if java_block is not None: 244 | block_name = java_block[0]['java'][0] 245 | # Cpy in the directory 246 | copy2(block.absolute(), path.join(f.name, MCJ_BLOCK_FOLDER, block_name[10:len(block_name)] + ".png")) 247 | else: 248 | # Check the additional dict 249 | java_block = additional_dict.get(block.stem) 250 | 251 | if java_block is not None: 252 | # Cpy in the directory 253 | copy2(block.absolute(), path.join(f.name, MCJ_BLOCK_FOLDER, java_block + ".png")) 254 | elif self.verbose is True: 255 | print(block.stem, " not recognized") 256 | # Create the archive 257 | make_archive(self.dest_path, 'zip', f.name) 258 | 259 | # delete the temp directory 260 | f.cleanup() 261 | 262 | -------------------------------------------------------------------------------- /examples/Set_Block_IDs_and_Data_Values.py: -------------------------------------------------------------------------------- 1 | import zlib 2 | import base64 3 | import math 4 | 5 | # Function for setting the ID and data value for a block. 6 | def set_block(blocks, tile_size, x, y, z, block_id, block_data): 7 | tile_volume = tile_size[0] * tile_size[1] * tile_size[2] 8 | block_id_index = (y * tile_size[2] + z) * tile_size[0] + x 9 | block_data_index = math.floor(block_id_index / 2) + tile_volume 10 | 11 | blocks[block_id_index] = block_id 12 | 13 | # To set the data value of the block, we need to check if the block index is 14 | # even or odd to know if we need to change the first or latter half of the byte. 15 | if block_id_index % 2 == 0: 16 | blocks[block_data_index] = blocks[block_data_index] & 0b00001111 | block_data << 4 17 | else: 18 | blocks[block_data_index] = blocks[block_data_index] & 0b11110000 | block_data 19 | 20 | 21 | # In this example, we're starting from scratch without a tile, so we need to create one 22 | # and create a blocks array to modify. 23 | tile = { 24 | 'id': 'my_custom_tile', 25 | 'size': [7, 3, 7] 26 | } 27 | blocks_array = [0] * math.ceil(tile['size'][0] * tile['size'][1] * tile['size'][2] * 1.5) 28 | 29 | # Using the function to change a block to light gray wool. 30 | set_block(blocks_array, tile['size'], x = 0, y = 2, z = 4, block_id = 35, block_data = 8) 31 | 32 | # Compress and encode the blocks and add them to the tile. 33 | tile['blocks'] = base64.b64encode(zlib.compress(bytes(blocks_array), 9)).decode('utf-8') 34 | 35 | print(tile) -------------------------------------------------------------------------------- /examples/SimpleTileViewer.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import json 3 | import re 4 | import PySimpleGUI as sg 5 | import numpy as np 6 | from PIL import Image, ImageTk 7 | from Tile import Tile 8 | 9 | # PySimpleGUI window layout 10 | 11 | tile_list_column = [ 12 | [ 13 | sg.Text('Object Group'), 14 | sg.In(size=(25, 1), enable_events=True, key='-OBJECTGROUP-'), 15 | sg.FileBrowse(), 16 | ], 17 | [ 18 | sg.Listbox( 19 | values=[], enable_events=True, size=(40, 20), key='-TILE LIST-' 20 | ) 21 | ], 22 | [sg.Text('0 / Green: Walkable')], 23 | [sg.Text('1 / Yellow: Walkable, no minimap')], 24 | [sg.Text('2 / Gray: Not walkable, no minimap')], 25 | [sg.Text('3 / Blue: Walkable')], 26 | [sg.Text('4 / Red: Not walkable, no minimap')], 27 | [sg.Text('Boundary / Magenta: Invisible wall')] 28 | ] 29 | 30 | tile_viewer_column = [ 31 | [ sg.Text('Select a tile to view', size=(40, 1), key='-TOUT-'), 32 | sg.Text('Scale:'), 33 | sg.Slider(range=(1, 8), orientation='h', size=(34, 20), default_value=4, key='-SCALE-', enable_events=True)], 34 | [ sg.Checkbox('Show boundaries', default=True, key='-BOUNDARIES-', enable_events=True), 35 | sg.Checkbox('Show height as shade', default=True, key='-HEIGHTMAP-', enable_events=True) 36 | ], 37 | [sg.Image(key='-IMAGE-')], 38 | ] 39 | 40 | layout = [ 41 | [ 42 | sg.Column(tile_list_column), 43 | sg.VSeperator(), 44 | sg.Column(tile_viewer_column), 45 | ] 46 | ] 47 | 48 | window = sg.Window('Simple Dungeons Tile Viewer', layout) 49 | 50 | # Tile image colors 51 | boundaries_color = (0xff, 0x00, 0xc0) # Magenta 52 | region_plane_colors = [ 53 | (0x1c, 0xbf, 0x18), # 0: Green 54 | (0xed, 0xb2, 0x00), # 1: Yellow/Orange 55 | (0x36, 0x36, 0x36), # 2: Dark Gray 56 | (0x00, 0x90, 0xff), # 3: Blue 57 | (0xb5, 0x11, 0x10) # 4: Red 58 | ] 59 | 60 | def update_tile_viewer(values): 61 | try: 62 | # Getting the tile from the object group based on the text in the selected list item 63 | tile_index = int(re.search('^(\d+):', values['-TILE LIST-'][0]).group(1)) 64 | tile_dict = objectgroup['objects'][tile_index] 65 | t = Tile.from_dict(tile_dict) 66 | 67 | img_data = np.array_split([region_plane_colors[v] for v in t.region_plane], t.size[2]) 68 | 69 | # Get / generate and cache tile height map, and apply shading to the image 70 | if values['-HEIGHTMAP-']: 71 | if not '_height' in tile_dict: 72 | tile_dict['_height'] = t.get_height_map() 73 | zr = range(0, t.size[2]) 74 | for x in range(0, t.size[0]): 75 | for z in zr: 76 | img_data[z][x] = [min(255, v * (0.25 + 1.25 * tile_dict['_height'][z * t.size[0] + x] / t.size[1])) for v in img_data[z][x]] 77 | 78 | # Draw boundaries 79 | if values['-BOUNDARIES-']: 80 | for b in t.boundaries: 81 | img_data[b.z][b.x] = boundaries_color 82 | 83 | # Convert array to Pillow image 84 | img = Image.fromarray(np.array(img_data, dtype=np.uint8), 'RGB') 85 | 86 | # Get image scale from slider 87 | scale = values['-SCALE-'] 88 | scaled_size = (int(t.size[0] * scale), int(t.size[2] * scale)) 89 | 90 | # Update UI with text and image 91 | window['-TOUT-'].update(values['-TILE LIST-'][0]) 92 | window['-IMAGE-'].update(data=ImageTk.PhotoImage(img.resize(scaled_size, Image.NEAREST))) 93 | 94 | except: 95 | if values['-TILE LIST-'][0]: 96 | window['-TOUT-'].update('ERROR while loading tile!') 97 | else: 98 | pass 99 | 100 | # Run the Event Loop 101 | while True: 102 | event, values = window.read() 103 | if event == 'Exit' or event == sg.WIN_CLOSED: 104 | break 105 | 106 | # Object group file selected 107 | if event == '-OBJECTGROUP-': 108 | objectgroupPath = values['-OBJECTGROUP-'] 109 | try: 110 | with open(objectgroupPath) as json_file: 111 | objectgroup = json.load(json_file) 112 | tile_list = objectgroup['objects'] 113 | except: 114 | objectgroup = None 115 | tile_list = [] 116 | 117 | # Add the index of the tile in front of the ID for the list in the UI, since the ID is sometimes blank 118 | tids = [str(i) + ': "' + f['id'] + '"' for i, f in zip(range(len(tile_list)), tile_list)] 119 | window['-TILE LIST-'].update(tids) 120 | 121 | # Tile was selected, or checkbox was (un)checked, or slider was moved 122 | else: 123 | update_tile_viewer(values) 124 | 125 | window.close() -------------------------------------------------------------------------------- /examples/Tile.py: -------------------------------------------------------------------------------- 1 | import zlib 2 | import base64 3 | from array import array 4 | from itertools import chain, zip_longest 5 | 6 | """ 7 | This module contains useful classes for different tile-related objects. 8 | 9 | The documentation here isn't great, but hopefully most of the function names 10 | are self-explanatory. 11 | 12 | There are still some parts that aren't implemented yet and parts that could be 13 | optimized better. 14 | """ 15 | 16 | def decompress(s): 17 | return zlib.decompress(base64.b64decode(s)) 18 | 19 | def compress(b): 20 | return base64.b64encode(zlib.compress(b, 9)).decode('utf-8') 21 | 22 | def pairwise(iterable): 23 | "s -> (s0, s1), (s2, s3), (s4, s5), ..." 24 | a = iter(iterable) 25 | return zip(a, a) 26 | 27 | 28 | class Boundary: 29 | """ 30 | Tile boundary, which is a column of invisible, solid blocks. 31 | Boundaries only have solid walls; the top and bottom are not solid. 32 | """ 33 | def __init__(self, x, y, z, h): 34 | self.x = x 35 | self.y = y 36 | self.z = z 37 | self.h = h 38 | 39 | @staticmethod 40 | def from_bytes(bytes_): 41 | """Returns a Boundary object with properties from the given bytes.""" 42 | return Boundary( 43 | x = bytes_[0] << 8 | bytes_[1], 44 | y = bytes_[2] << 8 | bytes_[3], 45 | z = bytes_[4] << 8 | bytes_[5], 46 | h = bytes_[6] << 8 | bytes_[7]) 47 | 48 | def bytes(self): 49 | """Returns the boundary represented as bytes.""" 50 | return bytes([ 51 | self.x >> 8 & 0xff, self.x & 0xff, 52 | self.y >> 8 & 0xff, self.y & 0xff, 53 | self.z >> 8 & 0xff, self.z & 0xff, 54 | self.h >> 8 & 0xff, self.h & 0xff]) 55 | 56 | 57 | class Door: 58 | """ 59 | Tile door, which is a tile connection or teleport point. 60 | """ 61 | def __init__(self, pos = [0, 0, 0], size = [1, 1, 1]): 62 | self.pos = pos 63 | self.size = size 64 | 65 | @staticmethod 66 | def from_dict(dict_door): 67 | """Returns a Door object with properties from the given dict.""" 68 | door = Door(dict_door['pos'], dict_door['size']) 69 | 70 | if 'name' in dict_door: 71 | door.name = dict_door['name'] 72 | 73 | if 'tags' in dict_door: 74 | door.tags = dict_door['tags'] 75 | 76 | return door 77 | 78 | def dict(self): 79 | """Returns the door represented as a dict.""" 80 | dict = {} 81 | 82 | if hasattr(self, 'name'): 83 | dict['name'] = self.name 84 | 85 | if hasattr(self, 'tags'): 86 | dict['tags'] = self.tags 87 | 88 | dict['pos'] = self.pos 89 | dict['size'] = self.size 90 | 91 | return dict 92 | 93 | 94 | class Region: 95 | """ 96 | Tile region, which is an area marker that can be used set up triggers 97 | or place objects in the level. 98 | 99 | Not yet implemented: 100 | - 'locked' property 101 | """ 102 | def __init__(self, pos = [0, 0, 0], size = [1, 1, 1]): 103 | self.pos = pos 104 | self.size = size 105 | 106 | @staticmethod 107 | def from_dict(dict_region): 108 | """Returns a Region object with properties from the given dict.""" 109 | region = Region(dict_region['pos'], dict_region['size']) 110 | 111 | if 'name' in dict_region: 112 | region.name = dict_region['name'] 113 | 114 | if 'tags' in dict_region: 115 | region.tags = dict_region['tags'] 116 | 117 | if 'type' in dict_region: 118 | region.type = dict_region['type'] 119 | 120 | return region 121 | 122 | def dict(self): 123 | """Returns the region represented as a dict.""" 124 | dict = {} 125 | 126 | if hasattr(self, 'name'): 127 | dict['name'] = self.name 128 | 129 | if hasattr(self, 'tags'): 130 | dict['tags'] = self.tags 131 | 132 | if hasattr(self, 'type'): 133 | dict['type'] = self.type 134 | 135 | dict['pos'] = self.pos 136 | dict['size'] = self.size 137 | 138 | return dict 139 | 140 | 141 | class Tile: 142 | """ 143 | A tile is a cuboid chunk of blocks. They are pieced together to create 144 | the levels in Dungeons. 145 | 146 | Not yet implemented: 147 | - 'is-leaky' property 148 | - 'locked' property 149 | - 'tags' property 150 | """ 151 | def __init__(self, name, size): 152 | self.id = name 153 | self.size = size 154 | self.volume = size[0] * size[1] * size[2] 155 | self.blocks = array('H', [0] * self.volume) # unsigned 16-bit int array 156 | self.block_data = bytearray([0] * self.volume) 157 | self.region_plane = bytearray([0] * (size[0] * size[2])) 158 | self.region_y_plane = bytearray([0] * (size[0] * size[2])) 159 | self.region_y_plane_copy_height = True 160 | self.walkable_plane = bytearray([0] * (size[0] * size[2])) 161 | self.write_walkable_plane = False 162 | self.y = 0 163 | self.pos = None 164 | self.boundaries = [] 165 | self.doors = [] 166 | self.regions = [] 167 | 168 | @staticmethod 169 | def from_dict(dict_tile): 170 | """Returns a Tile object with properties from the given dict.""" 171 | if 'size' in dict_tile: 172 | tile = Tile(dict_tile['id'], dict_tile['size']) 173 | 174 | if 'pos' in dict_tile: 175 | tile.pos = dict_tile['pos'] 176 | 177 | elif 'pos' in dict_tile and 'pos2' in dict_tile: 178 | tile = Tile(dict_tile['id'], [abs(a-b) + 1 for a, b in zip(dict_tile['pos'], dict_tile['pos2'])]) 179 | tile.pos = [min(a, b) for a, b in zip(dict_tile['pos'], dict_tile['pos2'])] 180 | else: 181 | raise Exception('Tile is missing the size property.') 182 | 183 | if 'blocks' in dict_tile: 184 | decompressed_blocks = decompress(dict_tile['blocks']) 185 | 186 | # If the number of bytes is greater than 2 times the tile volume, the tile must be using the 16-bit format 187 | if len(decompressed_blocks) > tile.volume * 2: 188 | # IDs are the first {tile.volume} 16-bit ints 189 | tile.blocks = array('H', [x[0] << 8 | x[1] for x in pairwise(decompressed_blocks[:tile.volume*2])]) 190 | # Data values are only 4 bits each, so we need to split each byte in 2 and create a 1D list from that 191 | tile.block_data = bytearray(chain.from_iterable([(d >> 4, d & 0xf) for d in decompressed_blocks[tile.volume*2:]])) 192 | else: 193 | # IDs are simply the first {tile.volume} bytes 194 | tile.blocks = array('H', iter(decompressed_blocks[:tile.volume])) 195 | # Data values are only 4 bits each, so we need to split each byte in 2 and create a 1D list from that 196 | tile.block_data = bytearray(chain.from_iterable([(d >> 4, d & 0xf) for d in decompressed_blocks[tile.volume:]])) 197 | 198 | if 'region-plane' in dict_tile: 199 | tile.region_plane = bytearray(decompress(dict_tile['region-plane'])) 200 | 201 | if 'region-y-plane' in dict_tile: 202 | tile.region_y_plane = bytearray(decompress(dict_tile['region-y-plane'])) 203 | tile.region_y_plane_copy_height = False 204 | 205 | if 'walkable-plane' in dict_tile: 206 | tile.walkable_plane = bytearray(decompress(dict_tile['walkable-plane'])) 207 | tile.write_walkable_plane = True 208 | 209 | if 'y' in dict_tile: 210 | tile.y = dict_tile['y'] 211 | 212 | if 'doors' in dict_tile: 213 | tile.doors = [Door.from_dict(d) for d in dict_tile['doors']] 214 | 215 | if 'regions' in dict_tile: 216 | tile.regions = [Region.from_dict(r) for r in dict_tile['regions']] 217 | 218 | if 'boundaries' in dict_tile: 219 | # Old uncompressed boundaries format 220 | if isinstance(dict_tile['boundaries'], list): 221 | tile.boundaries = [Boundary(*b) for b in dict_tile['boundaries']] 222 | 223 | else: # Normal compressed format 224 | boundaries_bytes = decompress(dict_tile['boundaries']) 225 | for i in range(0, len(boundaries_bytes), 8): 226 | tile.boundaries.append(Boundary.from_bytes(boundaries_bytes[i:i+8])) 227 | 228 | return tile 229 | 230 | def dict(self): 231 | """Returns the tile represented as a dict. 232 | 233 | The height-plane property is automatically generated. 234 | """ 235 | obj = { 236 | 'id': self.id, 237 | 'size': self.size 238 | } 239 | 240 | if self.pos != None: 241 | obj['pos'] = self.pos 242 | 243 | if any([x > 0xff for x in self.blocks]): # Requires 16-bit format 244 | obj['blocks'] = compress( 245 | bytearray(chain.from_iterable([(x >> 8, x & 0xff) for x in self.blocks])) + 246 | bytearray([a << 4 | b & 0xf for a, b in zip_longest(self.block_data[::2], self.block_data[1::2], fillvalue=0)]) 247 | ) 248 | else: # Can use 8-bit format 249 | obj['blocks'] = compress( 250 | bytearray(tuple(self.blocks)) + 251 | bytearray([a << 4 | b & 0xf for a, b in zip_longest(self.block_data[::2], self.block_data[1::2], fillvalue=0)]) 252 | ) 253 | obj['region-plane'] = compress(self.region_plane) 254 | obj['height-plane'] = compress(bytes(self.get_height_map())) 255 | 256 | if self.region_y_plane_copy_height: 257 | obj['region-y-plane'] = obj['height-plane'] 258 | else: 259 | obj['region-y-plane'] = compress(self.region_y_plane) 260 | 261 | if self.write_walkable_plane: 262 | obj['walkable-plane'] = compress(self.walkable_plane) 263 | 264 | if len(self.boundaries) > 0: 265 | boundaries = bytearray() 266 | for boundary in self.boundaries: 267 | boundaries.extend(boundary.bytes()) 268 | obj['boundaries'] = compress(boundaries) 269 | 270 | if self.y != 0: 271 | obj['y'] = self.y 272 | 273 | if len(self.doors) > 0: 274 | obj['doors'] = [d.dict() for d in self.doors] 275 | 276 | if len(self.regions) > 0: 277 | obj['regions'] = [r.dict() for r in self.regions] 278 | 279 | return obj 280 | 281 | def resize(self, x, y, z): 282 | """Resizes the tile to the given size. 283 | 284 | Anything that is dependant on the tile's size is reset. 285 | """ 286 | self.size = [x, y, z] 287 | self.volume = x * y * z 288 | self.blocks = array('H', [0] * self.volume) 289 | self.block_data = bytearray([0] * self.volume) 290 | self.region_plane = bytearray([0] * (x * z)) 291 | self.region_y_plane = bytearray([0] * (x * z)) 292 | 293 | def get_block_index(self, x, y, z): 294 | """Returns the index of the block at the given position. 295 | 296 | This function is useful if you need to get both the block ID and data value 297 | at the same time. get_block_id and get_block_data are more convenient, but 298 | when iterating over all blocks in the tile, using this will be faster.""" 299 | 300 | return (y * self.size[2] + z) * self.size[0] + x 301 | 302 | def get_block_id(self, x, y, z): 303 | """Returns the ID of the block at the given position.""" 304 | 305 | # We could use self.get_block_index(x, y, z) here, but this is faster 306 | return self.blocks[(y * self.size[2] + z) * self.size[0] + x] 307 | 308 | def get_block_data(self, x, y, z): 309 | """Returns the data value of the block at the given position.""" 310 | 311 | # We could use self.get_block_index(x, y, z) here, but this is faster 312 | return self.block_data[(y * self.size[2] + z) * self.size[0] + x] 313 | 314 | def set_block(self, x, y, z, block_id, block_data = 0): 315 | """Sets the block at the given position to the given block ID and data value.""" 316 | 317 | idx = (y * self.size[2] + z) * self.size[0] + x 318 | self.blocks[idx] = block_id 319 | self.block_data[idx] = block_data 320 | 321 | def get_region_value(self, x, z): 322 | """Returns the value of the region plane at the given position.""" 323 | 324 | return self.region_plane[z * self.size[0] + x] 325 | 326 | def set_region_value(self, x, z, value): 327 | """Sets the value of the region plane at the given position to the given value.""" 328 | 329 | self.region_plane[z * self.size[0] + x] = value 330 | 331 | def get_region_y_value(self, x, z): 332 | """Returns the value of the region-y plane at the given position.""" 333 | 334 | return self.region_y_plane[z * self.size[0] + x] 335 | 336 | def set_region_y_value(self, x, z, value): 337 | """Sets the value of the region-y plane at the given position to the given value.""" 338 | 339 | self.region_y_plane[z * self.size[0] + x] = value 340 | 341 | def get_height_map(self): 342 | """Returns a height map of the tile as a 1D list.""" 343 | 344 | zr = range(0, self.size[2]) 345 | yr = range(min(self.size[1] - 1, 254), -1, -1) 346 | height_map = [0] * (self.size[0] * self.size[2]) 347 | for x in range(0, self.size[0]): 348 | for z in zr: # zr and yr are created only once above to save time 349 | for y in yr: # Start at the top and go down until a solid block is found 350 | if self.get_block_id(x, y, z) != 0: # Block is not air 351 | height_map[z * self.size[0] + x] = y + 1 352 | break 353 | return height_map -------------------------------------------------------------------------------- /examples/docs/Using_ConversionTools.md: -------------------------------------------------------------------------------- 1 | # Using the [ConversionTools module](/examples/ConversionTools.py) 2 | 3 | :warning: The ConversionTools module and this guide are still under construction! More tools and information will be added over time. 4 | 5 | This module requires a [modified version](https://github.com/Dokucraft/anvil-parser) of [anvil-parser](https://github.com/matcool/anvil-parser) that supports reading/writing tile entities: 6 | 7 | ```pip install git+https://github.com/Dokucraft/anvil-parser.git``` 8 | 9 | ## Table of contents 10 | 11 | - [JavaWorldToObjectGroup](#JavaWorldToObjectGroup) 12 | - [ObjectGroupToJavaWorld](#ObjectGroupToJavaWorld) 13 | 14 | ## JavaWorldToObjectGroup 15 | 16 | This converter turns Minecraft Java Edition worlds into Minecraft Dungeons object groups. 17 | 18 | To use it, you will first need a Java world with the tiles you want to convert. Since Java Edition has a lot of blocks that Dungeons doesn't have and vice versa, we need to pick some blocks to map the ones that are missing to. This repo already has [a pretty good block map](/examples/BlockMap.py), but you can edit it if you want to change things around or add to it. There are also some blocks that are treated differently by the converter. These are `minecraft:air`, `minecraft:cave_air`, `minecraft:barrier`, `minecraft:player_head`, `minecraft:player_wall_head`, and `minecraft:structure_block`. 19 | 20 | - Air blocks will simply not be processed, to speed up the conversion. 21 | - Barrier blocks will be converted to tile [boundaries](/docs/Tile.md#boundaries). 22 | - Player heads will be converted to air, but will also add a playerstart region at its position. This is just an easier way to add player spawn points to tiles, it can also be done using structure blocks. 23 | - Structure blocks will be converted to air, but the information they store can be used to create [doors](/docs/Tile.md#doors) and [regions](/docs/Tile.md#regions): 24 | - Set the stucture block's structure position and size to cover the volume that you want the door or region to use. 25 | - For doors, the name in the structure block needs to start with `door:`. To name the door, simply add the name after the `door:` prefix, e.g. `door:entrance`. 26 | - For regions, the name needs to start with `region:`. They can be named just like the doors, e.g. `region:playerstart`. 27 | - To add tags to doors or regions or a type to regions, you can set the structure block data to a JSON object with the tags and/or type, e.g. `{ "type": "trigger", "tags": "death" }` 28 | - Note: You can edit the name, position, and size while the structure block is in SAVE mode, and you can edit the data while it is in DATA mode. It remembers the settings even if you change modes. 29 | 30 | Once you have a world that you want to convert, you need to create a file called `objectgroup.json` in the world directory. This file should be set up just like a real object group file from Dungeons, except the only properties you need to add to each tile are `id`, `pos`, `size`, and any other properties that won't be handled by the converter. The properties the converter handles are: `blocks`, `height-plane`, `doors`, `regions`, `boundaries` (You can still add extra doors, regions, or boundaries to the JSON file, if you want to) 31 | 32 | The `pos` property tells the converter where the tile starts, and the `size` property tells it how many blocks it needs to go in each direction. 33 | 34 | :information_source: You can also set `pos` to one of the corners of the tile and then set `pos2` to the opposite corner. The converter will automatically convert it to `pos` and `size`. This way of defining the tile's position and size is much easier to do than using `pos` and `size`, since you can just write down the coordinates of two blocks instead of having to find the right corner of the tile for the position and then having to count or calculate the size of it. 35 | 36 | Here is an example for the `objectgroup.json` file in the world directory: 37 | 38 | ```json 39 | { "objects": [ 40 | 41 | { "id": "example_tile01", 42 | "pos": [ 36, 12, 46 ], 43 | "pos2": [ 42, 14, 52 ] 44 | }, 45 | 46 | { "id": "example_tile02", 47 | "pos": [ 36, 12, 56 ], 48 | "size": [ 7, 3, 7 ] 49 | }, 50 | 51 | { "id": "example_tile03", 52 | "pos": [ 36, 12, 66 ], 53 | "size": [ 7, 3, 7 ] 54 | } 55 | 56 | ] 57 | } 58 | ``` 59 | 60 | Once that is set up, the world is ready for the converter. To convert the world, first create an instance of the converter with the world directory path, like this: 61 | 62 | ```py 63 | from ConversionTools import JavaWorldToObjectGroup 64 | 65 | converter = JavaWorldToObjectGroup(r'C:\my\java\saves\ExampleWorld') 66 | ``` 67 | 68 | You can then change the settings for it if you want something other than the default: 69 | 70 | ```py 71 | converter.boundary_block = 'minecraft:grass_block' # Default is 'minecraft:barrier' 72 | ``` 73 | 74 | Once your converter instance is configured, you can use it to turn the world into an object group: 75 | 76 | ```py 77 | objectgroup = converter.convert() 78 | ``` 79 | 80 | To save the object group to a file, I recommend using the [pretty_compact_json module](/examples/pretty_compact_json.py). 81 | 82 | ```py 83 | from pretty_compact_json import stringify 84 | 85 | with open('objectgroup.json', 'w') as out_file: 86 | out_file.write(stringify(objectgroup)) 87 | ``` 88 | 89 | Of course, you can also just use the Python json module, but the output file will not be nearly as pretty. 90 | 91 | ```py 92 | import json 93 | 94 | with open('objectgroup.json', 'w') as out_file: 95 | json.dump(objectgroup, out_file, indent=2) 96 | ``` 97 | 98 | Here is a full code example: 99 | 100 | ```py 101 | from ConversionTools import JavaWorldToObjectGroup 102 | from pretty_compact_json import stringify 103 | 104 | world_dir = r'C:\MC Java\saves\ExampleWorld' 105 | output_path = r'C:\MCD Mod\Dungeons\Content\data\lovika\objectgroups\my_example\objectgroup.json' 106 | 107 | # Just using the default settings this time 108 | objectgroup = JavaWorldToObjectGroup(world_dir).convert() 109 | 110 | with open(output_path, 'w') as out_file: 111 | out_file.write(stringify(objectgroup)) 112 | ``` 113 | 114 | 115 | ## ObjectGroupToJavaWorld 116 | 117 | This converter turns Minecraft Dungeons object groups into Minecraft Java Edition worlds. 118 | 119 | :warning: Some blocks will not appear correctly in Java Edition due to not having their block states set up properly. I have plans for fixing this issue, but that will come later. 120 | 121 | It is similar to JavaWorldToObjectGroup, but doesn't require any setup other than having an object group to convert and a folder to put the world files into: 122 | 123 | ```py 124 | from ConversionTools import ObjectGroupToJavaWorld 125 | 126 | objectgroup_path = r'C:\my\dungeons\objectgroups\example\objectgroup.json' 127 | output_world_path = r'C:\my\java\saves\ExampleWorld' 128 | 129 | converter = ObjectGroupToJavaWorld(objectgroup_path, output_world_path) 130 | ``` 131 | 132 | After you have created the converter, you can edit the settings for it if you want to before starting the conversion process: 133 | 134 | ```py 135 | # The blocks here need to be anvil-parser blocks, so we need to import that 136 | import anvil 137 | 138 | converter.level_name = 'My Example World' # Default is 'Converted Object Group' 139 | converter.boundary_block = anvil.Block('minecraft', 'glass') # Default is anvil.Block('minecraft', 'barrier') 140 | ``` 141 | 142 | Once your converter instance is configured, you can use it to turn the object group into a Java world: 143 | 144 | ```py 145 | converter.convert() 146 | ``` 147 | 148 | And that's it! The world should be in the folder you set at the start, ready to be explored in Java Edition 1.16.2. 149 | 150 | Here's a full code example: 151 | 152 | ```py 153 | from ConversionTools import ObjectGroupToJavaWorld 154 | 155 | objectgroup_path = r'C:\my\dungeons\objectgroups\example\objectgroup.json' 156 | output_world_path = r'C:\MC Java\saves\ExampleWorld' 157 | 158 | # Just using the default settings this time 159 | ObjectGroupToJavaWorld(objectgroup_path, output_world_path).convert() 160 | ``` -------------------------------------------------------------------------------- /examples/level_template.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dokucraft/Dungeons-Level-Format/9eb650235d65d506eaa17ac9de4c6a71e34ee18a/examples/level_template.dat -------------------------------------------------------------------------------- /examples/pretty_compact_json.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | # Copyright (c) 2014, 2016, 2017, 2019 Simon Lydell 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | # Based on https://github.com/lydell/json-stringify-pretty-compact/blob/master/index.js 24 | # Ported to Python with some modifications by CCCode 25 | 26 | import re 27 | import json 28 | 29 | start_or_end = r'([{\[])|([}\]])' 30 | 31 | def stringify(passedObj, indent=2, max_length=80): 32 | # The original code supports a replacer function/array, but for now it's 33 | # not implemented here. 34 | 35 | indent_str = ' ' * indent 36 | 37 | if indent == 0: 38 | max_length = float('inf') 39 | 40 | def _stringify(obj, current_indent, reserved, has_key): 41 | # The original code checks if obj has a toJSON function here and uses that 42 | # to convert obj to JSON before continuing. It's not really necessary for 43 | # what I use this function for, so I decided to just remove it. 44 | 45 | string = json.dumps(obj, separators=(', ', ': ')) 46 | 47 | length = max_length - len(current_indent) - reserved 48 | 49 | if len(string) <= length: 50 | prettified = re.sub(start_or_end, r'\1 \2', string) 51 | if len(prettified) <= length: 52 | return prettified 53 | 54 | if isinstance(obj, dict) or isinstance(obj, list): 55 | next_indent = current_indent + indent_str 56 | items = [] 57 | 58 | if isinstance(obj, dict): 59 | start = '{' 60 | end = '}' 61 | keys = list(obj.keys()) 62 | length = len(keys) 63 | for index in range(length): 64 | key = keys[index] 65 | key_part = json.dumps(key, separators=(',', ':')) + ': ' 66 | value = _stringify(obj[key], next_indent, len(key_part) + (0 if index == length - 1 else 1), True) 67 | if not value is None: 68 | items.append(key_part + value) 69 | 70 | else: # obj is list 71 | start = '[' 72 | end = ']' 73 | length = len(obj) 74 | for index in range(length): 75 | items.append(_stringify(obj[index], next_indent, 0 if index == length - 1 else 1, False) or 'null') 76 | 77 | if len(items) > 0: 78 | if has_key or len(items) == 1: 79 | return f'\n{current_indent}'.join([start, indent_str + f',\n{next_indent}'.join(items), end]) 80 | else: 81 | return f'\n{current_indent}'.join([start + indent_str[1:] + items[0] + ',', indent_str + f',\n{next_indent}'.join(items[1:]), end]) 82 | 83 | return string 84 | 85 | return _stringify(passedObj, '', 0, False) --------------------------------------------------------------------------------