Skip to content

Instantly share code, notes, and snippets.

@gitcrtn
Created November 6, 2020 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gitcrtn/3b0544c698bdb35d9bdd8eddf406027f to your computer and use it in GitHub Desktop.
Save gitcrtn/3b0544c698bdb35d9bdd8eddf406027f to your computer and use it in GitHub Desktop.
#!/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