Created
November 6, 2020 21:32
-
-
Save gitcrtn/3b0544c698bdb35d9bdd8eddf406027f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
""" | |
Show chest item IDs for /give command | |
Requires: | |
Python 2.7 | |
mceditlib | |
Usage: | |
1. Set SAVE_DIR to your saves directory path. | |
2. Put target item into chest at overworld. | |
3. Run this script as below. | |
python show_chest_items.py <map-name> <chest-position> | |
Example: | |
python show_chest_items.py "New World" 10,5,-4 | |
""" | |
import os | |
import sys | |
import traceback | |
from collections import namedtuple | |
from mceditlib import nbt | |
from mceditlib.findadapter import findAdapter | |
Pos = namedtuple('Pos', ['x', 'y', 'z']) | |
SAVE_DIR = '/path/to/saves' | |
LEVEL_DAT_TEMPLATE = '{savedir}/{game}/level.dat' | |
class BlockNotFoundError(Exception): | |
"""BlockNotFoundError""" | |
pass | |
class ItemsNotFoundError(Exception): | |
"""ItemsNotFoundError""" | |
pass | |
class ChestPositionInvalidError(Exception): | |
"""ChestPositionInvalidError""" | |
pass | |
class BlockDisplay(object): | |
def __init__(self, map_name): | |
""" | |
Constructor | |
Arguments: | |
map_name (str): map name in saves directory | |
""" | |
self._map_name = map_name | |
# Overworld | |
self._dim_name = '' | |
self._chunk_pos = Pos(0, 0, 0) | |
self._block_pos = Pos(0, 0, 0) | |
self._adapter = None | |
self._chunk = None | |
self._tile_entity = None | |
def setup(self): | |
""" | |
Setup | |
""" | |
self._adapter = self.get_adapter() | |
self._chunk = self.get_chunk() | |
self._tile_entity = self.get_tile_entity() | |
def clean(self): | |
""" | |
Clean internal objects | |
""" | |
self._adapter = None | |
self._chunk = None | |
self._tile_entity = None | |
def set_chunk_pos(self, x, z): | |
""" | |
Set chunk position | |
Arguments: | |
x (int): x position | |
z (int): z position | |
Notes: | |
Call this method before execute setup(). | |
""" | |
self._chunk_pos = Pos(x, 0, z) | |
def set_block_pos(self, x, y, z): | |
""" | |
Set block position | |
Arguments: | |
x (int): x position | |
y (int): y position | |
z (int): z position | |
Notes: | |
Call this method before execute setup(). | |
""" | |
self._block_pos = Pos(x, y, z) | |
self.set_chunk_pos(x >> 4, z >> 4) | |
def set_dim(self, name): | |
""" | |
Set dimension name | |
Arguments: | |
name (str): dimension name | |
Notes: | |
default demension is '' (Overworld). | |
""" | |
self._dim_name = name | |
def get_level_dat(self): | |
""" | |
Get file path of level.dat | |
Returns: | |
str: file path of level.dat | |
""" | |
return LEVEL_DAT_TEMPLATE.format(savedir=SAVE_DIR, game=self._map_name) | |
def get_adapter(self): | |
""" | |
Get adapter object by level.dat | |
Returns: | |
AnvilWorldAdapter: adapter object of mceditlib | |
Notes: | |
Call this method after execute setup(). | |
""" | |
return findAdapter(self.get_level_dat(), readonly=True, resume=None) | |
def get_chunk(self): | |
""" | |
Get chunk object from level.dat | |
Returns: | |
AnvilChunkData: chunk object of mceditlib | |
Notes: | |
Call this method after execute setup(). | |
""" | |
return self._adapter.readChunk(self._chunk_pos.x, self._chunk_pos.z, self._dim_name) | |
def get_tile_entity(self): | |
""" | |
Get block object from level.dat | |
Returns: | |
TAG_Compound: block object of mceditlib | |
Notes: | |
Call this method after execute setup(). | |
""" | |
tx = nbt.TAG_Int(self._block_pos.x) | |
ty = nbt.TAG_Int(self._block_pos.y) | |
tz = nbt.TAG_Int(self._block_pos.z) | |
for ref in self._chunk.TileEntities: | |
if ref['x'] == tx and ref['y'] == ty and ref['z'] == tz: | |
return ref | |
def print_info(self): | |
""" | |
Print block info | |
""" | |
try: | |
if not self._tile_entity: | |
raise BlockNotFoundError | |
for key in self._tile_entity.keys(): | |
print('%s: %s' % (key, self._tile_entity[key])) | |
except BlockNotFoundError: | |
print('Block not found.') | |
def print_items_info(self): | |
""" | |
Print items info | |
""" | |
try: | |
if not self._tile_entity: | |
raise ItemsNotFoundError | |
if 'Items' not in self._tile_entity.keys(): | |
raise ItemsNotFoundError | |
if not len(self._tile_entity['Items']): | |
raise ItemsNotFoundError | |
for item in self._tile_entity['Items']: | |
print('%s %s' % (item['id'].value, item['Damage'].value)) | |
except ItemsNotFoundError: | |
print('None') | |
def to_pos(value): | |
""" | |
Get Pos object from string position value | |
Arguments: | |
value (str): position value | |
Returns: | |
Pos: position object | |
""" | |
try: | |
return Pos(*[int(num) for num in value.split(',')]) | |
except Exception: | |
raise ChestPositionInvalidError | |
def main(): | |
map_name = sys.argv[1] | |
chest_pos = to_pos(sys.argv[2]) | |
print('map: %s' % map_name) | |
print('chest position: %d, %d, %d' % chest_pos) | |
print('') | |
display = BlockDisplay(map_name) | |
display.set_block_pos(chest_pos.x, chest_pos.y, chest_pos.z) | |
display.setup() | |
print('items:') | |
display.print_items_info() | |
display.clean() | |
if __name__ == '__main__': | |
try: | |
if len(sys.argv) != 3: | |
raise RuntimeError('Set map name and chest position as argument') | |
main() | |
except Exception: | |
traceback.print_exc() | |
# EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment