@@ -30,6 +30,69 @@ def mapshort2id(data):
3030 return data >> 4 , data & 0x0F
3131
3232
33+ class BlockEntityData (object ):
34+ def __init__ (self , nbt ):
35+ self .nbt = nbt
36+
37+ def __getattr__ (self , key ):
38+ return getattr (self .nbt , key )
39+
40+ def __str__ (self ):
41+ return str (self .nbt )
42+
43+ def __repr__ (self ):
44+ return repr (self .nbt )
45+
46+
47+ class SpawnerData (BlockEntityData ):
48+ pass # TODO get entity class from mcdata?
49+
50+
51+ class CommandBlockData (BlockEntityData ):
52+ pass
53+
54+
55+ class BeaconData (BlockEntityData ):
56+ pass
57+
58+
59+ class HeadData (BlockEntityData ):
60+ pass
61+
62+
63+ class FlowerPotData (BlockEntityData ):
64+ def __init__ (self , nbt ):
65+ super (FlowerPotData , self ).__init__ (nbt )
66+ self .block = nbt ['Item' ].value , nbt ['Data' ].value
67+ # TODO get block instance from mcdata?
68+
69+
70+ class BannerData (BlockEntityData ):
71+ pass
72+
73+
74+ class SignData (BlockEntityData ):
75+ def __init__ (self , line_data ):
76+ super (SignData , self ).__init__ (self )
77+ self .lines = [line_data ['line_%i' % (i + 1 )] for i in range (4 )]
78+
79+ def __str__ (self ):
80+ return 'Sign%s' % str (self .lines )
81+
82+ def __repr__ (self ):
83+ return '<SignData %s>' % repr (self .lines )
84+
85+
86+ block_entities = {
87+ 1 : SpawnerData ,
88+ 2 : CommandBlockData ,
89+ 3 : BeaconData ,
90+ 4 : HeadData ,
91+ 5 : FlowerPotData ,
92+ 6 : BannerData ,
93+ }
94+
95+
3396class ChunkData (object ):
3497 length = 16 * 16 * 16
3598 ty = 'B'
@@ -132,6 +195,9 @@ def __init__(self, dimension):
132195 self .dimension = dimension
133196 self .columns = {} # chunk columns are address by a tuple (x, z)
134197
198+ # BlockEntityData subclass instances, adressed by (x,y,z)
199+ self .block_entities = {}
200+
135201 def unpack_bulk (self , data ):
136202 bbuff = BoundBuffer (data ['data' ])
137203 skylight = data ['sky_light' ]
@@ -192,6 +258,34 @@ def set_block(self, pos_or_x, y=None, z=None,
192258 data = (block_id << 4 ) | (meta & 0x0F )
193259 chunk .block_data .set (rx , ry , rz , data )
194260
261+ def get_block_entity_data (self , pos_or_x , y = None , z = None ):
262+ """
263+ Access block entity data.
264+
265+ Returns:
266+ BlockEntityData subclass instance or
267+ None if no block entity data is stored for that location.
268+ """
269+ if None not in (y , z ): # x y z supplied
270+ pos_or_x = pos_or_x , y , z
271+ coord_tuple = tuple (floor (c ) for c in pos_or_x )
272+ return self .block_entities .get (coord_tuple , None )
273+
274+ def set_block_entity_data (self , pos_or_x , y = None , z = None , data = None ):
275+ """
276+ Update block entity data.
277+
278+ Returns:
279+ Old data if block entity data was already stored for that location,
280+ None otherwise.
281+ """
282+ if None not in (y , z ): # x y z supplied
283+ pos_or_x = pos_or_x , y , z
284+ coord_tuple = tuple (floor (c ) for c in pos_or_x )
285+ old_data = self .block_entities .get (coord_tuple , None )
286+ self .block_entities [coord_tuple ] = data
287+ return old_data
288+
195289 def get_light (self , pos_or_x , y = None , z = None ):
196290 if None in (y , z ): # pos supplied
197291 pos_or_x , y , z = pos_or_x
0 commit comments