Moved growing from cWorld / cChunk to cBlockHandler descendants.
This commit is contained in:
@@ -99,7 +99,7 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
PillowDirection = MetaDataToDirection(Meta & 0x3);
|
||||
if (a_ChunkInterface.GetBlock(Coords + PillowDirection) == E_BLOCK_BED) // Must always use pillow location for sleeping
|
||||
{
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{ a_BlockX, a_BlockY, a_BlockZ } + PillowDirection);
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{a_BlockX, a_BlockY, a_BlockZ} + PillowDirection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
||||
}
|
||||
);
|
||||
a_WorldInterface.SetTimeOfDay(0);
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
||||
a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
|
||||
|
||||
static void SetBedOccupationState(cChunkInterface & a_ChunkInterface, const Vector3i & a_BedPosition, bool a_IsOccupied)
|
||||
static void SetBedOccupationState(cChunkInterface & a_ChunkInterface, Vector3i a_BedPosition, bool a_IsOccupied)
|
||||
{
|
||||
auto Meta = a_ChunkInterface.GetBlockMeta(a_BedPosition);
|
||||
if (a_IsOccupied)
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
Meta &= 0x0b; // Clear the "occupied" bit of the bed's block
|
||||
}
|
||||
|
||||
a_ChunkInterface.SetBlockMeta(a_BedPosition.x, a_BedPosition.y, a_BedPosition.z, Meta);
|
||||
a_ChunkInterface.SetBlockMeta(a_BedPosition, Meta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,14 +11,19 @@
|
||||
class cBlockBigFlowerHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
public:
|
||||
typedef cBlockHandler super;
|
||||
using super = cBlockHandler;
|
||||
|
||||
cBlockBigFlowerHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
public:
|
||||
|
||||
cBlockBigFlowerHandler(BLOCKTYPE a_BlockType):
|
||||
super(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override
|
||||
{
|
||||
if (IsMetaTopPart(a_Meta))
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
// Set p the ON bit to on
|
||||
Meta |= 0x08;
|
||||
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta, false);
|
||||
a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta, false);
|
||||
a_WorldInterface.WakeUpSimulators(Pos);
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.stone_button.click_on", SoundPos, 0.5f, 0.6f);
|
||||
|
||||
|
||||
+85
-26
@@ -1,4 +1,3 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockPlant.h"
|
||||
@@ -8,9 +7,9 @@
|
||||
|
||||
|
||||
class cBlockCactusHandler :
|
||||
public cBlockPlant<false>
|
||||
public cClearMetaOnDrop<cBlockPlant<false>>
|
||||
{
|
||||
using super = cBlockPlant<false>;
|
||||
using super = cClearMetaOnDrop<cBlockPlant<false>>;
|
||||
|
||||
public:
|
||||
|
||||
@@ -23,16 +22,6 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
|
||||
{
|
||||
// Reset meta to 0
|
||||
return cItem(m_BlockType, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
if (a_RelY <= 0)
|
||||
@@ -77,13 +66,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
if (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth)
|
||||
{
|
||||
a_Chunk.GetWorld()->GrowCactus(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
@@ -91,17 +76,91 @@ public:
|
||||
return 7;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
|
||||
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
auto Action = paStay;
|
||||
if (((a_RelY + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_AIR))
|
||||
// Check the total height of the cacti blocks here:
|
||||
int top = a_RelPos.y + 1;
|
||||
while (
|
||||
(top < cChunkDef::Height) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_CACTUS)
|
||||
)
|
||||
{
|
||||
Action = super::CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
|
||||
++top;
|
||||
}
|
||||
int bottom = a_RelPos.y - 1;
|
||||
while (
|
||||
(bottom > 0) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_CACTUS)
|
||||
)
|
||||
{
|
||||
--bottom;
|
||||
}
|
||||
|
||||
return Action;
|
||||
// Refuse if already too high:
|
||||
auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (top - bottom));
|
||||
if (numToGrow <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLOCKTYPE blockType;
|
||||
for (int i = 0; i < numToGrow; ++i)
|
||||
{
|
||||
Vector3i pos(a_RelPos.x, top + i, a_RelPos.z);
|
||||
if (!a_Chunk.UnboundedRelGetBlockType(pos, blockType) || (blockType != E_BLOCK_AIR))
|
||||
{
|
||||
// Cannot grow there
|
||||
return i;
|
||||
}
|
||||
|
||||
a_Chunk.UnboundedRelFastSetBlock(pos, E_BLOCK_CACTUS, 0);
|
||||
|
||||
// Check surroundings. Cacti may ONLY be surrounded by non-solid blocks; if they aren't, drop as pickup and bail out the growing
|
||||
static const Vector3i neighborOffsets[] =
|
||||
{
|
||||
{-1, 0, 0},
|
||||
{ 1, 0, 0},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 0, 1},
|
||||
} ;
|
||||
for (const auto & ofs: neighborOffsets)
|
||||
{
|
||||
if (
|
||||
a_Chunk.UnboundedRelGetBlockType(pos + ofs, blockType) &&
|
||||
(
|
||||
cBlockInfo::IsSolid(blockType) ||
|
||||
(blockType == E_BLOCK_LAVA) ||
|
||||
(blockType == E_BLOCK_STATIONARY_LAVA)
|
||||
)
|
||||
)
|
||||
{
|
||||
// Remove the cactus
|
||||
auto absPos = a_Chunk.RelativeToAbsolute(pos);
|
||||
a_Chunk.GetWorld()->DropBlockAsPickups(absPos);
|
||||
return i + 1;
|
||||
}
|
||||
} // for neighbor
|
||||
} // for i - numToGrow
|
||||
return numToGrow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) override
|
||||
{
|
||||
// Only allow growing if there's an air block above:
|
||||
if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR))
|
||||
{
|
||||
return super::CanGrow(a_Chunk, a_RelPos);
|
||||
}
|
||||
return paStay;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
+10
-5
@@ -6,15 +6,20 @@
|
||||
|
||||
|
||||
|
||||
class cBlockCakeHandler :
|
||||
class cBlockCakeHandler:
|
||||
public cBlockHandler
|
||||
{
|
||||
using super = cBlockHandler;
|
||||
public:
|
||||
cBlockCakeHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
cBlockCakeHandler(BLOCKTYPE a_BlockType):
|
||||
super(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ});
|
||||
@@ -26,11 +31,11 @@ public:
|
||||
|
||||
if (Meta >= 5)
|
||||
{
|
||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||
a_ChunkInterface.DigBlock(a_WorldInterface, {a_BlockX, a_BlockY, a_BlockZ});
|
||||
}
|
||||
else
|
||||
{
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta + 1);
|
||||
a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+41
-12
@@ -10,12 +10,18 @@
|
||||
class cBlockCocoaPodHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
using super = cBlockHandler;
|
||||
|
||||
public:
|
||||
cBlockCocoaPodHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
cBlockCocoaPodHandler(BLOCKTYPE a_BlockType):
|
||||
super(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
eBlockFace BlockFace = MetaToBlockFace(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
@@ -28,19 +34,15 @@ public:
|
||||
return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x3) == E_META_LOG_JUNGLE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
if (GetRandomProvider().RandBool(0.20))
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
NIBBLETYPE TypeMeta = Meta & 0x03;
|
||||
int GrowState = Meta >> 2;
|
||||
|
||||
if (GrowState < 2)
|
||||
{
|
||||
++GrowState;
|
||||
a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, static_cast<NIBBLETYPE>(GrowState << 2 | TypeMeta));
|
||||
}
|
||||
Grow(a_Chunk, {a_RelX, a_RelY, a_RelZ});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +61,28 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
auto meta = a_Chunk.GetMeta(a_RelPos);
|
||||
auto typeMeta = meta & 0x03;
|
||||
auto growState = meta >> 2;
|
||||
|
||||
if (growState >= 3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
auto newState = std::min(growState + a_NumStages, 3);
|
||||
a_Chunk.SetMeta(a_RelPos, static_cast<NIBBLETYPE>(newState << 2 | typeMeta));
|
||||
return newState - growState;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static eBlockFace MetaToBlockFace(NIBBLETYPE a_Meta)
|
||||
{
|
||||
switch (a_Meta & 0x3)
|
||||
switch (a_Meta & 0x03)
|
||||
{
|
||||
case 0: return BLOCK_FACE_ZM;
|
||||
case 1: return BLOCK_FACE_XP;
|
||||
@@ -75,6 +96,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static NIBBLETYPE BlockFaceToMeta(eBlockFace a_BlockFace)
|
||||
{
|
||||
switch (a_BlockFace)
|
||||
@@ -94,6 +119,10 @@ public:
|
||||
UNREACHABLE("Unsupported block face");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
+11
-14
@@ -90,27 +90,24 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
|
||||
// Check to see if the plant can grow
|
||||
auto Action = CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
|
||||
|
||||
// If there is still room to grow and the plant can grow, then grow.
|
||||
// Otherwise if the plant needs to die, then dig it up
|
||||
if ((Meta < RipeMeta) && (Action == paGrowth))
|
||||
auto oldMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
if (oldMeta >= RipeMeta)
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, ++Meta);
|
||||
}
|
||||
else if (Action == paDeath)
|
||||
{
|
||||
a_Chunk.GetWorld()->DigBlock(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
// Already ripe
|
||||
return 0;
|
||||
}
|
||||
auto newMeta = std::min<int>(oldMeta + a_NumStages, RipeMeta);
|
||||
ASSERT(newMeta > oldMeta);
|
||||
a_Chunk.GetWorld()->SetBlock(a_Chunk.RelativeToAbsolute(a_RelPos), m_BlockType, static_cast<NIBBLETYPE>(newMeta));
|
||||
return newMeta - oldMeta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
|
||||
|
||||
+21
-13
@@ -10,13 +10,17 @@
|
||||
|
||||
|
||||
|
||||
/** Handler used for all types of dirt and grass */
|
||||
/** Handler used for all types of dirt and grassblock.
|
||||
TODO: Split the Grassblock handler away from this class. */
|
||||
class cBlockDirtHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
using super = cBlockHandler;
|
||||
|
||||
public:
|
||||
cBlockDirtHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
|
||||
cBlockDirtHandler(BLOCKTYPE a_BlockType):
|
||||
super(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -91,37 +95,41 @@ public:
|
||||
// Y Coord out of range
|
||||
continue;
|
||||
}
|
||||
int BlockX = a_RelX + OfsX;
|
||||
int BlockY = a_RelY + OfsY;
|
||||
int BlockZ = a_RelZ + OfsZ;
|
||||
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(BlockX, BlockZ);
|
||||
if (Chunk == nullptr)
|
||||
Vector3i pos(a_RelX + OfsX, a_RelY + OfsY, a_RelZ + OfsZ);
|
||||
auto chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(pos);
|
||||
if (chunk == nullptr)
|
||||
{
|
||||
// Unloaded chunk
|
||||
continue;
|
||||
}
|
||||
Chunk->GetBlockTypeMeta(BlockX, BlockY, BlockZ, DestBlock, DestMeta);
|
||||
chunk->GetBlockTypeMeta(pos, DestBlock, DestMeta);
|
||||
if ((DestBlock != E_BLOCK_DIRT) || (DestMeta != E_META_DIRT_NORMAL))
|
||||
{
|
||||
// Not a regular dirt block
|
||||
continue;
|
||||
}
|
||||
BLOCKTYPE above = Chunk->GetBlock(BlockX, BlockY + 1, BlockZ);
|
||||
NIBBLETYPE light = std::max(Chunk->GetBlockLight(BlockX, BlockY + 1, BlockZ), Chunk->GetTimeAlteredLight(Chunk->GetSkyLight(BlockX, BlockY + 1, BlockZ)));
|
||||
auto abovePos = pos.addedY(1);
|
||||
BLOCKTYPE above = chunk->GetBlock(abovePos);
|
||||
NIBBLETYPE light = std::max(chunk->GetBlockLight(abovePos), chunk->GetTimeAlteredLight(chunk->GetSkyLight(abovePos)));
|
||||
if ((light > 4) &&
|
||||
cBlockInfo::IsTransparent(above) &&
|
||||
(!IsBlockLava(above)) &&
|
||||
(!IsBlockWaterOrIce(above))
|
||||
)
|
||||
{
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
|
||||
auto absPos = chunk->RelativeToAbsolute(pos);
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*chunk->GetWorld(), absPos.x, absPos.y, absPos.z, ssGrassSpread))
|
||||
{
|
||||
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
|
||||
chunk->FastSetBlock(pos, E_BLOCK_GRASS, 0);
|
||||
}
|
||||
}
|
||||
} // for i - repeat twice
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
+34
-2
@@ -141,6 +141,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Converts the player's yaw to placed door's blockmeta */
|
||||
inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
|
||||
{
|
||||
@@ -169,6 +173,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns a vector pointing one block in the direction the door is facing (where the outside is). */
|
||||
inline static Vector3i GetRelativeDirectionToOutside(NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
@@ -181,6 +189,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns true if the specified blocktype is any kind of door */
|
||||
inline static bool IsDoorBlockType(BLOCKTYPE a_Block)
|
||||
{
|
||||
@@ -203,6 +215,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns true iff the door at the specified coords is open.
|
||||
The coords may point to either the top part or the bottom part of the door. */
|
||||
static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
@@ -211,6 +227,10 @@ public:
|
||||
return ((Meta & 0x04) != 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns the complete meta composed from the both parts of the door as (TopMeta << 4) | BottomMeta
|
||||
The coords may point to either part of the door.
|
||||
The returned value has bit 3 (0x08) set iff the coords point to the top part of the door.
|
||||
@@ -243,6 +263,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Sets the door to the specified state. If the door is already in that state, does nothing. */
|
||||
static void SetOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
|
||||
{
|
||||
@@ -264,24 +288,32 @@ public:
|
||||
if ((Meta & 0x08) == 0)
|
||||
{
|
||||
// The block is the bottom part of the door
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, NewMeta);
|
||||
a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, NewMeta);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The block is the top part of the door, set the meta to the corresponding top part
|
||||
if (a_BlockY > 0)
|
||||
{
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ, NewMeta);
|
||||
a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY - 1, a_BlockZ}, NewMeta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Changes the door at the specified coords from open to close or vice versa */
|
||||
static void ChangeDoor(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
SetOpen(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, !IsOpen(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
+20
-20
@@ -189,6 +189,7 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||
case E_BLOCK_ACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType);
|
||||
case E_BLOCK_AIR: return new cBlockWithNoDrops<> (a_BlockType);
|
||||
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
|
||||
case E_BLOCK_BEACON: return new cBlockEntityHandler (a_BlockType);
|
||||
@@ -204,20 +205,19 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_BROWN_MUSHROOM: return new cBlockMushroomHandler (a_BlockType);
|
||||
case E_BLOCK_CACTUS: return new cBlockCactusHandler (a_BlockType);
|
||||
case E_BLOCK_CAKE: return new cBlockCakeHandler (a_BlockType);
|
||||
case E_BLOCK_CARROTS: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
||||
case E_BLOCK_CARPET: return new cBlockCarpetHandler (a_BlockType);
|
||||
case E_BLOCK_CARROTS: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
||||
case E_BLOCK_CAULDRON: return new cBlockCauldronHandler (a_BlockType);
|
||||
case E_BLOCK_CHAIN_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType);
|
||||
case E_BLOCK_CHEST: return new cBlockChestHandler (a_BlockType);
|
||||
case E_BLOCK_CLAY: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_COAL_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_COCOA_POD: return new cBlockCocoaPodHandler (a_BlockType);
|
||||
case E_BLOCK_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType);
|
||||
case E_BLOCK_ACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType);
|
||||
case E_BLOCK_CONCRETE_POWDER: return new cBlockConcretePowderHandler (a_BlockType);
|
||||
case E_BLOCK_COBBLESTONE: return new cBlockStoneHandler (a_BlockType);
|
||||
case E_BLOCK_COBBLESTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType);
|
||||
case E_BLOCK_COCOA_POD: return new cBlockCocoaPodHandler (a_BlockType);
|
||||
case E_BLOCK_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType);
|
||||
case E_BLOCK_CONCRETE_POWDER: return new cBlockConcretePowderHandler (a_BlockType);
|
||||
case E_BLOCK_CROPS: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
||||
case E_BLOCK_DARK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_DARK_OAK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||
@@ -234,18 +234,18 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType);
|
||||
case E_BLOCK_EMERALD_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
|
||||
case E_BLOCK_END_PORTAL_FRAME: return new cBlockEndPortalFrameHandler (a_BlockType);
|
||||
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
|
||||
case E_BLOCK_END_PORTAL_FRAME: return new cBlockEndPortalFrameHandler (a_BlockType);
|
||||
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler (a_BlockType);
|
||||
case E_BLOCK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||
case E_BLOCK_FROSTED_ICE: return new cBlockIceHandler (a_BlockType);
|
||||
case E_BLOCK_FIRE: return new cBlockFireHandler (a_BlockType);
|
||||
case E_BLOCK_FLOWER_POT: return new cBlockFlowerPotHandler (a_BlockType);
|
||||
case E_BLOCK_FROSTED_ICE: return new cBlockIceHandler (a_BlockType);
|
||||
case E_BLOCK_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
|
||||
case E_BLOCK_GLOWSTONE: return new cBlockGlowstoneHandler (a_BlockType);
|
||||
case E_BLOCK_GOLD_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_GLASS: return new cBlockGlassHandler (a_BlockType);
|
||||
case E_BLOCK_GLASS_PANE: return new cBlockGlassHandler (a_BlockType);
|
||||
case E_BLOCK_GLOWSTONE: return new cBlockGlowstoneHandler (a_BlockType);
|
||||
case E_BLOCK_GOLD_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_GRASS: return new cBlockDirtHandler (a_BlockType);
|
||||
case E_BLOCK_GRAVEL: return new cBlockGravelHandler (a_BlockType);
|
||||
case E_BLOCK_HAY_BALE: return new cBlockSidewaysHandler (a_BlockType);
|
||||
@@ -264,29 +264,30 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_JUNGLE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||
case E_BLOCK_JUNGLE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_LADDER: return new cBlockLadderHandler (a_BlockType);
|
||||
case E_BLOCK_LEVER: return new cBlockLeverHandler (a_BlockType);
|
||||
case E_BLOCK_LAPIS_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_LAVA: return new cBlockLavaHandler (a_BlockType);
|
||||
case E_BLOCK_LEAVES: return new cBlockLeavesHandler (a_BlockType);
|
||||
case E_BLOCK_LEVER: return new cBlockLeverHandler (a_BlockType);
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler (a_BlockType);
|
||||
case E_BLOCK_LILY_PAD: return new cBlockLilypadHandler (a_BlockType);
|
||||
case E_BLOCK_LIT_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
|
||||
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
|
||||
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
|
||||
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
||||
case E_BLOCK_MELON_STEM: return new cBlockMelonStemHandler (a_BlockType);
|
||||
case E_BLOCK_MOB_SPAWNER: return new cBlockMobSpawnerHandler (a_BlockType);
|
||||
case E_BLOCK_MYCELIUM: return new cBlockMyceliumHandler (a_BlockType);
|
||||
case E_BLOCK_NETHERRACK: return new cBlockNetherrack (a_BlockType);
|
||||
case E_BLOCK_NETHER_BRICK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
|
||||
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
|
||||
case E_BLOCK_NETHERRACK: return new cBlockNetherrack (a_BlockType);
|
||||
case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
|
||||
case E_BLOCK_NEW_LEAVES: return new cBlockLeavesHandler (a_BlockType);
|
||||
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
|
||||
case E_BLOCK_RED_SANDSTONE_SLAB: return new cBlockSlabHandler (a_BlockType);
|
||||
case E_BLOCK_NOTE_BLOCK: return new cBlockEntityHandler (a_BlockType);
|
||||
case E_BLOCK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_OAK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||
case E_BLOCK_OAK_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_PACKED_ICE: return new cBlockIceHandler (a_BlockType);
|
||||
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
|
||||
case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler;
|
||||
@@ -294,14 +295,13 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_POTATOES: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
||||
case E_BLOCK_POWERED_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||
case E_BLOCK_PUMPKIN: return new cBlockPumpkinHandler (a_BlockType);
|
||||
case E_BLOCK_PUMPKIN_STEM: return new cBlockStemsHandler (a_BlockType);
|
||||
case E_BLOCK_PUMPKIN_STEM: return new cBlockPumpkinStemHandler (a_BlockType);
|
||||
case E_BLOCK_PURPUR_DOUBLE_SLAB: return new cBlockDoubleSlabHandler (a_BlockType);
|
||||
case E_BLOCK_PURPUR_SLAB: return new cBlockSlabHandler (a_BlockType);
|
||||
case E_BLOCK_PURPUR_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_QUARTZ_BLOCK: return new cBlockQuartzHandler (a_BlockType);
|
||||
case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||
case E_BLOCK_RED_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_REDSTONE_LAMP_ON: return new cBlockRedstoneLampHandler (a_BlockType);
|
||||
case E_BLOCK_REDSTONE_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_REDSTONE_ORE_GLOWING: return new cBlockOreHandler (a_BlockType);
|
||||
@@ -312,14 +312,16 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_REDSTONE_WIRE: return new cBlockRedstoneHandler (a_BlockType);
|
||||
case E_BLOCK_RED_MUSHROOM: return new cBlockMushroomHandler (a_BlockType);
|
||||
case E_BLOCK_RED_ROSE: return new cBlockFlowerHandler (a_BlockType);
|
||||
case E_BLOCK_RED_SANDSTONE_SLAB: return new cBlockSlabHandler (a_BlockType);
|
||||
case E_BLOCK_RED_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_REPEATING_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType);
|
||||
case E_BLOCK_SAND: return new cBlockSandHandler (a_BlockType);
|
||||
case E_BLOCK_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_SAPLING: return new cBlockSaplingHandler (a_BlockType);
|
||||
case E_BLOCK_SEA_LANTERN: return new cBlockSeaLanternHandler (a_BlockType);
|
||||
case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType);
|
||||
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
||||
case E_BLOCK_SLIME_BLOCK: return new cBlockSlimeHandler (a_BlockType);
|
||||
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
||||
case E_BLOCK_SPONGE: return new cBlockSpongeHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||
@@ -337,9 +339,9 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_STONE_SLAB: return new cBlockSlabHandler (a_BlockType);
|
||||
case E_BLOCK_SUGARCANE: return new cBlockSugarcaneHandler (a_BlockType);
|
||||
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType);
|
||||
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
|
||||
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
|
||||
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
|
||||
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
|
||||
case E_BLOCK_TRAPPED_CHEST: return new cBlockChestHandler (a_BlockType);
|
||||
case E_BLOCK_TRIPWIRE: return new cBlockTripwireHandler (a_BlockType);
|
||||
case E_BLOCK_TRIPWIRE_HOOK: return new cBlockTripwireHookHandler (a_BlockType);
|
||||
@@ -347,10 +349,8 @@ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_WALLSIGN: return new cBlockWallSignHandler (a_BlockType);
|
||||
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
|
||||
case E_BLOCK_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType);
|
||||
case E_BLOCK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE: return new cBlockPressurePlateHandler (a_BlockType);
|
||||
case E_BLOCK_WOODEN_SLAB: return new cBlockSlabHandler (a_BlockType);
|
||||
case E_BLOCK_OAK_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_WOOL: return new cBlockClothHandler (a_BlockType);
|
||||
case E_BLOCK_WORKBENCH: return new cBlockWorkbenchHandler (a_BlockType);
|
||||
case E_BLOCK_YELLOW_FLOWER: return new cBlockFlowerHandler (a_BlockType);
|
||||
|
||||
@@ -200,6 +200,10 @@ public:
|
||||
Returns block meta following rotation */
|
||||
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) { return a_Meta; }
|
||||
|
||||
/** 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). */
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) { return 0; }
|
||||
|
||||
/** 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);
|
||||
|
||||
@@ -42,17 +42,22 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
if ((Meta < 3) && (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth))
|
||||
auto oldMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
auto meta = std::min(oldMeta + a_NumStages, 3);
|
||||
if ((oldMeta < 3) && (CanGrow(a_Chunk, a_RelPos) == paGrowth))
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_NETHER_WART, ++Meta);
|
||||
a_Chunk.SetBlock(a_RelPos, m_BlockType, static_cast<NIBBLETYPE>(meta));
|
||||
return meta - oldMeta;
|
||||
}
|
||||
else if (Meta > 3) // In older versions of cuberite, there was a bug which made wart grow too much. This check fixes previously saved buggy warts.
|
||||
|
||||
// In older versions of cuberite, there was a bug which made wart grow too much. This check fixes previously saved buggy warts.
|
||||
if (oldMeta > 3)
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_NETHER_WART, 3);
|
||||
a_Chunk.FastSetBlock(a_RelPos, m_BlockType, 3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+44
-17
@@ -1,19 +1,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "BlockHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Base class for plants that use light values to decide whether to grow or not. */
|
||||
/** Base class for plants that use light values to decide whether to grow or not.
|
||||
On block update, the plant decides whether to grow, die or stay as-is, based on the CanGrow() overridable method result. */
|
||||
template <bool NeedsLightToGrow>
|
||||
class cBlockPlant:
|
||||
public cBlockHandler
|
||||
{
|
||||
using super = cBlockHandler;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
cBlockPlant(BLOCKTYPE a_BlockType):
|
||||
@@ -22,6 +23,33 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
Vector3i relPos(a_RelX, a_RelY, a_RelZ);
|
||||
auto action = CanGrow(a_Chunk, relPos);
|
||||
switch (action)
|
||||
{
|
||||
case paGrowth:
|
||||
{
|
||||
Grow(a_Chunk, relPos);
|
||||
break;
|
||||
}
|
||||
case paDeath:
|
||||
{
|
||||
a_ChunkInterface.DigBlock(a_WorldInterface, a_Chunk.RelativeToAbsolute(relPos));
|
||||
break;
|
||||
}
|
||||
case paStay: break; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** The action the plant can take on an update. */
|
||||
@@ -40,9 +68,8 @@ protected:
|
||||
If the plant doesn't require light to grow, then it returns paGrowth.
|
||||
If the plant requires light to grow and there is enough light, it returns paGrowth.
|
||||
If the plant requires light to grow and there isn't enough light, it returns paStay.
|
||||
If the plant requires light to grow and there is too little light, it returns paDeath.
|
||||
*/
|
||||
PlantAction HasEnoughLight(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
If the plant requires light to grow and there is too little light, it returns paDeath. */
|
||||
PlantAction HasEnoughLight(cChunk & a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
// If the plant requires light to grow, check to see if there is enough light
|
||||
// Otherwise, return true
|
||||
@@ -50,8 +77,8 @@ protected:
|
||||
{
|
||||
return paGrowth;
|
||||
}
|
||||
NIBBLETYPE Blocklight = a_Chunk.GetBlockLight(a_RelX, a_RelY, a_RelZ);
|
||||
NIBBLETYPE SkyLight = a_Chunk.GetSkyLight (a_RelX, a_RelY, a_RelZ);
|
||||
NIBBLETYPE Blocklight = a_Chunk.GetBlockLight(a_RelPos);
|
||||
NIBBLETYPE SkyLight = a_Chunk.GetSkyLight (a_RelPos);
|
||||
NIBBLETYPE Light = a_Chunk.GetTimeAlteredLight(SkyLight);
|
||||
|
||||
// If the amount of light provided by blocks is greater than the sky light, use it instead
|
||||
@@ -85,27 +112,27 @@ protected:
|
||||
paDeath is returned when there isn't enough light for the plant to survive.
|
||||
Plants that don't require light will never have a paDeath returned
|
||||
*/
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
// Plant can grow if it has the required amount of light, and it passes a random chance based on surrounding blocks
|
||||
PlantAction Action = HasEnoughLight(a_Chunk, a_RelX, a_RelY, a_RelZ);
|
||||
if ((Action == paGrowth) && !GetRandomProvider().RandBool(1.0 / GetGrowthChance(a_Chunk, a_RelX, a_RelY, a_RelZ)))
|
||||
auto action = HasEnoughLight(a_Chunk, a_RelPos);
|
||||
if ((action == paGrowth) && !GetRandomProvider().RandBool(1.0 / GetGrowthChance(a_Chunk, a_RelPos)))
|
||||
{
|
||||
Action = paStay;
|
||||
action = paStay;
|
||||
}
|
||||
return Action;
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Generates a int value between 4 and 25 based on surrounding blocks that affect how quickly the plant grows.
|
||||
/** Generates an int value between 4 and 25 based on surrounding blocks that affect how quickly the plant grows.
|
||||
The higher the value, the less likely the plant is to grow */
|
||||
virtual int GetGrowthChance(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
virtual int GetGrowthChance(cChunk & a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
float Chance = 1.0f;
|
||||
a_RelY -= 1;
|
||||
a_RelPos.y -= 1;
|
||||
for (int x = -1; x < 2; ++x)
|
||||
{
|
||||
for (int z = -1; z < 2; ++z)
|
||||
@@ -115,7 +142,7 @@ protected:
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
// If the chunk we are trying to get the block information from is loaded
|
||||
if (a_Chunk.UnboundedRelGetBlock(a_RelX + x, a_RelY, a_RelZ + z, Block, Meta))
|
||||
if (a_Chunk.UnboundedRelGetBlock(a_RelPos + Vector3i(x, 0, z), Block, Meta))
|
||||
{
|
||||
cBlockHandler * Handler = BlockHandler(Block);
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ public:
|
||||
return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
@@ -63,6 +67,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool CanGrowAt(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
a_Meta = a_Meta & 0x07;
|
||||
@@ -149,8 +157,6 @@ public:
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + 1, check);
|
||||
CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
|
||||
|
||||
|
||||
|
||||
while (CheckHeight && CanGrow)
|
||||
{
|
||||
check = a_Chunk.GetBlock(a_RelX, a_RelY + CheckHeight, a_RelZ);
|
||||
@@ -175,7 +181,51 @@ public:
|
||||
return CanGrow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
auto blockMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
auto typeMeta = blockMeta & 0x07;
|
||||
auto growState = blockMeta >> 3;
|
||||
int res = 0;
|
||||
|
||||
// Try to increase the sapling's growState:
|
||||
if (growState < 1)
|
||||
{
|
||||
++growState;
|
||||
a_Chunk.FastSetBlock(a_RelPos, m_BlockType, static_cast<NIBBLETYPE>(growState << 3 | typeMeta));
|
||||
if (a_NumStages == 1)
|
||||
{
|
||||
// Only asked to grow one stage, which we did. Bail out.
|
||||
return 1;
|
||||
}
|
||||
res = 1;
|
||||
}
|
||||
|
||||
// The sapling is grown, now it becomes a tree:
|
||||
a_Chunk.GetWorld()->GrowTreeFromSapling(a_Chunk.RelativeToAbsolute(a_RelPos), blockMeta);
|
||||
return res + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool IsLargeTree(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
BLOCKTYPE type;
|
||||
@@ -192,12 +242,6 @@ private:
|
||||
|
||||
return LargeTree;
|
||||
}
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
return 7;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
+124
-28
@@ -7,7 +7,11 @@
|
||||
|
||||
|
||||
|
||||
class cBlockStemsHandler :
|
||||
/** Handler for stems from which produce grows in an adjacent block (melon, pumpkin) after it becomes ripe (meta == 7).
|
||||
ProduceBlockType is the blocktype for the produce to be grown.
|
||||
StemPickupType is the item type for the pickup resulting from breaking the stem. */
|
||||
template <BLOCKTYPE ProduceBlockType, ENUM_ITEM_ID StemPickupType>
|
||||
class cBlockStemsHandler:
|
||||
public cBlockPlant<true>
|
||||
{
|
||||
using super = cBlockPlant<true>;
|
||||
@@ -25,51 +29,143 @@ public:
|
||||
|
||||
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
|
||||
{
|
||||
auto itemType = (m_BlockType == E_BLOCK_MELON_STEM) ? E_ITEM_MELON_SEEDS : E_ITEM_PUMPKIN_SEEDS;
|
||||
return cItem(itemType, 1, 0);
|
||||
return cItem(StemPickupType, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
auto Action = CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
|
||||
if (Action == paGrowth)
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
if (Meta >= 7)
|
||||
{
|
||||
// Grow the produce:
|
||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
a_Chunk.GetWorld()->GrowMelonPumpkin(BlockX, a_RelY, BlockZ, m_BlockType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grow the stem:
|
||||
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, Meta + 1);
|
||||
}
|
||||
}
|
||||
else if (Action == paDeath)
|
||||
{
|
||||
a_Chunk.GetWorld()->DigBlock(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
auto oldMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
auto meta = oldMeta + a_NumStages;
|
||||
a_Chunk.SetBlock(a_RelPos, m_BlockType, static_cast<NIBBLETYPE>(std::min(meta, 7))); // Update the stem
|
||||
if (meta > 7)
|
||||
{
|
||||
if (growProduce(a_Chunk, a_RelPos))
|
||||
{
|
||||
return 8 - oldMeta;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 7 - oldMeta;
|
||||
}
|
||||
}
|
||||
return meta - oldMeta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** Grows the final produce next to the stem at the specified pos.
|
||||
Returns true if successful, false if not. */
|
||||
bool growProduce(cChunk & a_Chunk, Vector3i a_StemRelPos)
|
||||
{
|
||||
auto & random = GetRandomProvider();
|
||||
|
||||
// Check if there's another produce around the stem, if so, abort:
|
||||
static const Vector3i neighborOfs[] =
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
};
|
||||
bool isValid;
|
||||
BLOCKTYPE blockType[4];
|
||||
NIBBLETYPE blockMeta; // unused
|
||||
isValid = a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[0], blockType[0], blockMeta);
|
||||
isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[1], blockType[1], blockMeta);
|
||||
isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[2], blockType[2], blockMeta);
|
||||
isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[3], blockType[3], blockMeta);
|
||||
if (
|
||||
!isValid ||
|
||||
(blockType[0] == ProduceBlockType) ||
|
||||
(blockType[1] == ProduceBlockType) ||
|
||||
(blockType[2] == ProduceBlockType) ||
|
||||
(blockType[3] == ProduceBlockType)
|
||||
)
|
||||
{
|
||||
// Neighbors not valid or already taken by the same produce
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pick a direction in which to place the produce:
|
||||
int x = 0, z = 0;
|
||||
int checkType = random.RandInt(3); // The index to the neighbors array which should be checked for emptiness
|
||||
switch (checkType)
|
||||
{
|
||||
case 0: x = 1; break;
|
||||
case 1: x = -1; break;
|
||||
case 2: z = 1; break;
|
||||
case 3: z = -1; break;
|
||||
}
|
||||
|
||||
// Check that the block in that direction is empty:
|
||||
switch (blockType[checkType])
|
||||
{
|
||||
case E_BLOCK_AIR:
|
||||
case E_BLOCK_SNOW:
|
||||
case E_BLOCK_TALL_GRASS:
|
||||
case E_BLOCK_DEAD_BUSH:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
|
||||
// Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok
|
||||
BLOCKTYPE soilType;
|
||||
auto produceRelPos = a_StemRelPos + Vector3i(x, 0, z);
|
||||
VERIFY(a_Chunk.UnboundedRelGetBlock(produceRelPos.addedY(-1), soilType, blockMeta));
|
||||
switch (soilType)
|
||||
{
|
||||
case E_BLOCK_DIRT:
|
||||
case E_BLOCK_GRASS:
|
||||
case E_BLOCK_FARMLAND:
|
||||
{
|
||||
// Place a randomly-facing produce:
|
||||
NIBBLETYPE meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast<NIBBLETYPE>(random.RandInt(4) % 4);
|
||||
auto produceAbsPos = a_Chunk.RelativeToAbsolute(produceRelPos);
|
||||
FLOGD("Growing melon / pumpkin at {0} (<{1}, {2}> from stem), overwriting {3}, growing on top of {4}, meta {5}",
|
||||
produceAbsPos,
|
||||
x, z,
|
||||
ItemTypeToString(blockType[checkType]),
|
||||
ItemTypeToString(soilType),
|
||||
meta
|
||||
);
|
||||
a_Chunk.GetWorld()->SetBlock(produceAbsPos, ProduceBlockType, meta);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} ;
|
||||
|
||||
using cBlockMelonStemHandler = cBlockStemsHandler<E_BLOCK_MELON, E_ITEM_MELON_SEEDS>;
|
||||
using cBlockPumpkinStemHandler = cBlockStemsHandler<E_BLOCK_PUMPKIN, E_ITEM_PUMPKIN_SEEDS>;
|
||||
|
||||
|
||||
|
||||
|
||||
+52
-13
@@ -82,13 +82,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
if (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth)
|
||||
{
|
||||
a_Chunk.GetWorld()->GrowSugarcane(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
@@ -97,17 +93,60 @@ public:
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
|
||||
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
auto Action = paStay;
|
||||
if (((a_RelY + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_AIR))
|
||||
// Check the total height of the sugarcane blocks here:
|
||||
int top = a_RelPos.y + 1;
|
||||
while (
|
||||
(top < cChunkDef::Height) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_SUGARCANE)
|
||||
)
|
||||
{
|
||||
Action = super::CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
|
||||
++top;
|
||||
}
|
||||
int bottom = a_RelPos.y - 1;
|
||||
while (
|
||||
(bottom > 0) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_SUGARCANE)
|
||||
)
|
||||
{
|
||||
--bottom;
|
||||
}
|
||||
|
||||
return Action;
|
||||
// Grow by at most a_NumStages, but no more than max height:
|
||||
auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top - bottom));
|
||||
Vector3i topPos(a_RelPos.x, top, a_RelPos.z);
|
||||
for (int i = 0; i < toGrow; i++)
|
||||
{
|
||||
if (a_Chunk.GetBlock(topPos.addedY(i)) == E_BLOCK_AIR)
|
||||
{
|
||||
a_Chunk.SetBlock(topPos.addedY(i), E_BLOCK_SUGARCANE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return i;
|
||||
}
|
||||
} // for i
|
||||
return toGrow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) override
|
||||
{
|
||||
// Only allow growing if there's an air block above:
|
||||
if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR))
|
||||
{
|
||||
return super::CanGrow(a_Chunk, a_RelPos);
|
||||
}
|
||||
return paStay;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
|
||||
/** Handles the grass that is 1 block tall */
|
||||
class cBlockTallGrassHandler:
|
||||
public cBlockHandler
|
||||
{
|
||||
@@ -68,6 +69,30 @@ public:
|
||||
|
||||
|
||||
|
||||
/** Growing a tall grass produces a big flower (2-block high fern or double-tall grass). */
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
|
||||
{
|
||||
if (a_RelPos.y > (cChunkDef::Height - 2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
auto blockMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
NIBBLETYPE largeFlowerMeta;
|
||||
switch (blockMeta)
|
||||
{
|
||||
case E_META_TALL_GRASS_GRASS: largeFlowerMeta = E_META_BIG_FLOWER_DOUBLE_TALL_GRASS; break;
|
||||
case E_META_TALL_GRASS_FERN: largeFlowerMeta = E_META_BIG_FLOWER_LARGE_FERN; break;
|
||||
default: return 0;
|
||||
}
|
||||
a_Chunk.SetBlock(a_RelPos, E_BLOCK_BIG_FLOWER, largeFlowerMeta);
|
||||
a_Chunk.SetBlock(a_RelPos.addedY(1), E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
BLOCKTYPE cChunkInterface::GetBlock(Vector3i a_Pos)
|
||||
{
|
||||
return m_ChunkMap->GetBlock(a_Pos.x, a_Pos.y, a_Pos.z);
|
||||
return m_ChunkMap->GetBlock(a_Pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ BLOCKTYPE cChunkInterface::GetBlock(Vector3i a_Pos)
|
||||
|
||||
NIBBLETYPE cChunkInterface::GetBlockMeta(Vector3i a_Pos)
|
||||
{
|
||||
return m_ChunkMap->GetBlockMeta(a_Pos.x, a_Pos.y, a_Pos.z);
|
||||
return m_ChunkMap->GetBlockMeta(a_Pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,30 +47,18 @@ void cChunkInterface::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBL
|
||||
|
||||
|
||||
|
||||
void cChunkInterface::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData, bool a_ShouldMarkDirty, bool a_ShouldInformClient)
|
||||
void cChunkInterface::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData, bool a_ShouldMarkDirty, bool a_ShouldInformClient)
|
||||
{
|
||||
m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData, a_ShouldMarkDirty, a_ShouldInformClient);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Sets the block at the specified coords to the specified value.
|
||||
The replacement doesn't trigger block updates.
|
||||
The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block)
|
||||
*/
|
||||
void cChunkInterface::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
|
||||
m_ChunkMap->SetBlockMeta(a_BlockPos, a_MetaData, a_ShouldMarkDirty, a_ShouldInformClient);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkInterface::FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
void cChunkInterface::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta);
|
||||
m_ChunkMap->FastSetBlock(a_BlockPos, a_BlockType, a_BlockMeta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,15 +33,26 @@ public:
|
||||
return SetBlock({a_BlockX, a_BlockY, a_BlockZ}, a_BlockType, a_BlockMeta);
|
||||
}
|
||||
|
||||
void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData, bool a_ShouldMarkDirty = true, bool a_ShouldInformClient = true);
|
||||
/** Sets the meta for the specified block, while keeping the blocktype.
|
||||
If a_ShouldMarkDirty is true, the chunk is marked dirty by this change (false is used eg. by water turning still).
|
||||
If a_ShouldInformClients is true, the change is broadcast to all clients of the chunk.
|
||||
Ignored if the chunk is invalid. */
|
||||
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData, bool a_ShouldMarkDirty = true, bool a_ShouldInformClient = true);
|
||||
|
||||
/** OBSOLETE, Use the Vector3-based overload instead.
|
||||
Sets the meta for the specified block, while keeping the blocktype.
|
||||
If a_ShouldMarkDirty is true, the chunk is marked dirty by this change (false is used eg. by water turning still).
|
||||
If a_ShouldInformClients is true, the change is broadcast to all clients of the chunk.
|
||||
Ignored if the chunk is invalid. */
|
||||
void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData, bool a_ShouldMarkDirty = true, bool a_ShouldInformClient = true)
|
||||
{
|
||||
return SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, a_MetaData, a_ShouldMarkDirty, a_ShouldInformClient);
|
||||
}
|
||||
|
||||
/** Sets the block at the specified coords to the specified value.
|
||||
The replacement doesn't trigger block updates.
|
||||
The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block)
|
||||
*/
|
||||
void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
|
||||
void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block). */
|
||||
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
|
||||
/** Use block entity on coordinate.
|
||||
returns true if the use was successful, return false to use the block as a "normal" block */
|
||||
|
||||
Reference in New Issue
Block a user