├── .github └── workflows │ └── run-pytest.yml ├── .gitignore ├── .readthedocs.yml ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── README.md ├── anvil ├── __init__.py ├── block.py ├── chunk.py ├── empty_chunk.py ├── empty_region.py ├── empty_section.py ├── errors.py ├── legacy.py ├── legacy_blocks.json ├── raw_section.py └── region.py ├── docs ├── Makefile ├── _static │ └── custom.css ├── api.rst ├── conf.py ├── index.rst ├── make.bat └── requirements.txt ├── examples ├── _path.py ├── basic_world_gen.py ├── cube.py └── top_view.py ├── pytest.ini ├── requirements.txt ├── setup.py └── tests ├── context.py ├── test_benchmark.py ├── test_mixed_chunk_types.py ├── test_read_region.py └── test_stream_blocks.py /.github/workflows/run-pytest.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies and run tests with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Tests 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python 3.9 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: 3.9 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install pytest 27 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 28 | - name: Test with pytest 29 | run: | 30 | pytest 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | textures/ 3 | dist/ 4 | build/ 5 | *.egg-info/ 6 | .pytest_cache/ 7 | .vscode/ 8 | docs/_build/ 9 | examples/test_112.py 10 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | configuration: docs/conf.py 5 | 6 | python: 7 | version: 3.7 8 | install: 9 | - requirements: docs/requirements.txt 10 | - requirements: requirements.txt 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.7" 4 | script: 5 | - pytest -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 mateus 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include anvil/legacy_blocks.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # anvil-parser 2 | 3 | [![CodeFactor](https://www.codefactor.io/repository/github/matcool/anvil-parser/badge/master)](https://www.codefactor.io/repository/github/matcool/anvil-parser/overview/master) 4 | [![Documentation Status](https://readthedocs.org/projects/anvil-parser/badge/?version=latest)](https://anvil-parser.readthedocs.io/en/latest/?badge=latest) 5 | [![Tests](https://github.com/matcool/anvil-parser/actions/workflows/run-pytest.yml/badge.svg)](https://github.com/matcool/anvil-parser/actions/workflows/run-pytest.yml) 6 | [![PyPI - Downloads](https://img.shields.io/pypi/dm/anvil-parser)](https://pypi.org/project/anvil-parser/) 7 | 8 | Simple parser for the [Minecraft anvil file format](https://minecraft.gamepedia.com/Anvil_file_format) 9 | # Installation 10 | This project is available on [PyPI](https://pypi.org/project/anvil-parser/) and can be installed with pip 11 | ``` 12 | pip install anvil-parser 13 | ``` 14 | or directly from github 15 | ``` 16 | pip install git+https://github.com/matcool/anvil-parser.git 17 | ``` 18 | # Usage 19 | ## Reading 20 | ```python 21 | import anvil 22 | 23 | region = anvil.Region.from_file('r.0.0.mca') 24 | 25 | # You can also provide the region file name instead of the object 26 | chunk = anvil.Chunk.from_region(region, 0, 0) 27 | 28 | # If `section` is not provided, will get it from the y coords 29 | # and assume it's global 30 | block = chunk.get_block(0, 0, 0) 31 | 32 | print(block) # 33 | print(block.id) # air 34 | print(block.properties) # {} 35 | ``` 36 | ## Making own regions 37 | ```python 38 | import anvil 39 | from random import choice 40 | 41 | # Create a new region with the `EmptyRegion` class at 0, 0 (in region coords) 42 | region = anvil.EmptyRegion(0, 0) 43 | 44 | # Create `Block` objects that are used to set blocks 45 | stone = anvil.Block('minecraft', 'stone') 46 | dirt = anvil.Block('minecraft', 'dirt') 47 | 48 | # Make a 16x16x16 cube of either stone or dirt blocks 49 | for y in range(16): 50 | for z in range(16): 51 | for x in range(16): 52 | region.set_block(choice((stone, dirt)), x, y, z) 53 | 54 | # Save to a file 55 | region.save('r.0.0.mca') 56 | ``` 57 | # Todo 58 | *things to do before 1.0.0* 59 | - [x] Proper documentation 60 | - [ ] Biomes 61 | - [x] CI 62 | - [ ] More tests 63 | - [ ] Tests for 20w17a+ BlockStates format 64 | # Note 65 | Testing done in 1.14.4 and 1.15.2, should work fine for other versions. 66 | -------------------------------------------------------------------------------- /anvil/__init__.py: -------------------------------------------------------------------------------- 1 | from .chunk import Chunk 2 | from .block import Block, OldBlock 3 | from .region import Region 4 | from .empty_region import EmptyRegion 5 | from .empty_chunk import EmptyChunk 6 | from .empty_section import EmptySection 7 | from .raw_section import RawSection 8 | -------------------------------------------------------------------------------- /anvil/block.py: -------------------------------------------------------------------------------- 1 | from nbt import nbt 2 | from frozendict import frozendict 3 | from .legacy import LEGACY_ID_MAP 4 | 5 | class Block: 6 | """ 7 | Represents a minecraft block. 8 | 9 | Attributes 10 | ---------- 11 | namespace: :class:`str` 12 | Namespace of the block, most of the time this is ``minecraft`` 13 | id: :class:`str` 14 | ID of the block, for example: stone, diamond_block, etc... 15 | properties: :class:`dict` 16 | Block properties as a dict 17 | """ 18 | __slots__ = ('namespace', 'id', 'properties') 19 | 20 | def __init__(self, namespace: str, block_id: str=None, properties: dict=None): 21 | """ 22 | Parameters 23 | ---------- 24 | namespace 25 | Namespace of the block. If no block_id is given, assume this is ``block_id`` and set namespace to ``"minecraft"`` 26 | block_id 27 | ID of the block 28 | properties 29 | Block properties 30 | """ 31 | if block_id is None: 32 | self.namespace = 'minecraft' 33 | self.id = namespace 34 | else: 35 | self.namespace = namespace 36 | self.id = block_id 37 | self.properties = properties or {} 38 | 39 | def name(self) -> str: 40 | """ 41 | Returns the block in the ``minecraft:block_id`` format 42 | """ 43 | return self.namespace + ':' + self.id 44 | 45 | def __repr__(self): 46 | return f'Block({self.name()})' 47 | 48 | def __eq__(self, other): 49 | if not isinstance(other, Block): 50 | return False 51 | return self.namespace == other.namespace and self.id == other.id and self.properties == other.properties 52 | 53 | def __hash__(self): 54 | return hash(self.name()) ^ hash(frozendict(self.properties)) 55 | 56 | @classmethod 57 | def from_name(cls, name: str, *args, **kwargs): 58 | """ 59 | Creates a new Block from the format: ``namespace:block_id`` 60 | 61 | Parameters 62 | ---------- 63 | name 64 | Block in said format 65 | , args, kwargs 66 | Will be passed on to the main constructor 67 | """ 68 | namespace, block_id = name.split(':') 69 | return cls(namespace, block_id, *args, **kwargs) 70 | 71 | @classmethod 72 | def from_palette(cls, tag: nbt.TAG_Compound): 73 | """ 74 | Creates a new Block from the tag format on Section.Palette 75 | 76 | Parameters 77 | ---------- 78 | tag 79 | Raw tag from a section's palette 80 | """ 81 | name = tag['Name'].value 82 | properties = tag.get('Properties') 83 | if properties: 84 | properties = dict(properties) 85 | return cls.from_name(name, properties=properties) 86 | 87 | @classmethod 88 | def from_numeric_id(cls, block_id: int, data: int=0): 89 | """ 90 | Creates a new Block from the block_id:data fromat used pre-flattening (pre-1.13) 91 | 92 | Parameters 93 | ---------- 94 | block_id 95 | Numeric ID of the block 96 | data 97 | Numeric data, used to represent variants of the block 98 | """ 99 | # See https://minecraft.gamepedia.com/Java_Edition_data_value/Pre-flattening 100 | # and https://minecraft.gamepedia.com/Java_Edition_data_value for current values 101 | key = f'{block_id}:{data}' 102 | if key not in LEGACY_ID_MAP: 103 | raise KeyError(f'Block {key} not found') 104 | name, properties = LEGACY_ID_MAP[key] 105 | return cls('minecraft', name, properties=properties) 106 | 107 | class OldBlock: 108 | """ 109 | Represents a pre 1.13 minecraft block, with a numeric id. 110 | 111 | Attributes 112 | ---------- 113 | id: :class:`int` 114 | Numeric ID of the block 115 | data: :class:`int` 116 | The block data, used to represent variants of the block 117 | """ 118 | __slots__ = ('id', 'data') 119 | 120 | def __init__(self, block_id: int, data: int=0): 121 | """ 122 | Parameters 123 | ---------- 124 | block_id 125 | ID of the block 126 | data 127 | Block data 128 | """ 129 | self.id = block_id 130 | self.data = data 131 | 132 | def convert(self) -> Block: 133 | return Block.from_numeric_id(self.id, self.data) 134 | 135 | def __repr__(self): 136 | return f'OldBlock(id={self.id}, data={self.data})' 137 | 138 | def __eq__(self, other): 139 | if isinstance(other, int): 140 | return self.id == other 141 | elif not isinstance(other, Block): 142 | return False 143 | else: 144 | return self.id == other.id and self.data == other.data 145 | 146 | def __hash__(self): 147 | return hash(self.id) ^ hash(self.data) 148 | -------------------------------------------------------------------------------- /anvil/chunk.py: -------------------------------------------------------------------------------- 1 | from typing import Union, Tuple, Generator, Optional 2 | from nbt import nbt 3 | from .block import Block, OldBlock 4 | from .region import Region 5 | from .errors import OutOfBoundsCoordinates, ChunkNotFound 6 | import math 7 | 8 | 9 | # This version removes block state value stretching from the storage 10 | # so a block value isn't in multiple elements of the array 11 | _VERSION_20w17a = 2529 12 | 13 | # This is the version where "The Flattening" (https://minecraft.gamepedia.com/Java_Edition_1.13/Flattening) happened 14 | # where blocks went from numeric ids to namespaced ids (namespace:block_id) 15 | _VERSION_17w47a = 1451 16 | 17 | def bin_append(a, b, length=None): 18 | """ 19 | Appends number a to the left of b 20 | bin_append(0b1, 0b10) = 0b110 21 | """ 22 | length = length or b.bit_length() 23 | return (a << length) | b 24 | 25 | def nibble(byte_array, index): 26 | value = byte_array[index // 2] 27 | if index % 2: 28 | return value >> 4 29 | else: 30 | return value & 0b1111 31 | 32 | class Chunk: 33 | """ 34 | Represents a chunk from a ``.mca`` file. 35 | 36 | Note that this is read only. 37 | 38 | Attributes 39 | ---------- 40 | x: :class:`int` 41 | Chunk's X position 42 | z: :class:`int` 43 | Chunk's Z position 44 | version: :class:`int` 45 | Version of the chunk NBT structure 46 | data: :class:`nbt.TAG_Compound` 47 | Raw NBT data of the chunk 48 | tile_entities: :class:`nbt.TAG_Compound` 49 | ``self.data['TileEntities']`` as an attribute for easier use 50 | """ 51 | __slots__ = ('version', 'data', 'x', 'z', 'tile_entities') 52 | 53 | def __init__(self, nbt_data: nbt.NBTFile): 54 | try: 55 | self.version = nbt_data['DataVersion'].value 56 | except KeyError: 57 | # Version is pre-1.9 snapshot 15w32a, so world does not have a Data Version. 58 | # See https://minecraft.fandom.com/wiki/Data_version 59 | self.version = None 60 | 61 | self.data = nbt_data['Level'] 62 | self.x = self.data['xPos'].value 63 | self.z = self.data['zPos'].value 64 | self.tile_entities = self.data['TileEntities'] 65 | 66 | def get_section(self, y: int) -> nbt.TAG_Compound: 67 | """ 68 | Returns the section at given y index 69 | can also return nothing if section is missing, aka it's empty 70 | 71 | Parameters 72 | ---------- 73 | y 74 | Section Y index 75 | 76 | Raises 77 | ------ 78 | anvil.OutOfBoundsCoordinates 79 | If Y is not in range of 0 to 15 80 | """ 81 | if y < 0 or y > 15: 82 | raise OutOfBoundsCoordinates(f'Y ({y!r}) must be in range of 0 to 15') 83 | 84 | try: 85 | sections = self.data["Sections"] 86 | except KeyError: 87 | return None 88 | 89 | for section in sections: 90 | if section['Y'].value == y: 91 | return section 92 | 93 | def get_palette(self, section: Union[int, nbt.TAG_Compound]) -> Tuple[Block]: 94 | """ 95 | Returns the block palette for given section 96 | 97 | Parameters 98 | ---------- 99 | section 100 | Either a section NBT tag or an index 101 | 102 | 103 | :rtype: Tuple[:class:`anvil.Block`] 104 | """ 105 | if isinstance(section, int): 106 | section = self.get_section(section) 107 | if section is None: 108 | return 109 | return tuple(Block.from_palette(i) for i in section['Palette']) 110 | 111 | def get_block(self, x: int, y: int, z: int, section: Union[int, nbt.TAG_Compound]=None, force_new: bool=False) -> Union[Block, OldBlock]: 112 | """ 113 | Returns the block in the given coordinates 114 | 115 | Parameters 116 | ---------- 117 | int x, y, z 118 | Block's coordinates in the chunk 119 | section : int 120 | Either a section NBT tag or an index. If no section is given, 121 | assume Y is global and use it for getting the section. 122 | force_new 123 | Always returns an instance of Block if True, otherwise returns type OldBlock for pre-1.13 versions. 124 | Defaults to False 125 | 126 | Raises 127 | ------ 128 | anvil.OutOfBoundCoordidnates 129 | If X, Y or Z are not in the proper range 130 | 131 | :rtype: :class:`anvil.Block` 132 | """ 133 | if x < 0 or x > 15: 134 | raise OutOfBoundsCoordinates(f'X ({x!r}) must be in range of 0 to 15') 135 | if z < 0 or z > 15: 136 | raise OutOfBoundsCoordinates(f'Z ({z!r}) must be in range of 0 to 15') 137 | if y < 0 or y > 255: 138 | raise OutOfBoundsCoordinates(f'Y ({y!r}) must be in range of 0 to 255') 139 | 140 | if section is None: 141 | section = self.get_section(y // 16) 142 | # global Y to section Y 143 | y %= 16 144 | 145 | if self.version is None or self.version < _VERSION_17w47a: 146 | # Explained in depth here https://minecraft.gamepedia.com/index.php?title=Chunk_format&oldid=1153403#Block_format 147 | 148 | if section is None or 'Blocks' not in section: 149 | if force_new: 150 | return Block.from_name('minecraft:air') 151 | else: 152 | return OldBlock(0) 153 | 154 | index = y * 16 * 16 + z * 16 + x 155 | 156 | block_id = section['Blocks'][index] 157 | if 'Add' in section: 158 | block_id += nibble(section['Add'], index) << 8 159 | 160 | block_data = nibble(section['Data'], index) 161 | 162 | block = OldBlock(block_id, block_data) 163 | if force_new: 164 | return block.convert() 165 | else: 166 | return block 167 | 168 | # If its an empty section its most likely an air block 169 | if section is None or 'BlockStates' not in section: 170 | return Block.from_name('minecraft:air') 171 | 172 | # Number of bits each block is on BlockStates 173 | # Cannot be lower than 4 174 | bits = max((len(section['Palette']) - 1).bit_length(), 4) 175 | 176 | # Get index on the block list with the order YZX 177 | index = y * 16*16 + z * 16 + x 178 | 179 | # BlockStates is an array of 64 bit numbers 180 | # that holds the blocks index on the palette list 181 | states = section['BlockStates'].value 182 | 183 | # in 20w17a and newer blocks cannot occupy more than one element on the BlockStates array 184 | stretches = self.version is None or self.version < _VERSION_20w17a 185 | # stretches = True 186 | 187 | # get location in the BlockStates array via the index 188 | if stretches: 189 | state = index * bits // 64 190 | else: 191 | state = index // (64 // bits) 192 | 193 | # makes sure the number is unsigned 194 | # by adding 2^64 195 | # could also use ctypes.c_ulonglong(n).value but that'd require an extra import 196 | data = states[state] 197 | if data < 0: 198 | data += 2**64 199 | 200 | if stretches: 201 | # shift the number to the right to remove the left over bits 202 | # and shift so the i'th block is the first one 203 | shifted_data = data >> ((bits * index) % 64) 204 | else: 205 | shifted_data = data >> (index % (64 // bits) * bits) 206 | 207 | # if there aren't enough bits it means the rest are in the next number 208 | if stretches and 64 - ((bits * index) % 64) < bits: 209 | data = states[state + 1] 210 | if data < 0: 211 | data += 2**64 212 | 213 | # get how many bits are from a palette index of the next block 214 | leftover = (bits - ((state + 1) * 64 % bits)) % bits 215 | 216 | # Make sure to keep the length of the bits in the first state 217 | # Example: bits is 5, and leftover is 3 218 | # Next state Current state (already shifted) 219 | # 0b101010110101101010010 0b01 220 | # will result in bin_append(0b010, 0b01, 2) = 0b01001 221 | shifted_data = bin_append(data & 2**leftover - 1, shifted_data, bits-leftover) 222 | 223 | # get `bits` least significant bits 224 | # which are the palette index 225 | palette_id = shifted_data & 2**bits - 1 226 | 227 | block = section['Palette'][palette_id] 228 | return Block.from_palette(block) 229 | 230 | def stream_blocks(self, index: int=0, section: Union[int, nbt.TAG_Compound]=None, force_new: bool=False) -> Generator[Block, None, None]: 231 | """ 232 | Returns a generator for all the blocks in given section 233 | 234 | Parameters 235 | ---------- 236 | index 237 | At what block to start from. 238 | 239 | To get an index from (x, y, z), simply do: 240 | 241 | ``y * 256 + z * 16 + x`` 242 | section 243 | Either a Y index or a section NBT tag. 244 | force_new 245 | Always returns an instance of Block if True, otherwise returns type OldBlock for pre-1.13 versions. 246 | Defaults to False 247 | 248 | Raises 249 | ------ 250 | anvil.OutOfBoundCoordidnates 251 | If `section` is not in the range of 0 to 15 252 | 253 | Yields 254 | ------ 255 | :class:`anvil.Block` 256 | """ 257 | if isinstance(section, int) and (section < 0 or section > 16): 258 | raise OutOfBoundsCoordinates(f'section ({section!r}) must be in range of 0 to 15') 259 | 260 | # For better understanding of this code, read get_block()'s source 261 | 262 | if section is None or isinstance(section, int): 263 | section = self.get_section(section or 0) 264 | 265 | if self.version < _VERSION_17w47a: 266 | if section is None or 'Blocks' not in section: 267 | air = Block.from_name('minecraft:air') if force_new else OldBlock(0) 268 | for i in range(4096): 269 | yield air 270 | return 271 | 272 | while index < 4096: 273 | block_id = section['Blocks'][index] 274 | if 'Add' in section: 275 | block_id += nibble(section['Add'], index) << 8 276 | 277 | block_data = nibble(section['Data'], index) 278 | 279 | block = OldBlock(block_id, block_data) 280 | if force_new: 281 | yield block.convert() 282 | else: 283 | yield block 284 | 285 | index += 1 286 | return 287 | 288 | if section is None or 'BlockStates' not in section: 289 | air = Block.from_name('minecraft:air') 290 | for i in range(4096): 291 | yield air 292 | return 293 | 294 | states = section['BlockStates'].value 295 | palette = section['Palette'] 296 | 297 | bits = max((len(palette) - 1).bit_length(), 4) 298 | 299 | stretches = self.version < _VERSION_20w17a 300 | 301 | if stretches: 302 | state = index * bits // 64 303 | else: 304 | state = index // (64 // bits) 305 | 306 | data = states[state] 307 | if data < 0: 308 | data += 2**64 309 | 310 | bits_mask = 2**bits - 1 311 | 312 | if stretches: 313 | offset = (bits * index) % 64 314 | else: 315 | offset = index % (64 // bits) * bits 316 | 317 | data_len = 64 - offset 318 | data >>= offset 319 | 320 | while index < 4096: 321 | if data_len < bits: 322 | state += 1 323 | new_data = states[state] 324 | if new_data < 0: 325 | new_data += 2**64 326 | 327 | if stretches: 328 | leftover = data_len 329 | data_len += 64 330 | 331 | data = bin_append(new_data, data, leftover) 332 | else: 333 | data = new_data 334 | data_len = 64 335 | 336 | palette_id = data & bits_mask 337 | yield Block.from_palette(palette[palette_id]) 338 | 339 | index += 1 340 | data >>= bits 341 | data_len -= bits 342 | 343 | def stream_chunk(self, index: int=0, section: Union[int, nbt.TAG_Compound]=None) -> Generator[Block, None, None]: 344 | """ 345 | Returns a generator for all the blocks in the chunk 346 | 347 | This is a helper function that runs Chunk.stream_blocks from section 0 to 15 348 | 349 | Yields 350 | ------ 351 | :class:`anvil.Block` 352 | """ 353 | for section in range(16): 354 | for block in self.stream_blocks(section=section): 355 | yield block 356 | 357 | def get_tile_entity(self, x: int, y: int, z: int) -> Optional[nbt.TAG_Compound]: 358 | """ 359 | Returns the tile entity at given coordinates, or ``None`` if there isn't a tile entity 360 | 361 | To iterate through all tile entities in the chunk, use :class:`Chunk.tile_entities` 362 | """ 363 | for tile_entity in self.tile_entities: 364 | t_x, t_y, t_z = [tile_entity[k].value for k in 'xyz'] 365 | if x == t_x and y == t_y and z == t_z: 366 | return tile_entity 367 | 368 | @classmethod 369 | def from_region(cls, region: Union[str, Region], chunk_x: int, chunk_z: int): 370 | """ 371 | Creates a new chunk from region and the chunk's X and Z 372 | 373 | Parameters 374 | ---------- 375 | region 376 | Either a :class:`anvil.Region` or a region file name (like ``r.0.0.mca``) 377 | 378 | Raises 379 | ---------- 380 | anvil.ChunkNotFound 381 | If a chunk is outside this region or hasn't been generated yet 382 | """ 383 | if isinstance(region, str): 384 | region = Region.from_file(region) 385 | nbt_data = region.chunk_data(chunk_x, chunk_z) 386 | if nbt_data is None: 387 | raise ChunkNotFound(f'Could not find chunk ({chunk_x}, {chunk_z})') 388 | return cls(nbt_data) 389 | -------------------------------------------------------------------------------- /anvil/empty_chunk.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from .block import Block 3 | from .empty_section import EmptySection 4 | from .errors import OutOfBoundsCoordinates, EmptySectionAlreadyExists 5 | from nbt import nbt 6 | 7 | class EmptyChunk: 8 | """ 9 | Used for making own chunks 10 | 11 | Attributes 12 | ---------- 13 | x: :class:`int` 14 | Chunk's X position 15 | z: :class:`int` 16 | Chunk's Z position 17 | sections: List[:class:`anvil.EmptySection`] 18 | List of all the sections in this chunk 19 | version: :class:`int` 20 | Chunk's DataVersion 21 | """ 22 | __slots__ = ('x', 'z', 'sections', 'version') 23 | def __init__(self, x: int, z: int): 24 | self.x = x 25 | self.z = z 26 | self.sections: List[EmptySection] = [None]*16 27 | self.version = 1976 28 | 29 | def add_section(self, section: EmptySection, replace: bool = True): 30 | """ 31 | Adds a section to the chunk 32 | 33 | Parameters 34 | ---------- 35 | section 36 | Section to add 37 | replace 38 | Whether to replace section if one at same Y already exists 39 | 40 | Raises 41 | ------ 42 | anvil.EmptySectionAlreadyExists 43 | If ``replace`` is ``False`` and section with same Y already exists in this chunk 44 | """ 45 | if self.sections[section.y] and not replace: 46 | raise EmptySectionAlreadyExists(f'EmptySection (Y={section.y}) already exists in this chunk') 47 | self.sections[section.y] = section 48 | 49 | def get_block(self, x: int, y: int, z: int) -> Block: 50 | """ 51 | Gets the block at given coordinates 52 | 53 | Parameters 54 | ---------- 55 | int x, z 56 | In range of 0 to 15 57 | y 58 | In range of 0 to 255 59 | 60 | Raises 61 | ------ 62 | anvil.OutOfBoundCoordidnates 63 | If X, Y or Z are not in the proper range 64 | 65 | Returns 66 | ------- 67 | block : :class:`anvil.Block` or None 68 | Returns ``None`` if the section is empty, meaning the block 69 | is most likely an air block. 70 | """ 71 | if x < 0 or x > 15: 72 | raise OutOfBoundsCoordinates(f'X ({x!r}) must be in range of 0 to 15') 73 | if z < 0 or z > 15: 74 | raise OutOfBoundsCoordinates(f'Z ({z!r}) must be in range of 0 to 15') 75 | if y < 0 or y > 255: 76 | raise OutOfBoundsCoordinates(f'Y ({y!r}) must be in range of 0 to 255') 77 | section = self.sections[y // 16] 78 | if section is None: 79 | return 80 | return section.get_block(x, y % 16, z) 81 | 82 | def set_block(self, block: Block, x: int, y: int, z: int): 83 | """ 84 | Sets block at given coordinates 85 | 86 | Parameters 87 | ---------- 88 | int x, z 89 | In range of 0 to 15 90 | y 91 | In range of 0 to 255 92 | 93 | Raises 94 | ------ 95 | anvil.OutOfBoundCoordidnates 96 | If X, Y or Z are not in the proper range 97 | 98 | """ 99 | if x < 0 or x > 15: 100 | raise OutOfBoundsCoordinates(f'X ({x!r}) must be in range of 0 to 15') 101 | if z < 0 or z > 15: 102 | raise OutOfBoundsCoordinates(f'Z ({z!r}) must be in range of 0 to 15') 103 | if y < 0 or y > 255: 104 | raise OutOfBoundsCoordinates(f'Y ({y!r}) must be in range of 0 to 255') 105 | section = self.sections[y // 16] 106 | if section is None: 107 | section = EmptySection(y // 16) 108 | self.add_section(section) 109 | section.set_block(block, x, y % 16, z) 110 | 111 | def save(self) -> nbt.NBTFile: 112 | """ 113 | Saves the chunk data to a :class:`NBTFile` 114 | 115 | Notes 116 | ----- 117 | Does not contain most data a regular chunk would have, 118 | but minecraft stills accept it. 119 | """ 120 | root = nbt.NBTFile() 121 | root.tags.append(nbt.TAG_Int(name='DataVersion',value=self.version)) 122 | level = nbt.TAG_Compound() 123 | # Needs to be in a separate line because it just gets 124 | # ignored if you pass it as a kwarg in the constructor 125 | level.name = 'Level' 126 | level.tags.extend([ 127 | nbt.TAG_List(name='Entities', type=nbt.TAG_Compound), 128 | nbt.TAG_List(name='TileEntities', type=nbt.TAG_Compound), 129 | nbt.TAG_List(name='LiquidTicks', type=nbt.TAG_Compound), 130 | nbt.TAG_Int(name='xPos', value=self.x), 131 | nbt.TAG_Int(name='zPos', value=self.z), 132 | nbt.TAG_Long(name='LastUpdate', value=0), 133 | nbt.TAG_Long(name='InhabitedTime', value=0), 134 | nbt.TAG_Byte(name='isLightOn', value=1), 135 | nbt.TAG_String(name='Status', value='full') 136 | ]) 137 | sections = nbt.TAG_List(name='Sections', type=nbt.TAG_Compound) 138 | for s in self.sections: 139 | if s: 140 | p = s.palette() 141 | # Minecraft does not save sections that are just air 142 | # So we can just skip them 143 | if len(p) == 1 and p[0].name() == 'minecraft:air': 144 | continue 145 | sections.tags.append(s.save()) 146 | level.tags.append(sections) 147 | root.tags.append(level) 148 | return root 149 | -------------------------------------------------------------------------------- /anvil/empty_region.py: -------------------------------------------------------------------------------- 1 | from typing import Union, List, BinaryIO 2 | from .empty_chunk import EmptyChunk 3 | from .chunk import Chunk 4 | from .empty_section import EmptySection 5 | from .block import Block 6 | from .errors import OutOfBoundsCoordinates 7 | from io import BytesIO 8 | from nbt import nbt 9 | import zlib 10 | import math 11 | 12 | def from_inclusive(a, b): 13 | """Returns a range from a to b, including both endpoints""" 14 | c = int(b > a)*2-1 15 | return range(a, b+c, c) 16 | 17 | class EmptyRegion: 18 | """ 19 | Used for making own regions 20 | 21 | Attributes 22 | ---------- 23 | chunks: List[:class:`anvil.EmptyChunk`] 24 | List of chunks in this region 25 | x: :class:`int` 26 | z: :class:`int` 27 | """ 28 | __slots__ = ('chunks', 'x', 'z') 29 | def __init__(self, x: int, z: int): 30 | # Create a 1d list for the 32x32 chunks 31 | self.chunks: List[EmptyChunk] = [None] * 1024 32 | self.x = x 33 | self.z = z 34 | 35 | def inside(self, x: int, y: int, z: int, chunk: bool=False) -> bool: 36 | """ 37 | Returns if the given coordinates are inside this region 38 | 39 | Parameters 40 | ---------- 41 | int x, y, z 42 | Coordinates 43 | chunk 44 | Whether coordinates are global or chunk coordinates 45 | """ 46 | factor = 32 if chunk else 512 47 | rx = x // factor 48 | rz = z // factor 49 | return not (rx != self.x or rz != self.z or y < 0 or y > 255) 50 | 51 | def get_chunk(self, x: int, z: int) -> EmptyChunk: 52 | """ 53 | Returns the chunk at given chunk coordinates 54 | 55 | Parameters 56 | ---------- 57 | int x, z 58 | Chunk's coordinates 59 | 60 | Raises 61 | ------ 62 | anvil.OutOfBoundCoordidnates 63 | If the chunk (x, z) is not inside this region 64 | 65 | :rtype: :class:`anvil.EmptyChunk` 66 | """ 67 | if not self.inside(x, 0, z, chunk=True): 68 | raise OutOfBoundsCoordinates(f'Chunk ({x}, {z}) is not inside this region') 69 | return self.chunks[z % 32 * 32 + x % 32] 70 | 71 | def add_chunk(self, chunk: EmptyChunk): 72 | """ 73 | Adds given chunk to this region. 74 | Will overwrite if a chunk already exists in this location 75 | 76 | Parameters 77 | ---------- 78 | chunk: :class:`EmptyChunk` 79 | 80 | Raises 81 | ------ 82 | anvil.OutOfBoundCoordidnates 83 | If the chunk (x, z) is not inside this region 84 | """ 85 | if not self.inside(chunk.x, 0, chunk.z, chunk=True): 86 | raise OutOfBoundsCoordinates(f'Chunk ({chunk.x}, {chunk.z}) is not inside this region') 87 | self.chunks[chunk.z % 32 * 32 + chunk.x % 32] = chunk 88 | 89 | def add_section(self, section: EmptySection, x: int, z: int, replace: bool=True): 90 | """ 91 | Adds section to chunk at (x, z). 92 | Same as ``EmptyChunk.add_section(section)`` 93 | 94 | Parameters 95 | ---------- 96 | section: :class:`EmptySection` 97 | Section to add 98 | int x, z 99 | Chunk's coordinate 100 | replace 101 | Whether to replace section if it already exists in the chunk 102 | 103 | Raises 104 | ------ 105 | anvil.OutOfBoundsCoordinates 106 | If the chunk (x, z) is not inside this region 107 | """ 108 | if not self.inside(x, 0, z, chunk=True): 109 | raise OutOfBoundsCoordinates(f'Chunk ({x}, {z}) is not inside this region') 110 | chunk = self.chunks[z % 32 * 32 + x % 32] 111 | if chunk is None: 112 | chunk = EmptyChunk(x, z) 113 | self.add_chunk(chunk) 114 | chunk.add_section(section, replace) 115 | 116 | def set_block(self, block: Block, x: int, y: int, z: int): 117 | """ 118 | Sets block at given coordinates. 119 | New chunk is made if it doesn't exist. 120 | 121 | Parameters 122 | ---------- 123 | block: :class:`Block` 124 | Block to place 125 | int x, y, z 126 | Coordinates 127 | 128 | Raises 129 | ------ 130 | anvil.OutOfBoundsCoordinates 131 | If the block (x, y, z) is not inside this region 132 | """ 133 | if not self.inside(x, y, z): 134 | raise OutOfBoundsCoordinates(f'Block ({x}, {y}, {z}) is not inside this region') 135 | cx = x // 16 136 | cz = z // 16 137 | chunk = self.get_chunk(cx, cz) 138 | if chunk is None: 139 | chunk = EmptyChunk(cx, cz) 140 | self.add_chunk(chunk) 141 | chunk.set_block(block, x % 16, y, z % 16) 142 | 143 | def set_if_inside(self, block: Block, x: int, y: int, z: int): 144 | """ 145 | Helper function that only sets 146 | the block if ``self.inside(x, y, z)`` is true 147 | 148 | Parameters 149 | ---------- 150 | block: :class:`Block` 151 | Block to place 152 | int x, y, z 153 | Coordinates 154 | """ 155 | if self.inside(x, y, z): 156 | self.set_block(block, x, y, z) 157 | 158 | def fill(self, block: Block, x1: int, y1: int, z1: int, x2: int, y2: int, z2: int, ignore_outside: bool=False): 159 | """ 160 | Fills in blocks from 161 | ``(x1, y1, z1)`` to ``(x2, y2, z2)`` 162 | in a rectangle. 163 | 164 | Parameters 165 | ---------- 166 | block: :class:`Block` 167 | int x1, y1, z1 168 | Coordinates 169 | int x2, y2, z2 170 | Coordinates 171 | ignore_outside 172 | Whether to ignore if coordinates are outside the region 173 | 174 | Raises 175 | ------ 176 | anvil.OutOfBoundsCoordinates 177 | If any of the coordinates are outside the region 178 | """ 179 | if not ignore_outside: 180 | if not self.inside(x1, y1, z1): 181 | raise OutOfBoundsCoordinates(f'First coords ({x1}, {y1}, {z1}) is not inside this region') 182 | if not self.inside(x2, y2, z2): 183 | raise OutOfBoundsCoordinates(f'Second coords ({x}, {y}, {z}) is not inside this region') 184 | 185 | for y in from_inclusive(y1, y2): 186 | for z in from_inclusive(z1, z2): 187 | for x in from_inclusive(x1, x2): 188 | if ignore_outside: 189 | self.set_if_inside(block, x, y, z) 190 | else: 191 | self.set_block(block, x, y, z) 192 | 193 | def save(self, file: Union[str, BinaryIO]=None) -> bytes: 194 | """ 195 | Returns the region as bytes with 196 | the anvil file format structure, 197 | aka the final ``.mca`` file. 198 | 199 | Parameters 200 | ---------- 201 | file 202 | Either a path or a file object, if given region 203 | will be saved there. 204 | """ 205 | # Store all the chunks data as zlib compressed nbt data 206 | chunks_data = [] 207 | for chunk in self.chunks: 208 | if chunk is None: 209 | chunks_data.append(None) 210 | continue 211 | chunk_data = BytesIO() 212 | if isinstance(chunk, Chunk): 213 | nbt_data = nbt.NBTFile() 214 | nbt_data.tags.append(nbt.TAG_Int(name='DataVersion', value=chunk.version)) 215 | nbt_data.tags.append(chunk.data) 216 | else: 217 | nbt_data = chunk.save() 218 | nbt_data.write_file(buffer=chunk_data) 219 | chunk_data.seek(0) 220 | chunk_data = zlib.compress(chunk_data.read()) 221 | chunks_data.append(chunk_data) 222 | 223 | # This is what is added after the location and timestamp header 224 | chunks_bytes = bytes() 225 | offsets = [] 226 | for chunk in chunks_data: 227 | if chunk is None: 228 | offsets.append(None) 229 | continue 230 | # 4 bytes are for length, b'\x02' is the compression type which is 2 since its using zlib 231 | to_add = (len(chunk)+1).to_bytes(4, 'big') + b'\x02' + chunk 232 | 233 | # offset in 4KiB sectors 234 | sector_offset = len(chunks_bytes) // 4096 235 | sector_count = math.ceil(len(to_add) / 4096) 236 | offsets.append((sector_offset, sector_count)) 237 | 238 | # Padding to be a multiple of 4KiB long 239 | to_add += bytes(4096 - (len(to_add) % 4096)) 240 | chunks_bytes += to_add 241 | 242 | locations_header = bytes() 243 | for offset in offsets: 244 | # None means the chunk is not an actual chunk in the region 245 | # and will be 4 null bytes, which represents non-generated chunks to minecraft 246 | if offset is None: 247 | locations_header += bytes(4) 248 | else: 249 | # offset is (sector offset, sector count) 250 | locations_header += (offset[0] + 2).to_bytes(3, 'big') + offset[1].to_bytes(1, 'big') 251 | 252 | # Set them all as 0 253 | timestamps_header = bytes(4096) 254 | 255 | final = locations_header + timestamps_header + chunks_bytes 256 | 257 | # Pad file to be a multiple of 4KiB in size 258 | # as Minecraft only accepts region files that are like that 259 | final += bytes(4096 - (len(final) % 4096)) 260 | assert len(final) % 4096 == 0 # just in case 261 | 262 | # Save to a file if it was given 263 | if file: 264 | if isinstance(file, str): 265 | with open(file, 'wb') as f: 266 | f.write(final) 267 | else: 268 | file.write(final) 269 | return final 270 | -------------------------------------------------------------------------------- /anvil/empty_section.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple 2 | from . import Block 3 | from .errors import OutOfBoundsCoordinates 4 | from nbt import nbt 5 | from struct import Struct 6 | import array 7 | 8 | # dirty mixin to change q to Q 9 | def _update_fmt(self, length): 10 | self.fmt = Struct(f'>{length}Q') 11 | nbt.TAG_Long_Array.update_fmt = _update_fmt 12 | 13 | def bin_append(a, b, length=None): 14 | length = length or b.bit_length() 15 | return (a << length) | b 16 | 17 | class EmptySection: 18 | """ 19 | Used for making own sections. 20 | 21 | This is where the blocks are actually stored, in a 16³ sized array. 22 | To save up some space, ``None`` is used instead of the air block object, 23 | and will be replaced with ``self.air`` when needed 24 | 25 | Attributes 26 | ---------- 27 | y: :class:`int` 28 | Section's Y index 29 | blocks: List[:class:`Block`] 30 | 1D list of blocks 31 | air: :class:`Block` 32 | An air block 33 | """ 34 | __slots__ = ('y', 'blocks', 'air') 35 | def __init__(self, y: int): 36 | self.y = y 37 | # None is the same as an air block 38 | self.blocks: List[Block] = [None] * 4096 39 | # Block that will be used when None 40 | self.air = Block('minecraft', 'air') 41 | 42 | @staticmethod 43 | def inside(x: int, y: int, z: int) -> bool: 44 | """ 45 | Check if X Y and Z are in range of 0-15 46 | 47 | Parameters 48 | ---------- 49 | int x, y, z 50 | Coordinates 51 | """ 52 | return x >= 0 and x <= 15 and y >= 0 and y <= 15 and z >= 0 and z <= 15 53 | 54 | def set_block(self, block: Block, x: int, y: int, z: int): 55 | """ 56 | Sets the block at given coordinates 57 | 58 | Parameters 59 | ---------- 60 | block 61 | Block to set 62 | int x, y, z 63 | Coordinates 64 | 65 | Raises 66 | ------ 67 | anvil.OutOfBoundsCoordinates 68 | If coordinates are not in range of 0-15 69 | """ 70 | if not self.inside(x, y, z): 71 | raise OutOfBoundsCoordinates('X Y and Z must be in range of 0-15') 72 | index = y * 256 + z * 16 + x 73 | self.blocks[index] = block 74 | 75 | def get_block(self, x: int, y: int, z: int) -> Block: 76 | """ 77 | Gets the block at given coordinates. 78 | 79 | Parameters 80 | ---------- 81 | int x, y, z 82 | Coordinates 83 | 84 | Raises 85 | ------ 86 | anvil.OutOfBoundsCoordinates 87 | If coordinates are not in range of 0-15 88 | """ 89 | if not self.inside(x, y, z): 90 | raise OutOfBoundsCoordinates('X Y and Z must be in range of 0-15') 91 | index = y * 256 + z * 16 + x 92 | return self.blocks[index] or self.air 93 | 94 | def palette(self) -> Tuple[Block]: 95 | """ 96 | Generates and returns a tuple of all the different blocks in the section 97 | The order can change as it uses sets, but should be fine when saving since 98 | it's only called once. 99 | """ 100 | palette = set(self.blocks) 101 | if None in palette: 102 | palette.remove(None) 103 | palette.add(self.air) 104 | return tuple(palette) 105 | 106 | def blockstates(self, palette: Tuple[Block]=None) -> array.array: 107 | """ 108 | Returns a list of each block's index in the palette. 109 | 110 | This is used in the BlockStates tag of the section. 111 | 112 | Parameters 113 | ---------- 114 | palette 115 | Section's palette. If not given will generate one. 116 | """ 117 | palette = palette or self.palette() 118 | bits = max((len(palette) - 1).bit_length(), 4) 119 | states = array.array('Q') 120 | current = 0 121 | current_len = 0 122 | for block in self.blocks: 123 | if block is None: 124 | index = palette.index(self.air) 125 | else: 126 | index = palette.index(block) 127 | # If it's more than 64 bits then add to list and start over 128 | # with the remaining bits from last one 129 | if current_len + bits > 64: 130 | leftover = 64 - current_len 131 | states.append(bin_append(index & ((1 << leftover) - 1), current, length=current_len)) 132 | current = index >> leftover 133 | current_len = bits - leftover 134 | else: 135 | current = bin_append(index, current, length=current_len) 136 | current_len += bits 137 | states.append(current) 138 | return states 139 | 140 | def save(self) -> nbt.TAG_Compound: 141 | """ 142 | Saves the section to a TAG_Compound and is used inside the chunk tag 143 | This is missing the SkyLight tag, but minecraft still accepts it anyway 144 | """ 145 | root = nbt.TAG_Compound() 146 | root.tags.append(nbt.TAG_Byte(name='Y', value=self.y)) 147 | 148 | palette = self.palette() 149 | nbt_pal = nbt.TAG_List(name='Palette', type=nbt.TAG_Compound) 150 | for block in palette: 151 | tag = nbt.TAG_Compound() 152 | tag.tags.append(nbt.TAG_String(name='Name', value=block.name())) 153 | if block.properties: 154 | properties = nbt.TAG_Compound() 155 | properties.name = 'Properties' 156 | for key, value in block.properties.items(): 157 | if isinstance(value, str): 158 | properties.tags.append(nbt.TAG_String(name=key, value=value)) 159 | elif isinstance(value, bool): 160 | # booleans are a string saved as either 'true' or 'false' 161 | properties.tags.append(nbt.TAG_String(name=key, value=str(value).lower())) 162 | elif isinstance(value, int): 163 | # ints also seem to be saved as a string 164 | properties.tags.append(nbt.TAG_String(name=key, value=str(value))) 165 | else: 166 | # assume its a nbt tag and just append it 167 | properties.tags.append(value) 168 | tag.tags.append(properties) 169 | nbt_pal.tags.append(tag) 170 | root.tags.append(nbt_pal) 171 | 172 | states = self.blockstates(palette=palette) 173 | bstates = nbt.TAG_Long_Array(name='BlockStates') 174 | bstates.value = states 175 | root.tags.append(bstates) 176 | 177 | return root 178 | -------------------------------------------------------------------------------- /anvil/errors.py: -------------------------------------------------------------------------------- 1 | class OutOfBoundsCoordinates(ValueError): 2 | """Exception used for when coordinates are out of bounds""" 3 | 4 | class ChunkNotFound(Exception): 5 | """Exception used for when a chunk was not found""" 6 | 7 | class EmptySectionAlreadyExists(Exception): 8 | """ 9 | Exception used for when trying to add an `EmptySection` to an `EmptyChunk` 10 | and the chunk already has a section with the same Y 11 | """ 12 | 13 | class GZipChunkData(Exception): 14 | """Exception used when trying to get chunk data compressed in gzip""" -------------------------------------------------------------------------------- /anvil/legacy.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | with open(os.path.join(os.path.dirname(__file__), 'legacy_blocks.json'), 'r') as file: 5 | LEGACY_ID_MAP = json.load(file) 6 | -------------------------------------------------------------------------------- /anvil/legacy_blocks.json: -------------------------------------------------------------------------------- 1 | { 2 | "0:0": ["air", null], 3 | "1:0": ["stone", null], 4 | "1:1": ["granite", null], 5 | "1:2": ["polished_granite", null], 6 | "1:3": ["diorite", null], 7 | "1:4": ["polished_diorite", null], 8 | "1:5": ["andesite", null], 9 | "1:6": ["polished_andesite", null], 10 | "2:0": ["grass_block", null], 11 | "3:0": ["dirt", null], 12 | "3:1": ["coarse_dirt", null], 13 | "3:2": ["podzol", null], 14 | "4:0": ["cobblestone", null], 15 | "5:0": ["oak_planks", null], 16 | "5:1": ["spruce_planks", null], 17 | "5:2": ["birch_planks", null], 18 | "5:3": ["jungle_planks", null], 19 | "5:4": ["acacia_planks", null], 20 | "5:5": ["dark_oak_planks", null], 21 | "6:0": ["oak_sapling", null], 22 | "6:1": ["spruce_sapling", null], 23 | "6:2": ["birch_sapling", null], 24 | "6:3": ["jungle_sapling", null], 25 | "6:4": ["acacia_sapling", null], 26 | "6:5": ["dark_oak_sapling", null], 27 | "7:0": ["bedrock", null], 28 | 29 | "8:0": ["flowing_water", {"level": 0, "falling": false}], 30 | "8:1": ["flowing_water", {"level": 1, "falling": false}], 31 | "8:2": ["flowing_water", {"level": 2, "falling": false}], 32 | "8:3": ["flowing_water", {"level": 3, "falling": false}], 33 | "8:4": ["flowing_water", {"level": 4, "falling": false}], 34 | "8:5": ["flowing_water", {"level": 5, "falling": false}], 35 | "8:6": ["flowing_water", {"level": 6, "falling": false}], 36 | "8:7": ["flowing_water", {"level": 7, "falling": false}], 37 | "8:8": ["flowing_water", {"level": 0, "falling": true}], 38 | "8:9": ["flowing_water", {"level": 1, "falling": true}], 39 | "8:10": ["flowing_water", {"level": 2, "falling": true}], 40 | "8:11": ["flowing_water", {"level": 3, "falling": true}], 41 | "8:12": ["flowing_water", {"level": 4, "falling": true}], 42 | "8:13": ["flowing_water", {"level": 5, "falling": true}], 43 | "8:14": ["flowing_water", {"level": 6, "falling": true}], 44 | "8:15": ["flowing_water", {"level": 7, "falling": true}], 45 | 46 | "9:0": ["water", {"level": 0}], 47 | "9:1": ["water", {"level": 1}], 48 | "9:2": ["water", {"level": 2}], 49 | "9:3": ["water", {"level": 3}], 50 | "9:4": ["water", {"level": 4}], 51 | "9:5": ["water", {"level": 5}], 52 | "9:6": ["water", {"level": 6}], 53 | "9:7": ["water", {"level": 7}], 54 | "9:8": ["water", {"level": 8}], 55 | "9:9": ["water", {"level": 9}], 56 | "9:10": ["water", {"level": 10}], 57 | "9:11": ["water", {"level": 11}], 58 | "9:12": ["water", {"level": 12}], 59 | "9:13": ["water", {"level": 13}], 60 | "9:14": ["water", {"level": 14}], 61 | "9:15": ["water", {"level": 15}], 62 | 63 | "10:0": ["flowing_lava", {"level": 0, "falling": false}], 64 | "10:1": ["flowing_lava", {"level": 1, "falling": false}], 65 | "10:2": ["flowing_lava", {"level": 2, "falling": false}], 66 | "10:3": ["flowing_lava", {"level": 3, "falling": false}], 67 | "10:4": ["flowing_lava", {"level": 4, "falling": false}], 68 | "10:5": ["flowing_lava", {"level": 5, "falling": false}], 69 | "10:6": ["flowing_lava", {"level": 6, "falling": false}], 70 | "10:7": ["flowing_lava", {"level": 7, "falling": false}], 71 | "10:8": ["flowing_lava", {"level": 0, "falling": true}], 72 | "10:9": ["flowing_lava", {"level": 1, "falling": true}], 73 | "10:10": ["flowing_lava", {"level": 2, "falling": true}], 74 | "10:11": ["flowing_lava", {"level": 3, "falling": true}], 75 | "10:12": ["flowing_lava", {"level": 4, "falling": true}], 76 | "10:13": ["flowing_lava", {"level": 5, "falling": true}], 77 | "10:14": ["flowing_lava", {"level": 6, "falling": true}], 78 | "10:15": ["flowing_lava", {"level": 7, "falling": true}], 79 | 80 | "11:0": ["lava", {"level": 0}], 81 | "11:1": ["lava", {"level": 1}], 82 | "11:2": ["lava", {"level": 2}], 83 | "11:3": ["lava", {"level": 3}], 84 | "11:4": ["lava", {"level": 4}], 85 | "11:5": ["lava", {"level": 5}], 86 | "11:6": ["lava", {"level": 6}], 87 | "11:7": ["lava", {"level": 7}], 88 | "11:8": ["lava", {"level": 8}], 89 | "11:9": ["lava", {"level": 9}], 90 | "11:10": ["lava", {"level": 10}], 91 | "11:11": ["lava", {"level": 11}], 92 | "11:12": ["lava", {"level": 12}], 93 | "11:13": ["lava", {"level": 13}], 94 | "11:14": ["lava", {"level": 14}], 95 | "11:15": ["lava", {"level": 15}], 96 | 97 | "12:0": ["sand", null], 98 | "12:1": ["red_sand", null], 99 | "13:0": ["gravel", null], 100 | "14:0": ["gold_ore", null], 101 | "15:0": ["iron_ore", null], 102 | "16:0": ["coal_ore", null], 103 | 104 | "17:0": ["oak_log", {"axis": "y"}], 105 | "17:1": ["spruce_log", {"axis": "y"}], 106 | "17:2": ["birch_log", {"axis": "y"}], 107 | "17:3": ["jungle_log", {"axis": "y"}], 108 | "17:4": ["oak_log", {"axis": "x"}], 109 | "17:5": ["spruce_log", {"axis": "x"}], 110 | "17:6": ["birch_log", {"axis": "x"}], 111 | "17:7": ["jungle_log", {"axis": "x"}], 112 | "17:8": ["oak_log", {"axis": "z"}], 113 | "17:9": ["spruce_log", {"axis": "z"}], 114 | "17:10": ["birch_log", {"axis": "z"}], 115 | "17:11": ["jungle_log", {"axis": "z"}], 116 | "17:12": ["oak_log", null], 117 | "17:13": ["spruce_log", null], 118 | "17:14": ["birch_log", null], 119 | "17:15": ["jungle_log", null], 120 | 121 | "18:0": ["oak_leaves", {"persistent": false}], 122 | "18:1": ["spruce_leaves", {"persistent": false}], 123 | "18:2": ["birch_leaves", {"persistent": false}], 124 | "18:3": ["jungle_leaves", {"persistent": false}], 125 | "18:4": ["oak_leaves", {"persistent": true}], 126 | "18:5": ["spruce_leaves", {"persistent": true}], 127 | "18:6": ["birch_leaves", {"persistent": true}], 128 | "18:7": ["jungle_leaves", {"persistent": true}], 129 | "18:8": ["oak_leaves", {"persistent": false}], 130 | "18:9": ["spruce_leaves", {"persistent": false}], 131 | "18:10": ["birch_leaves", {"persistent": false}], 132 | "18:11": ["jungle_leaves", {"persistent": false}], 133 | "18:12": ["oak_leaves", {"persistent": true}], 134 | "18:13": ["spruce_leaves", {"persistent": true}], 135 | "18:14": ["birch_leaves", {"persistent": true}], 136 | "18:15": ["jungle_leaves", {"persistent": true}], 137 | 138 | "19:0": ["sponge", null], 139 | "19:1": ["wet_sponge", null], 140 | "20:0": ["glass", null], 141 | "21:0": ["lapis_ore", null], 142 | "22:0": ["lapis_block", null], 143 | 144 | "23:0": ["dispenser", null], 145 | "23:0": ["dispenser", {"facing": "down", "triggered": false}], 146 | "23:1": ["dispenser", {"facing": "up", "triggered": false}], 147 | "23:2": ["dispenser", {"facing": "north", "triggered": false}], 148 | "23:3": ["dispenser", {"facing": "south", "triggered": false}], 149 | "23:4": ["dispenser", {"facing": "west", "triggered": false}], 150 | "23:5": ["dispenser", {"facing": "east", "triggered": false}], 151 | "23:8": ["dispenser", {"facing": "down", "triggered": true}], 152 | "23:9": ["dispenser", {"facing": "up", "triggered": true}], 153 | "23:10": ["dispenser", {"facing": "north", "triggered": true}], 154 | "23:11": ["dispenser", {"facing": "south", "triggered": true}], 155 | "23:12": ["dispenser", {"facing": "west", "triggered": true}], 156 | "23:13": ["dispenser", {"facing": "east", "triggered": true}], 157 | 158 | "24:0": ["sandstone", null], 159 | "24:1": ["chiseled_sandstone", null], 160 | "24:2": ["cut_sandstone", null], 161 | "25:0": ["note_block", null], 162 | 163 | "26:0": ["bed", {"facing": "south", "occupied": false, "part": "foot"}], 164 | "26:1": ["bed", {"facing": "west", "occupied": false, "part": "foot"}], 165 | "26:2": ["bed", {"facing": "north", "occupied": false, "part": "foot"}], 166 | "26:3": ["bed", {"facing": "east", "occupied": false, "part": "foot"}], 167 | "26:4": ["bed", {"facing": "south", "occupied": true, "part": "foot"}], 168 | "26:5": ["bed", {"facing": "west", "occupied": true, "part": "foot"}], 169 | "26:6": ["bed", {"facing": "north", "occupied": true, "part": "foot"}], 170 | "26:7": ["bed", {"facing": "east", "occupied": true, "part": "foot"}], 171 | "26:8": ["bed", {"facing": "south", "occupied": false, "part": "head"}], 172 | "26:9": ["bed", {"facing": "west", "occupied": false, "part": "head"}], 173 | "26:10": ["bed", {"facing": "north", "occupied": false, "part": "head"}], 174 | "26:11": ["bed", {"facing": "east", "occupied": false, "part": "head"}], 175 | "26:12": ["bed", {"facing": "south", "occupied": true, "part": "head"}], 176 | "26:13": ["bed", {"facing": "west", "occupied": true, "part": "head"}], 177 | "26:14": ["bed", {"facing": "north", "occupied": true, "part": "head"}], 178 | "26:15": ["bed", {"facing": "east", "occupied": true, "part": "head"}], 179 | 180 | "27:0": ["powered_rail", {"shape": "north_south", "powered": false}], 181 | "27:1": ["powered_rail", {"shape": "east_west", "powered": false}], 182 | "27:2": ["powered_rail", {"shape": "ascending_east", "powered": false}], 183 | "27:3": ["powered_rail", {"shape": "ascending_west", "powered": false}], 184 | "27:4": ["powered_rail", {"shape": "ascending_north", "powered": false}], 185 | "27:5": ["powered_rail", {"shape": "ascending_south", "powered": false}], 186 | "27:8": ["powered_rail", {"shape": "north_south", "powered": true}], 187 | "27:9": ["powered_rail", {"shape": "east_west", "powered": true}], 188 | "27:10": ["powered_rail", {"shape": "ascending_east", "powered": true}], 189 | "27:11": ["powered_rail", {"shape": "ascending_west", "powered": true}], 190 | "27:12": ["powered_rail", {"shape": "ascending_north", "powered": true}], 191 | "27:13": ["powered_rail", {"shape": "ascending_south", "powered": true}], 192 | 193 | "28:0": ["detector_rail", {"shape": "north_south", "powered": false}], 194 | "28:1": ["detector_rail", {"shape": "east_west", "powered": false}], 195 | "28:2": ["detector_rail", {"shape": "ascending_east", "powered": false}], 196 | "28:3": ["detector_rail", {"shape": "ascending_west", "powered": false}], 197 | "28:4": ["detector_rail", {"shape": "ascending_north", "powered": false}], 198 | "28:5": ["detector_rail", {"shape": "ascending_south", "powered": false}], 199 | "28:8": ["detector_rail", {"shape": "north_south", "powered": true}], 200 | "28:9": ["detector_rail", {"shape": "east_west", "powered": true}], 201 | "28:10": ["detector_rail", {"shape": "ascending_east", "powered": true}], 202 | "28:11": ["detector_rail", {"shape": "ascending_west", "powered": true}], 203 | "28:12": ["detector_rail", {"shape": "ascending_north", "powered": true}], 204 | "28:13": ["detector_rail", {"shape": "ascending_south", "powered": true}], 205 | 206 | "29:0": ["sticky_piston", {"facing": "down", "extended": false}], 207 | "29:1": ["sticky_piston", {"facing": "up", "extended": false}], 208 | "29:2": ["sticky_piston", {"facing": "north", "extended": false}], 209 | "29:3": ["sticky_piston", {"facing": "south", "extended": false}], 210 | "29:4": ["sticky_piston", {"facing": "west", "extended": false}], 211 | "29:5": ["sticky_piston", {"facing": "east", "extended": false}], 212 | "29:8": ["sticky_piston", {"facing": "down", "extended": true}], 213 | "29:9": ["sticky_piston", {"facing": "up", "extended": true}], 214 | "29:10": ["sticky_piston", {"facing": "north", "extended": true}], 215 | "29:11": ["sticky_piston", {"facing": "south", "extended": true}], 216 | "29:12": ["sticky_piston", {"facing": "west", "extended": true}], 217 | "29:13": ["sticky_piston", {"facing": "east", "extended": true}], 218 | 219 | "30:0": ["cobweb", null], 220 | "31:0": ["dead_shrub", null], 221 | "31:1": ["grass", null], 222 | "31:2": ["fern", null], 223 | "32:0": ["dead_bush", null], 224 | 225 | "33:0": ["piston", {"facing": "down", "extended": false}], 226 | "33:1": ["piston", {"facing": "up", "extended": false}], 227 | "33:2": ["piston", {"facing": "north", "extended": false}], 228 | "33:3": ["piston", {"facing": "south", "extended": false}], 229 | "33:4": ["piston", {"facing": "west", "extended": false}], 230 | "33:5": ["piston", {"facing": "east", "extended": false}], 231 | "33:8": ["piston", {"facing": "down", "extended": true}], 232 | "33:9": ["piston", {"facing": "up", "extended": true}], 233 | "33:10": ["piston", {"facing": "north", "extended": true}], 234 | "33:11": ["piston", {"facing": "south", "extended": true}], 235 | "33:12": ["piston", {"facing": "west", "extended": true}], 236 | "33:13": ["piston", {"facing": "east", "extended": true}], 237 | 238 | "34:0": ["piston_head", {"facing": "down", "type": "normal"}], 239 | "34:1": ["piston_head", {"facing": "up", "type": "normal"}], 240 | "34:2": ["piston_head", {"facing": "north", "type": "normal"}], 241 | "34:3": ["piston_head", {"facing": "south", "type": "normal"}], 242 | "34:4": ["piston_head", {"facing": "west", "type": "normal"}], 243 | "34:5": ["piston_head", {"facing": "east", "type": "normal"}], 244 | "34:8": ["piston_head", {"facing": "down", "type": "sticky"}], 245 | "34:9": ["piston_head", {"facing": "up", "type": "sticky"}], 246 | "34:10": ["piston_head", {"facing": "north", "type": "sticky"}], 247 | "34:11": ["piston_head", {"facing": "south", "type": "sticky"}], 248 | "34:12": ["piston_head", {"facing": "west", "type": "sticky"}], 249 | "34:13": ["piston_head", {"facing": "east", "type": "sticky"}], 250 | 251 | "35:0": ["white_wool", null], 252 | "35:1": ["orange_wool", null], 253 | "35:2": ["magenta_wool", null], 254 | "35:3": ["light_blue_wool", null], 255 | "35:4": ["yellow_wool", null], 256 | "35:5": ["lime_wool", null], 257 | "35:6": ["pink_wool", null], 258 | "35:7": ["gray_wool", null], 259 | "35:8": ["light_gray_wool", null], 260 | "35:9": ["cyan_wool", null], 261 | "35:10": ["purple_wool", null], 262 | "35:11": ["blue_wool", null], 263 | "35:12": ["brown_wool", null], 264 | "35:13": ["green_wool", null], 265 | "35:14": ["red_wool", null], 266 | "35:15": ["black_wool", null], 267 | "37:0": ["dandelion", null], 268 | "38:0": ["poppy", null], 269 | "38:1": ["blue_orchid", null], 270 | "38:2": ["allium", null], 271 | "38:3": ["azure_bluet", null], 272 | "38:4": ["red_tulip", null], 273 | "38:5": ["orange_tulip", null], 274 | "38:6": ["white_tulip", null], 275 | "38:7": ["pink_tulip", null], 276 | "38:8": ["oxeye_daisy", null], 277 | "39:0": ["brown_mushroom", null], 278 | "40:0": ["red_mushroom", null], 279 | "41:0": ["gold_block", null], 280 | "42:0": ["iron_block", null], 281 | 282 | "43:0": ["smooth_stone_slab", {"type": "double"}], 283 | "43:1": ["sandstone_slab", {"type": "double"}], 284 | "43:2": ["petrified_oak_slab", {"type": "double"}], 285 | "43:3": ["cobblestone_slab", {"type": "double"}], 286 | "43:4": ["brick_slab", {"type": "double"}], 287 | "43:5": ["stone_brick_slab", {"type": "double"}], 288 | "43:6": ["nether_brick_slab", {"type": "double"}], 289 | "43:7": ["quartz_slab", {"type": "double"}], 290 | "43:8": ["smooth_stone", null], 291 | "43:9": ["smooth_sandstone", null], 292 | "43:10": ["petrified_oak_slab", {"type": "double"}], 293 | "43:11": ["cobblestone_slab", {"type": "double"}], 294 | "43:12": ["brick_slab", {"type": "double"}], 295 | "43:13": ["stone_brick_slab", {"type": "double"}], 296 | "43:14": ["nether_brick_slab", {"type": "double"}], 297 | "43:15": ["smooth_quartz", null], 298 | 299 | "44:0": ["smooth_stone_slab", {"type": "bottom"}], 300 | "44:1": ["sandstone_slab", {"type": "bottom"}], 301 | "44:2": ["wooden_slab", {"type": "bottom"}], 302 | "44:3": ["cobblestone_slab", {"type": "bottom"}], 303 | "44:4": ["brick_slab", {"type": "bottom"}], 304 | "44:5": ["stone_brick_slab", {"type": "bottom"}], 305 | "44:6": ["nether_brick_slab", {"type": "bottom"}], 306 | "44:7": ["quartz_slab", {"type": "bottom"}], 307 | "44:8": ["smooth_stone_slab", {"type": "top"}], 308 | "44:9": ["sandstone_slab", {"type": "top"}], 309 | "44:10": ["wooden_slab", {"type": "top"}], 310 | "44:11": ["cobblestone_slab", {"type": "top"}], 311 | "44:12": ["brick_slab", {"type": "top"}], 312 | "44:13": ["stone_brick_slab", {"type": "top"}], 313 | "44:14": ["nether_brick_slab", {"type": "top"}], 314 | "44:15": ["quartz_slab", {"type": "top"}], 315 | 316 | "45:0": ["bricks", null], 317 | "46:0": ["tnt", null], 318 | "47:0": ["bookshelf", null], 319 | "48:0": ["mossy_cobblestone", null], 320 | "49:0": ["obsidian", null], 321 | 322 | "50:0": ["torch", null], 323 | "50:1": ["wall_torch", {"facing": "east"}], 324 | "50:2": ["wall_torch", {"facing": "west"}], 325 | "50:3": ["wall_torch", {"facing": "south"}], 326 | "50:4": ["wall_torch", {"facing": "north"}], 327 | "50:5": ["torch", null], 328 | 329 | "51:0": ["fire", null], 330 | "51:1": ["fire", null], 331 | "51:2": ["fire", null], 332 | "51:3": ["fire", null], 333 | "51:4": ["fire", null], 334 | "51:5": ["fire", null], 335 | "51:6": ["fire", null], 336 | "51:7": ["fire", null], 337 | "51:8": ["fire", null], 338 | "51:9": ["fire", null], 339 | "51:10": ["fire", null], 340 | "51:11": ["fire", null], 341 | "51:12": ["fire", null], 342 | "51:13": ["fire", null], 343 | "51:14": ["fire", null], 344 | "51:15": ["fire", null], 345 | 346 | "52:0": ["spawner", null], 347 | 348 | "53:0": ["oak_stairs", {"facing": "east", "half": "bottom"}], 349 | "53:1": ["oak_stairs", {"facing": "west", "half": "bottom"}], 350 | "53:2": ["oak_stairs", {"facing": "south", "half": "bottom"}], 351 | "53:3": ["oak_stairs", {"facing": "north", "half": "bottom"}], 352 | "53:4": ["oak_stairs", {"facing": "east", "half": "top"}], 353 | "53:5": ["oak_stairs", {"facing": "west", "half": "top"}], 354 | "53:6": ["oak_stairs", {"facing": "south", "half": "top"}], 355 | "53:7": ["oak_stairs", {"facing": "north", "half": "top"}], 356 | 357 | "54:0": ["chest", {"facing": "north"}], 358 | "54:1": ["chest", {"facing": "north"}], 359 | "54:2": ["chest", {"facing": "north"}], 360 | "54:3": ["chest", {"facing": "south"}], 361 | "54:4": ["chest", {"facing": "west"}], 362 | "54:5": ["chest", {"facing": "east"}], 363 | 364 | 365 | "55:0": ["redstone_wire", {"power": 0}], 366 | "55:1": ["redstone_wire", {"power": 1}], 367 | "55:2": ["redstone_wire", {"power": 2}], 368 | "55:3": ["redstone_wire", {"power": 3}], 369 | "55:4": ["redstone_wire", {"power": 4}], 370 | "55:5": ["redstone_wire", {"power": 5}], 371 | "55:6": ["redstone_wire", {"power": 6}], 372 | "55:7": ["redstone_wire", {"power": 7}], 373 | "55:8": ["redstone_wire", {"power": 8}], 374 | "55:9": ["redstone_wire", {"power": 9}], 375 | "55:10": ["redstone_wire", {"power": 10}], 376 | "55:11": ["redstone_wire", {"power": 11}], 377 | "55:12": ["redstone_wire", {"power": 12}], 378 | "55:13": ["redstone_wire", {"power": 13}], 379 | "55:14": ["redstone_wire", {"power": 14}], 380 | "55:15": ["redstone_wire", {"power": 15}], 381 | 382 | 383 | "56:0": ["diamond_ore", null], 384 | "57:0": ["diamond_block", null], 385 | "58:0": ["crafting_table", null], 386 | 387 | "59:0": ["wheat", {"age": 0}], 388 | "59:1": ["wheat", {"age": 1}], 389 | "59:2": ["wheat", {"age": 2}], 390 | "59:3": ["wheat", {"age": 3}], 391 | "59:4": ["wheat", {"age": 4}], 392 | "59:5": ["wheat", {"age": 5}], 393 | "59:6": ["wheat", {"age": 6}], 394 | "59:7": ["wheat", {"age": 7}], 395 | 396 | "60:0": ["farmland", {"moisture": 0}], 397 | "60:1": ["farmland", {"moisture": 1}], 398 | "60:2": ["farmland", {"moisture": 2}], 399 | "60:3": ["farmland", {"moisture": 3}], 400 | "60:4": ["farmland", {"moisture": 4}], 401 | "60:5": ["farmland", {"moisture": 5}], 402 | "60:6": ["farmland", {"moisture": 6}], 403 | "60:7": ["farmland", {"moisture": 7}], 404 | 405 | "61:0": ["furnace", {"lit": false, "facing": "north"}], 406 | "61:1": ["furnace", {"lit": false, "facing": "north"}], 407 | "61:2": ["furnace", {"lit": false, "facing": "north"}], 408 | "61:3": ["furnace", {"lit": false, "facing": "south"}], 409 | "61:4": ["furnace", {"lit": false, "facing": "west"}], 410 | "61:5": ["furnace", {"lit": false, "facing": "east"}], 411 | 412 | "62:0": ["furnace", {"lit": true, "facing": "north"}], 413 | "61:1": ["furnace", {"lit": false, "facing": "north"}], 414 | "62:2": ["furnace", {"lit": true, "facing": "north"}], 415 | "62:3": ["furnace", {"lit": true, "facing": "south"}], 416 | "62:4": ["furnace", {"lit": true, "facing": "west"}], 417 | "62:5": ["furnace", {"lit": true, "facing": "east"}], 418 | 419 | "63:0": ["oak_sign", {"rotation": 0}], 420 | "63:1": ["oak_sign", {"rotation": 1}], 421 | "63:2": ["oak_sign", {"rotation": 2}], 422 | "63:3": ["oak_sign", {"rotation": 3}], 423 | "63:4": ["oak_sign", {"rotation": 4}], 424 | "63:5": ["oak_sign", {"rotation": 5}], 425 | "63:6": ["oak_sign", {"rotation": 6}], 426 | "63:7": ["oak_sign", {"rotation": 7}], 427 | "63:8": ["oak_sign", {"rotation": 8}], 428 | "63:9": ["oak_sign", {"rotation": 9}], 429 | "63:10": ["oak_sign", {"rotation": 10}], 430 | "63:11": ["oak_sign", {"rotation": 11}], 431 | "63:12": ["oak_sign", {"rotation": 12}], 432 | "63:13": ["oak_sign", {"rotation": 13}], 433 | "63:14": ["oak_sign", {"rotation": 14}], 434 | "63:15": ["oak_sign", {"rotation": 15}], 435 | 436 | 437 | "64:0": ["oak_door", {"half": "lower", "facing": "east", "open": false}], 438 | "64:1": ["oak_door", {"half": "lower", "facing": "south", "open": false}], 439 | "64:2": ["oak_door", {"half": "lower", "facing": "west", "open": false}], 440 | "64:3": ["oak_door", {"half": "lower", "facing": "north", "open": false}], 441 | "64:4": ["oak_door", {"half": "lower", "facing": "east", "open": true}], 442 | "64:5": ["oak_door", {"half": "lower", "facing": "south", "open": true}], 443 | "64:6": ["oak_door", {"half": "lower", "facing": "west", "open": true}], 444 | "64:7": ["oak_door", {"half": "lower", "facing": "north", "open": true}], 445 | 446 | "64:8": ["oak_door", {"half": "upper", "hinge": "left", "powered": false}], 447 | "64:9": ["oak_door", {"half": "upper", "hinge": "right", "powered": false}], 448 | "64:10": ["oak_door", {"half": "upper", "hinge": "left", "powered": true}], 449 | "64:11": ["oak_door", {"half": "upper", "hinge": "right", "powered": true}], 450 | 451 | "65:0": ["ladder", {"facing": "north"}], 452 | "65:1": ["ladder", {"facing": "north"}], 453 | "65:2": ["ladder", {"facing": "north"}], 454 | "65:3": ["ladder", {"facing": "south"}], 455 | "65:4": ["ladder", {"facing": "west"}], 456 | "65:5": ["ladder", {"facing": "east"}], 457 | 458 | "66:0": ["rail", {"shape": "north_south"}], 459 | "66:1": ["rail", {"shape": "east_west"}], 460 | "66:2": ["rail", {"shape": "ascending_east"}], 461 | "66:3": ["rail", {"shape": "ascending_west"}], 462 | "66:4": ["rail", {"shape": "ascending_north"}], 463 | "66:5": ["rail", {"shape": "ascending_south"}], 464 | "66:6": ["rail", {"shape": "south_east"}], 465 | "66:7": ["rail", {"shape": "south_west"}], 466 | "66:8": ["rail", {"shape": "north_west"}], 467 | "66:9": ["rail", {"shape": "north_east"}], 468 | 469 | "67:0": ["cobblestone_stairs", {"facing": "east", "half": "bottom"}], 470 | "67:1": ["cobblestone_stairs", {"facing": "west", "half": "bottom"}], 471 | "67:2": ["cobblestone_stairs", {"facing": "south", "half": "bottom"}], 472 | "67:3": ["cobblestone_stairs", {"facing": "north", "half": "bottom"}], 473 | "67:4": ["cobblestone_stairs", {"facing": "east", "half": "top"}], 474 | "67:5": ["cobblestone_stairs", {"facing": "west", "half": "top"}], 475 | "67:6": ["cobblestone_stairs", {"facing": "south", "half": "top"}], 476 | "67:7": ["cobblestone_stairs", {"facing": "north", "half": "top"}], 477 | 478 | "68:0": ["oak_wall_sign", {"facing": "north"}], 479 | "68:1": ["oak_wall_sign", {"facing": "north"}], 480 | "68:2": ["oak_wall_sign", {"facing": "north"}], 481 | "68:3": ["oak_wall_sign", {"facing": "south"}], 482 | "68:4": ["oak_wall_sign", {"facing": "west"}], 483 | "68:5": ["oak_wall_sign", {"facing": "east"}], 484 | 485 | "69:0": ["lever", {"face": "ceiling", "facing": "west", "powered": false}], 486 | 487 | "69:1": ["lever", {"face": "wall", "facing": "east", "powered": false}], 488 | "69:2": ["lever", {"face": "wall", "facing": "west", "powered": false}], 489 | "69:3": ["lever", {"face": "wall", "facing": "south", "powered": false}], 490 | "69:4": ["lever", {"face": "wall", "facing": "north", "powered": false}], 491 | 492 | "69:5": ["lever", {"face": "floor", "facing": "north", "powered": false}], 493 | "69:6": ["lever", {"face": "floor", "facing": "west", "powered": false}], 494 | "69:7": ["lever", {"face": "ceiling", "facing": "north", "powered": false}], 495 | "69:8": ["lever", {"face": "ceiling", "facing": "west", "powered": true}], 496 | 497 | "69:9": ["lever", {"face": "wall", "facing": "east", "powered": true}], 498 | "69:10": ["lever", {"face": "wall", "facing": "west", "powered": true}], 499 | "69:11": ["lever", {"face": "wall", "facing": "south", "powered": true}], 500 | "69:12": ["lever", {"face": "wall", "facing": "north", "powered": true}], 501 | 502 | "69:13": ["lever", {"face": "floor", "facing": "north", "powered": true}], 503 | "69:14": ["lever", {"face": "floor", "facing": "west", "powered": true}], 504 | "69:15": ["lever", {"face": "ceiling", "facing": "north", "powered": true}], 505 | 506 | "70:0": ["stone_pressure_plate", {"powered": false}], 507 | "70:1": ["stone_pressure_plate", {"powered": true}], 508 | 509 | "71:0": ["iron_door", {"half": "lower", "facing": "east", "open": false}], 510 | "71:1": ["iron_door", {"half": "lower", "facing": "south", "open": false}], 511 | "71:2": ["iron_door", {"half": "lower", "facing": "west", "open": false}], 512 | "71:3": ["iron_door", {"half": "lower", "facing": "north", "open": false}], 513 | "71:4": ["iron_door", {"half": "lower", "facing": "east", "open": true}], 514 | "71:5": ["iron_door", {"half": "lower", "facing": "south", "open": true}], 515 | "71:6": ["iron_door", {"half": "lower", "facing": "west", "open": true}], 516 | "71:7": ["iron_door", {"half": "lower", "facing": "north", "open": true}], 517 | 518 | "71:8": ["iron_door", {"half": "upper", "hinge": "left", "powered": false}], 519 | "71:9": ["iron_door", {"half": "upper", "hinge": "right", "powered": false}], 520 | "71:10": ["iron_door", {"half": "upper", "hinge": "left", "powered": true}], 521 | "71:11": ["iron_door", {"half": "upper", "hinge": "right", "powered": true}], 522 | 523 | "72:0": ["oak_pressure_plate", {"powered": false}], 524 | "72:1": ["oak_pressure_plate", {"powered": true}], 525 | 526 | "73:0": ["redstone_ore", {"lit": false}], 527 | "74:0": ["redstone_ore", {"lit": true}], 528 | 529 | "75:0": ["redstone_torch", {"lit": false}], 530 | "75:1": ["redstone_wall_torch", {"facing": "east", "lit": false}], 531 | "75:2": ["redstone_wall_torch", {"facing": "west", "lit": false}], 532 | "75:3": ["redstone_wall_torch", {"facing": "south", "lit": false}], 533 | "75:4": ["redstone_wall_torch", {"facing": "north", "lit": false}], 534 | "75:5": ["redstone_torch", {"lit": false}], 535 | 536 | "76:0": ["redstone_torch", {"lit": true}], 537 | "76:1": ["redstone_wall_torch", {"facing": "east", "lit": true}], 538 | "76:2": ["redstone_wall_torch", {"facing": "west", "lit": true}], 539 | "76:3": ["redstone_wall_torch", {"facing": "south", "lit": true}], 540 | "76:4": ["redstone_wall_torch", {"facing": "north", "lit": true}], 541 | "76:5": ["redstone_torch", {"lit": true}], 542 | 543 | "77:0": ["stone_button", {"face": "ceiling", "powered": false}], 544 | "77:1": ["stone_button", {"face": "wall", "facing": "east", "powered": false}], 545 | "77:2": ["stone_button", {"face": "wall", "facing": "west", "powered": false}], 546 | "77:3": ["stone_button", {"face": "wall", "facing": "south", "powered": false}], 547 | "77:4": ["stone_button", {"face": "wall", "facing": "north", "powered": false}], 548 | "77:5": ["stone_button", {"face": "floor", "powered": false}], 549 | "77:8": ["stone_button", {"face": "ceiling", "powered": true}], 550 | "77:9": ["stone_button", {"face": "wall", "facing": "east", "powered": true}], 551 | "77:10": ["stone_button", {"face": "wall", "facing": "west", "powered": true}], 552 | "77:11": ["stone_button", {"face": "wall", "facing": "south", "powered": true}], 553 | "77:12": ["stone_button", {"face": "wall", "facing": "north", "powered": true}], 554 | "77:13": ["stone_button", {"face": "floor", "powered": true}], 555 | 556 | "78:0": ["snow", {"layers": 1}], 557 | "78:1": ["snow", {"layers": 2}], 558 | "78:2": ["snow", {"layers": 3}], 559 | "78:3": ["snow", {"layers": 4}], 560 | "78:4": ["snow", {"layers": 5}], 561 | "78:5": ["snow", {"layers": 6}], 562 | "78:6": ["snow", {"layers": 7}], 563 | "78:7": ["snow", {"layers": 8}], 564 | 565 | "79:0": ["ice", null], 566 | "80:0": ["snow_block", null], 567 | 568 | "81:0": ["cactus", {"age": 0}], 569 | "81:1": ["cactus", {"age": 1}], 570 | "81:2": ["cactus", {"age": 2}], 571 | "81:3": ["cactus", {"age": 3}], 572 | "81:4": ["cactus", {"age": 4}], 573 | "81:5": ["cactus", {"age": 5}], 574 | "81:6": ["cactus", {"age": 6}], 575 | "81:7": ["cactus", {"age": 7}], 576 | "81:8": ["cactus", {"age": 8}], 577 | "81:9": ["cactus", {"age": 9}], 578 | "81:10": ["cactus", {"age": 10}], 579 | "81:11": ["cactus", {"age": 11}], 580 | "81:12": ["cactus", {"age": 12}], 581 | "81:13": ["cactus", {"age": 13}], 582 | "81:14": ["cactus", {"age": 14}], 583 | "81:15": ["cactus", {"age": 15}], 584 | 585 | "82:0": ["clay", null], 586 | 587 | "83:0": ["sugar_cane", {"age": 0}], 588 | "83:1": ["sugar_cane", {"age": 1}], 589 | "83:2": ["sugar_cane", {"age": 2}], 590 | "83:3": ["sugar_cane", {"age": 3}], 591 | "83:4": ["sugar_cane", {"age": 4}], 592 | "83:5": ["sugar_cane", {"age": 5}], 593 | "83:6": ["sugar_cane", {"age": 6}], 594 | "83:7": ["sugar_cane", {"age": 7}], 595 | "83:8": ["sugar_cane", {"age": 8}], 596 | "83:9": ["sugar_cane", {"age": 9}], 597 | "83:10": ["sugar_cane", {"age": 10}], 598 | "83:11": ["sugar_cane", {"age": 11}], 599 | "83:12": ["sugar_cane", {"age": 12}], 600 | "83:13": ["sugar_cane", {"age": 13}], 601 | "83:14": ["sugar_cane", {"age": 14}], 602 | "83:15": ["sugar_cane", {"age": 15}], 603 | 604 | "84:0": ["jukebox", {"has_record": false}], 605 | "84:1": ["jukebox", {"has_record": true}], 606 | 607 | "85:0": ["oak_fence", null], 608 | 609 | "86:0": ["carved_pumpkin", {"facing": "south"}], 610 | "86:1": ["carved_pumpkin", {"facing": "west"}], 611 | "86:2": ["carved_pumpkin", {"facing": "north"}], 612 | "86:3": ["carved_pumpkin", {"facing": "east"}], 613 | 614 | "87:0": ["netherrack", null], 615 | "88:0": ["soul_sand", null], 616 | "89:0": ["glowstone", null], 617 | 618 | "90:0": ["nether_portal", null], 619 | "90:1": ["nether_portal", {"axis": "z"}], 620 | "90:2": ["nether_portal", {"axis": "x"}], 621 | 622 | "91:0": ["jack_o_lantern", {"facing": "south"}], 623 | "91:1": ["jack_o_lantern", {"facing": "west"}], 624 | "91:2": ["jack_o_lantern", {"facing": "north"}], 625 | "91:3": ["jack_o_lantern", {"facing": "east"}], 626 | 627 | "92:0": ["cake", {"bites": 0}], 628 | "92:1": ["cake", {"bites": 1}], 629 | "92:2": ["cake", {"bites": 2}], 630 | "92:3": ["cake", {"bites": 3}], 631 | "92:4": ["cake", {"bites": 4}], 632 | "92:5": ["cake", {"bites": 5}], 633 | "92:6": ["cake", {"bites": 6}], 634 | 635 | "93:0": ["repeater", {"facing": "south", "delay": 1, "powered": false}], 636 | "93:1": ["repeater", {"facing": "west", "delay": 1, "powered": false}], 637 | "93:2": ["repeater", {"facing": "north", "delay": 1, "powered": false}], 638 | "93:3": ["repeater", {"facing": "east", "delay": 1, "powered": false}], 639 | "93:4": ["repeater", {"facing": "south", "delay": 2, "powered": false}], 640 | "93:5": ["repeater", {"facing": "west", "delay": 2, "powered": false}], 641 | "93:6": ["repeater", {"facing": "north", "delay": 2, "powered": false}], 642 | "93:7": ["repeater", {"facing": "east", "delay": 2, "powered": false}], 643 | "93:8": ["repeater", {"facing": "south", "delay": 3, "powered": false}], 644 | "93:9": ["repeater", {"facing": "west", "delay": 3, "powered": false}], 645 | "93:10": ["repeater", {"facing": "north", "delay": 3, "powered": false}], 646 | "93:11": ["repeater", {"facing": "east", "delay": 3, "powered": false}], 647 | "93:12": ["repeater", {"facing": "south", "delay": 4, "powered": false}], 648 | "93:13": ["repeater", {"facing": "west", "delay": 4, "powered": false}], 649 | "93:14": ["repeater", {"facing": "north", "delay": 4, "powered": false}], 650 | "93:15": ["repeater", {"facing": "east", "delay": 4, "powered": false}], 651 | 652 | "94:0": ["repeater", {"facing": "south", "delay": 1, "powered": true}], 653 | "94:1": ["repeater", {"facing": "west", "delay": 1, "powered": true}], 654 | "94:2": ["repeater", {"facing": "north", "delay": 1, "powered": true}], 655 | "94:3": ["repeater", {"facing": "east", "delay": 1, "powered": true}], 656 | "94:4": ["repeater", {"facing": "south", "delay": 2, "powered": true}], 657 | "94:5": ["repeater", {"facing": "west", "delay": 2, "powered": true}], 658 | "94:6": ["repeater", {"facing": "north", "delay": 2, "powered": true}], 659 | "94:7": ["repeater", {"facing": "east", "delay": 2, "powered": true}], 660 | "94:8": ["repeater", {"facing": "south", "delay": 3, "powered": true}], 661 | "94:9": ["repeater", {"facing": "west", "delay": 3, "powered": true}], 662 | "94:10": ["repeater", {"facing": "north", "delay": 3, "powered": true}], 663 | "94:11": ["repeater", {"facing": "east", "delay": 3, "powered": true}], 664 | "94:12": ["repeater", {"facing": "south", "delay": 4, "powered": true}], 665 | "94:13": ["repeater", {"facing": "west", "delay": 4, "powered": true}], 666 | "94:14": ["repeater", {"facing": "north", "delay": 4, "powered": true}], 667 | "94:15": ["repeater", {"facing": "east", "delay": 4, "powered": true}], 668 | 669 | "95:0": ["white_stained_glass", null], 670 | "95:1": ["orange_stained_glass", null], 671 | "95:2": ["magenta_stained_glass", null], 672 | "95:3": ["light_blue_stained_glass", null], 673 | "95:4": ["yellow_stained_glass", null], 674 | "95:5": ["lime_stained_glass", null], 675 | "95:6": ["pink_stained_glass", null], 676 | "95:7": ["gray_stained_glass", null], 677 | "95:8": ["light_gray_stained_glass", null], 678 | "95:9": ["cyan_stained_glass", null], 679 | "95:10": ["purple_stained_glass", null], 680 | "95:11": ["blue_stained_glass", null], 681 | "95:12": ["brown_stained_glass", null], 682 | "95:13": ["green_stained_glass", null], 683 | "95:14": ["red_stained_glass", null], 684 | "95:15": ["black_stained_glass", null], 685 | 686 | "96:0": ["oak_trapdoor", {"facing": "north", "open": false, "half": "bottom"}], 687 | "96:1": ["oak_trapdoor", {"facing": "south", "open": false, "half": "bottom"}], 688 | "96:2": ["oak_trapdoor", {"facing": "west", "open": false, "half": "bottom"}], 689 | "96:3": ["oak_trapdoor", {"facing": "east", "open": false, "half": "bottom"}], 690 | "96:4": ["oak_trapdoor", {"facing": "north", "open": true, "half": "bottom"}], 691 | "96:5": ["oak_trapdoor", {"facing": "south", "open": true, "half": "bottom"}], 692 | "96:6": ["oak_trapdoor", {"facing": "west", "open": true, "half": "bottom"}], 693 | "96:7": ["oak_trapdoor", {"facing": "east", "open": true, "half": "bottom"}], 694 | "96:8": ["oak_trapdoor", {"facing": "north", "open": false, "half": "top"}], 695 | "96:9": ["oak_trapdoor", {"facing": "south", "open": false, "half": "top"}], 696 | "96:10": ["oak_trapdoor", {"facing": "west", "open": false, "half": "top"}], 697 | "96:11": ["oak_trapdoor", {"facing": "east", "open": false, "half": "top"}], 698 | "96:12": ["oak_trapdoor", {"facing": "north", "open": true, "half": "top"}], 699 | "96:13": ["oak_trapdoor", {"facing": "south", "open": true, "half": "top"}], 700 | "96:14": ["oak_trapdoor", {"facing": "west", "open": true, "half": "top"}], 701 | "96:15": ["oak_trapdoor", {"facing": "east", "open": true, "half": "top"}], 702 | 703 | 704 | "97:0": ["infested_stone", null], 705 | "97:1": ["infested_cobblestone", null], 706 | "97:2": ["infested_stone_bricks", null], 707 | "97:3": ["infested_mossy_stone_bricks", null], 708 | "97:4": ["infested_cracked_stone_bricks", null], 709 | "97:5": ["infested_chiseled_stone_bricks", null], 710 | "98:0": ["stone_bricks", null], 711 | "98:1": ["mossy_stone_bricks", null], 712 | "98:2": ["cracked_stone_bricks", null], 713 | "98:3": ["chiseled_stone_bricks", null], 714 | 715 | "99:0": ["brown_mushroom_block", null], 716 | "99:1": ["brown_mushroom_block", null], 717 | "99:2": ["brown_mushroom_block", null], 718 | "99:3": ["brown_mushroom_block", null], 719 | "99:4": ["brown_mushroom_block", null], 720 | "99:5": ["brown_mushroom_block", null], 721 | "99:6": ["brown_mushroom_block", null], 722 | "99:7": ["brown_mushroom_block", null], 723 | "99:8": ["brown_mushroom_block", null], 724 | "99:9": ["brown_mushroom_block", null], 725 | "99:10": ["brown_mushroom_block", null], 726 | "99:11": ["brown_mushroom_block", null], 727 | "99:12": ["brown_mushroom_block", null], 728 | "99:13": ["brown_mushroom_block", null], 729 | "99:14": ["brown_mushroom_block", null], 730 | "99:15": ["brown_mushroom_block", null], 731 | 732 | "100:0": ["red_mushroom_block", null], 733 | "100:1": ["red_mushroom_block", null], 734 | "100:2": ["red_mushroom_block", null], 735 | "100:3": ["red_mushroom_block", null], 736 | "100:4": ["red_mushroom_block", null], 737 | "100:5": ["red_mushroom_block", null], 738 | "100:6": ["red_mushroom_block", null], 739 | "100:7": ["red_mushroom_block", null], 740 | "100:8": ["red_mushroom_block", null], 741 | "100:9": ["red_mushroom_block", null], 742 | "100:10": ["red_mushroom_block", null], 743 | "100:11": ["red_mushroom_block", null], 744 | "100:12": ["red_mushroom_block", null], 745 | "100:13": ["red_mushroom_block", null], 746 | "100:14": ["red_mushroom_block", null], 747 | "100:15": ["red_mushroom_block", null], 748 | 749 | 750 | "101:0": ["iron_bars", null], 751 | "102:0": ["glass_pane", null], 752 | "103:0": ["melon", null], 753 | 754 | "104:0": ["pumpkin_stem", {"age": 0}], 755 | "104:1": ["pumpkin_stem", {"age": 1}], 756 | "104:2": ["pumpkin_stem", {"age": 2}], 757 | "104:3": ["pumpkin_stem", {"age": 3}], 758 | "104:4": ["pumpkin_stem", {"age": 4}], 759 | "104:5": ["pumpkin_stem", {"age": 5}], 760 | "104:6": ["pumpkin_stem", {"age": 6}], 761 | "104:7": ["pumpkin_stem", {"age": 7}], 762 | 763 | "105:0": ["melon_stem", {"age": 0}], 764 | "105:1": ["melon_stem", {"age": 1}], 765 | "105:2": ["melon_stem", {"age": 2}], 766 | "105:3": ["melon_stem", {"age": 3}], 767 | "105:4": ["melon_stem", {"age": 4}], 768 | "105:5": ["melon_stem", {"age": 5}], 769 | "105:6": ["melon_stem", {"age": 6}], 770 | "105:7": ["melon_stem", {"age": 7}], 771 | 772 | "106:0": ["vine", {"south": false, "west": false, "north": false, "east": false}], 773 | "106:1": ["vine", {"south": true, "west": false, "north": false, "east": false}], 774 | "106:2": ["vine", {"south": false, "west": true, "north": false, "east": false}], 775 | "106:3": ["vine", {"south": true, "west": true, "north": false, "east": false}], 776 | "106:4": ["vine", {"south": false, "west": false, "north": true, "east": false}], 777 | "106:5": ["vine", {"south": true, "west": false, "north": true, "east": false}], 778 | "106:6": ["vine", {"south": false, "west": true, "north": true, "east": false}], 779 | "106:7": ["vine", {"south": true, "west": true, "north": true, "east": false}], 780 | "106:8": ["vine", {"south": false, "west": false, "north": false, "east": true}], 781 | "106:9": ["vine", {"south": true, "west": false, "north": false, "east": true}], 782 | "106:10": ["vine", {"south": false, "west": true, "north": false, "east": true}], 783 | "106:11": ["vine", {"south": true, "west": true, "north": false, "east": true}], 784 | "106:12": ["vine", {"south": false, "west": false, "north": true, "east": true}], 785 | "106:13": ["vine", {"south": true, "west": false, "north": true, "east": true}], 786 | "106:14": ["vine", {"south": false, "west": true, "north": true, "east": true}], 787 | "106:15": ["vine", {"south": true, "west": true, "north": true, "east": true}], 788 | 789 | "107:0": ["oak_fence_gate", {"facing": "south", "open": false}], 790 | "107:1": ["oak_fence_gate", {"facing": "west", "open": false}], 791 | "107:2": ["oak_fence_gate", {"facing": "north", "open": false}], 792 | "107:3": ["oak_fence_gate", {"facing": "east", "open": false}], 793 | "107:4": ["oak_fence_gate", {"facing": "south", "open": true}], 794 | "107:5": ["oak_fence_gate", {"facing": "west", "open": true}], 795 | "107:6": ["oak_fence_gate", {"facing": "north", "open": true}], 796 | "107:7": ["oak_fence_gate", {"facing": "east", "open": true}], 797 | 798 | "108:0": ["brick_stairs", {"facing": "east", "half": "bottom"}], 799 | "108:1": ["brick_stairs", {"facing": "west", "half": "bottom"}], 800 | "108:2": ["brick_stairs", {"facing": "south", "half": "bottom"}], 801 | "108:3": ["brick_stairs", {"facing": "north", "half": "bottom"}], 802 | "108:4": ["brick_stairs", {"facing": "east", "half": "top"}], 803 | "108:5": ["brick_stairs", {"facing": "west", "half": "top"}], 804 | "108:6": ["brick_stairs", {"facing": "south", "half": "top"}], 805 | "108:7": ["brick_stairs", {"facing": "north", "half": "top"}], 806 | 807 | "109:0": ["stone_brick_stairs", {"facing": "east", "half": "bottom"}], 808 | "109:1": ["stone_brick_stairs", {"facing": "west", "half": "bottom"}], 809 | "109:2": ["stone_brick_stairs", {"facing": "south", "half": "bottom"}], 810 | "109:3": ["stone_brick_stairs", {"facing": "north", "half": "bottom"}], 811 | "109:4": ["stone_brick_stairs", {"facing": "east", "half": "top"}], 812 | "109:5": ["stone_brick_stairs", {"facing": "west", "half": "top"}], 813 | "109:6": ["stone_brick_stairs", {"facing": "south", "half": "top"}], 814 | "109:7": ["stone_brick_stairs", {"facing": "north", "half": "top"}], 815 | 816 | "110:0": ["mycelium", null], 817 | "111:0": ["lily_pad", null], 818 | "112:0": ["nether_bricks", null], 819 | "113:0": ["nether_brick_fence", null], 820 | 821 | "114:0": ["nether_brick_stairs", {"facing": "east", "half": "bottom"}], 822 | "114:1": ["nether_brick_stairs", {"facing": "west", "half": "bottom"}], 823 | "114:2": ["nether_brick_stairs", {"facing": "south", "half": "bottom"}], 824 | "114:3": ["nether_brick_stairs", {"facing": "north", "half": "bottom"}], 825 | "114:4": ["nether_brick_stairs", {"facing": "east", "half": "top"}], 826 | "114:5": ["nether_brick_stairs", {"facing": "west", "half": "top"}], 827 | "114:6": ["nether_brick_stairs", {"facing": "south", "half": "top"}], 828 | "114:7": ["nether_brick_stairs", {"facing": "north", "half": "top"}], 829 | 830 | "115:0": ["nether_wart", {"age": 0}], 831 | "115:1": ["nether_wart", {"age": 1}], 832 | "115:2": ["nether_wart", {"age": 2}], 833 | "115:3": ["nether_wart", {"age": 3}], 834 | 835 | "116:0": ["enchanting_table", null], 836 | 837 | "117:0": ["brewing_stand", {"has_bottle_0": false, "has_bottle_1": false, "has_bottle_2": false}], 838 | "117:1": ["brewing_stand", {"has_bottle_0": true, "has_bottle_1": false, "has_bottle_2": false}], 839 | "117:2": ["brewing_stand", {"has_bottle_0": false, "has_bottle_1": true, "has_bottle_2": false}], 840 | "117:3": ["brewing_stand", {"has_bottle_0": true, "has_bottle_1": true, "has_bottle_2": false}], 841 | "117:4": ["brewing_stand", {"has_bottle_0": false, "has_bottle_1": false, "has_bottle_2": true}], 842 | "117:5": ["brewing_stand", {"has_bottle_0": true, "has_bottle_1": false, "has_bottle_2": true}], 843 | "117:6": ["brewing_stand", {"has_bottle_0": false, "has_bottle_1": true, "has_bottle_2": true}], 844 | "117:7": ["brewing_stand", {"has_bottle_0": true, "has_bottle_1": true, "has_bottle_2": true}], 845 | 846 | 847 | "118:0": ["cauldron", {"level": 0}], 848 | "118:1": ["cauldron", {"level": 1}], 849 | "118:2": ["cauldron", {"level": 2}], 850 | "118:3": ["cauldron", {"level": 3}], 851 | 852 | "119:0": ["end_portal", null], 853 | 854 | "120:0": ["end_portal_frame", {"facing": "south", "eye": false}], 855 | "120:1": ["end_portal_frame", {"facing": "west", "eye": false}], 856 | "120:2": ["end_portal_frame", {"facing": "north", "eye": false}], 857 | "120:3": ["end_portal_frame", {"facing": "east", "eye": false}], 858 | "120:4": ["end_portal_frame", {"facing": "south", "eye": true}], 859 | "120:5": ["end_portal_frame", {"facing": "west", "eye": true}], 860 | "120:6": ["end_portal_frame", {"facing": "north", "eye": true}], 861 | "120:7": ["end_portal_frame", {"facing": "east", "eye": true}], 862 | 863 | "121:0": ["end_stone", null], 864 | "122:0": ["dragon_egg", null], 865 | "123:0": ["redstone_lamp", {"lit": false}], 866 | "124:0": ["redstone_lamp", {"lit": true}], 867 | 868 | "125:0": ["oak_slab", {"type": "double"}], 869 | "125:1": ["spruce_slab", {"type": "double"}], 870 | "125:2": ["birch_slab", {"type": "double"}], 871 | "125:3": ["jungle_slab", {"type": "double"}], 872 | "125:4": ["acacia_slab", {"type": "double"}], 873 | "125:5": ["dark_oak_slab", {"type": "double"}], 874 | 875 | "126:0": ["oak_slab", {"type": "bottom"}], 876 | "126:1": ["spruce_slab", {"type": "bottom"}], 877 | "126:2": ["birch_slab", {"type": "bottom"}], 878 | "126:3": ["jungle_slab", {"type": "bottom"}], 879 | "126:4": ["acacia_slab", {"type": "bottom"}], 880 | "126:5": ["dark_oak_slab", {"type": "bottom"}], 881 | "126:8": ["oak_slab", {"type": "top"}], 882 | "126:9": ["spruce_slab", {"type": "top"}], 883 | "126:10": ["birch_slab", {"type": "top"}], 884 | "126:11": ["jungle_slab", {"type": "top"}], 885 | "126:12": ["acacia_slab", {"type": "top"}], 886 | "126:13": ["dark_oak_slab", {"type": "top"}], 887 | 888 | "127:0": ["cocoa", {"facing": "north", "age": 0}], 889 | "127:1": ["cocoa", {"facing": "east", "age": 0}], 890 | "127:2": ["cocoa", {"facing": "south", "age": 0}], 891 | "127:3": ["cocoa", {"facing": "west", "age": 0}], 892 | "127:4": ["cocoa", {"facing": "north", "age": 1}], 893 | "127:5": ["cocoa", {"facing": "east", "age": 1}], 894 | "127:6": ["cocoa", {"facing": "south", "age": 1}], 895 | "127:7": ["cocoa", {"facing": "west", "age": 1}], 896 | "127:8": ["cocoa", {"facing": "north", "age": 2}], 897 | "127:9": ["cocoa", {"facing": "east", "age": 2}], 898 | "127:10": ["cocoa", {"facing": "south", "age": 2}], 899 | "127:11": ["cocoa", {"facing": "west", "age": 2}], 900 | "127:12": ["cocoa", {"facing": "north", "age": 3}], 901 | "127:13": ["cocoa", {"facing": "east", "age": 3}], 902 | "127:14": ["cocoa", {"facing": "south", "age": 3}], 903 | "127:15": ["cocoa", {"facing": "west", "age": 3}], 904 | 905 | "128:0": ["sandstone_stairs", {"facing": "east", "half": "bottom"}], 906 | "128:1": ["sandstone_stairs", {"facing": "west", "half": "bottom"}], 907 | "128:2": ["sandstone_stairs", {"facing": "south", "half": "bottom"}], 908 | "128:3": ["sandstone_stairs", {"facing": "north", "half": "bottom"}], 909 | "128:4": ["sandstone_stairs", {"facing": "east", "half": "top"}], 910 | "128:5": ["sandstone_stairs", {"facing": "west", "half": "top"}], 911 | "128:6": ["sandstone_stairs", {"facing": "south", "half": "top"}], 912 | "128:7": ["sandstone_stairs", {"facing": "north", "half": "top"}], 913 | 914 | "129:0": ["emerald_ore", null], 915 | 916 | "130:0": ["ender_chest", {"facing": "north"}], 917 | "130:1": ["ender_chest", {"facing": "north"}], 918 | "130:2": ["ender_chest", {"facing": "north"}], 919 | "130:3": ["ender_chest", {"facing": "south"}], 920 | "130:4": ["ender_chest", {"facing": "west"}], 921 | "130:5": ["ender_chest", {"facing": "east"}], 922 | 923 | "131:0": ["tripwire_hook", {"facing": "south", "attached": false, "powered": false}], 924 | "131:1": ["tripwire_hook", {"facing": "west", "attached": false, "powered": false}], 925 | "131:2": ["tripwire_hook", {"facing": "north", "attached": false, "powered": false}], 926 | "131:3": ["tripwire_hook", {"facing": "east", "attached": false, "powered": false}], 927 | "131:4": ["tripwire_hook", {"facing": "south", "attached": true, "powered": false}], 928 | "131:5": ["tripwire_hook", {"facing": "west", "attached": true, "powered": false}], 929 | "131:6": ["tripwire_hook", {"facing": "north", "attached": true, "powered": false}], 930 | "131:7": ["tripwire_hook", {"facing": "east", "attached": true, "powered": false}], 931 | "131:8": ["tripwire_hook", {"facing": "south", "attached": false, "powered": true}], 932 | "131:9": ["tripwire_hook", {"facing": "west", "attached": false, "powered": true}], 933 | "131:10": ["tripwire_hook", {"facing": "north", "attached": false, "powered": true}], 934 | "131:11": ["tripwire_hook", {"facing": "east", "attached": false, "powered": true}], 935 | "131:12": ["tripwire_hook", {"facing": "south", "attached": true, "powered": true}], 936 | "131:13": ["tripwire_hook", {"facing": "west", "attached": true, "powered": true}], 937 | "131:14": ["tripwire_hook", {"facing": "north", "attached": true, "powered": true}], 938 | "131:15": ["tripwire_hook", {"facing": "east", "attached": true, "powered": true}], 939 | 940 | "132:0": ["tripwire", {"powered": false, "attached": false, "disarmed": false}], 941 | "132:1": ["tripwire", {"powered": true, "attached": false, "disarmed": false}], 942 | "132:4": ["tripwire", {"powered": false, "attached": true, "disarmed": false}], 943 | "132:5": ["tripwire", {"powered": true, "attached": true, "disarmed": false}], 944 | "132:8": ["tripwire", {"powered": false, "attached": false, "disarmed": true}], 945 | "132:9": ["tripwire", {"powered": true, "attached": false, "disarmed": true}], 946 | "132:12": ["tripwire", {"powered": false, "attached": true, "disarmed": true}], 947 | "132:13": ["tripwire", {"powered": true, "attached": true, "disarmed": true}], 948 | 949 | "133:0": ["emerald_block", null], 950 | 951 | "134:0": ["spruce_stairs", {"facing": "east", "half": "bottom"}], 952 | "134:1": ["spruce_stairs", {"facing": "west", "half": "bottom"}], 953 | "134:2": ["spruce_stairs", {"facing": "south", "half": "bottom"}], 954 | "134:3": ["spruce_stairs", {"facing": "north", "half": "bottom"}], 955 | "134:4": ["spruce_stairs", {"facing": "east", "half": "top"}], 956 | "134:5": ["spruce_stairs", {"facing": "west", "half": "top"}], 957 | "134:6": ["spruce_stairs", {"facing": "south", "half": "top"}], 958 | "134:7": ["spruce_stairs", {"facing": "north", "half": "top"}], 959 | 960 | "135:0": ["birch_stairs", {"facing": "east", "half": "bottom"}], 961 | "135:1": ["birch_stairs", {"facing": "west", "half": "bottom"}], 962 | "135:2": ["birch_stairs", {"facing": "south", "half": "bottom"}], 963 | "135:3": ["birch_stairs", {"facing": "north", "half": "bottom"}], 964 | "135:4": ["birch_stairs", {"facing": "east", "half": "top"}], 965 | "135:5": ["birch_stairs", {"facing": "west", "half": "top"}], 966 | "135:6": ["birch_stairs", {"facing": "south", "half": "top"}], 967 | "135:7": ["birch_stairs", {"facing": "north", "half": "top"}], 968 | 969 | "136:0": ["jungle_stairs", {"facing": "east", "half": "bottom"}], 970 | "136:1": ["jungle_stairs", {"facing": "west", "half": "bottom"}], 971 | "136:2": ["jungle_stairs", {"facing": "south", "half": "bottom"}], 972 | "136:3": ["jungle_stairs", {"facing": "north", "half": "bottom"}], 973 | "136:4": ["jungle_stairs", {"facing": "east", "half": "top"}], 974 | "136:5": ["jungle_stairs", {"facing": "west", "half": "top"}], 975 | "136:6": ["jungle_stairs", {"facing": "south", "half": "top"}], 976 | "136:7": ["jungle_stairs", {"facing": "north", "half": "top"}], 977 | 978 | "137:0": ["command_block", null], 979 | "138:0": ["beacon", null], 980 | 981 | "139:0": ["cobblestone_wall", null], 982 | 983 | "139:1": ["mossy_cobblestone_wall", null], 984 | 985 | "140:0": ["flower_pot", null], 986 | "140:1": ["potted_poppy", null], 987 | "140:2": ["potted_dandelion", null], 988 | "140:3": ["potted_oak_sapling", null], 989 | "140:4": ["potted_spruce_sapling", null], 990 | "140:5": ["potted_birch_sapling", null], 991 | "140:6": ["potted_jungle_sapling", null], 992 | "140:7": ["potted_red_mushroom", null], 993 | "140:8": ["potted_brown_mushroom", null], 994 | "140:9": ["potted_cactus", null], 995 | "140:10": ["potted_dead_bush", null], 996 | "140:11": ["potted_fern", null], 997 | "140:12": ["potted_acacia_sapling", null], 998 | "140:13": ["potted_dark_oak_sapling", null], 999 | "140:14": ["flower_pot", null], 1000 | "140:15": ["flower_pot", null], 1001 | 1002 | "141:0": ["carrots", {"age": 0}], 1003 | "141:1": ["carrots", {"age": 1}], 1004 | "141:2": ["carrots", {"age": 2}], 1005 | "141:3": ["carrots", {"age": 3}], 1006 | "141:4": ["carrots", {"age": 4}], 1007 | "141:5": ["carrots", {"age": 5}], 1008 | "141:6": ["carrots", {"age": 6}], 1009 | "141:7": ["carrots", {"age": 7}], 1010 | 1011 | "142:0": ["potatoes", {"age": 0}], 1012 | "142:1": ["potatoes", {"age": 1}], 1013 | "142:2": ["potatoes", {"age": 2}], 1014 | "142:3": ["potatoes", {"age": 3}], 1015 | "142:4": ["potatoes", {"age": 4}], 1016 | "142:5": ["potatoes", {"age": 5}], 1017 | "142:6": ["potatoes", {"age": 6}], 1018 | "142:7": ["potatoes", {"age": 7}], 1019 | 1020 | "143:0": ["oak_button", {"face": "ceiling", "powered": false}], 1021 | "143:1": ["oak_button", {"face": "wall", "facing": "east", "powered": false}], 1022 | "143:2": ["oak_button", {"face": "wall", "facing": "west", "powered": false}], 1023 | "143:3": ["oak_button", {"face": "wall", "facing": "south", "powered": false}], 1024 | "143:4": ["oak_button", {"face": "wall", "facing": "north", "powered": false}], 1025 | "143:5": ["oak_button", {"face": "floor", "powered": false}], 1026 | "143:8": ["oak_button", {"face": "ceiling", "powered": true}], 1027 | "143:9": ["oak_button", {"face": "wall", "facing": "east", "powered": true}], 1028 | "143:10": ["oak_button", {"face": "wall", "facing": "west", "powered": true}], 1029 | "143:11": ["oak_button", {"face": "wall", "facing": "south", "powered": true}], 1030 | "143:12": ["oak_button", {"face": "wall", "facing": "north", "powered": true}], 1031 | "143:13": ["oak_button", {"face": "floor", "powered": true}], 1032 | 1033 | "144:0": ["skull", null], 1034 | "144:1": ["skull", null], 1035 | "144:2": ["wall_skull", null], 1036 | "144:3": ["wall_skull", null], 1037 | "144:4": ["wall_skull", null], 1038 | "144:4": ["wall_skull", null], 1039 | 1040 | "145:0": ["anvil", {"facing": "south"}], 1041 | "145:1": ["anvil", {"facing": "west"}], 1042 | "145:2": ["anvil", {"facing": "north"}], 1043 | "145:3": ["anvil", {"facing": "east"}], 1044 | "145:4": ["chipped_anvil", {"facing": "south"}], 1045 | "145:5": ["chipped_anvil", {"facing": "west"}], 1046 | "145:6": ["chipped_anvil", {"facing": "north"}], 1047 | "145:7": ["chipped_anvil", {"facing": "east"}], 1048 | "145:8": ["damaged_anvil", {"facing": "south"}], 1049 | "145:9": ["damaged_anvil", {"facing": "west"}], 1050 | "145:10": ["damaged_anvil", {"facing": "north"}], 1051 | "145:11": ["damaged_anvil", {"facing": "east"}], 1052 | 1053 | "146:0": ["trapped_chest", {"facing": "north"}], 1054 | "146:1": ["trapped_chest", {"facing": "north"}], 1055 | "146:2": ["trapped_chest", {"facing": "north"}], 1056 | "146:3": ["trapped_chest", {"facing": "south"}], 1057 | "146:4": ["trapped_chest", {"facing": "west"}], 1058 | "146:5": ["trapped_chest", {"facing": "east"}], 1059 | 1060 | "147:0": ["light_weighted_pressure_plate", {"power": 0}], 1061 | "147:1": ["light_weighted_pressure_plate", {"power": 1}], 1062 | "147:2": ["light_weighted_pressure_plate", {"power": 2}], 1063 | "147:3": ["light_weighted_pressure_plate", {"power": 3}], 1064 | "147:4": ["light_weighted_pressure_plate", {"power": 4}], 1065 | "147:5": ["light_weighted_pressure_plate", {"power": 5}], 1066 | "147:6": ["light_weighted_pressure_plate", {"power": 6}], 1067 | "147:7": ["light_weighted_pressure_plate", {"power": 7}], 1068 | "147:8": ["light_weighted_pressure_plate", {"power": 8}], 1069 | "147:9": ["light_weighted_pressure_plate", {"power": 9}], 1070 | "147:10": ["light_weighted_pressure_plate", {"power": 10}], 1071 | "147:11": ["light_weighted_pressure_plate", {"power": 11}], 1072 | "147:12": ["light_weighted_pressure_plate", {"power": 12}], 1073 | "147:13": ["light_weighted_pressure_plate", {"power": 13}], 1074 | "147:14": ["light_weighted_pressure_plate", {"power": 14}], 1075 | "147:15": ["light_weighted_pressure_plate", {"power": 15}], 1076 | 1077 | "148:0": ["heavy_weighted_pressure_plate", {"power": 0}], 1078 | "148:1": ["heavy_weighted_pressure_plate", {"power": 1}], 1079 | "148:2": ["heavy_weighted_pressure_plate", {"power": 2}], 1080 | "148:3": ["heavy_weighted_pressure_plate", {"power": 3}], 1081 | "148:4": ["heavy_weighted_pressure_plate", {"power": 4}], 1082 | "148:5": ["heavy_weighted_pressure_plate", {"power": 5}], 1083 | "148:6": ["heavy_weighted_pressure_plate", {"power": 6}], 1084 | "148:7": ["heavy_weighted_pressure_plate", {"power": 7}], 1085 | "148:8": ["heavy_weighted_pressure_plate", {"power": 8}], 1086 | "148:9": ["heavy_weighted_pressure_plate", {"power": 9}], 1087 | "148:10": ["heavy_weighted_pressure_plate", {"power": 10}], 1088 | "148:11": ["heavy_weighted_pressure_plate", {"power": 11}], 1089 | "148:12": ["heavy_weighted_pressure_plate", {"power": 12}], 1090 | "148:13": ["heavy_weighted_pressure_plate", {"power": 13}], 1091 | "148:14": ["heavy_weighted_pressure_plate", {"power": 14}], 1092 | "148:15": ["heavy_weighted_pressure_plate", {"power": 15}], 1093 | 1094 | "149:0": ["comparator", {"facing": "south", "mode": "compare", "powered": false}], 1095 | "149:1": ["comparator", {"facing": "west", "mode": "compare", "powered": false}], 1096 | "149:2": ["comparator", {"facing": "north", "mode": "compare", "powered": false}], 1097 | "149:3": ["comparator", {"facing": "east", "mode": "compare", "powered": false}], 1098 | "149:4": ["comparator", {"facing": "south", "mode": "subtract", "powered": false}], 1099 | "149:5": ["comparator", {"facing": "west", "mode": "subtract", "powered": false}], 1100 | "149:6": ["comparator", {"facing": "north", "mode": "subtract", "powered": false}], 1101 | "149:7": ["comparator", {"facing": "east", "mode": "subtract", "powered": false}], 1102 | 1103 | "149:8": ["comparator", {"facing": "south", "mode": "compare", "powered": true}], 1104 | "149:9": ["comparator", {"facing": "west", "mode": "compare", "powered": true}], 1105 | "149:10": ["comparator", {"facing": "north", "mode": "compare", "powered": true}], 1106 | "149:11": ["comparator", {"facing": "east", "mode": "compare", "powered": true}], 1107 | "149:12": ["comparator", {"facing": "south", "mode": "subtract", "powered": true}], 1108 | "149:13": ["comparator", {"facing": "west", "mode": "subtract", "powered": true}], 1109 | "149:14": ["comparator", {"facing": "north", "mode": "subtract", "powered": true}], 1110 | "149:15": ["comparator", {"facing": "east", "mode": "subtract", "powered": true}], 1111 | 1112 | "150:0": ["comparator", {"facing": "south", "mode": "compare", "powered": true}], 1113 | "150:1": ["comparator", {"facing": "west", "mode": "compare", "powered": true}], 1114 | "150:2": ["comparator", {"facing": "north", "mode": "compare", "powered": true}], 1115 | "150:3": ["comparator", {"facing": "east", "mode": "compare", "powered": true}], 1116 | "150:4": ["comparator", {"facing": "south", "mode": "subtract", "powered": true}], 1117 | "150:5": ["comparator", {"facing": "west", "mode": "subtract", "powered": true}], 1118 | "150:6": ["comparator", {"facing": "north", "mode": "subtract", "powered": true}], 1119 | "150:7": ["comparator", {"facing": "east", "mode": "subtract", "powered": true}], 1120 | 1121 | "151:0": ["daylight_detector", {"power": 0, "inverted": false}], 1122 | "151:1": ["daylight_detector", {"power": 1, "inverted": false}], 1123 | "151:2": ["daylight_detector", {"power": 2, "inverted": false}], 1124 | "151:3": ["daylight_detector", {"power": 3, "inverted": false}], 1125 | "151:4": ["daylight_detector", {"power": 4, "inverted": false}], 1126 | "151:5": ["daylight_detector", {"power": 5, "inverted": false}], 1127 | "151:6": ["daylight_detector", {"power": 6, "inverted": false}], 1128 | "151:7": ["daylight_detector", {"power": 7, "inverted": false}], 1129 | "151:8": ["daylight_detector", {"power": 8, "inverted": false}], 1130 | "151:9": ["daylight_detector", {"power": 9, "inverted": false}], 1131 | "151:10": ["daylight_detector", {"power": 10, "inverted": false}], 1132 | "151:11": ["daylight_detector", {"power": 11, "inverted": false}], 1133 | "151:12": ["daylight_detector", {"power": 12, "inverted": false}], 1134 | "151:13": ["daylight_detector", {"power": 13, "inverted": false}], 1135 | "151:14": ["daylight_detector", {"power": 14, "inverted": false}], 1136 | "151:15": ["daylight_detector", {"power": 15, "inverted": false}], 1137 | 1138 | 1139 | "152:0": ["redstone_block", null], 1140 | "153:0": ["nether_quartz_ore", null], 1141 | 1142 | "154:0": ["hopper", {"facing": "down", "enabled": true}], 1143 | "154:2": ["hopper", {"facing": "north", "enabled": true}], 1144 | "154:3": ["hopper", {"facing": "south", "enabled": true}], 1145 | "154:4": ["hopper", {"facing": "west", "enabled": true}], 1146 | "154:5": ["hopper", {"facing": "east", "enabled": true}], 1147 | "154:8": ["hopper", {"facing": "down", "enabled": false}], 1148 | "154:10": ["hopper", {"facing": "north", "enabled": false}], 1149 | "154:11": ["hopper", {"facing": "south", "enabled": false}], 1150 | "154:12": ["hopper", {"facing": "west", "enabled": false}], 1151 | "154:13": ["hopper", {"facing": "east", "enabled": false}], 1152 | 1153 | "155:0": ["quartz_block", null], 1154 | "155:1": ["chiseled_quartz_block", null], 1155 | "155:2": ["quartz_pillar", {"axis": "y"}], 1156 | "155:3": ["quartz_pillar", {"axis": "x"}], 1157 | "155:4": ["quartz_pillar", {"axis": "z"}], 1158 | 1159 | 1160 | 1161 | 1162 | "156:0": ["quartz_stairs", {"facing": "east", "half": "bottom"}], 1163 | "156:1": ["quartz_stairs", {"facing": "west", "half": "bottom"}], 1164 | "156:2": ["quartz_stairs", {"facing": "south", "half": "bottom"}], 1165 | "156:3": ["quartz_stairs", {"facing": "north", "half": "bottom"}], 1166 | "156:4": ["quartz_stairs", {"facing": "east", "half": "top"}], 1167 | "156:5": ["quartz_stairs", {"facing": "west", "half": "top"}], 1168 | "156:6": ["quartz_stairs", {"facing": "south", "half": "top"}], 1169 | "156:7": ["quartz_stairs", {"facing": "north", "half": "top"}], 1170 | 1171 | "157:0": ["activator_rail", {"shape": "north_south", "powered": false}], 1172 | "157:1": ["activator_rail", {"shape": "east_west", "powered": false}], 1173 | "157:2": ["activator_rail", {"shape": "ascending_east", "powered": false}], 1174 | "157:3": ["activator_rail", {"shape": "ascending_west", "powered": false}], 1175 | "157:4": ["activator_rail", {"shape": "ascending_north", "powered": false}], 1176 | "157:5": ["activator_rail", {"shape": "ascending_south", "powered": false}], 1177 | "157:8": ["activator_rail", {"shape": "north_south", "powered": true}], 1178 | "157:9": ["activator_rail", {"shape": "east_west", "powered": true}], 1179 | "157:10": ["activator_rail", {"shape": "ascending_east", "powered": true}], 1180 | "157:11": ["activator_rail", {"shape": "ascending_west", "powered": true}], 1181 | "157:12": ["activator_rail", {"shape": "ascending_north", "powered": true}], 1182 | "157:13": ["activator_rail", {"shape": "ascending_south", "powered": true}], 1183 | 1184 | "158:0": ["dropper", {"facing": "down", "triggered": false}], 1185 | "158:1": ["dropper", {"facing": "up", "triggered": false}], 1186 | "158:2": ["dropper", {"facing": "north", "triggered": false}], 1187 | "158:3": ["dropper", {"facing": "south", "triggered": false}], 1188 | "158:4": ["dropper", {"facing": "west", "triggered": false}], 1189 | "158:5": ["dropper", {"facing": "east", "triggered": false}], 1190 | "158:8": ["dropper", {"facing": "down", "triggered": true}], 1191 | "158:9": ["dropper", {"facing": "up", "triggered": true}], 1192 | "158:10": ["dropper", {"facing": "north", "triggered": true}], 1193 | "158:11": ["dropper", {"facing": "south", "triggered": true}], 1194 | "158:12": ["dropper", {"facing": "west", "triggered": true}], 1195 | "158:13": ["dropper", {"facing": "east", "triggered": true}], 1196 | 1197 | "159:0": ["white_terracotta", null], 1198 | "159:1": ["orange_terracotta", null], 1199 | "159:2": ["magenta_terracotta", null], 1200 | "159:3": ["light_blue_terracotta", null], 1201 | "159:4": ["yellow_terracotta", null], 1202 | "159:5": ["lime_terracotta", null], 1203 | "159:6": ["pink_terracotta", null], 1204 | "159:7": ["gray_terracotta", null], 1205 | "159:8": ["light_gray_terracotta", null], 1206 | "159:9": ["cyan_terracotta", null], 1207 | "159:10": ["purple_terracotta", null], 1208 | "159:11": ["blue_terracotta", null], 1209 | "159:12": ["brown_terracotta", null], 1210 | "159:13": ["green_terracotta", null], 1211 | "159:14": ["red_terracotta", null], 1212 | "159:15": ["black_terracotta", null], 1213 | 1214 | "160:0": ["white_stained_glass_pane", null], 1215 | "160:1": ["orange_stained_glass_pane", null], 1216 | "160:2": ["magenta_stained_glass_pane", null], 1217 | "160:3": ["light_blue_stained_glass_pane", null], 1218 | "160:4": ["yellow_stained_glass_pane", null], 1219 | "160:5": ["lime_stained_glass_pane", null], 1220 | "160:6": ["pink_stained_glass_pane", null], 1221 | "160:7": ["gray_stained_glass_pane", null], 1222 | "160:8": ["light_gray_stained_glass_pane", null], 1223 | "160:9": ["cyan_stained_glass_pane", null], 1224 | "160:10": ["purple_stained_glass_pane", null], 1225 | "160:11": ["blue_stained_glass_pane", null], 1226 | "160:12": ["brown_stained_glass_pane", null], 1227 | "160:13": ["green_stained_glass_pane", null], 1228 | "160:14": ["red_stained_glass_pane", null], 1229 | "160:15": ["black_stained_glass_pane", null], 1230 | 1231 | "161:0": ["acacia_leaves", {"persistent": false}], 1232 | "161:1": ["dark_oak_leaves", {"persistent": false}], 1233 | "161:4": ["acacia_leaves", {"persistent": true}], 1234 | "161:5": ["dark_oak_leaves", {"persistent": true}], 1235 | "161:8": ["acacia_leaves", {"persistent": false}], 1236 | "161:9": ["dark_oak_leaves", {"persistent": false}], 1237 | "161:12": ["acacia_leaves", {"persistent": true}], 1238 | "161:13": ["dark_oak_leaves", {"persistent": true}], 1239 | 1240 | "162:0": ["acacia_log", {"axis": "y"}], 1241 | "162:1": ["dark_oak_log", {"axis": "y"}], 1242 | "162:4": ["acacia_log", {"axis": "x"}], 1243 | "162:5": ["dark_oak_log", {"axis": "x"}], 1244 | "162:8": ["acacia_log", {"axis": "z"}], 1245 | "162:9": ["dark_oak_log", {"axis": "z"}], 1246 | "162:12": ["acacia_log", null], 1247 | "162:13": ["dark_oak_log", null], 1248 | 1249 | "163:0": ["acacia_stairs", {"facing": "east", "half": "bottom"}], 1250 | "163:1": ["acacia_stairs", {"facing": "west", "half": "bottom"}], 1251 | "163:2": ["acacia_stairs", {"facing": "south", "half": "bottom"}], 1252 | "163:3": ["acacia_stairs", {"facing": "north", "half": "bottom"}], 1253 | "163:4": ["acacia_stairs", {"facing": "east", "half": "top"}], 1254 | "163:5": ["acacia_stairs", {"facing": "west", "half": "top"}], 1255 | "163:6": ["acacia_stairs", {"facing": "south", "half": "top"}], 1256 | "163:7": ["acacia_stairs", {"facing": "north", "half": "top"}], 1257 | 1258 | "164:0": ["dark_oak_stairs", {"facing": "east", "half": "bottom"}], 1259 | "164:1": ["dark_oak_stairs", {"facing": "west", "half": "bottom"}], 1260 | "164:2": ["dark_oak_stairs", {"facing": "south", "half": "bottom"}], 1261 | "164:3": ["dark_oak_stairs", {"facing": "north", "half": "bottom"}], 1262 | "164:4": ["dark_oak_stairs", {"facing": "east", "half": "top"}], 1263 | "164:5": ["dark_oak_stairs", {"facing": "west", "half": "top"}], 1264 | "164:6": ["dark_oak_stairs", {"facing": "south", "half": "top"}], 1265 | "164:7": ["dark_oak_stairs", {"facing": "north", "half": "top"}], 1266 | 1267 | "165:0": ["slime_block", null], 1268 | "166:0": ["barrier", null], 1269 | 1270 | "167:0": ["iron_trapdoor", {"facing": "north", "open": false, "half": "bottom"}], 1271 | "167:1": ["iron_trapdoor", {"facing": "south", "open": false, "half": "bottom"}], 1272 | "167:2": ["iron_trapdoor", {"facing": "west", "open": false, "half": "bottom"}], 1273 | "167:3": ["iron_trapdoor", {"facing": "east", "open": false, "half": "bottom"}], 1274 | "167:4": ["iron_trapdoor", {"facing": "north", "open": true, "half": "bottom"}], 1275 | "167:5": ["iron_trapdoor", {"facing": "south", "open": true, "half": "bottom"}], 1276 | "167:6": ["iron_trapdoor", {"facing": "west", "open": true, "half": "bottom"}], 1277 | "167:7": ["iron_trapdoor", {"facing": "east", "open": true, "half": "bottom"}], 1278 | "167:8": ["iron_trapdoor", {"facing": "north", "open": false, "half": "top"}], 1279 | "167:9": ["iron_trapdoor", {"facing": "south", "open": false, "half": "top"}], 1280 | "167:10": ["iron_trapdoor", {"facing": "west", "open": false, "half": "top"}], 1281 | "167:11": ["iron_trapdoor", {"facing": "east", "open": false, "half": "top"}], 1282 | "167:12": ["iron_trapdoor", {"facing": "north", "open": true, "half": "top"}], 1283 | "167:13": ["iron_trapdoor", {"facing": "south", "open": true, "half": "top"}], 1284 | "167:14": ["iron_trapdoor", {"facing": "west", "open": true, "half": "top"}], 1285 | "167:15": ["iron_trapdoor", {"facing": "east", "open": true, "half": "top"}], 1286 | 1287 | "168:0": ["prismarine", null], 1288 | "168:1": ["prismarine_bricks", null], 1289 | "168:2": ["dark_prismarine", null], 1290 | "169:0": ["sea_lantern", null], 1291 | 1292 | "170:0": ["hay_block", {"axis": "y"}], 1293 | "170:4": ["hay_block", {"axis": "x"}], 1294 | "170:8": ["hay_block", {"axis": "z"}], 1295 | 1296 | "171:0": ["white_carpet", null], 1297 | "171:1": ["orange_carpet", null], 1298 | "171:2": ["magenta_carpet", null], 1299 | "171:3": ["light_blue_carpet", null], 1300 | "171:4": ["yellow_carpet", null], 1301 | "171:5": ["lime_carpet", null], 1302 | "171:6": ["pink_carpet", null], 1303 | "171:7": ["gray_carpet", null], 1304 | "171:8": ["light_gray_carpet", null], 1305 | "171:9": ["cyan_carpet", null], 1306 | "171:10": ["purple_carpet", null], 1307 | "171:11": ["blue_carpet", null], 1308 | "171:12": ["brown_carpet", null], 1309 | "171:13": ["green_carpet", null], 1310 | "171:14": ["red_carpet", null], 1311 | "171:15": ["black_carpet", null], 1312 | "172:0": ["terracotta", null], 1313 | "173:0": ["coal_block", null], 1314 | "174:0": ["packed_ice", null], 1315 | 1316 | "175:0": ["sunflower", {"half": "lower"}], 1317 | "175:1": ["lilac", {"half": "lower"}], 1318 | "175:2": ["tall_grass", {"half": "lower"}], 1319 | "175:3": ["large_fern", {"half": "lower"}], 1320 | "175:4": ["rose_bush", {"half": "lower"}], 1321 | "175:5": ["peony", {"half": "lower"}], 1322 | "175:8": ["sunflower", {"half": "upper"}], 1323 | "175:9": ["lilac", {"half": "upper"}], 1324 | "175:10": ["tall_grass", {"half": "upper"}], 1325 | "175:11": ["large_fern", {"half": "upper"}], 1326 | "175:12": ["rose_bush", {"half": "upper"}], 1327 | "175:13": ["peony", {"half": "upper"}], 1328 | 1329 | "176:0": ["banner", {"rotation": 0}], 1330 | "176:1": ["banner", {"rotation": 1}], 1331 | "176:2": ["banner", {"rotation": 2}], 1332 | "176:3": ["banner", {"rotation": 3}], 1333 | "176:4": ["banner", {"rotation": 4}], 1334 | "176:5": ["banner", {"rotation": 5}], 1335 | "176:6": ["banner", {"rotation": 6}], 1336 | "176:7": ["banner", {"rotation": 7}], 1337 | "176:8": ["banner", {"rotation": 8}], 1338 | "176:9": ["banner", {"rotation": 9}], 1339 | "176:10": ["banner", {"rotation": 10}], 1340 | "176:11": ["banner", {"rotation": 11}], 1341 | "176:12": ["banner", {"rotation": 12}], 1342 | "176:13": ["banner", {"rotation": 13}], 1343 | "176:14": ["banner", {"rotation": 14}], 1344 | "176:15": ["banner", {"rotation": 15}], 1345 | 1346 | "177:2": ["wall_banner", {"facing": "north"}], 1347 | "177:3": ["wall_banner", {"facing": "south"}], 1348 | "177:4": ["wall_banner", {"facing": "west"}], 1349 | "177:5": ["wall_banner", {"facing": "east"}], 1350 | 1351 | "178:0": ["daylight_detector", {"power": 0, "inverted": true}], 1352 | "178:1": ["daylight_detector", {"power": 1, "inverted": true}], 1353 | "178:2": ["daylight_detector", {"power": 2, "inverted": true}], 1354 | "178:3": ["daylight_detector", {"power": 3, "inverted": true}], 1355 | "178:4": ["daylight_detector", {"power": 4, "inverted": true}], 1356 | "178:5": ["daylight_detector", {"power": 5, "inverted": true}], 1357 | "178:6": ["daylight_detector", {"power": 6, "inverted": true}], 1358 | "178:7": ["daylight_detector", {"power": 7, "inverted": true}], 1359 | "178:8": ["daylight_detector", {"power": 8, "inverted": true}], 1360 | "178:9": ["daylight_detector", {"power": 9, "inverted": true}], 1361 | "178:10": ["daylight_detector", {"power": 10, "inverted": true}], 1362 | "178:11": ["daylight_detector", {"power": 11, "inverted": true}], 1363 | "178:12": ["daylight_detector", {"power": 12, "inverted": true}], 1364 | "178:13": ["daylight_detector", {"power": 13, "inverted": true}], 1365 | "178:14": ["daylight_detector", {"power": 14, "inverted": true}], 1366 | "178:15": ["daylight_detector", {"power": 15, "inverted": true}], 1367 | 1368 | "179:0": ["red_sandstone", null], 1369 | "179:1": ["chiseled_red_sandstone", null], 1370 | "179:2": ["cut_red_sandstone", null], 1371 | 1372 | "180:0": ["red_sandstone_stairs", {"facing": "east", "half": "bottom"}], 1373 | "180:1": ["red_sandstone_stairs", {"facing": "west", "half": "bottom"}], 1374 | "180:2": ["red_sandstone_stairs", {"facing": "south", "half": "bottom"}], 1375 | "180:3": ["red_sandstone_stairs", {"facing": "north", "half": "bottom"}], 1376 | "180:4": ["red_sandstone_stairs", {"facing": "east", "half": "top"}], 1377 | "180:5": ["red_sandstone_stairs", {"facing": "west", "half": "top"}], 1378 | "180:6": ["red_sandstone_stairs", {"facing": "south", "half": "top"}], 1379 | "180:7": ["red_sandstone_stairs", {"facing": "north", "half": "top"}], 1380 | 1381 | "181:0": ["red_sandstone", null], 1382 | "181:1": ["purpur_block", null], 1383 | "181:2": ["prismarine", null], 1384 | "181:3": ["prismarine_bricks", null], 1385 | "181:4": ["dark_prismarine", null], 1386 | 1387 | "182:0": ["red_sandstone_slab", {"type": "bottom"}], 1388 | "182:8": ["red_sandstone_slab", {"type": "top"}], 1389 | 1390 | "183:0": ["spruce_fence_gate", {"facing": "south", "open": false, "powered": false}], 1391 | "183:1": ["spruce_fence_gate", {"facing": "west", "open": false, "powered": false}], 1392 | "183:2": ["spruce_fence_gate", {"facing": "north", "open": false, "powered": false}], 1393 | "183:3": ["spruce_fence_gate", {"facing": "east", "open": false, "powered": false}], 1394 | "183:4": ["spruce_fence_gate", {"facing": "south", "open": true, "powered": false}], 1395 | "183:5": ["spruce_fence_gate", {"facing": "west", "open": true, "powered": false}], 1396 | "183:6": ["spruce_fence_gate", {"facing": "north", "open": true, "powered": false}], 1397 | "183:7": ["spruce_fence_gate", {"facing": "east", "open": true, "powered": false}], 1398 | "183:8": ["spruce_fence_gate", {"facing": "south", "open": false, "powered": true}], 1399 | "183:9": ["spruce_fence_gate", {"facing": "west", "open": false, "powered": true}], 1400 | "183:10": ["spruce_fence_gate", {"facing": "north", "open": false, "powered": true}], 1401 | "183:11": ["spruce_fence_gate", {"facing": "east", "open": false, "powered": true}], 1402 | "183:12": ["spruce_fence_gate", {"facing": "south", "open": true, "powered": true}], 1403 | "183:13": ["spruce_fence_gate", {"facing": "west", "open": true, "powered": true}], 1404 | "183:14": ["spruce_fence_gate", {"facing": "north", "open": true, "powered": true}], 1405 | "183:15": ["spruce_fence_gate", {"facing": "east", "open": true, "powered": true}], 1406 | 1407 | "184:0": ["birch_fence_gate", {"facing": "south", "open": false, "powered": false}], 1408 | "184:1": ["birch_fence_gate", {"facing": "west", "open": false, "powered": false}], 1409 | "184:2": ["birch_fence_gate", {"facing": "north", "open": false, "powered": false}], 1410 | "184:3": ["birch_fence_gate", {"facing": "east", "open": false, "powered": false}], 1411 | "184:4": ["birch_fence_gate", {"facing": "south", "open": true, "powered": false}], 1412 | "184:5": ["birch_fence_gate", {"facing": "west", "open": true, "powered": false}], 1413 | "184:6": ["birch_fence_gate", {"facing": "north", "open": true, "powered": false}], 1414 | "184:7": ["birch_fence_gate", {"facing": "east", "open": true, "powered": false}], 1415 | "184:8": ["birch_fence_gate", {"facing": "south", "open": false, "powered": true}], 1416 | "184:9": ["birch_fence_gate", {"facing": "west", "open": false, "powered": true}], 1417 | "184:10": ["birch_fence_gate", {"facing": "north", "open": false, "powered": true}], 1418 | "184:11": ["birch_fence_gate", {"facing": "east", "open": false, "powered": true}], 1419 | "184:12": ["birch_fence_gate", {"facing": "south", "open": true, "powered": true}], 1420 | "184:13": ["birch_fence_gate", {"facing": "west", "open": true, "powered": true}], 1421 | "184:14": ["birch_fence_gate", {"facing": "north", "open": true, "powered": true}], 1422 | "184:15": ["birch_fence_gate", {"facing": "east", "open": true, "powered": true}], 1423 | 1424 | "185:0": ["jungle_fence_gate", {"facing": "south", "open": false, "powered": false}], 1425 | "185:1": ["jungle_fence_gate", {"facing": "west", "open": false, "powered": false}], 1426 | "185:2": ["jungle_fence_gate", {"facing": "north", "open": false, "powered": false}], 1427 | "185:3": ["jungle_fence_gate", {"facing": "east", "open": false, "powered": false}], 1428 | "185:4": ["jungle_fence_gate", {"facing": "south", "open": true, "powered": false}], 1429 | "185:5": ["jungle_fence_gate", {"facing": "west", "open": true, "powered": false}], 1430 | "185:6": ["jungle_fence_gate", {"facing": "north", "open": true, "powered": false}], 1431 | "185:7": ["jungle_fence_gate", {"facing": "east", "open": true, "powered": false}], 1432 | "185:8": ["jungle_fence_gate", {"facing": "west", "open": false, "powered": true}], 1433 | "185:9": ["jungle_fence_gate", {"facing": "west", "open": false, "powered": true}], 1434 | "185:10": ["jungle_fence_gate", {"facing": "north", "open": false, "powered": true}], 1435 | "185:11": ["jungle_fence_gate", {"facing": "east", "open": false, "powered": true}], 1436 | "185:12": ["jungle_fence_gate", {"facing": "south", "open": true, "powered": true}], 1437 | "185:13": ["jungle_fence_gate", {"facing": "west", "open": true, "powered": true}], 1438 | "185:14": ["jungle_fence_gate", {"facing": "north", "open": true, "powered": true}], 1439 | "185:15": ["jungle_fence_gate", {"facing": "east", "open": true, "powered": true}], 1440 | 1441 | "186:0": ["dark_oak_fence_gate", {"facing": "south", "open": false, "powered": false}], 1442 | "186:1": ["dark_oak_fence_gate", {"facing": "west", "open": false, "powered": false}], 1443 | "186:2": ["dark_oak_fence_gate", {"facing": "north", "open": false, "powered": false}], 1444 | "186:3": ["dark_oak_fence_gate", {"facing": "east", "open": false, "powered": false}], 1445 | "186:4": ["dark_oak_fence_gate", {"facing": "south", "open": true, "powered": false}], 1446 | "186:5": ["dark_oak_fence_gate", {"facing": "west", "open": true, "powered": false}], 1447 | "186:6": ["dark_oak_fence_gate", {"facing": "north", "open": true, "powered": false}], 1448 | "186:7": ["dark_oak_fence_gate", {"facing": "east", "open": true, "powered": false}], 1449 | "186:8": ["dark_oak_fence_gate", {"facing": "south", "open": false, "powered": true}], 1450 | "186:9": ["dark_oak_fence_gate", {"facing": "west", "open": false, "powered": true}], 1451 | "186:10": ["dark_oak_fence_gate", {"facing": "north", "open": false, "powered": true}], 1452 | "186:11": ["dark_oak_fence_gate", {"facing": "east", "open": false, "powered": true}], 1453 | "186:12": ["dark_oak_fence_gate", {"facing": "south", "open": true, "powered": true}], 1454 | "186:13": ["dark_oak_fence_gate", {"facing": "west", "open": true, "powered": true}], 1455 | "186:14": ["dark_oak_fence_gate", {"facing": "north", "open": true, "powered": true}], 1456 | "186:15": ["dark_oak_fence_gate", {"facing": "east", "open": true, "powered": true}], 1457 | 1458 | "187:0": ["acacia_fence_gate", {"facing": "south", "open": false, "powered": false}], 1459 | "187:1": ["acacia_fence_gate", {"facing": "west", "open": false, "powered": false}], 1460 | "187:2": ["acacia_fence_gate", {"facing": "north", "open": false, "powered": false}], 1461 | "187:3": ["acacia_fence_gate", {"facing": "east", "open": false, "powered": false}], 1462 | "187:4": ["acacia_fence_gate", {"facing": "south", "open": true, "powered": false}], 1463 | "187:5": ["acacia_fence_gate", {"facing": "west", "open": true, "powered": false}], 1464 | "187:6": ["acacia_fence_gate", {"facing": "north", "open": true, "powered": false}], 1465 | "187:7": ["acacia_fence_gate", {"facing": "east", "open": true, "powered": false}], 1466 | "187:8": ["acacia_fence_gate", {"facing": "south", "open": false, "powered": true}], 1467 | "187:9": ["acacia_fence_gate", {"facing": "west", "open": false, "powered": true}], 1468 | "187:10": ["acacia_fence_gate", {"facing": "north", "open": false, "powered": true}], 1469 | "187:11": ["acacia_fence_gate", {"facing": "east", "open": false, "powered": true}], 1470 | "187:12": ["acacia_fence_gate", {"facing": "south", "open": true, "powered": true}], 1471 | "187:13": ["acacia_fence_gate", {"facing": "west", "open": true, "powered": true}], 1472 | "187:14": ["acacia_fence_gate", {"facing": "north", "open": true, "powered": true}], 1473 | "187:15": ["acacia_fence_gate", {"facing": "east", "open": true, "powered": true}], 1474 | 1475 | "188:0": ["spruce_fence", null], 1476 | "189:0": ["birch_fence", null], 1477 | "190:0": ["jungle_fence", null], 1478 | "191:0": ["dark_oak_fence", null], 1479 | "192:0": ["acacia_fence", null], 1480 | 1481 | "193:0": ["spruce_door", {"half": "lower", "facing": "east", "open": false}], 1482 | "193:1": ["spruce_door", {"half": "lower", "facing": "south", "open": false}], 1483 | "193:2": ["spruce_door", {"half": "lower", "facing": "west", "open": false}], 1484 | "193:3": ["spruce_door", {"half": "lower", "facing": "north", "open": false}], 1485 | "193:4": ["spruce_door", {"half": "lower", "facing": "east", "open": true}], 1486 | "193:5": ["spruce_door", {"half": "lower", "facing": "south", "open": true}], 1487 | "193:6": ["spruce_door", {"half": "lower", "facing": "west", "open": true}], 1488 | "193:7": ["spruce_door", {"half": "lower", "facing": "north", "open": true}], 1489 | 1490 | "193:8": ["spruce_door", {"half": "upper", "hinge": "left", "powered": false}], 1491 | "193:9": ["spruce_door", {"half": "upper", "hinge": "right", "powered": false}], 1492 | "193:10": ["spruce_door", {"half": "upper", "hinge": "left", "powered": true}], 1493 | "193:11": ["spruce_door", {"half": "upper", "hinge": "right", "powered": true}], 1494 | 1495 | "194:0": ["birch_door", {"half": "lower", "facing": "east", "open": false}], 1496 | "194:1": ["birch_door", {"half": "lower", "facing": "south", "open": false}], 1497 | "194:2": ["birch_door", {"half": "lower", "facing": "west", "open": false}], 1498 | "194:3": ["birch_door", {"half": "lower", "facing": "north", "open": false}], 1499 | "194:4": ["birch_door", {"half": "lower", "facing": "east", "open": true}], 1500 | "194:5": ["birch_door", {"half": "lower", "facing": "south", "open": true}], 1501 | "194:6": ["birch_door", {"half": "lower", "facing": "west", "open": true}], 1502 | "194:7": ["birch_door", {"half": "lower", "facing": "north", "open": true}], 1503 | 1504 | "194:8": ["birch_door", {"half": "upper", "hinge": "left", "powered": false}], 1505 | "194:9": ["birch_door", {"half": "upper", "hinge": "right", "powered": false}], 1506 | "194:10": ["birch_door", {"half": "upper", "hinge": "left", "powered": true}], 1507 | "194:11": ["birch_door", {"half": "upper", "hinge": "right", "powered": true}], 1508 | 1509 | "195:0": ["jungle_door", {"half": "lower", "facing": "east", "open": false}], 1510 | "195:1": ["jungle_door", {"half": "lower", "facing": "south", "open": false}], 1511 | "195:2": ["jungle_door", {"half": "lower", "facing": "west", "open": false}], 1512 | "195:3": ["jungle_door", {"half": "lower", "facing": "north", "open": false}], 1513 | "195:4": ["jungle_door", {"half": "lower", "facing": "east", "open": true}], 1514 | "195:5": ["jungle_door", {"half": "lower", "facing": "south", "open": true}], 1515 | "195:6": ["jungle_door", {"half": "lower", "facing": "west", "open": true}], 1516 | "195:7": ["jungle_door", {"half": "lower", "facing": "north", "open": true}], 1517 | 1518 | "195:8": ["jungle_door", {"half": "upper", "hinge": "left", "powered": false}], 1519 | "195:9": ["jungle_door", {"half": "upper", "hinge": "right", "powered": false}], 1520 | "195:10": ["jungle_door", {"half": "upper", "hinge": "left", "powered": true}], 1521 | "195:11": ["jungle_door", {"half": "upper", "hinge": "right", "powered": true}], 1522 | 1523 | "196:0": ["acacia_door", {"half": "lower", "facing": "east", "open": false}], 1524 | "196:1": ["acacia_door", {"half": "lower", "facing": "south", "open": false}], 1525 | "196:2": ["acacia_door", {"half": "lower", "facing": "west", "open": false}], 1526 | "196:3": ["acacia_door", {"half": "lower", "facing": "north", "open": false}], 1527 | "196:4": ["acacia_door", {"half": "lower", "facing": "east", "open": true}], 1528 | "196:5": ["acacia_door", {"half": "lower", "facing": "south", "open": true}], 1529 | "196:6": ["acacia_door", {"half": "lower", "facing": "west", "open": true}], 1530 | "196:7": ["acacia_door", {"half": "lower", "facing": "north", "open": true}], 1531 | 1532 | "196:8": ["acacia_door", {"half": "upper", "hinge": "left", "powered": false}], 1533 | "196:9": ["acacia_door", {"half": "upper", "hinge": "right", "powered": false}], 1534 | "196:10": ["acacia_door", {"half": "upper", "hinge": "left", "powered": true}], 1535 | "196:11": ["acacia_door", {"half": "upper", "hinge": "right", "powered": true}], 1536 | 1537 | "197:0": ["dark_oak_door", {"half": "lower", "facing": "east", "open": false}], 1538 | "197:1": ["dark_oak_door", {"half": "lower", "facing": "south", "open": false}], 1539 | "197:2": ["dark_oak_door", {"half": "lower", "facing": "west", "open": false}], 1540 | "197:3": ["dark_oak_door", {"half": "lower", "facing": "north", "open": false}], 1541 | "197:4": ["dark_oak_door", {"half": "lower", "facing": "east", "open": true}], 1542 | "197:5": ["dark_oak_door", {"half": "lower", "facing": "south", "open": true}], 1543 | "197:6": ["dark_oak_door", {"half": "lower", "facing": "west", "open": true}], 1544 | "197:7": ["dark_oak_door", {"half": "lower", "facing": "north", "open": true}], 1545 | 1546 | "197:8": ["dark_oak_door", {"half": "upper", "hinge": "left", "powered": false}], 1547 | "197:9": ["dark_oak_door", {"half": "upper", "hinge": "right", "powered": false}], 1548 | "197:10": ["dark_oak_door", {"half": "upper", "hinge": "left", "powered": true}], 1549 | "197:11": ["dark_oak_door", {"half": "upper", "hinge": "right", "powered": true}], 1550 | 1551 | "198:0": ["end_rod", {"facing": "down"}], 1552 | "198:1": ["end_rod", {"facing": "up"}], 1553 | "198:2": ["end_rod", {"facing": "north"}], 1554 | "198:3": ["end_rod", {"facing": "south"}], 1555 | "198:4": ["end_rod", {"facing": "west"}], 1556 | "198:5": ["end_rod", {"facing": "east"}], 1557 | 1558 | "199:0": ["chorus_plant", null], 1559 | 1560 | "200:0": ["chorus_flower", {"age": 0}], 1561 | "200:1": ["chorus_flower", {"age": 1}], 1562 | "200:2": ["chorus_flower", {"age": 2}], 1563 | "200:3": ["chorus_flower", {"age": 3}], 1564 | "200:4": ["chorus_flower", {"age": 4}], 1565 | "200:5": ["chorus_flower", {"age": 5}], 1566 | 1567 | "201:0": ["purpur_block", null], 1568 | 1569 | "202:0": ["purpur_pillar", {"axis": "y"}], 1570 | "202:4": ["purpur_pillar", {"axis": "x"}], 1571 | "202:8": ["purpur_pillar", {"axis": "z"}], 1572 | 1573 | "203:0": ["purpur_stairs", {"facing": "east", "half": "bottom"}], 1574 | "203:1": ["purpur_stairs", {"facing": "west", "half": "bottom"}], 1575 | "203:2": ["purpur_stairs", {"facing": "south", "half": "bottom"}], 1576 | "203:3": ["purpur_stairs", {"facing": "north", "half": "bottom"}], 1577 | "203:4": ["purpur_stairs", {"facing": "east", "half": "top"}], 1578 | "203:5": ["purpur_stairs", {"facing": "west", "half": "top"}], 1579 | "203:6": ["purpur_stairs", {"facing": "south", "half": "top"}], 1580 | "203:7": ["purpur_stairs", {"facing": "north", "half": "top"}], 1581 | 1582 | "204:0": ["purpur_slab", {"type": "double"}], 1583 | 1584 | "205:0": ["purpur_slab", {"type": "bottom"}], 1585 | "205:8": ["purpur_slab", {"type": "top"}], 1586 | 1587 | "206:0": ["end_stone_bricks", null], 1588 | 1589 | "207:0": ["beetroots", {"age": 0}], 1590 | "207:1": ["beetroots", {"age": 1}], 1591 | "207:2": ["beetroots", {"age": 2}], 1592 | "207:3": ["beetroots", {"age": 3}], 1593 | 1594 | "208:0": ["grass_path", null], 1595 | "209:0": ["end_gateway", null], 1596 | "210:0": ["repeating_command_block", null], 1597 | "211:0": ["chain_command_block", null], 1598 | "212:0": ["frosted_ice", null], 1599 | "213:0": ["magma_block", null], 1600 | "214:0": ["nether_wart_block", null], 1601 | 1602 | "216:0": ["bone_block", {"axis": "y"}], 1603 | "216:4": ["bone_block", {"axis": "x"}], 1604 | "216:8": ["bone_block", {"axis": "z"}], 1605 | 1606 | "215:0": ["red_nether_bricks", null], 1607 | "217:0": ["structure_void", null], 1608 | 1609 | "218:0": ["observer", {"facing": "down", "powered": false}], 1610 | "218:1": ["observer", {"facing": "up", "powered": false}], 1611 | "218:2": ["observer", {"facing": "north", "powered": false}], 1612 | "218:3": ["observer", {"facing": "south", "powered": false}], 1613 | "218:4": ["observer", {"facing": "west", "powered": false}], 1614 | "218:5": ["observer", {"facing": "east", "powered": false}], 1615 | "218:6": ["observer", {"facing": "down", "powered": true}], 1616 | "218:7": ["observer", {"facing": "up", "powered": true}], 1617 | "218:8": ["observer", {"facing": "north", "powered": true}], 1618 | "218:9": ["observer", {"facing": "south", "powered": true}], 1619 | "218:10": ["observer", {"facing": "west", "powered": true}], 1620 | "218:11": ["observer", {"facing": "east", "powered": true}], 1621 | 1622 | "219:0": ["white_shulker_box", {"facing": "down"}], 1623 | "219:1": ["white_shulker_box", {"facing": "up"}], 1624 | "219:2": ["white_shulker_box", {"facing": "north"}], 1625 | "219:3": ["white_shulker_box", {"facing": "south"}], 1626 | "219:4": ["white_shulker_box", {"facing": "west"}], 1627 | "219:5": ["white_shulker_box", {"facing": "east"}], 1628 | 1629 | "220:0": ["orange_shulker_box", {"facing": "down"}], 1630 | "220:1": ["orange_shulker_box", {"facing": "up"}], 1631 | "220:2": ["orange_shulker_box", {"facing": "north"}], 1632 | "220:3": ["orange_shulker_box", {"facing": "south"}], 1633 | "220:4": ["orange_shulker_box", {"facing": "west"}], 1634 | "220:5": ["orange_shulker_box", {"facing": "east"}], 1635 | 1636 | "221:0": ["magenta_shulker_box", {"facing": "down"}], 1637 | "221:1": ["magenta_shulker_box", {"facing": "up"}], 1638 | "221:2": ["magenta_shulker_box", {"facing": "north"}], 1639 | "221:3": ["magenta_shulker_box", {"facing": "south"}], 1640 | "221:4": ["magenta_shulker_box", {"facing": "west"}], 1641 | "221:5": ["magenta_shulker_box", {"facing": "east"}], 1642 | 1643 | "222:0": ["light_blue_shulker_box", {"facing": "down"}], 1644 | "222:1": ["light_blue_shulker_box", {"facing": "up"}], 1645 | "222:2": ["light_blue_shulker_box", {"facing": "north"}], 1646 | "222:3": ["light_blue_shulker_box", {"facing": "south"}], 1647 | "222:4": ["light_blue_shulker_box", {"facing": "west"}], 1648 | "222:5": ["light_blue_shulker_box", {"facing": "east"}], 1649 | 1650 | "223:0": ["yellow_shulker_box", {"facing": "down"}], 1651 | "223:1": ["yellow_shulker_box", {"facing": "up"}], 1652 | "223:2": ["yellow_shulker_box", {"facing": "north"}], 1653 | "223:3": ["yellow_shulker_box", {"facing": "south"}], 1654 | "223:4": ["yellow_shulker_box", {"facing": "west"}], 1655 | "223:5": ["yellow_shulker_box", {"facing": "east"}], 1656 | 1657 | "224:0": ["lime_shulker_box", {"facing": "down"}], 1658 | "224:1": ["lime_shulker_box", {"facing": "up"}], 1659 | "224:2": ["lime_shulker_box", {"facing": "north"}], 1660 | "224:3": ["lime_shulker_box", {"facing": "south"}], 1661 | "224:4": ["lime_shulker_box", {"facing": "west"}], 1662 | "224:5": ["lime_shulker_box", {"facing": "east"}], 1663 | 1664 | "225:0": ["pink_shulker_box", {"facing": "down"}], 1665 | "225:1": ["pink_shulker_box", {"facing": "up"}], 1666 | "225:2": ["pink_shulker_box", {"facing": "north"}], 1667 | "225:3": ["pink_shulker_box", {"facing": "south"}], 1668 | "225:4": ["pink_shulker_box", {"facing": "west"}], 1669 | "225:5": ["pink_shulker_box", {"facing": "east"}], 1670 | 1671 | "226:0": ["gray_shulker_box", {"facing": "down"}], 1672 | "226:1": ["gray_shulker_box", {"facing": "up"}], 1673 | "226:2": ["gray_shulker_box", {"facing": "north"}], 1674 | "226:3": ["gray_shulker_box", {"facing": "south"}], 1675 | "226:4": ["gray_shulker_box", {"facing": "west"}], 1676 | "226:5": ["gray_shulker_box", {"facing": "east"}], 1677 | 1678 | "227:0": ["light_gray_shulker_box", {"facing": "down"}], 1679 | "227:1": ["light_gray_shulker_box", {"facing": "up"}], 1680 | "227:2": ["light_gray_shulker_box", {"facing": "north"}], 1681 | "227:3": ["light_gray_shulker_box", {"facing": "south"}], 1682 | "227:4": ["light_gray_shulker_box", {"facing": "west"}], 1683 | "227:5": ["light_gray_shulker_box", {"facing": "east"}], 1684 | 1685 | "228:0": ["cyan_shulker_box", { "facing": "down"}], 1686 | "228:1": ["cyan_shulker_box", {"facing": "up"}], 1687 | "228:2": ["cyan_shulker_box", {"facing": "north"}], 1688 | "228:3": ["cyan_shulker_box", {"facing": "south"}], 1689 | "228:4": ["cyan_shulker_box", {"facing": "west"}], 1690 | "228:5": ["cyan_shulker_box", {"facing": "east"}], 1691 | 1692 | "229:0": ["purple_shulker_box", {"facing": "down"}], 1693 | "229:1": ["purple_shulker_box", {"facing": "up"}], 1694 | "229:2": ["purple_shulker_box", {"facing": "north"}], 1695 | "229:3": ["purple_shulker_box", {"facing": "south"}], 1696 | "229:4": ["purple_shulker_box", {"facing": "west"}], 1697 | "229:5": ["purple_shulker_box", {"facing": "east"}], 1698 | 1699 | "230:0": ["blue_shulker_box", {"facing": "down"}], 1700 | "230:1": ["blue_shulker_box", {"facing": "up"}], 1701 | "230:2": ["blue_shulker_box", {"facing": "north"}], 1702 | "230:3": ["blue_shulker_box", {"facing": "south"}], 1703 | "230:4": ["blue_shulker_box", {"facing": "west"}], 1704 | "230:5": ["blue_shulker_box", {"facing": "east"}], 1705 | 1706 | "231:0": ["brown_shulker_box", {"facing": "down"}], 1707 | "231:1": ["brown_shulker_box", {"facing": "up"}], 1708 | "231:2": ["brown_shulker_box", {"facing": "north"}], 1709 | "231:3": ["brown_shulker_box", {"facing": "south"}], 1710 | "231:4": ["brown_shulker_box", {"facing": "west"}], 1711 | "231:5": ["brown_shulker_box", {"facing": "east"}], 1712 | 1713 | "232:0": ["green_shulker_box", {"facing": "down"}], 1714 | "232:1": ["green_shulker_box", {"facing": "up"}], 1715 | "232:2": ["green_shulker_box", {"facing": "north"}], 1716 | "232:3": ["green_shulker_box", {"facing": "south"}], 1717 | "232:4": ["green_shulker_box", {"facing": "west"}], 1718 | "232:5": ["green_shulker_box", {"facing": "east"}], 1719 | 1720 | "233:0": ["red_shulker_box", {"facing": "down"}], 1721 | "233:1": ["red_shulker_box", {"facing": "up"}], 1722 | "233:2": ["red_shulker_box", {"facing": "north"}], 1723 | "233:3": ["red_shulker_box", {"facing": "south"}], 1724 | "233:4": ["red_shulker_box", {"facing": "west"}], 1725 | "233:5": ["red_shulker_box", {"facing": "east"}], 1726 | 1727 | "234:0": ["black_shulker_box", {"facing": "up"}], 1728 | "233:1": ["black_shulker_box", {"facing": "up"}], 1729 | "234:2": ["black_shulker_box", {"facing": "north"}], 1730 | "234:3": ["black_shulker_box", {"facing": "south"}], 1731 | "234:4": ["black_shulker_box", {"facing": "west"}], 1732 | "234:5": ["black_shulker_box", {"facing": "east"}], 1733 | 1734 | 1735 | "235:0": ["white_glazed_terracotta", {"facing": "south"}], 1736 | "235:1": ["white_glazed_terracotta", {"facing": "west"}], 1737 | "235:2": ["white_glazed_terracotta", {"facing": "north"}], 1738 | "235:3": ["white_glazed_terracotta", {"facing": "east"}], 1739 | 1740 | "236:0": ["orange_glazed_terracotta", {"facing": "south"}], 1741 | "236:1": ["orange_glazed_terracotta", {"facing": "west"}], 1742 | "236:2": ["orange_glazed_terracotta", {"facing": "north"}], 1743 | "236:3": ["orange_glazed_terracotta", {"facing": "east"}], 1744 | 1745 | "237:0": ["magenta_glazed_terracotta", {"facing": "south"}], 1746 | "237:1": ["magenta_glazed_terracotta", {"facing": "west"}], 1747 | "237:2": ["magenta_glazed_terracotta", {"facing": "north"}], 1748 | "237:3": ["magenta_glazed_terracotta", {"facing": "east"}], 1749 | 1750 | "238:0": ["light_blue_glazed_terracotta", {"facing": "south"}], 1751 | "238:1": ["light_blue_glazed_terracotta", {"facing": "west"}], 1752 | "238:2": ["light_blue_glazed_terracotta", {"facing": "north"}], 1753 | "238:3": ["light_blue_glazed_terracotta", {"facing": "east"}], 1754 | 1755 | "239:0": ["yellow_glazed_terracotta", {"facing": "south"}], 1756 | "239:1": ["yellow_glazed_terracotta", {"facing": "west"}], 1757 | "239:2": ["yellow_glazed_terracotta", {"facing": "north"}], 1758 | "239:3": ["yellow_glazed_terracotta", {"facing": "east"}], 1759 | 1760 | "240:0": ["lime_glazed_terracotta", {"facing": "south"}], 1761 | "240:1": ["lime_glazed_terracotta", {"facing": "west"}], 1762 | "240:2": ["lime_glazed_terracotta", {"facing": "north"}], 1763 | "240:3": ["lime_glazed_terracotta", {"facing": "east"}], 1764 | 1765 | "241:0": ["pink_glazed_terracotta", {"facing": "south"}], 1766 | "241:1": ["pink_glazed_terracotta", {"facing": "west"}], 1767 | "241:2": ["pink_glazed_terracotta", {"facing": "north"}], 1768 | "241:3": ["pink_glazed_terracotta", {"facing": "east"}], 1769 | 1770 | "242:0": ["gray_glazed_terracotta", {"facing": "south"}], 1771 | "242:1": ["gray_glazed_terracotta", {"facing": "west"}], 1772 | "242:2": ["gray_glazed_terracotta", {"facing": "north"}], 1773 | "242:3": ["gray_glazed_terracotta", {"facing": "east"}], 1774 | 1775 | "243:0": ["light_gray_glazed_terracotta", {"facing": "south"}], 1776 | "243:1": ["light_gray_glazed_terracotta", {"facing": "west"}], 1777 | "243:2": ["light_gray_glazed_terracotta", {"facing": "north"}], 1778 | "243:3": ["light_gray_glazed_terracotta", {"facing": "east"}], 1779 | 1780 | "244:0": ["cyan_glazed_terracotta", {"facing": "south"}], 1781 | "244:1": ["cyan_glazed_terracotta", {"facing": "west"}], 1782 | "244:2": ["cyan_glazed_terracotta", {"facing": "north"}], 1783 | "244:3": ["cyan_glazed_terracotta", {"facing": "east"}], 1784 | 1785 | "245:0": ["purple_glazed_terracotta", {"facing": "south"}], 1786 | "245:1": ["purple_glazed_terracotta", {"facing": "west"}], 1787 | "245:2": ["purple_glazed_terracotta", {"facing": "north"}], 1788 | "245:3": ["purple_glazed_terracotta", {"facing": "east"}], 1789 | 1790 | "246:0": ["blue_glazed_terracotta", {"facing": "south"}], 1791 | "246:1": ["blue_glazed_terracotta", {"facing": "west"}], 1792 | "246:2": ["blue_glazed_terracotta", {"facing": "north"}], 1793 | "246:3": ["blue_glazed_terracotta", {"facing": "east"}], 1794 | 1795 | "247:0": ["brown_glazed_terracotta", {"facing": "south"}], 1796 | "247:1": ["brown_glazed_terracotta", {"facing": "west"}], 1797 | "247:2": ["brown_glazed_terracotta", {"facing": "north"}], 1798 | "247:3": ["brown_glazed_terracotta", {"facing": "east"}], 1799 | 1800 | "248:0": ["green_glazed_terracotta", {"facing": "south"}], 1801 | "248:1": ["green_glazed_terracotta", {"facing": "west"}], 1802 | "248:2": ["green_glazed_terracotta", {"facing": "north"}], 1803 | "248:3": ["green_glazed_terracotta", {"facing": "east"}], 1804 | 1805 | "249:0": ["red_glazed_terracotta", {"facing": "south"}], 1806 | "249:1": ["red_glazed_terracotta", {"facing": "west"}], 1807 | "249:2": ["red_glazed_terracotta", {"facing": "north"}], 1808 | "249:3": ["red_glazed_terracotta", {"facing": "east"}], 1809 | 1810 | "250:0": ["black_glazed_terracotta", {"facing": "south"}], 1811 | "250:1": ["black_glazed_terracotta", {"facing": "west"}], 1812 | "250:2": ["black_glazed_terracotta", {"facing": "north"}], 1813 | "250:3": ["black_glazed_terracotta", {"facing": "east"}], 1814 | 1815 | "251:0": ["white_concrete", null], 1816 | "251:1": ["orange_concrete", null], 1817 | "251:2": ["magenta_concrete", null], 1818 | "251:3": ["light_blue_concrete", null], 1819 | "251:4": ["yellow_concrete", null], 1820 | "251:5": ["lime_concrete", null], 1821 | "251:6": ["pink_concrete", null], 1822 | "251:7": ["gray_concrete", null], 1823 | "251:8": ["light_gray_concrete", null], 1824 | "251:9": ["cyan_concrete", null], 1825 | "251:10": ["purple_concrete", null], 1826 | "251:11": ["blue_concrete", null], 1827 | "251:12": ["brown_concrete", null], 1828 | "251:13": ["green_concrete", null], 1829 | "251:14": ["red_concrete", null], 1830 | "251:15": ["black_concrete", null], 1831 | "252:0": ["white_concrete_powder", null], 1832 | "252:1": ["orange_concrete_powder", null], 1833 | "252:2": ["magenta_concrete_powder", null], 1834 | "252:3": ["light_blue_concrete_powder", null], 1835 | "252:4": ["yellow_concrete_powder", null], 1836 | "252:5": ["lime_concrete_powder", null], 1837 | "252:6": ["pink_concrete_powder", null], 1838 | "252:7": ["gray_concrete_powder", null], 1839 | "252:8": ["light_gray_concrete_powder", null], 1840 | "252:9": ["cyan_concrete_powder", null], 1841 | "252:10": ["purple_concrete_powder", null], 1842 | "252:11": ["blue_concrete_powder", null], 1843 | "252:12": ["brown_concrete_powder", null], 1844 | "252:13": ["green_concrete_powder", null], 1845 | "252:14": ["red_concrete_powder", null], 1846 | "252:15": ["black_concrete_powder", null], 1847 | 1848 | "255:0": ["structure_block", {"mode": "save"}], 1849 | "255:1": ["structure_block", {"mode": "load"}], 1850 | "255:2": ["structure_block", {"mode": "data"}], 1851 | "255:3": ["structure_block", {"mode": "corner"}] 1852 | } 1853 | -------------------------------------------------------------------------------- /anvil/raw_section.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple, Sequence, Iterable 2 | from . import EmptySection, Block 3 | from .errors import OutOfBoundsCoordinates 4 | import array 5 | from nbt import nbt 6 | 7 | def bin_append(a, b, length=None): 8 | length = length or b.bit_length() 9 | return (a << length) | b 10 | 11 | class RawSection: 12 | """ 13 | Same as :class:`EmptySection` but you manually 14 | set the palette and the blocks array (which instead 15 | of :class:`Block`, it's indexes on the palette) 16 | 17 | Attributes 18 | ---------- 19 | y: :class:`int` 20 | Section's Y index 21 | blocks: Iterable[:class:`int`] 22 | Array of palette indexes 23 | _palette: Sequence[:class:`Block`] 24 | Section's palette 25 | """ 26 | __slots__ = ('y', '_palette', 'blocks') 27 | def __init__(self, y: int, blocks: Iterable[int], palette: Sequence[Block]): 28 | self.y = y 29 | self.blocks: Iterable[int] = blocks 30 | self._palette: Sequence[Block] = palette 31 | 32 | def palette(self) -> Sequence[Block]: 33 | """Returns ``self._palette``""" 34 | return self._palette 35 | 36 | def blockstates(self, palette: Sequence[Block]=None) -> array.array: 37 | """Refer to :class:`EmptySection.blockstates()`""" 38 | bits = max((len(self._palette) - 1).bit_length(), 4) 39 | states = array.array('Q') 40 | current = 0 41 | current_len = 0 42 | for index in self.blocks: 43 | if current_len + bits > 64: 44 | leftover = 64 - current_len 45 | states.append(bin_append(index & ((1 << leftover) - 1), current, length=current_len)) 46 | current = index >> leftover 47 | current_len = bits - leftover 48 | else: 49 | current = bin_append(index, current, length=current_len) 50 | current_len += bits 51 | states.append(current) 52 | return states 53 | 54 | def save(self) -> nbt.TAG_Compound: 55 | """Refer to :class:`EmptySection.save()`""" 56 | return EmptySection.save(self) 57 | -------------------------------------------------------------------------------- /anvil/region.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple, Union, BinaryIO 2 | from nbt import nbt 3 | import zlib 4 | from io import BytesIO 5 | import anvil 6 | from .errors import GZipChunkData 7 | 8 | class Region: 9 | """ 10 | Read-only region 11 | 12 | Attributes 13 | ---------- 14 | data: :class:`bytes` 15 | Region file (``.mca``) as bytes 16 | """ 17 | __slots__ = ('data',) 18 | def __init__(self, data: bytes): 19 | """Makes a Region object from data, which is the region file content""" 20 | self.data = data 21 | 22 | @staticmethod 23 | def header_offset(chunk_x: int, chunk_z: int) -> int: 24 | """ 25 | Returns the byte offset for given chunk in the header 26 | 27 | Parameters 28 | ---------- 29 | chunk_x 30 | Chunk's X value 31 | chunk_z 32 | Chunk's Z value 33 | """ 34 | return 4 * (chunk_x % 32 + chunk_z % 32 * 32) 35 | 36 | def chunk_location(self, chunk_x: int, chunk_z: int) -> Tuple[int, int]: 37 | """ 38 | Returns the chunk offset in the 4KiB sectors from the start of the file, 39 | and the length of the chunk in sectors of 4KiB 40 | 41 | Will return ``(0, 0)`` if chunk hasn't been generated yet 42 | 43 | Parameters 44 | ---------- 45 | chunk_x 46 | Chunk's X value 47 | chunk_z 48 | Chunk's Z value 49 | """ 50 | b_off = self.header_offset(chunk_x, chunk_z) 51 | off = int.from_bytes(self.data[b_off : b_off + 3], byteorder='big') 52 | sectors = self.data[b_off + 3] 53 | return (off, sectors) 54 | 55 | def chunk_data(self, chunk_x: int, chunk_z: int) -> nbt.NBTFile: 56 | """ 57 | Returns the NBT data for a chunk 58 | 59 | Parameters 60 | ---------- 61 | chunk_x 62 | Chunk's X value 63 | chunk_z 64 | Chunk's Z value 65 | 66 | Raises 67 | ------ 68 | anvil.GZipChunkData 69 | If the chunk's compression is gzip 70 | """ 71 | off = self.chunk_location(chunk_x, chunk_z) 72 | # (0, 0) means it hasn't generated yet, aka it doesn't exist yet 73 | if off == (0, 0): 74 | return 75 | off = off[0] * 4096 76 | length = int.from_bytes(self.data[off:off + 4], byteorder='big') 77 | compression = self.data[off + 4] # 2 most of the time 78 | if compression == 1: 79 | raise GZipChunkData('GZip is not supported') 80 | compressed_data = self.data[off + 5 : off + 5 + length - 1] 81 | return nbt.NBTFile(buffer=BytesIO(zlib.decompress(compressed_data))) 82 | 83 | def get_chunk(self, chunk_x: int, chunk_z: int) -> 'anvil.Chunk': 84 | """ 85 | Returns the chunk at given coordinates, 86 | same as doing ``Chunk.from_region(region, chunk_x, chunk_z)`` 87 | 88 | Parameters 89 | ---------- 90 | chunk_x 91 | Chunk's X value 92 | chunk_z 93 | Chunk's Z value 94 | 95 | 96 | :rtype: :class:`anvil.Chunk` 97 | """ 98 | return anvil.Chunk.from_region(self, chunk_x, chunk_z) 99 | 100 | @classmethod 101 | def from_file(cls, file: Union[str, BinaryIO]): 102 | """ 103 | Creates a new region with the data from reading the given file 104 | 105 | Parameters 106 | ---------- 107 | file 108 | Either a file path or a file object 109 | """ 110 | if isinstance(file, str): 111 | with open(file, 'rb') as f: 112 | return cls(data=f.read()) 113 | else: 114 | return cls(data=file.read()) 115 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme is 99.9% https://userstyles.org/styles/170804/dark-discord-py-rewrite-docs 3 | just has a few tweaks so it works on alabaster 4 | */ 5 | 6 | body { 7 | font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu; 8 | font-size: 1.0em; 9 | 10 | /* Scrolling: Firefox */ 11 | scrollbar-width: 10px; 12 | scrollbar-color: #2C2F33 #23272A; /* Thumb Track */ 13 | } 14 | 15 | h1, h2 { 16 | font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu !important; 17 | } 18 | 19 | /* Dark */ 20 | .indexwrapper, 21 | body { 22 | background-color: #23272A; /* Dark 1 */ 23 | color: #dcddde; /* Light 1 */ 24 | } 25 | 26 | div.body, 27 | .rst-versions.rst-badge .rst-current-version { 28 | background-color: #2C2F33; /* Dark 2 */ 29 | color: #dcddde; /* Light 1 */ 30 | } 31 | 32 | .active { 33 | background-color: #2C2F33; /* Dark 2 */ 34 | border-left: 5px solid #2C2F33; /* Dark 2 */ 35 | } 36 | 37 | /* Get rid of extra bgs */ 38 | tt, 39 | code, 40 | div.highlight { 41 | background-color: transparent; 42 | } 43 | 44 | /* Light font for dark bg */ 45 | div.sphinxsidebar a, 46 | div.sphinxsidebar h3 a, 47 | div.sphinxsidebar h3, 48 | div.sphinxsidebar h4, 49 | div.sphinxsidebar ul, 50 | div.body h1, 51 | div.body h2, 52 | div.body h3, 53 | div.body h4 { 54 | color: #dcddde; 55 | } 56 | 57 | /* Primary color */ 58 | a { 59 | color: #7289da; 60 | } 61 | 62 | a:hover { 63 | color: #7d96f0; 64 | } 65 | 66 | /* Dark bg, light font combo */ 67 | dl.describe > dt, 68 | dl.function > dt, 69 | dl.attribute > dt, 70 | dl.classmethod > dt, 71 | dl.method > dt, 72 | dl.class > dt, 73 | dl.exception > dt, 74 | .container.operations > dl.describe > dt, 75 | table.docutils thead, 76 | table.docutils tfoot, 77 | table.docutils thead tr th, 78 | code.sig-prename, code.sig-name { 79 | background-color: #23272A; /* Dark 1 */ 80 | color: #dcddde; /* Light 1 */ 81 | } 82 | 83 | pre { 84 | background-color: #23272A; /* Dark 1 */ 85 | color: #dcddde; /* Light 1 */ 86 | border: 1px solid rgba(32, 34, 37, .3); 87 | } 88 | 89 | /* Custom colors */ 90 | div.important, 91 | div.note, 92 | div.hint, 93 | div.tip, 94 | highlight, 95 | div.sphinxsidebar input { 96 | background-color: #23272A; /* Dark 1 */ 97 | border: 1px solid #959595; 98 | color: #839496; 99 | } 100 | 101 | div.attention, 102 | div.warning, 103 | div.caution, 104 | div.seealso { 105 | background-color: #665623; 106 | } 107 | 108 | div.helpful { 109 | background-color: #162f44; 110 | border: 1px solid #4478ac; 111 | } 112 | 113 | div.danger, 114 | div.error { 115 | background-color: #401414; 116 | border: 1px solid #f66; 117 | } 118 | 119 | .container.operations::before { 120 | color: #dcddde; /* Light 1 */ 121 | } 122 | 123 | .highlight .k, 124 | .highlight .ow, 125 | .highlight .nb, 126 | .highlight .kc, 127 | .highlight .bp { 128 | color: #00ae32; 129 | } 130 | 131 | .highlight .nf { 132 | color: #5183ff; 133 | } 134 | 135 | .highlight .hll { 136 | background-color: #0076ff30; 137 | } 138 | /* Rounding */ 139 | div.body, 140 | div.admonition, 141 | dl.describe > dt, dl.function > dt, dl.attribute > dt, dl.classmethod > dt, dl.method > dt, dl.class > dt, dl.exception > dt, 142 | .container.operations, 143 | .rst-versions.rst-badge .rst-current-version, 144 | .active, 145 | pre, 146 | img { 147 | border-radius: 5px; 148 | } 149 | 150 | div.sphinxsidebar #searchbox input[type="text"] { 151 | border-top-left-radius: 5px; 152 | border-bottom-left-radius: 5px; 153 | } 154 | 155 | div.sphinxsidebar #searchbox input[type="submit"] { 156 | border-top-right-radius: 5px; 157 | border-bottom-right-radius: 5px; 158 | } 159 | 160 | dl.describe > dt, dl.function > dt, dl.attribute > dt, dl.classmethod > dt, dl.method > dt, dl.class > dt, dl.exception > dt { 161 | padding: 2px 10px; 162 | } 163 | 164 | /* Scrolling: Chrome etc */ 165 | ::-webkit-scrollbar { 166 | width: 10px; 167 | } 168 | 169 | ::-webkit-scrollbar-track { 170 | background: #23272A; /* Dark 1 */ 171 | } 172 | 173 | ::-webkit-scrollbar-thumb { 174 | background: #2C2F33; /* Dark 2 */ 175 | border-radius: 5px; 176 | } 177 | 178 | ::-webkit-scrollbar-thumb:hover { 179 | background: #2C2F33; /* Dark 2 */ 180 | } 181 | 182 | div.sphinxsidebarwrapper { 183 | padding-right: 10px; 184 | box-sizing: border-box; 185 | } 186 | 187 | div.sphinxsidebarwrapper:hover { 188 | padding-right: 0; 189 | overflow-y: scroll; 190 | } 191 | 192 | /* My changes */ 193 | 194 | div.document { 195 | width: 1000px; 196 | min-width: 500px; 197 | max-width: 1200px; 198 | } 199 | 200 | div.body { 201 | width: 800px; 202 | min-width: 500px; 203 | max-width: 1000px; 204 | 205 | padding-top: 10px; 206 | padding-bottom: 10px; 207 | } 208 | 209 | code.xref { 210 | background: transparent; 211 | color: #7289da; 212 | font-weight: normal; 213 | text-decoration: none; 214 | border-bottom: none; 215 | } 216 | 217 | code.xref:hover > span.pre { 218 | background: transparent; 219 | text-decoration: underline; 220 | } 221 | 222 | a.reference:hover, code.xref:hover { 223 | background: transparent; 224 | } 225 | 226 | code.literal:not(.xref) > span.pre { 227 | color: #dcddde; 228 | background-color: #00000020; 229 | } 230 | 231 | li > a.reference.internal { 232 | border-bottom: none; 233 | } 234 | 235 | li > a.reference.internal:hover { 236 | text-decoration: underline; 237 | } 238 | 239 | code.xref.py.docutils.literal.notranslate { 240 | background: transparent; 241 | } -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | Block 5 | ----- 6 | .. autoclass:: anvil.Block 7 | :members: 8 | 9 | .. automethod:: __init__ 10 | 11 | .. autoclass:: anvil.OldBlock 12 | :members: 13 | 14 | .. automethod:: __init__ 15 | 16 | Region 17 | ------ 18 | .. autoclass:: anvil.Region 19 | :members: 20 | 21 | Chunk 22 | ----- 23 | .. autoclass:: anvil.Chunk 24 | :members: 25 | 26 | Empty 27 | ----- 28 | 29 | Region 30 | ~~~~~~ 31 | .. autoclass:: anvil.EmptyRegion 32 | :members: 33 | 34 | Chunk 35 | ~~~~~ 36 | .. autoclass:: anvil.EmptyChunk 37 | :members: 38 | 39 | Section 40 | ~~~~~~~ 41 | .. autoclass:: anvil.EmptySection 42 | :members: 43 | 44 | .. autoclass:: anvil.RawSection 45 | :members: 46 | 47 | Errors 48 | ------ 49 | .. automodule:: anvil.errors 50 | :members: 51 | :undoc-members: 52 | :show-inheritance: 53 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | sys.path.insert(0, os.path.abspath('../')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'anvil-parser' 21 | copyright = '2020, mat' 22 | author = 'mat' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.4.0' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'sphinx.ext.autodoc', 35 | 'sphinx.ext.napoleon', 36 | 'sphinx.ext.intersphinx', 37 | 'sphinx_autodoc_typehints', 38 | 'sphinxcontrib_trio' 39 | ] 40 | 41 | intersphinx_mapping = {'py': ('https://docs.python.org/3', None)} 42 | 43 | napoleon_google_docstring = False 44 | 45 | # Add any paths that contain templates here, relative to this directory. 46 | templates_path = [] 47 | 48 | # List of patterns, relative to source directory, that match files and 49 | # directories to ignore when looking for source files. 50 | # This pattern also affects html_static_path and html_extra_path. 51 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 52 | 53 | 54 | # -- Options for HTML output ------------------------------------------------- 55 | 56 | # The theme to use for HTML and HTML Help pages. See the documentation for 57 | # a list of builtin themes. 58 | # 59 | html_theme = 'alabaster' 60 | 61 | # Add any paths that contain custom static files (such as style sheets) here, 62 | # relative to this directory. They are copied after the builtin static files, 63 | # so a file named "default.css" will overwrite the builtin "default.css". 64 | html_static_path = ['_static'] 65 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | anvil-parser 2 | ============ 3 | 4 | Simple parser for the `Minecraft anvil file format `_ 5 | 6 | .. toctree:: 7 | :maxdepth: 3 8 | 9 | api -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx-autodoc-typehints==1.10.3 2 | sphinxcontrib-trio==1.1.0 3 | -------------------------------------------------------------------------------- /examples/_path.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is an utility script to add the parent folder to the path 3 | so i can do `import anvil` in the examples 4 | Code entirely from: https://stackoverflow.com/a/33532002/9124836 5 | """ 6 | from inspect import getsourcefile 7 | import os.path 8 | import sys 9 | 10 | current_path = os.path.abspath(getsourcefile(lambda:0)) 11 | current_dir = os.path.dirname(current_path) 12 | parent_dir = current_dir[:current_dir.rfind(os.path.sep)] 13 | 14 | sys.path.insert(0, parent_dir) 15 | -------------------------------------------------------------------------------- /examples/basic_world_gen.py: -------------------------------------------------------------------------------- 1 | """ 2 | Basic terrain generation made to test out EmptyRegion and related 3 | Needs the `opensimplex` package to work 4 | 5 | Generated terrain is 128x128 blocks and in the North-West corner 6 | """ 7 | import _path 8 | import anvil 9 | from opensimplex import OpenSimplex 10 | import random 11 | import math 12 | 13 | noise = OpenSimplex() 14 | 15 | region = anvil.EmptyRegion(0, 0) 16 | grass = anvil.Block('minecraft', 'grass_block') 17 | dirt = anvil.Block('minecraft', 'dirt') 18 | glass = anvil.Block('minecraft', 'glass') 19 | oak_log_up = anvil.Block('minecraft', 'oak_log', properties={'axis': 'y'}) 20 | oak_leaves = anvil.Block('minecraft', 'oak_leaves', properties={'persistent': True}) 21 | 22 | grass_plant = anvil.Block('minecraft', 'grass') 23 | poppy = anvil.Block('minecraft', 'poppy') 24 | dandelion = anvil.Block('minecraft', 'dandelion') 25 | tall_grass_l = anvil.Block('minecraft', 'tall_grass', properties={'half': 'lower'}) 26 | tall_grass_u = anvil.Block('minecraft', 'tall_grass', properties={'half': 'upper'}) 27 | 28 | scale = 0.01 29 | plant_scale = 1 30 | xoff = region.x * 512 31 | zoff = region.z * 512 32 | random.seed(0) 33 | for z in range(128): 34 | for x in range(128): 35 | x += xoff 36 | z += zoff 37 | v = noise.noise2d(x*scale, z*scale) 38 | v = (v + 1) / 2 # now its from 0 to 1 39 | v = math.floor(v * 100) 40 | region.set_block(grass, x, v, z) 41 | if v > 0: 42 | region.set_block(dirt, x, v-1, z) 43 | n = noise.noise2d(x*plant_scale+100, z*plant_scale) 44 | if n > 0.4: 45 | # flower 46 | if random.random() > 0.95: 47 | region.set_block(random.choice((poppy, dandelion)), x, v+1, z) 48 | else: 49 | if random.random() > 0.9: 50 | region.set_block(tall_grass_l, x, v+1, z) 51 | region.set_block(tall_grass_u, x, v+2, z) 52 | else: 53 | region.set_block(grass_plant, x, v+1, z) 54 | # Tree 55 | if random.random() > 0.99: 56 | region.fill(oak_leaves, x-2, v+4, z-2, x+2, v+5, z+2, ignore_outside=True) 57 | for y in range(6): 58 | region.set_if_inside(oak_log_up, x, v+y+1, z) 59 | region.set_if_inside(oak_leaves, x, v+7, z) 60 | for y in range(2): 61 | region.set_if_inside(oak_leaves, x+1, v+6+y, z) 62 | region.set_if_inside(oak_leaves, x , v+6+y, z+1) 63 | region.set_if_inside(oak_leaves, x-1, v+6+y, z) 64 | region.set_if_inside(oak_leaves, x , v+6+y, z-1) 65 | 66 | save = region.save('r.0.0.mca') 67 | -------------------------------------------------------------------------------- /examples/cube.py: -------------------------------------------------------------------------------- 1 | import _path 2 | import anvil 3 | from random import choice 4 | 5 | # Create a new region with the `EmptyRegion` class at 0, 0 (in region coords) 6 | region = anvil.EmptyRegion(0, 0) 7 | 8 | # Create `Block` objects that are used to set blocks 9 | stone = anvil.Block('minecraft', 'stone') 10 | dirt = anvil.Block('minecraft', 'dirt') 11 | 12 | # Make a 16x16x16 cube of either stone or dirt blocks 13 | for y in range(16): 14 | for z in range(16): 15 | for x in range(16): 16 | region.set_block(choice((stone, dirt)), x, y, z) 17 | 18 | # Save to a file 19 | region.save('r.0.0.mca') 20 | -------------------------------------------------------------------------------- /examples/top_view.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generates a image of the top view of a chunk 3 | Needs a textures folder with a block folder inside 4 | """ 5 | import sys 6 | if len(sys.argv) == 1: 7 | print('You must give a region file') 8 | exit() 9 | else: 10 | region = sys.argv[1] 11 | chx = int(sys.argv[2]) 12 | chz = int(sys.argv[3]) 13 | import os 14 | from PIL import Image 15 | import _path 16 | import anvil 17 | 18 | chunk = anvil.Chunk.from_region(region, chx, chz) 19 | img = Image.new('RGBA', (16*16,16*16)) 20 | grid = [[None for i in range(16)] for j in range(16)] 21 | for y in reversed(range(256)): 22 | for z in range(16): 23 | for x in range(16): 24 | b = chunk.get_block(x, y, z).id 25 | if b == 'air' or grid[z][x] is not None: 26 | continue 27 | grid[z][x] = b 28 | 29 | texturesf = os.listdir('textures/block') 30 | textures = {} 31 | for z in range(16): 32 | for x in range(16): 33 | b = grid[z][x] 34 | if b is None: 35 | continue 36 | if b not in textures: 37 | if b+'.png' not in texturesf: 38 | print(f'Skipping {b}') 39 | textures[b] = None 40 | continue 41 | textures[b] = Image.open(f'textures/block/{b}.png') 42 | if textures[b] is None: 43 | continue 44 | img.paste(textures[b], box=(x*16, z*16)) 45 | 46 | img.show() 47 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | log_cli = True 3 | log_cli_level = INFO 4 | log_cli_format = %(levelname)8s %(message)s 5 | # blame the nbt library 6 | filterwarnings = 7 | ignore::DeprecationWarning 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | NBT==1.5.0 2 | frozendict==1.2 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open('README.md', 'r') as file: 4 | long_description = file.read() 5 | 6 | setuptools.setup( 7 | name='anvil-parser', 8 | version='0.9.0', 9 | author='mat', 10 | description='A Minecraft anvil file format parser', 11 | long_description=long_description, 12 | long_description_content_type='text/markdown', 13 | url='https://github.com/matcool/anvil-parser', 14 | packages=setuptools.find_packages(), 15 | classifiers=[ 16 | 'Programming Language :: Python :: 3', 17 | 'License :: OSI Approved :: MIT License', 18 | 'Operating System :: OS Independent', 19 | ], 20 | install_requires=[ 21 | 'nbt', 22 | 'frozendict', 23 | ], 24 | include_package_data=True 25 | ) 26 | -------------------------------------------------------------------------------- /tests/context.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) 4 | -------------------------------------------------------------------------------- /tests/test_benchmark.py: -------------------------------------------------------------------------------- 1 | import context as _ 2 | from anvil import EmptyRegion, Block, RawSection 3 | import math 4 | import time 5 | import logging 6 | import array 7 | 8 | LOGGER = logging.getLogger(__name__) 9 | 10 | def test_benchmark(): 11 | region = EmptyRegion(0, 0) 12 | 13 | block = Block('iron_block') 14 | 15 | def func(x: int, z: int) -> int: 16 | return math.sin(x * x + z * z) * 0.5 + 0.5 17 | 18 | w = 256 19 | scale = 0.05 20 | y_scale = 15 21 | 22 | start = time.time() 23 | for x in range(w): 24 | for z in range(w): 25 | u = x - w / 2 26 | v = z - w / 2 27 | y = int(func(u * scale, v * scale) * y_scale) 28 | region.set_block(block, x, y, z) 29 | end = time.time() 30 | 31 | LOGGER.info(f'Generating took: {end - start:.3f}s') 32 | 33 | times = [] 34 | n = 3 35 | for _ in range(n): 36 | start = time.time() 37 | region.save() 38 | end = time.time() 39 | times.append(end - start) 40 | 41 | LOGGER.info(f'Saving (average of {n}) took: {sum(times) / len(times):.3f}s') 42 | 43 | def test_raw_section(): 44 | region = EmptyRegion(0, 0) 45 | 46 | block = Block('iron_block') 47 | air = Block('air') 48 | palette = (air, block) 49 | 50 | def func(x: int, z: int) -> int: 51 | return math.sin(x * x + z * z) * 0.5 + 0.5 52 | 53 | w = 256 54 | chunk_w = w // 16 55 | scale = 0.05 56 | y_scale = 15 57 | 58 | start = time.time() 59 | 60 | # from 0 to y_scale 61 | heights = array.array('B') 62 | for z in range(w): 63 | for x in range(w): 64 | u = z - w / 2 65 | v = x - w / 2 66 | height = int(func(u * scale, v * scale) * y_scale) 67 | heights.append(height) 68 | 69 | for chunk_x in range(chunk_w): 70 | for chunk_z in range(chunk_w): 71 | blocks = array.array('B') 72 | for y in range(16): 73 | for z in range(16): 74 | for x in range(16): 75 | rx = x + chunk_x * 16 76 | rz = z + chunk_z * 16 77 | i = rz * w + rx 78 | height = heights[i] 79 | if y == height: 80 | blocks.append(1) 81 | else: 82 | blocks.append(0) 83 | region.add_section(RawSection(0, blocks, palette), chunk_x, chunk_z) 84 | 85 | end = time.time() 86 | 87 | LOGGER.info(f'Generating took: {end - start:.3f}s') 88 | 89 | times = [] 90 | n = 3 91 | for _ in range(n): 92 | start = time.time() 93 | region.save() 94 | end = time.time() 95 | times.append(end - start) 96 | 97 | LOGGER.info(f'Saving (average of {n}) took: {sum(times) / len(times):.3f}s') 98 | 99 | def test_raw_section_simple(): 100 | region = EmptyRegion(0, 0) 101 | 102 | air = Block('air') 103 | palette = (air, Block('white_concrete'), Block('light_gray_concrete'), Block('gray_concrete')) 104 | 105 | blocks = array.array('B') 106 | for z in range(16): 107 | for x in range(16): 108 | d = x * x + z * z 109 | if d < 25: 110 | blocks.append(1) 111 | elif d < 100: 112 | blocks.append(2) 113 | elif d < 225: 114 | blocks.append(3) 115 | else: 116 | blocks.append(0) 117 | 118 | blocks.extend(0 for _ in range(16 * 16 * 16 - len(blocks))) 119 | 120 | assert len(blocks) == 16 * 16 * 16 121 | 122 | section = RawSection(0, blocks, palette) 123 | region.add_section(section, 0, 0) 124 | 125 | region.save() 126 | -------------------------------------------------------------------------------- /tests/test_mixed_chunk_types.py: -------------------------------------------------------------------------------- 1 | import context as _ 2 | from anvil import Chunk, EmptyChunk, EmptyRegion, Block, Region 3 | import random 4 | 5 | def test_mixed_chunk_types(): 6 | colors = ['red', 'orange', 'yellow', 'green'] 7 | 8 | region = EmptyRegion(0, 0) 9 | 10 | chunk = EmptyChunk(0, 0) 11 | empty_chunk = EmptyChunk(1, 0) 12 | for i, color in enumerate(colors): 13 | chunk.set_block(Block(color), i, 0, 0) 14 | empty_chunk.set_block(Block(color), i, 0, 0) 15 | 16 | chunk = Chunk(chunk.save()) 17 | 18 | region.add_chunk(chunk) 19 | region.add_chunk(empty_chunk) 20 | 21 | region = Region(region.save()) 22 | 23 | for i in range(2): 24 | chunk = region.get_chunk(i, 0) 25 | for i, color in enumerate(colors): 26 | assert chunk.get_block(i, 0, 0).id == color 27 | -------------------------------------------------------------------------------- /tests/test_read_region.py: -------------------------------------------------------------------------------- 1 | import context as _ 2 | from anvil import Region 3 | import io 4 | import secrets 5 | 6 | def test_from_filename(tmp_path): 7 | filename = tmp_path / "region.mca" 8 | contents = secrets.token_bytes() 9 | 10 | with open(filename, 'wb') as f: 11 | f.write(contents) 12 | 13 | region = Region.from_file(str(filename)) 14 | assert region.data == contents 15 | 16 | def test_from_filelike(): 17 | contents = secrets.token_bytes() 18 | filelike = io.BytesIO(contents) 19 | 20 | region = Region.from_file(filelike) 21 | assert region.data == contents 22 | -------------------------------------------------------------------------------- /tests/test_stream_blocks.py: -------------------------------------------------------------------------------- 1 | import context as _ 2 | from anvil import EmptyRegion, Region, Block 3 | 4 | def coord_to_index(x, y, z): 5 | return y * 16 * 16 + z * 16 + x 6 | 7 | def test_4bits(): 8 | region = EmptyRegion(0, 0) 9 | 10 | region.set_block(Block('minecraft', 'stone'), 0, 0, 0) 11 | region.set_block(Block('minecraft', 'dirt'), 1, 0, 0) 12 | region.set_block(Block('minecraft', 'oak_planks'), 2, 0, 0) 13 | region.set_block(Block('minecraft', 'sand'), 10, 7, 5) 14 | region.set_block(Block('minecraft', 'white_wool'), 8, 6, 0) 15 | region.set_block(Block('minecraft', 'bedrock'), 15, 15, 15) 16 | 17 | region = Region(region.save()) 18 | 19 | for i, block in enumerate(region.get_chunk(0, 0).stream_blocks()): 20 | if i == 0: 21 | assert block.id == 'stone' 22 | elif i == 1: 23 | assert block.id == 'dirt' 24 | elif i == 2: 25 | assert block.id == 'oak_planks' 26 | elif i == coord_to_index(10, 7, 5): 27 | assert block.id == 'sand' 28 | elif i == coord_to_index(15, 15, 15): 29 | assert block.id == 'bedrock' 30 | elif i == coord_to_index(8, 6, 0): 31 | assert block.id == 'white_wool' 32 | else: 33 | assert block.id == 'air' 34 | 35 | def test_5bits(): 36 | from random import randint 37 | region = EmptyRegion(0, 0) 38 | 39 | blocks = 'stone,dirt,oak_planks,sand,bedrock,white_wool,red_wool,green_wool,sponge,awesome,these,dont,need,to,exist,foo,bar'.split(',') 40 | positions = [(randint(0, 15), randint(0, 15), randint(0, 15)) for _ in range(len(blocks))] 41 | for block, pos in zip(blocks, positions): 42 | region.set_block(Block('minecraft', block), *pos) 43 | 44 | region = Region(region.save()) 45 | 46 | for i, block in enumerate(region.get_chunk(0, 0).stream_blocks()): 47 | if block.id in blocks: 48 | assert coord_to_index(*positions[blocks.index(block.id)]) == i 49 | else: 50 | assert block.id == 'air' 51 | 52 | def test_index(): 53 | region = EmptyRegion(0, 0) 54 | 55 | region.set_block(Block('minecraft', 'dirt'), 2, 0, 0) 56 | region.set_block(Block('minecraft', 'stone'), 3, 0, 0) 57 | blocks = 'stone,dirt,oak_planks,sand,bedrock'.split(',') 58 | for i, block in enumerate(blocks): 59 | region.set_block(Block('minecraft', block), i % 16, 0, i // 16) 60 | 61 | region = Region(region.save()) 62 | 63 | for i, block in enumerate(region.get_chunk(0, 0).stream_blocks(index=2)): 64 | i += 2 65 | if i < len(blocks): 66 | assert block.id == blocks[i] 67 | else: 68 | assert block.id == 'air' 69 | 70 | def test_index_5bits(): 71 | region = EmptyRegion(0, 0) 72 | 73 | region.set_block(Block('minecraft', 'dirt'), 2, 0, 0) 74 | region.set_block(Block('minecraft', 'stone'), 3, 0, 0) 75 | blocks = 'stone,dirt,oak_planks,sand,bedrock,white_wool,red_wool,green_wool,sponge,awesome,these,dont,need,to,exist,foo,bar'.split(',') 76 | for i, block in enumerate(blocks): 77 | region.set_block(Block('minecraft', block), i % 16, 0, i // 16) 78 | 79 | region = Region(region.save()) 80 | 81 | for i, block in enumerate(region.get_chunk(0, 0).stream_blocks(index=17)): 82 | i += 17 83 | if i < len(blocks): 84 | assert block.id == blocks[i] 85 | else: 86 | assert block.id == 'air' 87 | --------------------------------------------------------------------------------