U
    9º¯a,<  ã                B   @   s  d Z ddlmZ ddlmZ ddlmZ ddlZdddd	d
dddddddddddddddddddddd d!d"d#d$d%d%d&d'd(d)d*d+d,d-d.d/d0d1d2d2d3d4d5d6d7d8d9d9d:d;d<d=d>d?d@dAdBdCdDœAZdEdF„ Z	G dGdH„ dHe
ƒZG dIdJ„ dJeƒZG dKdL„ dLe
ƒZG dMdN„ dNeƒZG dOdP„ dPe
ƒZdS )Qz¦
Handles a single chunk of data (16x16x128 blocks) from a Minecraft save.

For more information about the chunck format:
https://minecraft.gamepedia.com/Chunk_format
é    )ÚBytesIO)Úpack)ÚceilNZairZstoneZgrass_blockZdirtZcobblestoneZ
oak_planksZsaplingZbedrockZflowing_waterZwaterZflowing_lavaZlavaZsandZgravelZgold_oreZiron_oreZcoal_oreZoak_logZ
oak_leavesZspongeZglassZ	lapis_oreZ	sandstoneZcobwebZgrassZ	dead_bushZ
white_woolZ	dandelionZpoppyZbrown_mushroomZred_mushroomZ
stone_slabZ	bookshelfZmossy_cobblestoneZobsidianZtorchZfireZspawnerZ
oak_stairsZchestZdiamond_oreZcrafting_tableZwheatZfarmlandZfurnaceZsignZoak_doorZladderZrailZcobblestone_stairsZoak_pressure_plateZredstone_oreZsnowZiceZcactusZclayZ
sugar_caneZ	oak_fenceZpumpkinZlit_pumpkinZ	iron_barsZ
glass_pane)Ar   é   é   é   é   é   é   é   é   é	   é
   é   é   é   é   é   é   é   é   é   é   é   é   é   é   é    é#   é%   é&   é'   é(   é+   é,   é/   é0   é1   é2   é3   é4   é5   é6   é8   é:   é;   é<   é=   é>   é?   é@   éA   éB   éC   éH   éI   éJ   éN   éO   éQ   éR   éS   éU   éV   é[   ée   éf   c                 C   sD   zt |  }W n2 tk
r>   d| f }td|  ƒ tdƒ Y nX |S )Nz
unknown_%dzwarning: unknown block id %iz+hint: add that block to the 'block_ids' map)Ú	block_idsÚKeyErrorÚprint)ÚbidÚname© rJ   ú%/home/brian/mcmap/coffee/nbt/chunk.pyÚblock_id_to_nameX   s    
rL   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚChunkz&Class for representing a single chunk.c                 C   s@   |d j | _d|kr |d | _n|| _| jd | jd f| _d S )NÚDataVersionZLevelZxPosZzPos)ÚvalueÚversionÚ
chunk_dataÚcoords©ÚselfÚnbtrJ   rJ   rK   Ú__init__f   s
    zChunk.__init__c                 C   s   | j d j| j d jfS )z%Return the coordinates of this chunk.r   r   )rR   rO   ©rT   rJ   rJ   rK   Ú
get_coordso   s    zChunk.get_coordsc                 C   s(   dt | jd ƒ d t | jd ƒ d S )z&Return a representation of this Chunk.zChunk(r   ú,r   ú))ÚstrrR   rW   rJ   rJ   rK   Ú__repr__s   s    zChunk.__repr__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rV   rX   r\   rJ   rJ   rJ   rK   rM   d   s   	rM   c                   @   s,   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	S )
ÚMcRegionChunkc                 C   s,   t  | |¡ t| jd j| jd jƒ| _d S )NÚBlocksZData)rM   rV   Ú
BlockArrayrQ   rO   ÚblocksrS   rJ   rJ   rK   rV   |   s    zMcRegionChunk.__init__c                 C   s   dS )Né   rJ   rW   rJ   rJ   rK   Úget_max_height€   s    zMcRegionChunk.get_max_heightc                 C   s   t | j |||¡ƒ}|S ©N)rL   rd   Ú	get_block)rT   ÚxÚyÚzrI   rJ   rJ   rK   rh   ƒ   s    zMcRegionChunk.get_blockc                 c   sD   t ddƒD ]4}t ddƒD ]$}t ddƒD ]}|  |||¡V  q&qq
d S )Nr   é€   r   )Úrangerh   )rT   rj   rk   ri   rJ   rJ   rK   Ú
iter_block‡   s    zMcRegionChunk.iter_blockN)r]   r^   r_   rV   rf   rh   rn   rJ   rJ   rJ   rK   ra   z   s   ra   c                   @   s<   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )ÚAnvilSectionc                 C   sz   || _ g | _g | _|dks"|dkr.|  |¡ n6|dkrJ|dkrJ|  |¡ n|dkr^|  |¡ ntƒ ‚t| jƒdksvt‚d S )Nr   é?  é_  i¶  i
  é   )	rP   ÚnamesÚindexesÚ_init_arrayÚ_init_index_unpaddedÚ_init_index_paddedÚNotImplementedErrorÚlenÚAssertionError)rT   rU   rP   rJ   rJ   rK   rV   ’   s    zAnvilSection.__init__c              	   C   s|   g }|d j D ]J}z| |¡}W n* tk
rJ   | |¡ t|ƒd }Y nX | j |¡ q|D ]}t|ƒ}| j |¡ q^d S )Nrb   r   )rO   ÚindexÚ
ValueErrorÚappendry   rt   rL   rs   )rT   rU   ZbidsrH   ÚiZbnamerJ   rJ   rK   ru   «   s    
zAnvilSection._init_arrayc                 C   s€  | j dkr:|d D ]}|d j}| j |¡ q|d j}n.|d D ]}|d j}| j |¡ qB|d j}t| jƒd  ¡ }|dk r†d}|t|ƒd	 d
 ksžt‚td|ƒd }d}d	}|d }	tdd
ƒD ]´}
|dkræ|d }|| }	d	}||kr| j	 |	|@ ¡ |	|? }	|| }qÆ|d }|| }|| }|td|ƒd @ |> }|	td|ƒd @ }	| j	 ||	B ¡ || }	|	|? }	d	| }qÆd S )Né,  ÚpaletteÚNameÚblock_statesÚPaletteÚBlockStatesr   r   r4   rr   r   r   )
rP   rO   rs   r}   ry   Ú
bit_lengthrz   Úpowrm   rt   )rT   rU   ÚprI   ÚstatesÚnum_bitsÚmaskr~   Z	bits_leftZ	curr_longÚ_Z	next_longZremaining_bitsrJ   rJ   rK   rv   ½   sF    



 

z!AnvilSection._init_index_unpaddedc                 C   sn  | j dkr4|d d D ]}|d j}| j |¡ qn$|d D ]}|d j}| j |¡ q<| j dkrŠd|d krzdgd }q”|d d j}n
|d	 j}t| jƒd
  ¡ }|dk r²d}d| d
 }d| }d| }|dkrÚ|}t|ƒtd| ƒksòt‚tt|ƒd
 ƒD ]6}	||	 }
t|ƒD ]}| j	 |
|@ ¡ |
|? }
qq|d }
t|ƒD ]}| j	 |
|@ ¡ |
|? }
qJd S )Nr   r‚   r€   r   rƒ   Údatar   é   r„   r   r   r   r4   rr   éÿÿÿÿ)
rP   rO   rs   r}   ry   r…   r   rz   rm   rt   )rT   rU   r‡   rI   rˆ   r‰   rŠ   Zindexes_per_elementZlast_state_elementsr~   Zlongr‹   rJ   rJ   rK   rw   ó   s<    


	

  zAnvilSection._init_index_paddedc                 C   s(   |d |d  | }| j | }| j| S )Nr   r   )rt   rs   )rT   ri   rj   rk   r~   r‡   rJ   rJ   rK   rh   '  s    
zAnvilSection.get_blockc                 c   s*   t ddƒD ]}| j| }| j| V  q
d S )Nr   rr   )rm   rt   rs   )rT   r~   r‡   rJ   rJ   rK   rn   .  s    
zAnvilSection.iter_blockN)	r]   r^   r_   rV   ru   rv   rw   rh   rn   rJ   rJ   rJ   rK   ro      s   64ro   c                   @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )Ú
AnvilChunkc                 C   sº   t  | |¡ z4|d j}|dkr>|dks>|dks>td|f ƒ‚W n tk
rX   d}Y nX |dkrld}d}nd	}d
}i | _|| jkr¶| j| D ]&}|| ¡ krŽt||ƒ| j|d j< qŽd S )NrN   rp   rq   r   zDataVersion %d not implementedr   Úsectionsr‚   ZSectionsr„   ÚY)	rM   rV   rO   rx   rF   r   rQ   Úkeysro   )rT   rU   rP   ZSECTIONSZBLOCKSTATESÚsrJ   rJ   rK   rV   8  s"    


zAnvilChunk.__init__c                 C   s   || j kr| j | S dS )zGet a section from Y index.N)r   )rT   rj   rJ   rJ   rK   Úget_sectionW  s    

zAnvilChunk.get_sectionc                 C   s,   d}| j  ¡ D ]}||kr|}q|d d S )Nr   r   r   )r   r’   )rT   Zymaxrj   rJ   rJ   rK   rf   _  s
     zAnvilChunk.get_max_heightc                 C   s2   t |dƒ\}}|  |¡}|dkr$dS | |||¡S )z Get a block from relative x,y,z.r   N)Údivmodr”   rh   )rT   ri   rj   rk   ZsyZbyZsectionrJ   rJ   rK   rh   f  s
    
zAnvilChunk.get_blockc                 c   s(   | j  ¡ D ]}| ¡ D ]
}|V  qq
d S rg   )r   Úvaluesrn   )rT   r“   ÚbrJ   rJ   rK   rn   p  s    zAnvilChunk.iter_blockN)r]   r^   r_   rV   r”   rf   rh   rn   rJ   rJ   rJ   rK   r   6  s
   
r   c                   @   s^   e Zd ZdZddd„Zdd„ Zddd	„Zdd
d„Zddd„Zddd„Z	ddd„Z
ddd„ZdS )rc   z;Convenience class for dealing with a Block/data byte array.Nc                 C   sT   t |ttjfƒrt|ƒ| _ndgd | _t |ttjfƒrDt|ƒ| _ndgd | _dS )z>Create a new BlockArray, defaulting to no block or data bytes.r   i €  i @  N)Ú
isinstanceÚ	bytearrayÚarrayÚlistÚ
blocksListÚdataList)rT   ZblocksBytesZ	dataBytesrJ   rJ   rK   rV   x  s    zBlockArray.__init__c                 C   s^   d}d}d}i }| j D ]B}|||||f< |d7 }|dkrd}|d7 }|dkrd}|d7 }q|S )z6Return a dictionary with block ids keyed to (x, y, z).r   r   re   r   ©rœ   )rT   Zcur_xZcur_yZcur_zrd   Úblock_idrJ   rJ   rK   Úget_blocks_struct„  s    

zBlockArray.get_blocks_structFc                 C   s:   |r$t | jƒ}ttd|ƒ|  ¡  ƒS t d| j¡ ¡ S dS )z*Return a list of all blocks in this chunk.ú>iÚBN)ry   rœ   r   r   Úget_blocks_byte_arrayrš   Útostring©rT   ÚbufferÚlengthrJ   rJ   rK   r£   –  s    
z BlockArray.get_blocks_byte_arrayc                 C   s:   |r$t | jƒ}ttd|ƒ|  ¡  ƒS t d| j¡ ¡ S dS )z3Return a list of data for all blocks in this chunk.r¡   r¢   N)ry   r   r   r   Úget_data_byte_arrayrš   r¤   r¥   rJ   rJ   rK   r¨   ž  s    
zBlockArray.get_data_byte_arrayc           	   	   C   s¾   ddddddddd	g	}|r0t td
dƒ|  ¡  ƒS g }tdƒD ]d}tdƒD ]V}tdddƒD ]D}||d  |d d  }| j| |ksŠ|dkrX| |d ¡  qHqXqHq<|rª|S t d|¡ ¡ S dS )zHReturn a heightmap, representing the highest solid blocks in this chunk.r   r   r   r   r   r    r   r   r   r¡   r   r   re   rŽ   rl   r   r¢   N)r   r   Úgenerate_heightmaprm   rœ   r}   rš   r¤   )	rT   r¦   Zas_arrayZ
non_solidsÚbytesrk   ri   rj   ÚoffsetrJ   rJ   rK   r©   ¦  s    
zBlockArray.generate_heightmapc           	      C   s²   |r|| _ n¢|rªg }tdƒD ]„}tdƒD ]v}tdƒD ]h}|||f}||d  |d d  }||krr| || ¡ q4| j | r’|s’| | j | ¡ q4| d¡ q4q(q|| _ ndS dS )z©
        Sets all blocks in this chunk, using either a list or dictionary.  
        Blocks not explicitly set can be filled to air by setting fill_air to True.
        r   rl   r   FT)rœ   rm   r}   )	rT   r›   ÚdictZfill_airri   rk   rj   Úcoordr«   rJ   rJ   rK   Ú
set_blocks¹  s"    
zBlockArray.set_blocksr   c           	      C   sŒ   ||d  |d d  }|| j |< |d dkr\|d d }| j| }|d@ |d@  | j|< n,|d }| j| }|d@ |d> d@  | j|< dS )	zBSets the block a x, y, z to the specified id, and optionally data.rl   r   r   r   éð   r   r   N)rœ   r   )	rT   ri   rj   rk   ÚidrŒ   r«   r{   r—   rJ   rJ   rK   Ú	set_blockÖ  s    


zBlockArray.set_blockc                 C   sN   |dkr ||d  |d d  n"|d |d d  |d d d  }| j | S )z&Return the id of the block at x, y, z.Frl   r   r   r   r   rž   )rT   ri   rj   rk   r­   r«   rJ   rJ   rK   rh   æ  s    DzBlockArray.get_block)NN)F)F)FF)NNF)r   )F)r]   r^   r_   r`   rV   r    r£   r¨   r©   r®   r±   rh   rJ   rJ   rJ   rK   rc   v  s   





rc   )r`   Úior   Ústructr   Úmathr   rš   rE   rL   ÚobjectrM   ra   ro   r   rc   rJ   rJ   rJ   rK   Ú<module>   sš   	¿E '@