2017-09-02 03:45:06 -04:00
2012-06-14 09:06:06 -04:00
# pragma once
2020-04-03 17:23:38 -04:00
# include "BlockEntities/BlockEntity.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"
2013-03-01 14:35:29 -05:00
2014-09-26 13:13:19 -04:00
# include "ChunkMap.h"
2012-06-14 09:06:06 -04:00
class cWorld ;
class cClientHandle ;
class cPlayer ;
class cChunkMap ;
2014-09-26 13:13:19 -04:00
class cBoundingBox ;
2014-10-03 16:32:41 -04:00
class cChunkDataCallback ;
2012-07-02 15:22:05 -04:00
class cBlockArea ;
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 ;
2021-03-28 10:09:01 -04:00
class cRedstoneSimulatorChunkData ;
2021-03-05 08:03:55 -05:00
struct SetChunkData ;
2012-06-14 09:06:06 -04:00
2021-03-28 10:09:01 -04:00
typedef std : : list < cClientHandle * > cClientHandleList ;
2012-06-14 09:06:06 -04:00
2016-01-17 09:09:25 -05:00
// A convenience macro for calling GetChunkAndRelByAbsolute.
2019-08-11 05:39:43 -04:00
# define PREPARE_REL_AND_CHUNK(Position, OriginalChunk) cChunk * Chunk; Vector3i Rel; bool RelSuccess = (OriginalChunk).GetChunkAndRelByAbsolute(Position, &Chunk, Rel)
2012-06-14 09:06:06 -04:00
2021-01-18 11:09:10 -05:00
class cChunk
2012-06-14 09:06:06 -04:00
{
public :
2016-12-19 15:12:23 -05:00
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
2021-03-05 08:03:55 -05:00
cChunkMap * a_ChunkMap , cWorld * a_World // Parent objects
2012-12-14 17:38:30 -05:00
) ;
2020-08-20 13:29:20 -04:00
cChunk ( const cChunk & Other ) = delete ;
2012-06-14 09:06:06 -04:00
~ cChunk ( ) ;
2021-03-28 09:44:20 -04:00
/** Flushes the pending block (entity) queue, and clients' outgoing data buffers. */
void BroadcastPendingChanges ( void ) ;
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 ) ;
/** 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 ; }
2020-08-20 07:50:22 -04:00
bool CanUnload ( void ) const ;
2016-01-17 09:09:25 -05:00
2016-09-03 11:38:29 -04:00
/** Returns true if the chunk could have been unloaded if it weren't dirty */
2020-08-20 07:50:22 -04:00
bool CanUnloadAfterSaving ( void ) const ;
2016-09-03 11:38:29 -04:00
2020-09-22 16:21:47 -04:00
/** Called when the chunkmap unloads unused chunks.
Notifies contained entities that they are being unloaded and should for example , broadcast a destroy packet .
Not called during server shutdown ; such cleanup during shutdown is unnecessary . */
void OnUnload ( ) ;
2012-06-14 09:06:06 -04:00
bool IsLightValid ( void ) const { return m_IsLightValid ; }
2016-01-17 09:09:25 -05:00
2012-06-14 09:06:06 -04:00
/*
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
2020-08-28 16:26:04 -04:00
/** Queues the chunk for generating. */
2014-09-05 16:16:48 -04:00
void MarkLoadFailed ( void ) ;
2016-01-17 09:09:25 -05:00
2014-02-08 15:55:21 -05:00
/** Gets all chunk data, calls the a_Callback's methods for each data type */
2020-12-21 09:31:44 -05:00
void GetAllData ( cChunkDataCallback & a_Callback ) const ;
2016-01-17 09:09:25 -05:00
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 . */
2021-03-05 08:03:55 -05:00
void SetAllData ( SetChunkData & & a_SetChunkData ) ;
2016-01-17 09:09:25 -05:00
2012-06-14 09:06:06 -04:00
void SetLight (
const cChunkDef : : BlockNibbles & a_BlockLight ,
const cChunkDef : : BlockNibbles & a_SkyLight
) ;
2016-01-17 09:09:25 -05:00
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 */
2018-07-23 14:12:51 -04:00
bool HasBlockEntityAt ( Vector3i a_BlockPos ) ;
2016-01-17 09:09:25 -05:00
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 ) ;
2016-01-17 09:09:25 -05:00
2014-02-08 15:55:21 -05:00
/** Recence all mobs proximities to players in order to know what to do with them */
2015-05-09 05:16:56 -04:00
void CollectMobCensus ( cMobCensus & toFill ) ;
2013-09-07 16:19:56 -04:00
2014-02-08 15:55:21 -05:00
/** Try to Spawn Monsters inside chunk */
2015-05-09 05:16:56 -04:00
void SpawnMobs ( cMobSpawner & a_MobSpawner ) ;
2013-09-07 18:11:38 -04:00
2015-01-11 16:12:26 -05:00
void Tick ( std : : chrono : : milliseconds a_Dt ) ;
2016-01-17 09:09:25 -05:00
2014-02-08 15:55:21 -05:00
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
2020-04-17 05:36:37 -04:00
void TickBlock ( const Vector3i a_RelPos ) ;
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 ; }
2020-04-05 15:20:52 -04:00
cChunkCoords GetPos ( ) const { return { m_PosX , m_PosZ } ; }
2016-01-17 09:09:25 -05:00
2013-03-15 16:18:11 -04:00
cWorld * GetWorld ( void ) const { return m_World ; }
2012-06-14 09:06:06 -04:00
2019-10-16 04:06:34 -04:00
void SetBlock ( Vector3i a_RelBlockPos , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
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
2016-01-17 09:09:25 -05:00
2020-08-26 16:45:13 -04:00
void FastSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , BLOCKTYPE a_BlockMeta ) ; // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
void FastSetBlock ( Vector3i a_RelPos , BLOCKTYPE a_BlockType , BLOCKTYPE a_BlockMeta )
2018-02-04 17:15:31 -05:00
{
2020-08-26 16:45:13 -04:00
FastSetBlock ( a_RelPos . x , a_RelPos . y , a_RelPos . z , a_BlockType , a_BlockMeta ) ;
2018-02-04 17:15:31 -05:00
}
2021-03-05 08:03:55 -05:00
BLOCKTYPE GetBlock ( int a_RelX , int a_RelY , int a_RelZ ) const { return m_BlockData . GetBlock ( { a_RelX , a_RelY , a_RelZ } ) ; }
BLOCKTYPE GetBlock ( Vector3i a_RelCoords ) const { return m_BlockData . GetBlock ( a_RelCoords ) ; }
2018-02-04 17:15:31 -05:00
void GetBlockTypeMeta ( Vector3i a_RelPos , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
void GetBlockTypeMeta ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const
{
GetBlockTypeMeta ( { a_RelX , a_RelY , a_RelZ } , a_BlockType , a_BlockMeta ) ;
}
2020-12-21 09:31:44 -05:00
void GetBlockInfo ( Vector3i a_RelPos , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_Meta , NIBBLETYPE & a_SkyLight , NIBBLETYPE & a_BlockLight ) const ;
2016-01-17 09:09:25 -05:00
/** Convert absolute coordinates into relative coordinates.
Returns false on failure to obtain a valid chunk . Returns true otherwise .
@ param a_Position The position you ' d like to convert , a_Position need not be in the calling chunk and can safely be out
of its bounds , but for best performance , it should not be too far from the calling chunk .
@ param a_Chunk Returns the chunk in which a_Position is in . If a_Position is within the calling chunk ' s bounds ,
returns the calling chunk . For best performance , a_Position shouldn ' t be too far from the calling chunk .
@ param a_Rel Returns the converted relative position . Note that it is relative to the returned a_Chunk .
The vector will not be modified if the function returns false . */
bool GetChunkAndRelByAbsolute ( const Vector3d & a_Position , cChunk * * a_Chunk , Vector3i & a_Rel ) ;
/** Convert absolute coordinates into relative coordinates.
Returns false on failure to obtain a valid chunk . Returns true otherwise .
@ param a_Position The position you ' d like to convert , a_Position need not be in the calling chunk and can safely be out
of its bounds , but for best performance , it should not be too far from the calling chunk .
@ param a_Chunk Returns the chunk in which a_Position is in . If a_Position is within the calling chunk ' s bounds ,
returns the calling chunk . For best performance , a_Position shouldn ' t be too far from the calling chunk .
@ param a_Rel Returns the converted relative position . Note that it is relative to the returned a_Chunk .
The vector will not be modified if the function returns false . */
bool GetChunkAndRelByAbsolute ( const Vector3i & a_Position , cChunk * * a_Chunk , Vector3i & a_Rel ) ;
2013-02-28 02:42:45 -05:00
/** Returns the chunk into which the specified block belongs, by walking the neighbors.
2019-10-11 05:02:53 -04:00
Will return self if appropriate . Returns nullptr if not reachable through neighbors . */
2013-03-01 14:35:29 -05:00
cChunk * GetNeighborChunk ( int a_BlockX , int a_BlockZ ) ;
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04:00
/** Returns the chunk into which the relatively-specified block belongs, by walking the neighbors.
Will return self if appropriate . Returns nullptr if not reachable through neighbors . */
2013-03-01 14:35:29 -05:00
cChunk * GetRelNeighborChunk ( int a_RelX , int a_RelZ ) ;
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -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 .
2019-10-11 05:02:53 -04:00
Will try walking the neighbors first ; if that fails , will query the chunkmap . */
cChunk * GetRelNeighborChunkAdjustCoords ( Vector3i & a_RelPos ) const ;
2016-01-17 09:09:25 -05: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 ) ; }
2016-01-17 09:09:25 -05:00
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 ) ;
2016-01-17 09:09:25 -05:00
2014-02-18 07:06:18 -05:00
/** 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 ) ;
2016-01-17 09:09:25 -05:00
2021-01-04 21:13:02 -05:00
int GetHeight ( int a_X , int a_Z ) const ;
/** Returns true if it is sunny at the specified location. This takes into account biomes. */
bool IsWeatherSunnyAt ( int a_RelX , int a_RelZ ) const ;
/** Returns true if it is raining or storming at the specified location, taking into account biomes. */
bool IsWeatherWetAt ( int a_RelX , int a_RelZ ) const ;
/** Returns true if it is raining or storming at the specified location,
and the rain reaches ( the bottom of ) the specified block position . */
bool IsWeatherWetAt ( Vector3i a_Position ) const ;
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 ) ;
2016-01-17 09:09:25 -05: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 ) ;
2016-01-17 09:09:25 -05:00
2014-07-10 12:18:32 -04:00
/** Returns true if the specified client is present in this chunk. */
bool HasClient ( cClientHandle * a_Client ) ;
2016-01-17 09:09:25 -05:00
2014-07-10 12:18:32 -04:00
/** Returns true if theres any client in the chunk; false otherwise */
bool HasAnyClients ( void ) const ;
2012-06-14 09:06:06 -04:00
2016-12-19 15:12:23 -05:00
void AddEntity ( OwnedEntity a_Entity ) ;
/** Releases ownership of the given entity if it was found in this chunk.
Returns an owning reference to the found entity . */
OwnedEntity RemoveEntity ( cEntity & a_Entity ) ;
2020-08-08 07:09:40 -04:00
bool HasEntity ( UInt32 a_EntityID ) const ;
2016-01-17 09:09:25 -05: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 */
2020-08-08 07:09:40 -04:00
bool ForEachEntity ( cEntityCallback a_Callback ) const ; // Lua-accessible
2012-06-16 04:35:07 -04:00
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 . */
2020-08-08 07:09:40 -04:00
bool ForEachEntityInBox ( const cBoundingBox & a_Box , cEntityCallback a_Callback ) const ; // Lua-accessible
2014-09-03 11:00:26 -04:00
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. */
2020-08-08 07:09:40 -04:00
bool DoWithEntityByID ( UInt32 a_EntityID , cEntityCallback a_Callback , bool & a_CallbackResult ) const ; // Lua-accessible
2013-04-13 17:02:10 -04:00
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 */
2017-09-11 17:20:49 -04:00
bool ForEachBlockEntity ( cBlockEntityCallback a_Callback ) ; // Lua-accessible
2013-11-20 15:53:29 -05:00
2021-03-28 09:40:57 -04:00
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, and whatever the callback returns if found. */
2020-07-25 15:31:48 -04:00
bool DoWithBlockEntityAt ( Vector3i a_Position , cBlockEntityCallback a_Callback ) ; // Lua-acessible
2016-01-17 09:09:25 -05:00
2015-12-01 17:12:44 -05:00
/** Use block entity on coordinate.
returns true if the use was successful , return false to use the block as a " normal " block */
bool UseBlockEntity ( cPlayer * a_Player , int a_X , int a_Y , int a_Z ) ; // [x, y, z] in world block coords
2012-06-14 09:06:06 -04:00
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
2017-09-25 12:17:45 -04:00
Vector3i PositionToWorldPosition ( Vector3i a_RelPos )
2012-08-25 13:52:08 -04:00
{
return PositionToWorldPosition ( a_RelPos . x , a_RelPos . y , a_RelPos . z ) ;
}
2016-01-17 09:09:25 -05:00
2012-08-25 13:52:08 -04:00
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 ;
}
2016-01-17 09:09:25 -05:00
2020-04-17 05:36:37 -04:00
/** Causes the specified block to be ticked on the next Tick() call.
Plugins can use this via the cWorld : SetNextBlockToTick ( ) API .
Only one block coord per chunk may be set , a second call overwrites the first call */
inline void SetNextBlockToTick ( const Vector3i a_RelPos )
2012-06-14 09:06:06 -04:00
{
2020-04-17 05:36:37 -04:00
m_BlockToTick = a_RelPos ;
2012-06-14 09:06:06 -04:00
}
2016-01-17 09:09:25 -05:00
2014-04-26 13:50:23 -04:00
inline NIBBLETYPE GetMeta ( int a_RelX , int a_RelY , int a_RelZ ) const
{
2021-03-05 08:03:55 -05:00
return m_BlockData . GetMeta ( { a_RelX , a_RelY , a_RelZ } ) ;
2018-02-04 17:15:31 -05:00
}
2021-03-05 08:03:55 -05:00
NIBBLETYPE GetMeta ( Vector3i a_RelPos ) const { return m_BlockData . GetMeta ( a_RelPos ) ; }
2018-02-04 17:15:31 -05:00
2020-08-26 16:45:13 -04:00
void SetMeta ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE a_Meta )
2018-02-04 17:15:31 -05:00
{
2020-08-26 16:45:13 -04:00
SetMeta ( { a_RelX , a_RelY , a_RelZ } , a_Meta ) ;
2014-04-26 13:50:23 -04:00
}
2016-04-06 09:16:16 -04:00
2020-08-26 16:45:13 -04:00
inline void SetMeta ( Vector3i a_RelPos , NIBBLETYPE a_Meta )
2014-04-26 13:50:23 -04:00
{
2021-03-05 08:03:55 -05:00
m_BlockData . SetMeta ( a_RelPos , a_Meta ) ;
MarkDirty ( ) ;
2021-03-07 11:31:43 -05:00
m_PendingSendBlocks . emplace_back ( m_PosX , m_PosZ , a_RelPos . x , a_RelPos . y , a_RelPos . z , GetBlock ( a_RelPos ) , a_Meta ) ;
2014-04-26 13:50:23 -04:00
}
2012-06-14 09:06:06 -04:00
2016-01-17 09:09:25 -05:00
/** Light alterations based on time */
NIBBLETYPE GetTimeAlteredLight ( NIBBLETYPE a_Skylight ) const ;
/** Get the level of artificial light illuminating the block (0 - 15) */
2021-03-05 08:03:55 -05:00
inline NIBBLETYPE GetBlockLight ( Vector3i a_RelPos ) const { return m_LightData . GetBlockLight ( a_RelPos ) ; }
inline NIBBLETYPE GetBlockLight ( int a_RelX , int a_RelY , int a_RelZ ) const { return m_LightData . GetBlockLight ( { a_RelX , a_RelY , a_RelZ } ) ; }
2016-01-17 09:09:25 -05:00
/** Get the level of sky light illuminating the block (0 - 15) independent of daytime. */
2021-03-05 08:03:55 -05:00
inline NIBBLETYPE GetSkyLight ( Vector3i a_RelPos ) const { return m_LightData . GetSkyLight ( a_RelPos ) ; }
inline NIBBLETYPE GetSkyLight ( int a_RelX , int a_RelY , int a_RelZ ) const { return m_LightData . GetSkyLight ( { a_RelX , a_RelY , a_RelZ } ) ; }
2016-01-17 09:09:25 -05:00
/** Get the level of sky light illuminating the block (0 - 15), taking daytime into a account. */
2021-03-05 08:03:55 -05:00
inline NIBBLETYPE GetSkyLightAltered ( Vector3i a_RelPos ) const { return GetTimeAlteredLight ( m_LightData . GetSkyLight ( a_RelPos ) ) ; }
2018-02-04 17:15:31 -05:00
inline NIBBLETYPE GetSkyLightAltered ( int a_RelX , int a_RelY , int a_RelZ ) const { return GetSkyLightAltered ( { a_RelX , a_RelY , a_RelZ } ) ; }
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04: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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlock ( Vector3i a_RelCoords , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const ;
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType , NIBBLETYPE & a_BlockMeta ) const
{
return UnboundedRelGetBlock ( { a_RelX , a_RelY , a_RelZ } , a_BlockType , a_BlockMeta ) ;
}
/** 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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockType ( Vector3i a_RelCoords , BLOCKTYPE & a_BlockType ) const ;
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockType ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE & a_BlockType ) const
{
return UnboundedRelGetBlockType ( { a_RelX , a_RelY , a_RelZ } , a_BlockType ) ;
}
/** 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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockMeta ( Vector3i a_RelPos , NIBBLETYPE & a_BlockMeta ) const ;
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04:00
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockMeta ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockMeta ) const
{
return UnboundedRelGetBlockMeta ( { a_RelX , a_RelY , a_RelZ } , a_BlockMeta ) ;
}
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04: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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockBlockLight ( Vector3i a_RelPos , NIBBLETYPE & a_BlockLight ) const ;
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockBlockLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockLight ) const
{
return UnboundedRelGetBlockBlockLight ( { a_RelX , a_RelY , a_RelZ } , a_BlockLight ) ;
}
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04: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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockSkyLight ( Vector3i a_RelPos , NIBBLETYPE & a_SkyLight ) const ;
2013-10-22 11:54:09 -04:00
2019-10-11 05:02:53 -04:00
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockSkyLight ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_SkyLight ) const
{
return UnboundedRelGetBlockSkyLight ( { a_RelX , a_RelY , a_RelZ } , a_SkyLight ) ;
}
2013-10-22 11:54:09 -04:00
2019-10-11 05:02:53 -04: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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockLights ( Vector3i a_RelPos , NIBBLETYPE & a_BlockLight , NIBBLETYPE & a_SkyLight ) const ;
2013-10-27 04:19:13 -04:00
2019-10-11 05:02:53 -04:00
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelGetBlockLights ( int a_RelX , int a_RelY , int a_RelZ , NIBBLETYPE & a_BlockLight , NIBBLETYPE & a_SkyLight ) const
{
return UnboundedRelGetBlockLights ( { a_RelX , a_RelY , a_RelZ } , a_BlockLight , a_SkyLight ) ;
}
2013-03-01 14:35:29 -05:00
2019-10-11 05:02:53 -04: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 , false if queried chunk not loaded . */
bool UnboundedRelSetBlock ( Vector3i a_RelPos , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
2016-01-17 09:09:25 -05:00
2019-10-11 05:02:53 -04:00
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta )
{
return UnboundedRelSetBlock ( { a_RelX , a_RelY , a_RelZ } , a_BlockType , a_BlockMeta ) ;
}
/** 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 , false if queried chunk not loaded . */
bool UnboundedRelFastSetBlock ( Vector3i a_RelPos , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta ) ;
/** OBSOLETE, use the Vector3i-based overload.
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 , false if queried chunk not loaded . */
bool UnboundedRelFastSetBlock ( int a_RelX , int a_RelY , int a_RelZ , BLOCKTYPE a_BlockType , NIBBLETYPE a_BlockMeta )
{
return UnboundedRelFastSetBlock ( { a_RelX , a_RelY , a_RelZ } , a_BlockType , a_BlockMeta ) ;
}
2013-10-29 12:44:51 -04:00
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 ; }
2020-08-08 07:09:40 -04:00
cFluidSimulatorData * GetWaterSimulatorData ( void ) const { return m_WaterSimulatorData ; }
cFluidSimulatorData * GetLavaSimulatorData ( void ) const { return m_LavaSimulatorData ; }
2013-03-02 14:57:09 -05:00
cSandSimulatorChunkData & GetSandSimulatorData ( void ) { return m_SandSimulatorData ; }
2020-08-08 07:09:40 -04:00
cRedstoneSimulatorChunkData * GetRedstoneSimulatorData ( void ) const { return m_RedstoneSimulatorData ; }
2012-06-14 09:06:06 -04:00
2019-10-16 04:06:34 -04:00
/** Returns the block entity at the specified (absolute) coords.
Returns nullptr if no such BE or outside this chunk . */
cBlockEntity * GetBlockEntity ( Vector3i a_AbsPos ) ;
2019-10-11 05:02:53 -04:00
/** OBSOLETE, use the Vector3i-based overload instead.
Returns the block entity at the specified ( absolute ) coords .
Returns nullptr if no such BE or outside this chunk . */
cBlockEntity * GetBlockEntity ( int a_BlockX , int a_BlockY , int a_BlockZ ) { return GetBlockEntity ( { a_BlockX , a_BlockY , a_BlockZ } ) ; }
2019-10-16 04:06:34 -04:00
/** Returns the block entity at the specified (relative) coords.
Returns nullptr if no such BE .
Asserts that the position is a valid relative position . */
cBlockEntity * GetBlockEntityRel ( Vector3i a_RelPos ) ;
2016-01-17 09:09:25 -05:00
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 ;
2016-01-17 09:09:25 -05:00
2014-07-10 12:18:32 -04:00
/** 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
2016-10-09 08:46:09 -04:00
whether it has any clients or not . When this is set , the chunk never unloads .
2014-07-10 12:18:32 -04:00
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
2021-03-28 09:40:57 -04:00
const auto & GetAllClients ( void ) const
2015-09-16 12:04:05 -04:00
{
2021-03-28 09:40:57 -04:00
return m_LoadedByClient ;
2015-09-16 12:04:05 -04:00
}
2015-03-21 13:17:26 -04:00
2019-09-29 08:59:24 -04:00
/** Converts the coord relative to this chunk into an absolute coord.
Doesn ' t check relative coord validity . */
2020-04-21 16:19:22 -04:00
Vector3i RelativeToAbsolute ( Vector3i a_RelBlockPosition ) const
2019-09-29 08:59:24 -04:00
{
2019-10-11 05:02:53 -04:00
return cChunkDef : : RelativeToAbsolute ( a_RelBlockPosition , { m_PosX , m_PosZ } ) ;
2019-09-29 08:59:24 -04:00
}
2012-06-14 09:06:06 -04:00
private :
friend class cChunkMap ;
2016-01-17 09:09:25 -05:00
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 ;
2016-01-17 09:09:25 -05: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 ;
2016-01-17 09:09:25 -05:00
2013-08-18 16:44:22 -04:00
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 ;
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
2016-01-17 09:09:25 -05:00
2021-03-28 09:40:57 -04:00
/** Blocks that have changed and need to be sent to all clients.
The protocol has a provision for coalescing block changes , and this is the buffer .
It will collect the block changes that occur in a tick , before being flushed in BroadcastPendingSendBlocks . */
sSetBlockVector m_PendingSendBlocks ;
/** Block entities that have been touched and need to be sent to all clients.
Because block changes are buffered and we need to happen after them , this buffer exists too .
Pointers to block entities that were destroyed are guaranteed to be removed from this array by RemoveBlockEntity . */
std : : vector < cBlockEntity * > m_PendingSendBlockEntities ;
/** A queue of relative positions to call cBlockHandler::Check on.
Processed at the end of each tick by CheckBlocks . */
std : : queue < Vector3i > m_BlocksToCheck ;
2016-01-17 09:09:25 -05:00
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
2015-09-16 12:04:05 -04:00
std : : vector < cClientHandle * > m_LoadedByClient ;
2016-12-19 15:12:23 -05:00
std : : vector < OwnedEntity > m_Entities ;
2020-08-28 16:40:40 -04:00
cBlockEntities m_BlockEntities ;
2016-01-17 09:09:25 -05:00
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 */
2020-10-05 08:09:42 -04:00
unsigned m_StayCount ;
2012-06-14 09:06:06 -04:00
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 ;
2021-03-05 08:03:55 -05:00
ChunkBlockData m_BlockData ;
ChunkLightData m_LightData ;
2012-06-14 09:06:06 -04:00
cChunkDef : : HeightMap m_HeightMap ;
cChunkDef : : BiomeMap m_BiomeMap ;
2020-04-17 05:36:37 -04:00
/** Relative coords of the block to tick first in the next Tick() call.
Plugins can use this to force a tick in a specific block , using cWorld : SetNextBlockToTick ( ) API . */
Vector3i m_BlockToTick ;
2016-01-17 09:09:25 -05:00
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]
2016-01-17 09:09:25 -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-09-26 12:00:34 -04:00
cRedstoneSimulatorChunkData * m_RedstoneSimulatorData ;
2014-09-16 15:29:31 -04:00
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 . */
2020-10-05 08:09:42 -04:00
unsigned 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 ) ;
2020-04-03 17:23:38 -04:00
void AddBlockEntity ( OwnedBlockEntity a_BlockEntity ) ;
2012-06-14 09:06:06 -04:00
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
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 ( ) ;
2016-01-17 09:09:25 -05:00
2021-04-10 15:01:01 -04:00
/** Ticks several random blocks in the chunk. */
2013-04-13 17:02:10 -04:00
void TickBlocks ( void ) ;
2016-01-17 09:09:25 -05: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 ) ;
2016-01-17 09:09:25 -05:00
2019-10-16 04:06:34 -04:00
/** Returns the pickups that would be produced, if the specified block was dug up by a_Digger using a_Tool.
Doesn ' t dig the block , only queries the block handlers and then plugins for the pickups . */
cItems PickupsFromBlock ( Vector3i a_RelPos , const cEntity * a_Digger , const cItem * a_Tool ) ;
2019-10-11 05:02:53 -04:00
/** Grows the plant at the specified position by at most a_NumStages.
The block ' s Grow handler is invoked .
Returns the number of stages the plant has grown , 0 if not a plant . */
int GrowPlantAt ( Vector3i a_RelPos , int a_NumStages = 1 ) ;
2016-01-17 09:09:25 -05:00
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 */
2016-12-19 15:12:23 -05:00
void MoveEntityToNewChunk ( OwnedEntity a_Entity ) ;
2020-03-18 13:17:59 -04:00
/** Check m_Entities for cPlayer objects. */
2020-08-20 07:50:22 -04:00
bool HasPlayerEntities ( ) const ;
2012-06-14 09:06:06 -04:00
} ;