2012-06-14 09:06:06 -04:00
# pragma once
2013-08-19 05:39:13 -04:00
# include "Entities/Entity.h"
2012-06-14 09:06:06 -04:00
# include "ChunkDef.h"
2014-05-21 14:58:48 -04:00
# include "ChunkData.h"
2012-06-14 09:06:06 -04:00
2013-03-01 14:35:29 -05:00
# include "Simulator/FireSimulator.h"
2013-03-02 14:57:09 -05:00
# include "Simulator/SandSimulator.h"
2014-02-07 16:59:08 -05:00
# include "Simulator/IncrementalRedstoneSimulator.h"
2013-03-01 14:35:29 -05:00
2014-09-11 12:48:21 -04:00
# include "Blocks/GetHandlerCompileTimeTemplate.h"
2014-09-26 13:13:19 -04:00
# include "ChunkMap.h"
2012-06-14 09:06:06 -04:00
namespace Json
{
class Value ;
} ;
class cWorld ;
class cClientHandle ;
class cServer ;
class MTRand ;
class cPlayer ;
class cChunkMap ;
2014-07-30 16:19:51 -04:00
class cBeaconEntity ;
2014-09-26 13:13:19 -04:00
class cBoundingBox ;
2012-06-17 15:58:39 -04:00
class cChestEntity ;
2014-10-03 16:32:41 -04:00
class cChunkDataCallback ;
2014-09-26 13:13:19 -04:00
class cCommandBlockEntity ;
2012-12-19 16:19:36 -05:00
class cDispenserEntity ;
2012-06-17 15:58:39 -04:00
class cFurnaceEntity ;
2013-12-14 11:52:22 -05:00
class cNoteEntity ;
2014-02-19 08:45:09 -05:00
class cMobHeadEntity ;
2014-03-06 19:30:34 -05:00
class cFlowerPotEntity ;
2012-07-02 15:22:05 -04:00
class cBlockArea ;
2012-08-19 17:14:45 -04:00
class cPawn ;
2012-08-24 05:49:00 -04:00
class cPickup ;
2012-08-26 17:01:07 -04:00
class cChunkDataSerializer ;
2012-10-06 12:58:31 -04:00
class cBlockArea ;
2013-03-02 10:44:31 -05:00
class cFluidSimulatorData ;
2013-09-07 16:19:56 -04:00
class cMobCensus ;
2013-09-07 18:11:38 -04:00
class cMobSpawner ;
2014-08-05 16:48:23 -04:00
class cRedstonePoweredEntity ;
2014-09-26 13:13:19 -04:00
class cSetChunkData ;
2012-06-14 09:06:06 -04:00
2014-01-18 08:16:47 -05:00
typedef std : : list < cClientHandle * > cClientHandleList ;
typedef cItemCallback < cEntity > cEntityCallback ;
2014-07-30 16:19:51 -04:00
typedef cItemCallback < cBeaconEntity > cBeaconCallback ;
2014-01-18 08:16:47 -05:00
typedef cItemCallback < cChestEntity > cChestCallback ;
typedef cItemCallback < cDispenserEntity > cDispenserCallback ;
typedef cItemCallback < cFurnaceEntity > cFurnaceCallback ;
typedef cItemCallback < cNoteEntity > cNoteBlockCallback ;
typedef cItemCallback < cCommandBlockEntity > cCommandBlockCallback ;
2014-03-07 05:44:16 -05:00
typedef cItemCallback < cMobHeadEntity > cMobHeadCallback ;
2014-03-06 19:30:34 -05:00
typedef cItemCallback < cFlowerPotEntity > cFlowerPotCallback ;
2014-08-05 16:48:23 -04:00
typedef cItemCallback < cRedstonePoweredEntity > cRedstonePoweredCallback ;
2012-06-14 09:06:06 -04:00
// This class is not to be used directly
// Instead, call actions on cChunkMap (such as cChunkMap::SetBlock() etc.)
class cChunk :
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
{
public :
2014-09-05 16:16:48 -04:00
/** Represents the presence state of the chunk */
enum ePresence
{
cpInvalid , /**< The chunk is not present at all and is not queued in the loader / generator */
cpQueued , /**< The chunk is not present, but is queued for loading / generation */
cpPresent , /**< The chunk is present */
} ;
2012-12-14 17:38:30 -05:00
cChunk (
2014-08-28 05:36:35 -04:00
int a_ChunkX , int a_ChunkZ , // Chunk coords
2012-12-14 17:38:30 -05:00
cChunkMap * a_ChunkMap , cWorld * a_World , // Parent objects
2014-06-16 10:12:50 -04:00
cChunk * a_NeighborXM , cChunk * a_NeighborXP , cChunk * a_NeighborZM , cChunk * a_NeighborZP , // Neighbor chunks
cAllocationPool < cChunkData : : sChunkSection > & a_Pool
2012-12-14 17:38:30 -05:00
) ;
2014-05-24 08:33:40 -04:00
cChunk ( cChunk & other ) ;
2012-06-14 09:06:06 -04:00
~ cChunk ( ) ;
2014-09-05 16:16:48 -04:00
/** Returns true iff the chunk block data is valid (loaded / generated) */
bool IsValid ( void ) const { return ( m_Presence = = cpPresent ) ; }
/** Returns true iff the chunk is in the queue for loading / generating */
bool IsQueued ( void ) const { return ( m_Presence = = cpQueued ) ; }
/** Sets the chunk's presence.
Wakes up any calls to cChunkMap : : GetHeight ( ) when setting to cpPresent . */
void SetPresence ( ePresence a_Presence ) ;
/** Called to indicate whether the chunk should be queued in the generator if it fails to load. Set by cChunkMap::GetChunk(). */
void SetShouldGenerateIfLoadFailed ( bool a_ShouldGenerateIfLoadFailed ) ;
/** Marks all clients attached to this chunk as wanting this chunk. Also sets presence to cpQueued. */
void MarkRegenerating ( void ) ;
/** Returns true iff the chunk has changed since it was last saved. */
bool IsDirty ( void ) const { return m_IsDirty ; }
2012-06-14 09:06:06 -04:00
bool CanUnload ( void ) ;
bool IsLightValid ( void ) const { return m_IsLightValid ; }
/*
To save a chunk , the WSSchema must :
2014-07-21 09:19:48 -04:00
1. Mark the chunk as being saved ( MarkSaving ( ) )
2012-06-14 09:06:06 -04:00
2. Get the chunk ' s data using GetAllData ( )
2014-07-21 09:19:48 -04:00
3. Mark the chunk as saved ( MarkSaved ( ) )
2012-06-14 09:06:06 -04:00
If anywhere inside this sequence another thread mmodifies the chunk , the chunk will not get marked as saved in MarkSaved ( )
*/
2014-07-17 10:33:09 -04:00
void MarkSaving ( void ) ; // Marks the chunk as being saved.
2012-06-14 09:06:06 -04:00
void MarkSaved ( void ) ; // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
void MarkLoaded ( void ) ; // Marks the chunk as freshly loaded. Fails if the chunk is already valid
2014-09-05 16:16:48 -04:00
/** Marks the chunk as failed to load.
If m_ShouldGenerateIfLoadFailed is set , queues the chunk for generating . */
void MarkLoadFailed ( void ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Gets all chunk data, calls the a_Callback's methods for each data type */
2012-06-14 09:06:06 -04:00
void GetAllData ( cChunkDataCallback & a_Callback ) ;
2014-07-24 12:32:05 -04:00
/** Sets all chunk data as either loaded from the storage or generated.
BlockLight and BlockSkyLight are optional , if not present , chunk will be marked as unlighted .
Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk . */
void SetAllData ( cSetChunkData & a_SetChunkData ) ;
2012-06-14 09:06:06 -04:00
void SetLight (
const cChunkDef : : BlockNibbles & a_BlockLight ,
const cChunkDef : : BlockNibbles & a_SkyLight
) ;
2014-02-08 15:55:21 -05:00
/** Copies m_BlockData into a_BlockTypes, only the block types */
2012-06-14 09:06:06 -04:00
void GetBlockTypes ( BLOCKTYPE * a_BlockTypes ) ;
2014-02-08 15:55:21 -05:00
/** Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! */
2012-10-06 12:58:31 -04:00
void WriteBlockArea ( cBlockArea & a_Area , int a_MinBlockX , int a_MinBlockY , int a_MinBlockZ , int a_DataTypes ) ;
2014-02-08 15:55:21 -05:00
/** Returns true if there is a block entity at the coords specified */
2012-06-14 09:06:06 -04:00
bool HasBlockEntityAt ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2014-02-08 15:55:21 -05:00
/** Sets or resets the internal flag that prevents chunk from being unloaded.
The flag is cumulative - it can be set multiple times and then needs to be un - set that many times
before the chunk is unloadable again . */
2012-06-14 09:06:06 -04:00
void Stay ( bool a_Stay = true ) ;
2014-02-08 15:55:21 -05:00
/** Recence all mobs proximities to players in order to know what to do with them */
2013-09-07 16:19:56 -04:00
void CollectMobCensus ( cMobCensus & toFill ) ;
2014-02-08 15:55:21 -05:00
/** Try to Spawn Monsters inside chunk */
2013-09-07 18:11:38 -04:00
void SpawnMobs ( cMobSpawner & a_MobSpawner ) ;
2015-01-11 16:12:26 -05:00
void Tick ( std : : chrono : : milliseconds a_Dt ) ;
2013-11-30 09:58:27 -05:00
2014-02-08 15:55:21 -05:00
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
2013-11-30 09:58:27 -05:00
void TickBlock ( int a_RelX , int a_RelY , int a_RelZ ) ;
2012-06-14 09:06:06 -04:00
2013-03-15 16:18:11 -04:00
int GetPosX ( void ) const { return m_PosX ; }
int GetPosZ ( void ) const { return m_PosZ ; }
cWorld * GetWorld ( void ) const { return m_World ; }
2012-06-14 09:06:06 -04:00
2014-05-25 08:46:34 -04:00
void SetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta , bool a_SendToClients = true ) ;
2012-06-14 09:06:06 -04:00
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
2014-07-21 09:19:48 -04:00
void SetBlock ( const Vector3i & a_RelBlockPos , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) { SetBlock ( a_RelBlockPos . x , a_RelBlockPos . y , a_RelBlockPos . z , a_BlockType , a_BlockMeta ) ; }
2013-02-28 02:42:45 -05:00
2014-02-08 15:55:21 -05:00
/** Queues a block change till the specified world tick */
2013-12-06 17:29:15 -05:00
void QueueSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta , Int64 a_Tick , BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR ) ;
2013-08-18 16:44:22 -04:00
2014-02-08 15:55:21 -05:00
/** Queues block for ticking (m_ToTickQueue) */
2013-02-28 02:42:45 -05:00
void QueueTickBlock ( int a_RelX , int a_RelY , int a_RelZ ) ;
2014-02-08 15:55:21 -05:00
/** Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk */
2013-02-28 02:42:45 -05:00
void QueueTickBlockNeighbors ( int a_RelX , int a_RelY , int a_RelZ ) ;
2014-05-25 08:46:34 -04:00
void FastSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , BLOCKTYPE a_BlockMeta , bool a_SendToClients = true ) ; // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
2013-03-15 16:18:11 -04:00
BLOCKTYPE GetBlock ( int a_RelX , int a_RelY , int a_RelZ ) const ;
2014-08-29 16:21:58 -04:00
BLOCKTYPE GetBlock ( const Vector3i & a_RelCoords ) const { return GetBlock ( a_RelCoords . x , a_RelCoords . y , a_RelCoords . z ) ; }
2014-10-19 09:11:53 -04:00
void GetBlockTypeMeta ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
2012-10-20 07:40:34 -04:00
void GetBlockInfo ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_Meta , NIBBLETYPE & a_SkyLight , NIBBLETYPE & a_BlockLight ) ;
2012-06-14 09:06:06 -04:00
2013-02-28 02:42:45 -05:00
/** Returns the chunk into which the specified block belongs, by walking the neighbors.
2014-10-20 16:55:07 -04:00
Will return self if appropriate . Returns nullptr if not reachable through neighbors .
2013-02-28 02:42:45 -05:00
*/
2013-03-01 14:35:29 -05:00
cChunk * GetNeighborChunk ( int a_BlockX , int a_BlockZ ) ;
2013-02-28 02:42:45 -05:00
/**
Returns the chunk into which the relatively - specified block belongs , by walking the neighbors .
2014-10-20 16:55:07 -04:00
Will return self if appropriate . Returns nullptr if not reachable through neighbors .
2013-02-28 02:42:45 -05:00
*/
2013-03-01 14:35:29 -05:00
cChunk * GetRelNeighborChunk ( int a_RelX , int a_RelZ ) ;
2013-02-28 02:42:45 -05:00
2013-05-28 08:18:03 -04:00
/**
2013-10-22 11:54:09 -04:00
Returns the chunk into which the relatively - specified block belongs .
2013-05-28 08:18:03 -04:00
Also modifies the relative coords from this - relative to return - relative .
2013-10-22 11:54:09 -04:00
Will return self if appropriate .
Will try walking the neighbors first ; if that fails , will query the chunkmap
2013-05-28 08:18:03 -04:00
*/
2013-10-22 11:54:09 -04:00
cChunk * GetRelNeighborChunkAdjustCoords ( int & a_RelX , int & a_RelZ ) const ;
2013-05-28 08:18:03 -04:00
2012-06-14 09:06:06 -04:00
EMCSBiome GetBiomeAt ( int a_RelX , int a_RelZ ) const { return cChunkDef : : GetBiome ( m_BiomeMap , a_RelX , a_RelZ ) ; }
2014-02-18 07:06:18 -05:00
/** Sets the biome at the specified relative coords.
Doesn ' t resend the chunk to clients . */
void SetBiomeAt ( int a_RelX , int a_RelZ , EMCSBiome a_Biome ) ;
/** Sets the biome in the specified relative coords area. All the coords are inclusive.
Sends the chunk to all relevant clients . */
void SetAreaBiome ( int a_MinRelX , int a_MaxRelX , int a_MinRelZ , int a_MaxRelZ , EMCSBiome a_Biome ) ;
2014-10-15 13:01:55 -04:00
void CollectPickupsByPlayer ( cPlayer & a_Player ) ;
2013-06-12 03:14:06 -04:00
2014-02-08 15:55:21 -05:00
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
2013-06-12 03:14:06 -04:00
bool SetSignLines ( int a_RelX , int a_RelY , int a_RelZ , const AString & a_Line1 , const AString & a_Line2 , const AString & a_Line3 , const AString & a_Line4 ) ;
2012-06-14 09:06:06 -04:00
2014-07-21 09:19:48 -04:00
int GetHeight ( int a_X , int a_Z ) ;
2012-06-14 09:06:06 -04:00
2012-08-25 13:52:08 -04:00
void SendBlockTo ( int a_RelX , int a_RelY , int a_RelZ , cClientHandle * a_Client ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Adds a client to the chunk; returns true if added, false if already there */
2014-07-10 12:18:32 -04:00
bool AddClient ( cClientHandle * a_Client ) ;
2012-06-14 09:06:06 -04:00
2014-07-10 12:18:32 -04:00
/** Removes the specified client from the chunk; ignored if client not in chunk. */
void RemoveClient ( cClientHandle * a_Client ) ;
/** Returns true if the specified client is present in this chunk. */
bool HasClient ( cClientHandle * a_Client ) ;
/** Returns true if theres any client in the chunk; false otherwise */
bool HasAnyClients ( void ) const ;
2012-06-14 09:06:06 -04:00
2013-04-13 17:02:10 -04:00
void AddEntity ( cEntity * a_Entity ) ;
void RemoveEntity ( cEntity * a_Entity ) ;
bool HasEntity ( int a_EntityID ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
2012-06-16 04:35:07 -04:00
bool ForEachEntity ( cEntityCallback & a_Callback ) ; // Lua-accessible
2014-09-03 11:00:26 -04:00
/** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
Returns true if all entities processed , false if the callback aborted by returning true . */
bool ForEachEntityInBox ( const cBoundingBox & a_Box , cEntityCallback & a_Callback ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
2013-04-13 17:02:10 -04:00
bool DoWithEntityByID ( int a_EntityID , cEntityCallback & a_Callback , bool & a_CallbackResult ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
2013-11-20 15:53:29 -05:00
bool ForEachBlockEntity ( cBlockEntityCallback & a_Callback ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true */
2012-06-17 15:58:39 -04:00
bool ForEachChest ( cChestCallback & a_Callback ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true */
2012-12-27 10:07:12 -05:00
bool ForEachDispenser ( cDispenserCallback & a_Callback ) ;
2012-12-26 12:16:33 -05:00
2014-02-08 15:55:21 -05:00
/** Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true */
2013-05-26 10:39:04 -04:00
bool ForEachDropper ( cDropperCallback & a_Callback ) ;
2014-02-08 15:55:21 -05:00
/** Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true */
2013-05-26 10:39:04 -04:00
bool ForEachDropSpenser ( cDropSpenserCallback & a_Callback ) ;
2014-02-08 15:55:21 -05:00
/** Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true */
2012-06-17 15:58:39 -04:00
bool ForEachFurnace ( cFurnaceCallback & a_Callback ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
2013-11-20 15:53:29 -05:00
bool DoWithBlockEntityAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cBlockEntityCallback & a_Callback ) ; // Lua-acessible
2014-08-05 16:48:23 -04:00
/** Calls the callback for the redstone powered entity at the specified coords; returns false if there's no redstone powered entity at those coords, true if found */
2014-08-13 19:03:30 -04:00
bool DoWithRedstonePoweredEntityAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cRedstonePoweredCallback & a_Callback ) ;
2014-07-30 16:19:51 -04:00
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cBeaconCallback & a_Callback ) ; // Lua-acessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
2012-06-17 15:58:39 -04:00
bool DoWithChestAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cChestCallback & a_Callback ) ; // Lua-acessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
2012-12-27 10:07:12 -05:00
bool DoWithDispenserAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cDispenserCallback & a_Callback ) ;
2012-12-26 12:16:33 -05:00
2014-02-08 15:55:21 -05:00
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
2013-05-26 10:39:04 -04:00
bool DoWithDropperAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cDropperCallback & a_Callback ) ;
2014-02-08 15:55:21 -05:00
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
2013-05-26 10:39:04 -04:00
bool DoWithDropSpenserAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cDropSpenserCallback & a_Callback ) ;
2014-02-08 15:55:21 -05:00
/** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
2012-06-17 15:58:39 -04:00
bool DoWithFurnaceAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cFurnaceCallback & a_Callback ) ; // Lua-accessible
2014-02-08 15:55:21 -05:00
/** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
2013-12-14 11:52:22 -05:00
bool DoWithNoteBlockAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cNoteBlockCallback & a_Callback ) ;
2014-02-08 15:55:21 -05:00
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
2014-02-18 15:40:02 -05:00
bool DoWithCommandBlockAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cCommandBlockCallback & a_Callback ) ;
2014-03-06 19:30:34 -05:00
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
2014-03-07 05:44:16 -05:00
bool DoWithMobHeadAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cMobHeadCallback & a_Callback ) ;
2014-03-06 19:30:34 -05:00
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
bool DoWithFlowerPotAt ( int a_BlockX , int a_BlockY , int a_BlockZ , cFlowerPotCallback & a_Callback ) ;
2014-01-18 08:16:47 -05:00
2014-02-08 15:55:21 -05:00
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
2012-06-17 15:58:39 -04:00
bool GetSignLines ( int a_BlockX , int a_BlockY , int a_BlockZ , AString & a_Line1 , AString & a_Line2 , AString & a_Line3 , AString & a_Line4 ) ; // Lua-accessible
2012-06-14 09:06:06 -04:00
void UseBlockEntity ( cPlayer * a_Player , int a_X , int a_Y , int a_Z ) ; // [x, y, z] in world block coords
2014-04-07 15:57:14 -04:00
void CalculateHeightmap ( const BLOCKTYPE * a_BlockTypes ) ;
2012-06-14 09:06:06 -04:00
2013-07-07 09:06:06 -04:00
// Broadcast various packets to all clients of this chunk:
// (Please keep these alpha-sorted)
2013-03-03 14:05:11 -05:00
void BroadcastAttachEntity ( const cEntity & a_Entity , const cEntity * a_Vehicle ) ;
2014-10-20 16:55:07 -04:00
void BroadcastBlockAction ( int a_BlockX , int a_BlockY , int a_BlockZ , char a_Byte1 , char a_Byte2 , BLOCKTYPE a_BlockType , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastBlockBreakAnimation ( int a_EntityID , int a_BlockX , int a_BlockY , int a_BlockZ , char a_Stage , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastBlockEntity ( int a_BlockX , int a_BlockY , int a_BlockZ , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastChunkData ( cChunkDataSerializer & a_Serializer , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastCollectEntity ( const cEntity & a_Entity , const cPlayer & a_Player , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastDestroyEntity ( const cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityEffect ( const cEntity & a_Entity , int a_EffectID , int a_Amplifier , short a_Duration , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityEquipment ( const cEntity & a_Entity , short a_SlotNum , const cItem & a_Item , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityHeadLook ( const cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityLook ( const cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityMetadata ( const cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityRelMove ( const cEntity & a_Entity , char a_RelX , char a_RelY , char a_RelZ , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityRelMoveLook ( const cEntity & a_Entity , char a_RelX , char a_RelY , char a_RelZ , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityStatus ( const cEntity & a_Entity , char a_Status , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityVelocity ( const cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastEntityAnimation ( const cEntity & a_Entity , char a_Animation , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastParticleEffect ( const AString & a_ParticleName , float a_SrcX , float a_SrcY , float a_SrcZ , float a_OffsetX , float a_OffsetY , float a_OffsetZ , float a_ParticleData , int a_ParticleAmount , cClientHandle * a_Exclude = nullptr ) ;
void BroadcastRemoveEntityEffect ( const cEntity & a_Entity , int a_EffectID , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastSoundEffect ( const AString & a_SoundName , double a_X , double a_Y , double a_Z , float a_Volume , float a_Pitch , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastSoundParticleEffect ( int a_EffectID , int a_SrcX , int a_SrcY , int a_SrcZ , int a_Data , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastSpawnEntity ( cEntity & a_Entity , const cClientHandle * a_Exclude = nullptr ) ;
void BroadcastThunderbolt ( int a_BlockX , int a_BlockY , int a_BlockZ , const cClientHandle * a_Exclude = nullptr ) ;
2014-07-21 09:19:48 -04:00
void BroadcastUseBed ( const cEntity & a_Entity , int a_BlockX , int a_BlockY , int a_BlockZ ) ;
2012-10-21 03:46:28 -04:00
void SendBlockEntity ( int a_BlockX , int a_BlockY , int a_BlockZ , cClientHandle & a_Client ) ;
2012-06-14 09:06:06 -04:00
2012-08-25 13:52:08 -04:00
Vector3i PositionToWorldPosition ( const Vector3i & a_RelPos )
{
return PositionToWorldPosition ( a_RelPos . x , a_RelPos . y , a_RelPos . z ) ;
}
void PositionToWorldPosition ( int a_RelX , int a_RelY , int a_RelZ , int & a_BlockX , int & a_BlockY , int & a_BlockZ ) ;
2014-07-21 09:19:48 -04:00
Vector3i PositionToWorldPosition ( int a_RelX , int a_RelY , int a_RelZ ) ;
2012-06-14 09:06:06 -04:00
inline void MarkDirty ( void )
{
m_IsDirty = true ;
m_IsSaving = false ;
}
2014-02-08 15:55:21 -05:00
/** Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call */
2012-06-14 09:06:06 -04:00
inline void SetNextBlockTick ( int a_RelX , int a_RelY , int a_RelZ )
{
m_BlockTickX = a_RelX ;
m_BlockTickY = a_RelY ;
m_BlockTickZ = a_RelZ ;
}
2014-04-26 13:50:23 -04:00
inline NIBBLETYPE GetMeta ( int a_RelX , int a_RelY , int a_RelZ ) const
{
2014-05-21 14:58:48 -04:00
return m_ChunkData . GetMeta ( a_RelX , a_RelY , a_RelZ ) ;
2014-04-26 13:50:23 -04:00
}
inline void SetMeta ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_Meta )
{
2014-05-21 15:18:09 -04:00
bool hasChanged = m_ChunkData . SetMeta ( a_RelX , a_RelY , a_RelZ , a_Meta ) ;
if ( hasChanged )
2014-05-10 10:19:06 -04:00
{
MarkDirty ( ) ;
2014-06-04 18:23:09 -04:00
m_IsRedstoneDirty = true ;
2014-05-21 15:18:09 -04:00
2014-05-10 10:19:06 -04:00
m_PendingSendBlocks . push_back ( sSetBlock ( m_PosX , m_PosZ , a_RelX , a_RelY , a_RelZ , GetBlock ( a_RelX , a_RelY , a_RelZ ) , a_Meta ) ) ;
}
2014-04-26 13:50:23 -04:00
}
2012-06-14 09:06:06 -04:00
2014-05-21 14:58:48 -04:00
inline NIBBLETYPE GetBlockLight ( int a_RelX , int a_RelY , int a_RelZ ) const { return m_ChunkData . GetBlockLight ( a_RelX , a_RelY , a_RelZ ) ; }
inline NIBBLETYPE GetSkyLight ( int a_RelX , int a_RelY , int a_RelZ ) const { return m_ChunkData . GetSkyLight ( a_RelX , a_RelY , a_RelZ ) ; }
2013-03-01 14:35:29 -05:00
2014-02-08 15:55:21 -05:00
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-03-15 16:18:11 -04:00
bool UnboundedRelGetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
2013-03-01 14:35:29 -05:00
2014-02-08 15:55:21 -05:00
/** Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-05-28 08:05:23 -04:00
bool UnboundedRelGetBlockType ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType ) const ;
2014-02-08 15:55:21 -05:00
/** Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-05-28 08:05:23 -04:00
bool UnboundedRelGetBlockMeta ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockMeta ) const ;
2014-02-08 15:55:21 -05:00
/** Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-10-22 11:54:09 -04:00
bool UnboundedRelGetBlockBlockLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockLight ) const ;
2014-02-08 15:55:21 -05:00
/** Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-10-22 11:54:09 -04:00
bool UnboundedRelGetBlockSkyLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_SkyLight ) const ;
2014-02-08 15:55:21 -05:00
/** Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-10-27 04:19:13 -04:00
bool UnboundedRelGetBlockLights ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockLight , NIBBLETYPE & a_SkyLight ) const ;
2014-02-08 15:55:21 -05:00
/** Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-03-01 14:35:29 -05:00
bool UnboundedRelSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
2014-02-08 15:55:21 -05:00
/** Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
2013-03-01 14:35:29 -05:00
bool UnboundedRelFastSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
2013-03-22 12:48:45 -04:00
2014-02-08 15:55:21 -05:00
/** Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts */
2013-03-22 12:48:45 -04:00
void UnboundedQueueTickBlock ( int a_RelX , int a_RelY , int a_RelZ ) ;
2013-03-01 14:35:29 -05:00
2014-02-08 15:55:21 -05:00
/** Light alterations based on time */
2013-10-29 12:44:51 -04:00
NIBBLETYPE GetTimeAlteredLight ( NIBBLETYPE a_Skylight ) const ;
2013-10-21 16:38:38 -04:00
2014-02-15 10:51:49 -05:00
// Per-chunk simulator data:
2013-03-02 10:44:31 -05:00
cFireSimulatorChunkData & GetFireSimulatorData ( void ) { return m_FireSimulatorData ; }
cFluidSimulatorData * GetWaterSimulatorData ( void ) { return m_WaterSimulatorData ; }
cFluidSimulatorData * GetLavaSimulatorData ( void ) { return m_LavaSimulatorData ; }
2013-03-02 14:57:09 -05:00
cSandSimulatorChunkData & GetSandSimulatorData ( void ) { return m_SandSimulatorData ; }
2014-02-15 10:51:49 -05:00
2014-09-26 12:00:34 -04:00
cRedstoneSimulatorChunkData * GetRedstoneSimulatorData ( void ) { return m_RedstoneSimulatorData ; }
2014-09-27 09:46:50 -04:00
void SetRedstoneSimulatorData ( cRedstoneSimulatorChunkData * a_Data ) { m_RedstoneSimulatorData = a_Data ; }
2014-06-04 18:23:09 -04:00
bool IsRedstoneDirty ( void ) const { return m_IsRedstoneDirty ; }
void SetIsRedstoneDirty ( bool a_Flag ) { m_IsRedstoneDirty = a_Flag ; }
2012-06-14 09:06:06 -04:00
2013-06-13 03:36:43 -04:00
cBlockEntity * GetBlockEntity ( int a_BlockX , int a_BlockY , int a_BlockZ ) ;
cBlockEntity * GetBlockEntity ( const Vector3i & a_BlockPos ) { return GetBlockEntity ( a_BlockPos . x , a_BlockPos . y , a_BlockPos . z ) ; }
2014-07-10 12:18:32 -04:00
/** Returns true if the chunk should be ticked in the tick-thread.
Checks if there are any clients and if the always - tick flag is set */
bool ShouldBeTicked ( void ) const ;
/** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter.
If the m_AlwaysTicked counter is greater than zero , the chunk is ticked in the tick - thread regardless of
whether it has any clients or not .
This function allows nesting and task - concurrency ( multiple separate tasks can request ticking and as long
as at least one requests is active the chunk will be ticked ) . */
void SetAlwaysTicked ( bool a_AlwaysTicked ) ;
2013-06-13 03:36:43 -04:00
2012-06-14 09:06:06 -04:00
private :
friend class cChunkMap ;
2013-08-18 16:44:22 -04:00
struct sSetBlockQueueItem
{
2014-04-18 15:09:44 -04:00
Int64 m_Tick ;
2013-08-18 16:44:22 -04:00
int m_RelX , m_RelY , m_RelZ ;
BLOCKTYPE m_BlockType ;
NIBBLETYPE m_BlockMeta ;
2013-12-06 17:29:15 -05:00
BLOCKTYPE m_PreviousType ;
2013-08-18 16:44:22 -04:00
2013-12-06 17:29:15 -05:00
sSetBlockQueueItem ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta , Int64 a_Tick , BLOCKTYPE a_PreviousBlockType ) :
2014-04-18 16:47:59 -04:00
m_Tick ( a_Tick ) , m_RelX ( a_RelX ) , m_RelY ( a_RelY ) , m_RelZ ( a_RelZ ) , m_BlockType ( a_BlockType ) , m_BlockMeta ( a_BlockMeta ) , m_PreviousType ( a_PreviousBlockType )
2013-08-18 16:44:22 -04:00
{
}
} ;
typedef std : : vector < sSetBlockQueueItem > sSetBlockQueueVector ;
2014-09-05 16:16:48 -04:00
/** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */
ePresence m_Presence ;
/** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
bool m_ShouldGenerateIfLoadFailed ;
2012-06-14 09:06:06 -04:00
bool m_IsLightValid ; // True if the blocklight and skylight are calculated
bool m_IsDirty ; // True if the chunk has changed since it was last saved
bool m_IsSaving ; // True if the chunk is being saved
bool m_HasLoadFailed ; // True if chunk failed to load and hasn't been generated yet since then
2014-04-26 13:50:23 -04:00
std : : vector < Vector3i > m_ToTickBlocks ;
sSetBlockVector m_PendingSendBlocks ; ///< Blocks that have changed and need to be sent to all clients
2012-06-14 09:06:06 -04:00
2013-08-18 16:44:22 -04:00
sSetBlockQueueVector m_SetBlockQueue ; ///< Block changes that are queued to a specific tick
2012-06-14 09:06:06 -04:00
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
cClientHandleList m_LoadedByClient ;
cEntityList m_Entities ;
cBlockEntityList m_BlockEntities ;
2014-02-08 15:55:21 -05:00
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
2012-06-14 09:06:06 -04:00
int m_StayCount ;
2014-09-06 13:01:30 -04:00
int m_PosX , m_PosZ ;
2012-06-14 09:06:06 -04:00
cWorld * m_World ;
cChunkMap * m_ChunkMap ;
2014-05-21 14:58:48 -04:00
cChunkData m_ChunkData ;
2012-06-14 09:06:06 -04:00
cChunkDef : : HeightMap m_HeightMap ;
cChunkDef : : BiomeMap m_BiomeMap ;
int m_BlockTickX , m_BlockTickY , m_BlockTickZ ;
2012-12-14 17:38:30 -05:00
cChunk * m_NeighborXM ; // Neighbor at [X - 1, Z]
cChunk * m_NeighborXP ; // Neighbor at [X + 1, Z]
cChunk * m_NeighborZM ; // Neighbor at [X, Z - 1]
cChunk * m_NeighborZP ; // Neighbor at [X, Z + 1]
2013-03-01 14:35:29 -05:00
2013-03-02 10:44:31 -05:00
// Per-chunk simulator data:
2013-03-01 14:35:29 -05:00
cFireSimulatorChunkData m_FireSimulatorData ;
2013-03-02 10:44:31 -05:00
cFluidSimulatorData * m_WaterSimulatorData ;
cFluidSimulatorData * m_LavaSimulatorData ;
2013-03-02 14:57:09 -05:00
cSandSimulatorChunkData m_SandSimulatorData ;
2014-02-15 10:51:49 -05:00
2014-09-26 12:00:34 -04:00
cRedstoneSimulatorChunkData * m_RedstoneSimulatorData ;
2014-09-16 15:29:31 -04:00
2013-03-01 14:35:29 -05:00
2014-06-04 18:23:09 -04:00
/** Indicates if simulate-once blocks should be updated by the redstone simulator */
bool m_IsRedstoneDirty ;
2014-07-10 12:18:32 -04:00
/** If greater than zero, the chunk is ticked even if it has no clients.
Manipulated by the SetAlwaysTicked ( ) function , allows for nested calls of the function .
This is the support for plugin - accessible chunk tick forcing . */
int m_AlwaysTicked ;
2012-06-14 09:06:06 -04:00
2014-06-04 18:23:09 -04:00
// Pick up a random block of this chunk
2014-07-10 17:04:33 -04:00
void GetRandomBlockCoords ( int & a_X , int & a_Y , int & a_Z ) ;
void GetThreeRandomNumbers ( int & a_X , int & a_Y , int & a_Z , int a_MaxX , int a_MaxY , int a_MaxZ ) ;
2013-09-07 18:11:38 -04:00
2013-03-01 14:35:29 -05:00
void RemoveBlockEntity ( cBlockEntity * a_BlockEntity ) ;
void AddBlockEntity ( cBlockEntity * a_BlockEntity ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Creates a block entity for each block that needs a block entity and doesn't have one in the list */
2012-06-14 09:06:06 -04:00
void CreateBlockEntities ( void ) ;
2014-02-08 15:55:21 -05:00
/** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */
2013-03-03 10:33:55 -05:00
void WakeUpSimulators ( void ) ;
2012-06-14 09:06:06 -04:00
// Makes a copy of the list
cClientHandleList GetAllClients ( void ) const { return m_LoadedByClient ; }
2014-02-08 15:55:21 -05:00
/** Sends m_PendingSendBlocks to all clients */
2012-08-25 13:52:08 -04:00
void BroadcastPendingBlockChanges ( void ) ;
2014-02-08 15:55:21 -05:00
/** Checks the block scheduled for checking in m_ToTickBlocks[] */
2014-01-31 18:17:41 -05:00
void CheckBlocks ( ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Ticks several random blocks in the chunk */
2013-04-13 17:02:10 -04:00
void TickBlocks ( void ) ;
2012-10-21 17:15:57 -04:00
2014-02-08 15:55:21 -05:00
/** Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes */
2013-04-01 16:56:25 -04:00
void ApplyWeatherToTop ( void ) ;
2012-06-14 09:06:06 -04:00
2014-02-08 15:55:21 -05:00
/** Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
2012-06-14 09:06:06 -04:00
void GrowSugarcane ( int a_RelX , int a_RelY , int a_RelZ , int a_NumBlocks ) ;
2014-02-08 15:55:21 -05:00
/** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
2012-06-14 09:06:06 -04:00
void GrowCactus ( int a_RelX , int a_RelY , int a_RelZ , int a_NumBlocks ) ;
2014-02-08 15:55:21 -05:00
/** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
2012-06-14 09:06:06 -04:00
void GrowMelonPumpkin ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , MTRand & a_Random ) ;
2014-02-08 15:55:21 -05:00
/** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */
2013-04-13 17:02:10 -04:00
void MoveEntityToNewChunk ( cEntity * a_Entity ) ;
2013-08-18 16:44:22 -04:00
2014-02-08 15:55:21 -05:00
/** Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function */
2013-08-18 16:44:22 -04:00
void ProcessQueuedSetBlocks ( void ) ;
2012-06-14 09:06:06 -04:00
} ;
typedef cChunk * cChunkPtr ;
typedef std : : list < cChunkPtr > cChunkPtrList ;