2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../Defines.h"
|
2020-04-03 02:57:01 -04:00
|
|
|
#include "../Item.h"
|
2017-07-28 12:59:21 -04:00
|
|
|
#include "../BoundingBox.h"
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fwd:
|
|
|
|
class cPlayer;
|
2014-02-01 09:01:13 -05:00
|
|
|
class cChunk;
|
2014-09-26 13:13:19 -04:00
|
|
|
class cBlockPluginInterface;
|
|
|
|
class cChunkInterface;
|
2021-05-05 09:25:10 -04:00
|
|
|
class cWorld;
|
2014-09-26 13:13:19 -04:00
|
|
|
class cWorldInterface;
|
|
|
|
class cItems;
|
2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cBlockHandler
|
|
|
|
{
|
|
|
|
public:
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-09-20 09:50:52 -04:00
|
|
|
constexpr cBlockHandler(BLOCKTYPE a_BlockType) :
|
|
|
|
m_BlockType(a_BlockType)
|
|
|
|
{
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Called when the block gets ticked either by a random tick or by a queued tick.
|
2020-04-17 05:36:37 -04:00
|
|
|
Note that the coords in a_RelPos are chunk-relative! */
|
|
|
|
virtual void OnUpdate(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cBlockPluginInterface & a_BlockPluginInterface,
|
|
|
|
cChunk & a_Chunk,
|
|
|
|
const Vector3i a_RelPos
|
2020-09-20 09:50:52 -04:00
|
|
|
) const;
|
2013-07-29 07:13:03 -04:00
|
|
|
|
2017-07-28 12:59:21 -04:00
|
|
|
/** Returns the relative bounding box that must be entity-free in
|
|
|
|
order for the block to be placed. a_XM, a_XP, etc. stand for the
|
|
|
|
blocktype of the minus-X neighbor, the positive-X neighbor, etc. */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const;
|
2017-07-28 12:59:21 -04:00
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
/** Called by cWorld::SetBlock() after the block has been set */
|
2020-04-21 16:19:22 -04:00
|
|
|
virtual void OnPlaced(
|
|
|
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
|
|
|
Vector3i a_BlockPos,
|
|
|
|
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
2020-10-05 06:27:14 -04:00
|
|
|
) const {}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-10-08 15:13:44 -04:00
|
|
|
/** Called after a block gets broken (replaced with air), by natural means.
|
2019-10-16 04:06:34 -04:00
|
|
|
The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta.
|
2020-10-08 15:13:44 -04:00
|
|
|
By default notifies all direct neighbors via their OnNeighborChanged() callbacks.
|
|
|
|
You can determine what kind of entity broke the block (e.g. player) by checking a_Digger! */
|
2019-10-16 04:06:34 -04:00
|
|
|
virtual void OnBroken(
|
|
|
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
|
|
|
Vector3i a_BlockPos,
|
2020-10-08 15:13:44 -04:00
|
|
|
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
|
|
|
|
const cEntity * a_Digger
|
2020-10-05 06:27:14 -04:00
|
|
|
) const {}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
/** Called when a direct neighbor of this block has been changed.
|
|
|
|
The position is the block's own position, NOT the changed neighbor's position.
|
2015-07-01 04:40:16 -04:00
|
|
|
a_WhichNeighbor indicates which neighbor has changed. For example, BLOCK_FACE_YP meant the neighbor above has changed.
|
|
|
|
BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-01 04:40:16 -04:00
|
|
|
/** Notifies the specified neighbor that the current block has changed.
|
2019-10-16 04:06:34 -04:00
|
|
|
a_NeighborPos are the coords of the neighbor to be notified
|
|
|
|
a_WhichNeighbor specifies which neighbor (relative to a_NeighborPos) has changed.
|
2015-07-01 04:40:16 -04:00
|
|
|
For example BLOCK_FACE_YP means that the block at {a_NeighborX, a_NeighborY + 1, a_NeighborZ} has changed.
|
|
|
|
BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */
|
2019-10-16 04:06:34 -04:00
|
|
|
static void NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_NeighborPos, eBlockFace a_WhichNeighbor);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-01 04:40:16 -04:00
|
|
|
/** Called when the player starts digging the block. */
|
2020-04-17 05:36:37 -04:00
|
|
|
virtual void OnDigging(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cPlayer & a_Player,
|
2020-04-21 16:19:22 -04:00
|
|
|
const Vector3i a_BlockPos
|
2020-09-20 09:50:52 -04:00
|
|
|
) const
|
2020-04-17 05:36:37 -04:00
|
|
|
{
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-04-21 16:19:22 -04:00
|
|
|
/** Called when the user right clicks the block and the block is useable.
|
|
|
|
a_CursorPos is the cursor position within the clicked block face.
|
|
|
|
Returns true if the use was successful, return false to use the block as a "normal" block */
|
|
|
|
virtual bool OnUse(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cPlayer & a_Player,
|
|
|
|
const Vector3i a_BlockPos,
|
|
|
|
eBlockFace a_BlockFace,
|
|
|
|
const Vector3i a_CursorPos
|
2020-09-20 09:50:52 -04:00
|
|
|
) const
|
2020-04-21 16:19:22 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2018-01-08 08:37:10 -05:00
|
|
|
/** Called when a right click to this block is cancelled.
|
2020-04-21 16:19:22 -04:00
|
|
|
Descendants should force the server to send the real state of a block to the client to prevent client assuming the operation was successfull. */
|
|
|
|
virtual void OnCancelRightClick(
|
|
|
|
cChunkInterface & a_ChunkInterface,
|
|
|
|
cWorldInterface & a_WorldInterface,
|
|
|
|
cPlayer & a_Player,
|
|
|
|
const Vector3i a_BlockPos,
|
|
|
|
eBlockFace a_BlockFace
|
2020-09-20 09:50:52 -04:00
|
|
|
) const
|
2020-04-21 16:19:22 -04:00
|
|
|
{
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
/** Returns the pickups that would result if the block was mined by a_Digger using a_Tool.
|
|
|
|
Doesn't do any actual block change / mining, only calculates the pickups.
|
|
|
|
a_Digger is the entity that caused the conversion, usually the player digging.
|
|
|
|
a_Tool is the tool used for the digging.
|
|
|
|
The default implementation drops a single item created from m_BlockType and the current meta. */
|
2021-03-28 09:41:34 -04:00
|
|
|
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool = nullptr) const;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Checks if the block can stay at the specified relative coords in the chunk */
|
2021-05-05 09:25:10 -04:00
|
|
|
virtual bool CanBeAt(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) const;
|
2015-08-19 12:45:53 -04:00
|
|
|
|
|
|
|
/** Checks whether the block has an effect on growing the plant */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const { return false; }
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
/** Called to check whether this block supports a rclk action.
|
|
|
|
If it returns true, OnUse() is called */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual bool IsUseable(void) const;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-07-17 16:50:58 -04:00
|
|
|
/** Checks if the player can build "inside" this block.
|
2013-07-29 07:13:03 -04:00
|
|
|
For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
|
2017-07-07 10:37:53 -04:00
|
|
|
@param a_Pos Position of the block
|
|
|
|
@param a_Player Player trying to build on the block
|
2020-04-21 16:19:22 -04:00
|
|
|
@param a_Meta Meta value of the block currently at a_Pos */
|
2021-05-05 09:25:10 -04:00
|
|
|
virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const;
|
2013-11-29 19:31:21 -05:00
|
|
|
|
2020-04-21 16:19:22 -04:00
|
|
|
/** Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the block.
|
|
|
|
Coords in a_RelPosition are guaranteed to be in the [0..1] range. */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const;
|
2015-11-10 08:02:07 -05:00
|
|
|
|
2014-07-17 16:50:58 -04:00
|
|
|
/** Called when one of the neighbors gets set; equivalent to MC block update.
|
2019-10-16 04:06:34 -04:00
|
|
|
By default drops (DropBlockAsPickup() / SetBlock()) if the position is no longer suitable (CanBeAt(), DoesDropOnUnsuitable()),
|
|
|
|
otherwise wakes up all simulators on the block. */
|
2020-07-29 14:30:38 -04:00
|
|
|
void Check(
|
2019-10-16 04:06:34 -04:00
|
|
|
cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
|
|
|
Vector3i a_RelPos,
|
|
|
|
cChunk & a_Chunk
|
2020-09-20 09:50:52 -04:00
|
|
|
) const;
|
2015-06-30 10:50:15 -04:00
|
|
|
|
2017-08-24 05:19:40 -04:00
|
|
|
/** Returns the base colour ID of the block, as will be represented on a map, as per documentation: https://minecraft.gamepedia.com/Map_item_format */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Rotates a given block meta counter-clockwise. Default: no change
|
|
|
|
Returns block meta following rotation */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const { return a_Meta; }
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Rotates a given block meta clockwise. Default: no change
|
|
|
|
Returns block meta following rotation */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const { return a_Meta; }
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Mirrors a given block meta around the XY plane. Default: no change
|
|
|
|
Returns block meta following rotation */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const { return a_Meta; }
|
2013-07-29 07:13:03 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Mirros a given block meta around the XZ plane. Default: no change
|
|
|
|
Returns block meta following rotation */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const { return a_Meta; }
|
2013-07-29 07:13:03 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Mirros a given block meta around the YZ plane. Default: no change
|
|
|
|
Returns block meta following rotation */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const { return a_Meta; }
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
/** Grows this block, if it supports growing, by the specified amount of stages (at most).
|
|
|
|
Returns the number of stages actually grown, zero if not supported (default). */
|
2020-09-20 09:50:52 -04:00
|
|
|
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const { return 0; }
|
2019-10-11 05:02:53 -04:00
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
/** Returns true if the specified tool is valid and has a non-zero silk-touch enchantment.
|
|
|
|
Helper used in many ConvertToPickups() implementations. */
|
|
|
|
static bool ToolHasSilkTouch(const cItem * a_Tool);
|
|
|
|
|
2020-09-20 14:06:28 -04:00
|
|
|
/** Returns the fortune level of a tool, if it is a valid tool.
|
|
|
|
Can be used in ConvertToPickups() implementations. */
|
2020-09-22 06:08:12 -04:00
|
|
|
static unsigned char ToolFortuneLevel(const cItem * a_Tool);
|
2020-09-20 14:06:28 -04:00
|
|
|
|
2020-09-28 08:41:49 -04:00
|
|
|
/** Returns a random number of drops taking into account fortune.
|
|
|
|
Only applies to drops following clamped discrete random distribution.
|
|
|
|
a_DefaultMax is the maximum items from one block without fortune.
|
|
|
|
a_BonusMax is the amount to increase the max of randInt by, usually the fortune level (but not always)
|
|
|
|
a_DropCap is the maximum items from one block with fortune,
|
|
|
|
if unspecified set to 25 to prevent lag or crash with high level tools.
|
|
|
|
Similar to uniform_bonus_count at https://minecraft.gamepedia.com/Loot_table#Functions */
|
|
|
|
static char FortuneDiscreteRandom(char a_MinDrop, char a_DefaultMax, unsigned char a_BonusMax, char a_DropCap = 25);
|
|
|
|
|
2020-09-17 09:51:42 -04:00
|
|
|
// Gets the blockhandler for the given block type.
|
2020-09-20 09:50:52 -04:00
|
|
|
static const cBlockHandler & For(BLOCKTYPE a_BlockType);
|
2019-10-16 04:06:34 -04:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
protected:
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-10-05 06:27:14 -04:00
|
|
|
~cBlockHandler() = default;
|
|
|
|
|
|
|
|
const BLOCKTYPE m_BlockType;
|
2014-03-02 14:25:05 -05:00
|
|
|
};
|