2013-07-29 07:13:03 -04:00
// BlockArea.h
// Interfaces to the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries
// The object also supports writing the blockdata back into cWorld, even into other coords
// NOTE: All Nibble values (meta, blocklight, skylight) are stored one-nibble-per-byte for faster access / editting!
# pragma once
2014-01-20 12:17:24 -05:00
# include "ForEachChunkProvider.h"
2014-03-11 10:01:17 -04:00
# include "Vector3.h"
2013-07-29 07:13:03 -04:00
2014-02-24 17:17:12 -05:00
// fwd:
class cCuboid ;
2013-07-29 07:13:03 -04:00
// tolua_begin
class cBlockArea
{
// tolua_end
DISALLOW_COPY_AND_ASSIGN ( cBlockArea ) ;
// tolua_begin
public :
2014-02-23 08:08:05 -05:00
/** What data is to be queried (bit-mask) */
2013-07-29 07:13:03 -04:00
enum
{
baTypes = 1 ,
baMetas = 2 ,
baLight = 4 ,
baSkyLight = 8 ,
} ;
2014-03-25 16:59:25 -04:00
/** The per-block strategy to use when merging another block area into this object.
See the Merge function for the description of these */
2013-07-29 07:13:03 -04:00
enum eMergeStrategy
{
msOverwrite ,
msFillAir ,
msImprint ,
msLake ,
2014-03-28 13:03:37 -04:00
msSpongePrint ,
2014-03-31 13:47:18 -04:00
msDifference ,
2014-04-01 14:50:10 -04:00
msMask ,
2013-07-29 07:13:03 -04:00
} ;
cBlockArea ( void ) ;
~ cBlockArea ( ) ;
2014-02-23 08:08:05 -05:00
/** Clears the data stored to reclaim memory */
2013-07-29 07:13:03 -04:00
void Clear ( void ) ;
2014-03-25 17:05:45 -04:00
/** Creates a new area of the specified size and contents.
Origin is set to all zeroes .
2013-07-29 07:13:03 -04:00
BlockTypes are set to air , block metas to zero , blocklights to zero and skylights to full light .
*/
void Create ( int a_SizeX , int a_SizeY , int a_SizeZ , int a_DataTypes = baTypes | baMetas ) ;
2014-03-25 17:05:45 -04:00
/** Creates a new area of the specified size and contents.
Origin is set to all zeroes .
BlockTypes are set to air , block metas to zero , blocklights to zero and skylights to full light .
*/
void Create ( const Vector3i & a_Size , int a_DataTypes = baTypes | baMetas ) ;
2014-02-23 08:08:05 -05:00
/** Resets the origin. No other changes are made, contents are untouched. */
2013-07-29 07:13:03 -04:00
void SetOrigin ( int a_OriginX , int a_OriginY , int a_OriginZ ) ;
2014-02-24 17:17:12 -05:00
/** Resets the origin. No other changes are made, contents are untouched. */
void SetOrigin ( const Vector3i & a_Origin ) ;
2014-02-23 08:08:05 -05:00
/** Reads an area of blocks specified. Returns true if successful. All coords are inclusive. */
2014-01-20 12:17:24 -05:00
bool Read ( cForEachChunkProvider * a_ForEachChunkProvider , int a_MinBlockX , int a_MaxBlockX , int a_MinBlockY , int a_MaxBlockY , int a_MinBlockZ , int a_MaxBlockZ , int a_DataTypes = baTypes | baMetas ) ;
2013-07-29 07:13:03 -04:00
2014-02-24 17:17:12 -05:00
/** Reads an area of blocks specified. Returns true if successful. The bounds are included in the read area. */
bool Read ( cForEachChunkProvider * a_ForEachChunkProvider , const cCuboid & a_Bounds , int a_DataTypes = baTypes | baMetas ) ;
/** Reads an area of blocks specified. Returns true if successful. The bounds are included in the read area. */
bool Read ( cForEachChunkProvider * a_ForEachChunkProvider , const Vector3i & a_Point1 , const Vector3i & a_Point2 , int a_DataTypes = baTypes | baMetas ) ;
2013-07-29 07:13:03 -04:00
// TODO: Write() is not too good an interface: if it fails, there's no way to repeat only for the parts that didn't write
// A better way may be to return a list of cBlockAreas for each part that didn't succeed writing, so that the caller may try again
2014-02-23 08:08:05 -05:00
/** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all */
2014-01-20 12:17:24 -05:00
bool Write ( cForEachChunkProvider * a_ForEachChunkProvider , int a_MinBlockX , int a_MinBlockY , int a_MinBlockZ , int a_DataTypes = baTypes | baMetas ) ;
2013-07-29 07:13:03 -04:00
2014-02-24 17:17:12 -05:00
/** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all */
bool Write ( cForEachChunkProvider * a_ForEachChunkProvider , const Vector3i & a_MinCoords , int a_DataTypes = baTypes | baMetas ) ;
2014-02-23 08:08:05 -05:00
/** Copies this object's contents into the specified BlockArea. */
2013-07-29 07:13:03 -04:00
void CopyTo ( cBlockArea & a_Into ) const ;
2014-02-23 08:08:05 -05:00
/** Copies the contents from the specified BlockArea into this object. */
2013-07-29 07:13:03 -04:00
void CopyFrom ( const cBlockArea & a_From ) ;
2014-02-23 08:08:05 -05:00
/** For testing purposes only, dumps the area into a file. */
2013-07-29 07:13:03 -04:00
void DumpToRawFile ( const AString & a_FileName ) ;
2014-02-23 08:08:05 -05:00
/** Crops the internal contents by the specified amount of blocks from each border. */
2013-07-29 07:13:03 -04:00
void Crop ( int a_AddMinX , int a_SubMaxX , int a_AddMinY , int a_SubMaxY , int a_AddMinZ , int a_SubMaxZ ) ;
2014-02-23 08:08:05 -05:00
/** Expands the internal contents by the specified amount of blocks from each border */
2013-07-29 07:13:03 -04:00
void Expand ( int a_SubMinX , int a_AddMaxX , int a_SubMinY , int a_AddMaxY , int a_SubMinZ , int a_AddMaxZ ) ;
/** Merges another block area into this one, using the specified block combinating strategy
This function combines another BlockArea into the current object .
The strategy parameter specifies how individual blocks are combined together , using the table below .
| area block | result |
| this | Src | msOverwrite | msFillAir | msImprint |
+ - - - - - - + - - - - - + - - - - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
| air | air | air | air | air |
| A | air | air | A | A |
| air | B | B | B | B |
| A | B | B | A | B |
So to sum up :
- msOverwrite completely overwrites all blocks with the Src ' s blocks
- msFillAir overwrites only those blocks that were air
- msImprint overwrites with only those blocks that are non - air
2014-03-28 13:03:37 -04:00
Special strategies ( evaluate top - down , first match wins ) :
msLake :
2013-07-29 07:13:03 -04:00
| area block | |
| this | Src | result |
+ - - - - - - - - - - + - - - - - - - - + - - - - - - - - +
| A | sponge | A | Sponge is the NOP block
| * | air | air | Air always gets hollowed out , even under the oceans
| water | * | water | Water is never overwritten
| lava | * | lava | Lava is never overwritten
| * | water | water | Water always overwrites anything
| * | lava | lava | Lava always overwrites anything
| dirt | stone | stone | Stone overwrites dirt
| grass | stone | stone | . . . and grass
| mycelium | stone | stone | . . . and mycelium
| A | stone | A | . . . but nothing else
| A | * | A | Everything else is left as it is
2014-03-28 13:03:37 -04:00
msSpongePrint :
Used for most generators , it allows carving out air pockets , too , and uses the Sponge as the NOP block
| area block | |
| this | Src | result |
+ - - - - - - - - - - + - - - - - - - - + - - - - - - - - +
| A | sponge | A | Sponge is the NOP block
| * | B | B | Everything else overwrites anything
2014-04-01 14:50:10 -04:00
msMask :
Combines two areas , the blocks that are the same are kept , differing ones are reset to air
| area block | |
| this | Src | result |
+ - - - - - - + - - - - - - - + - - - - - - - - +
| A | A | A | Same blocks are kept
| A | non - A | air | Everything else is replaced with air
2013-07-29 07:13:03 -04:00
*/
void Merge ( const cBlockArea & a_Src , int a_RelX , int a_RelY , int a_RelZ , eMergeStrategy a_Strategy ) ;
2014-02-24 17:17:12 -05:00
/** Merges another block area into this one, using the specified block combinating strategy.
See Merge ( ) above for details . */
void Merge ( const cBlockArea & a_Src , const Vector3i & a_RelMinCoords , eMergeStrategy a_Strategy ) ;
2014-02-23 08:08:05 -05:00
/** Fills the entire block area with the specified data */
2013-07-29 07:13:03 -04:00
void Fill ( int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta = 0 , NIBBLETYPE a_BlockLight = 0 , NIBBLETYPE a_BlockSkyLight = 0x0f ) ;
2014-02-23 08:08:05 -05:00
/** Fills a cuboid inside the block area with the specified data */
2013-07-29 07:13:03 -04:00
void FillRelCuboid ( int a_MinRelX , int a_MaxRelX , int a_MinRelY , int a_MaxRelY , int a_MinRelZ , int a_MaxRelZ ,
int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta = 0 ,
NIBBLETYPE a_BlockLight = 0 , NIBBLETYPE a_BlockSkyLight = 0x0f
) ;
2014-02-24 17:17:12 -05:00
/** Fills a cuboid inside the block area with the specified data. a_Cuboid must be sorted. */
void FillRelCuboid ( const cCuboid & a_RelCuboid ,
int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta = 0 ,
NIBBLETYPE a_BlockLight = 0 , NIBBLETYPE a_BlockSkyLight = 0x0f
) ;
2014-02-23 08:08:05 -05:00
/** Draws a line from between two points with the specified data */
2013-07-29 07:13:03 -04:00
void RelLine ( int a_RelX1 , int a_RelY1 , int a_RelZ1 , int a_RelX2 , int a_RelY2 , int a_RelZ2 ,
int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta = 0 ,
NIBBLETYPE a_BlockLight = 0 , NIBBLETYPE a_BlockSkyLight = 0x0f
) ;
2014-02-24 17:17:12 -05:00
/** Draws a line from between two points with the specified data */
void RelLine ( const Vector3i & a_Point1 , const Vector3i & a_Point2 ,
int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta = 0 ,
NIBBLETYPE a_BlockLight = 0 , NIBBLETYPE a_BlockSkyLight = 0x0f
) ;
2014-02-23 08:08:05 -05:00
/** Rotates the entire area counter-clockwise around the Y axis */
2013-07-29 07:13:03 -04:00
void RotateCCW ( void ) ;
2014-02-23 08:08:05 -05:00
/** Rotates the entire area clockwise around the Y axis */
2013-07-29 07:13:03 -04:00
void RotateCW ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the XY plane */
2013-07-29 07:13:03 -04:00
void MirrorXY ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the XZ plane */
2013-07-29 07:13:03 -04:00
void MirrorXZ ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the YZ plane */
2013-07-29 07:13:03 -04:00
void MirrorYZ ( void ) ;
2014-02-23 08:08:05 -05:00
/** Rotates the entire area counter-clockwise around the Y axis, doesn't use blockhandlers for block meta */
2013-07-29 07:13:03 -04:00
void RotateCCWNoMeta ( void ) ;
2014-02-23 08:08:05 -05:00
/** Rotates the entire area clockwise around the Y axis, doesn't use blockhandlers for block meta */
2013-07-29 07:13:03 -04:00
void RotateCWNoMeta ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the XY plane, doesn't use blockhandlers for block meta */
2013-07-29 07:13:03 -04:00
void MirrorXYNoMeta ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the XZ plane, doesn't use blockhandlers for block meta */
2013-07-29 07:13:03 -04:00
void MirrorXZNoMeta ( void ) ;
2014-02-23 08:08:05 -05:00
/** Mirrors the entire area around the YZ plane, doesn't use blockhandlers for block meta */
2013-07-29 07:13:03 -04:00
void MirrorYZNoMeta ( void ) ;
// Setters:
void SetRelBlockType ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType ) ;
void SetBlockType ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_BlockType ) ;
void SetRelBlockMeta ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_BlockMeta ) ;
void SetBlockMeta ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_BlockMeta ) ;
void SetRelBlockLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_BlockLight ) ;
void SetBlockLight ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_BlockLight ) ;
void SetRelBlockSkyLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_BlockSkyLight ) ;
void SetBlockSkyLight ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_BlockSkyLight ) ;
2014-03-12 02:46:14 -04:00
void SetWEOffset ( int a_OffsetX , int a_OffsetY , int a_OffsetZ ) ;
void SetWEOffset ( const Vector3i & a_Offset ) ;
2013-07-29 07:13:03 -04:00
// Getters:
BLOCKTYPE GetRelBlockType ( int a_RelX , int a_RelY , int a_RelZ ) const ;
BLOCKTYPE GetBlockType ( int a_BlockX , int a_BlockY , int a_BlockZ ) const ;
NIBBLETYPE GetRelBlockMeta ( int a_RelX , int a_RelY , int a_RelZ ) const ;
NIBBLETYPE GetBlockMeta ( int a_BlockX , int a_BlockY , int a_BlockZ ) const ;
NIBBLETYPE GetRelBlockLight ( int a_RelX , int a_RelY , int a_RelZ ) const ;
NIBBLETYPE GetBlockLight ( int a_BlockX , int a_BlockY , int a_BlockZ ) const ;
NIBBLETYPE GetRelBlockSkyLight ( int a_RelX , int a_RelY , int a_RelZ ) const ;
NIBBLETYPE GetBlockSkyLight ( int a_BlockX , int a_BlockY , int a_BlockZ ) const ;
2014-03-12 02:46:14 -04:00
const Vector3i & GetWEOffset ( void ) const { return m_WEOffset ; }
2013-07-29 07:13:03 -04:00
void SetBlockTypeMeta ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
void SetRelBlockTypeMeta ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
2014-02-20 04:48:29 -05:00
// tolua_end
// These need manual exporting, tolua generates the binding as requiring 2 extra input params
2013-07-29 07:13:03 -04:00
void GetBlockTypeMeta ( int a_BlockX , int a_BlockY , int a_BlockZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
void GetRelBlockTypeMeta ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
2014-03-25 16:59:25 -04:00
// GetSize() is already exported manually to return 3 numbers, can't auto-export
const Vector3i & GetSize ( void ) const { return m_Size ; }
// GetOrigin() is already exported manually to return 3 numbers, can't auto-export
const Vector3i & GetOrigin ( void ) const { return m_Origin ; }
2014-02-20 04:48:29 -05:00
// tolua_begin
2014-03-25 16:59:25 -04:00
int GetSizeX ( void ) const { return m_Size . x ; }
int GetSizeY ( void ) const { return m_Size . y ; }
int GetSizeZ ( void ) const { return m_Size . z ; }
2013-07-29 07:13:03 -04:00
2014-02-23 08:08:05 -05:00
/** Returns the volume of the area, as number of blocks */
2014-03-25 16:59:25 -04:00
int GetVolume ( void ) const { return m_Size . x * m_Size . y * m_Size . z ; }
2014-02-23 08:08:05 -05:00
2014-03-25 16:59:25 -04:00
int GetOriginX ( void ) const { return m_Origin . x ; }
int GetOriginY ( void ) const { return m_Origin . y ; }
int GetOriginZ ( void ) const { return m_Origin . z ; }
2013-07-29 07:13:03 -04:00
2014-02-23 08:08:05 -05:00
/** Returns the datatypes that are stored in the object (bitmask of baXXX values) */
2013-07-29 07:13:03 -04:00
int GetDataTypes ( void ) const ;
bool HasBlockTypes ( void ) const { return ( m_BlockTypes ! = NULL ) ; }
bool HasBlockMetas ( void ) const { return ( m_BlockMetas ! = NULL ) ; }
bool HasBlockLights ( void ) const { return ( m_BlockLight ! = NULL ) ; }
bool HasBlockSkyLights ( void ) const { return ( m_BlockSkyLight ! = NULL ) ; }
// tolua_end
// Clients can use these for faster access to all blocktypes. Be careful though!
2014-02-23 08:08:05 -05:00
/** Returns the internal pointer to the block types */
2013-07-29 07:13:03 -04:00
BLOCKTYPE * GetBlockTypes ( void ) const { return m_BlockTypes ; }
NIBBLETYPE * GetBlockMetas ( void ) const { return m_BlockMetas ; } // NOTE: one byte per block!
NIBBLETYPE * GetBlockLight ( void ) const { return m_BlockLight ; } // NOTE: one byte per block!
NIBBLETYPE * GetBlockSkyLight ( void ) const { return m_BlockSkyLight ; } // NOTE: one byte per block!
2014-04-28 13:31:07 -04:00
size_t GetBlockCount ( void ) const { return m_Size . x * m_Size . y * m_Size . z ; }
2013-07-29 07:13:03 -04:00
int MakeIndex ( int a_RelX , int a_RelY , int a_RelZ ) const ;
protected :
friend class cChunkDesc ;
2014-01-20 12:59:12 -05:00
friend class cSchematicFileSerializer ;
2013-07-29 07:13:03 -04:00
class cChunkReader :
public cChunkDataCallback
{
public :
cChunkReader ( cBlockArea & a_Area ) ;
protected :
cBlockArea & m_Area ;
2014-03-25 16:59:25 -04:00
Vector3i m_Origin ;
2013-07-29 07:13:03 -04:00
int m_CurrentChunkX ;
int m_CurrentChunkZ ;
void CopyNibbles ( NIBBLETYPE * a_AreaDst , const NIBBLETYPE * a_ChunkSrc ) ;
// cChunkDataCallback overrides:
virtual bool Coords ( int a_ChunkX , int a_ChunkZ ) override ;
virtual void BlockTypes ( const BLOCKTYPE * a_BlockTypes ) override ;
virtual void BlockMeta ( const NIBBLETYPE * a_BlockMetas ) override ;
virtual void BlockLight ( const NIBBLETYPE * a_BlockLight ) override ;
virtual void BlockSkyLight ( const NIBBLETYPE * a_BlockSkyLight ) override ;
} ;
typedef NIBBLETYPE * NIBBLEARRAY ;
2014-03-25 16:59:25 -04:00
Vector3i m_Origin ;
Vector3i m_Size ;
2013-07-29 07:13:03 -04:00
2014-03-12 02:46:14 -04:00
/** An extra data value sometimes stored in the .schematic file. Used mainly by the WorldEdit plugin.
cBlockArea doesn ' t use this value in any way . */
2014-03-11 13:23:21 -04:00
Vector3i m_WEOffset ;
2014-03-10 12:07:46 -04:00
2013-07-29 07:13:03 -04:00
BLOCKTYPE * m_BlockTypes ;
NIBBLETYPE * m_BlockMetas ; // Each meta is stored as a separate byte for faster access
NIBBLETYPE * m_BlockLight ; // Each light value is stored as a separate byte for faster access
NIBBLETYPE * m_BlockSkyLight ; // Each light value is stored as a separate byte for faster access
2014-02-23 08:08:05 -05:00
/** Clears the data stored and prepares a fresh new block area with the specified dimensions */
2013-07-29 07:13:03 -04:00
bool SetSize ( int a_SizeX , int a_SizeY , int a_SizeZ , int a_DataTypes ) ;
// Basic Setters:
void SetRelNibble ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_Value , NIBBLETYPE * a_Array ) ;
void SetNibble ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE a_Value , NIBBLETYPE * a_Array ) ;
// Basic Getters:
NIBBLETYPE GetRelNibble ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE * a_Array ) const ;
NIBBLETYPE GetNibble ( int a_BlockX , int a_BlockY , int a_BlockZ , NIBBLETYPE * a_Array ) const ;
// Crop helpers:
void CropBlockTypes ( int a_AddMinX , int a_SubMaxX , int a_AddMinY , int a_SubMaxY , int a_AddMinZ , int a_SubMaxZ ) ;
void CropNibbles ( NIBBLEARRAY & a_Array , int a_AddMinX , int a_SubMaxX , int a_AddMinY , int a_SubMaxY , int a_AddMinZ , int a_SubMaxZ ) ;
// Expand helpers:
void ExpandBlockTypes ( int a_SubMinX , int a_AddMaxX , int a_SubMinY , int a_AddMaxY , int a_SubMinZ , int a_AddMaxZ ) ;
void ExpandNibbles ( NIBBLEARRAY & a_Array , int a_SubMinX , int a_AddMaxX , int a_SubMinY , int a_AddMaxY , int a_SubMinZ , int a_AddMaxZ ) ;
2014-02-23 08:08:05 -05:00
/** Sets the specified datatypes at the specified location. */
2013-07-29 07:13:03 -04:00
void RelSetData (
int a_RelX , int a_RelY , int a_RelZ ,
int a_DataTypes , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ,
NIBBLETYPE a_BlockLight , NIBBLETYPE a_BlockSkyLight
) ;
2014-04-28 13:31:07 -04:00
template < bool MetasValid >
void MergeByStrategy ( const cBlockArea & a_Src , int a_RelX , int a_RelY , int a_RelZ , eMergeStrategy a_Strategy , const NIBBLETYPE * SrcMetas , NIBBLETYPE * DstMetas ) ;
2013-07-29 07:13:03 -04:00
// tolua_begin
} ;
// tolua_end