Merge branch 'master' into MobSpawner
Conflicts: MCServer/Plugins/Core
This commit is contained in:
@@ -17,15 +17,25 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
// Don't drop anything
|
||||
}
|
||||
|
||||
|
||||
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_SAND);
|
||||
if (a_RelY <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
|
||||
switch (BelowBlock)
|
||||
{
|
||||
case E_BLOCK_CLAY:
|
||||
case E_BLOCK_HARDENED_CLAY:
|
||||
case E_BLOCK_STAINED_CLAY:
|
||||
case E_BLOCK_SAND:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
+11
-3
@@ -21,7 +21,15 @@ public:
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_DIRT, 1, 0));
|
||||
if (a_BlockMeta == E_META_DIRT_COARSE)
|
||||
{
|
||||
// Drop the coarse block (dirt, meta 1)
|
||||
a_Pickups.Add(E_BLOCK_DIRT, 1, E_META_DIRT_COARSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Pickups.Add(E_BLOCK_DIRT, 1, E_META_DIRT_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +72,7 @@ public:
|
||||
int BlockY = a_RelY + OfsY;
|
||||
int BlockZ = a_RelZ + OfsZ;
|
||||
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(BlockX, BlockZ);
|
||||
if (Chunk == NULL)
|
||||
if (Chunk == nullptr)
|
||||
{
|
||||
// Unloaded chunk
|
||||
continue;
|
||||
@@ -81,7 +89,7 @@ public:
|
||||
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
|
||||
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
|
||||
{
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
|
||||
{
|
||||
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
|
||||
}
|
||||
|
||||
+60
-2
@@ -55,7 +55,49 @@ public:
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.push_back(cItem((m_BlockType == E_BLOCK_WOODEN_DOOR) ? E_ITEM_WOODEN_DOOR : E_ITEM_IRON_DOOR, 1, 0));
|
||||
switch (m_BlockType)
|
||||
{
|
||||
case E_BLOCK_WOODEN_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_WOODEN_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_ACACIA_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_ACACIA_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_BIRCH_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_BIRCH_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_DARK_OAK_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_DARK_OAK_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_JUNGLE_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_JUNGLE_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_SPRUCE_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_SPRUCE_DOOR);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_IRON_DOOR:
|
||||
{
|
||||
a_Pickups.Add(E_ITEM_IRON_DOOR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled door type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +173,23 @@ public:
|
||||
/** Returns true if the specified blocktype is any kind of door */
|
||||
inline static bool IsDoor(BLOCKTYPE a_Block)
|
||||
{
|
||||
return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
|
||||
switch (a_Block)
|
||||
{
|
||||
case E_BLOCK_ACACIA_DOOR:
|
||||
case E_BLOCK_BIRCH_DOOR:
|
||||
case E_BLOCK_DARK_OAK_DOOR:
|
||||
case E_BLOCK_IRON_DOOR:
|
||||
case E_BLOCK_JUNGLE_DOOR:
|
||||
case E_BLOCK_SPRUCE_DOOR:
|
||||
case E_BLOCK_WOODEN_DOOR:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.Add(E_BLOCK_FENCE_GATE, 1, 0); // Reset meta to zero
|
||||
a_Pickups.Add(m_BlockType, 1, 0); // Reset meta to zero
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../Item.h"
|
||||
#include "../World.h"
|
||||
#include "../Chunk.h"
|
||||
#include "BlockPluginInterface.h"
|
||||
#include "BlockAnvil.h"
|
||||
#include "BlockBed.h"
|
||||
#include "BlockBigFlower.h"
|
||||
@@ -36,7 +37,6 @@
|
||||
#include "BlockGlass.h"
|
||||
#include "BlockGlowstone.h"
|
||||
#include "BlockGravel.h"
|
||||
#include "BlockHayBale.h"
|
||||
#include "BlockMobHead.h"
|
||||
#include "BlockHopper.h"
|
||||
#include "BlockIce.h"
|
||||
@@ -83,7 +83,6 @@
|
||||
#include "BlockWorkbench.h"
|
||||
|
||||
|
||||
#include "BlockPluginInterface.h"
|
||||
|
||||
|
||||
|
||||
@@ -100,9 +99,9 @@ public:
|
||||
for (BLOCKTYPE Type = 0; Type < E_BLOCK_MAX_TYPE_ID; Type++)
|
||||
{
|
||||
cBlockHandler * Handler = cBlockInfo::GetHandler(Type);
|
||||
if (Handler == NULL)
|
||||
if (Handler == nullptr)
|
||||
{
|
||||
printf("NULL handler for block type %d!\n", Type);
|
||||
printf("nullptr handler for block type %d!\n", Type);
|
||||
continue;
|
||||
}
|
||||
AString BlockName = ItemTypeToString(Type);
|
||||
@@ -231,7 +230,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_GLASS_PANE: return new cBlockGlassHandler (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 cBlockHayBaleHandler (a_BlockType);
|
||||
case E_BLOCK_HAY_BALE: return new cBlockSidewaysHandler (a_BlockType);
|
||||
case E_BLOCK_HEAD: return new cBlockMobHeadHandler (a_BlockType);
|
||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
|
||||
case E_BLOCK_HOPPER: return new cBlockHopperHandler (a_BlockType);
|
||||
@@ -294,6 +293,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType);
|
||||
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||
case E_BLOCK_SPRUCE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_STAINED_GLASS: return new cBlockGlassHandler (a_BlockType);
|
||||
case E_BLOCK_STAINED_GLASS_PANE: return new cBlockGlassHandler (a_BlockType);
|
||||
@@ -441,7 +441,7 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
|
||||
|
||||
if (a_CanDrop)
|
||||
{
|
||||
if ((a_Digger != NULL) && (a_Digger->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0))
|
||||
if ((a_Digger != nullptr) && (a_Digger->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0))
|
||||
{
|
||||
switch (m_BlockType)
|
||||
{
|
||||
@@ -562,7 +562,7 @@ void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterf
|
||||
{
|
||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
DropBlock(a_ChunkInterface, *a_Chunk.GetWorld(), a_PluginInterface, NULL, BlockX, a_RelY, BlockZ);
|
||||
DropBlock(a_ChunkInterface, *a_Chunk.GetWorld(), a_PluginInterface, nullptr, BlockX, a_RelY, BlockZ);
|
||||
}
|
||||
|
||||
a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
|
||||
|
||||
/** Handles the dropping, but not destruction, of a block based on what ConvertTo(Verbatim)Pickups() returns, including the spawning of pickups and alertion of plugins
|
||||
@param a_Digger The entity causing the drop; it may be NULL
|
||||
@param a_Digger The entity causing the drop; it may be nullptr
|
||||
@param a_CanDrop Informs the handler whether the block should be dropped at all. One example when this is false is when stone is destroyed by hand
|
||||
@param a_DropVerbatim Calls ConvertToVerbatimPickups() instead of its counterpart, meaning the block itself is dropped by default (due to a speical tool or enchantment)
|
||||
*/
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockSideways.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockHayBaleHandler :
|
||||
public cBlockSidewaysHandler
|
||||
{
|
||||
public:
|
||||
cBlockHayBaleHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockSidewaysHandler(a_BlockType)
|
||||
{
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
}
|
||||
|
||||
// Decay the leaves:
|
||||
DropBlock(a_ChunkInterface, a_WorldInterface, a_PluginInterface, NULL, BlockX, a_RelY, BlockZ);
|
||||
DropBlock(a_ChunkInterface, a_WorldInterface, a_PluginInterface, nullptr, BlockX, a_RelY, BlockZ);
|
||||
a_ChunkInterface.DigBlock(a_WorldInterface, BlockX, a_RelY, BlockZ);
|
||||
}
|
||||
} ;
|
||||
|
||||
+29
-7
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../Chunk.h"
|
||||
#include "MetaRotator.h"
|
||||
|
||||
|
||||
#include "BlockSlab.h"
|
||||
|
||||
|
||||
class cBlockLeverHandler :
|
||||
@@ -93,13 +93,35 @@ public:
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
NIBBLETYPE Meta;
|
||||
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
|
||||
eBlockFace Face = BlockMetaDataToBlockFace(Meta);
|
||||
|
||||
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
|
||||
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
||||
AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
|
||||
|
||||
return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
|
||||
if ((a_RelY < 0) || (a_RelY >= cChunkDef::Height -1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BlockIsOn;
|
||||
a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockIsOn, Meta);
|
||||
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BlockIsOn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (cBlockSlabHandler::IsAnySlabType(BlockIsOn))
|
||||
{
|
||||
// Check if the slab is turned up side down
|
||||
if (((Meta & 0x08) == 0x08) && (Face == BLOCK_FACE_TOP))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
|
||||
{
|
||||
cChunkInterface ChunkInterface(a_World->GetChunkMap());
|
||||
cBlockInServerPluginInterface PluginInterface(*a_World);
|
||||
Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, NULL, a_BlockX, a_BlockY, a_BlockZ);
|
||||
Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, nullptr, a_BlockX, a_BlockY, a_BlockZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ private:
|
||||
case E_BLOCK_BREWING_STAND:
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_COMMAND_BLOCK:
|
||||
case E_BLOCK_DAYLIGHT_SENSOR:
|
||||
case E_BLOCK_DISPENSER:
|
||||
case E_BLOCK_DROPPER:
|
||||
case E_BLOCK_ENCHANTMENT_TABLE:
|
||||
@@ -108,6 +109,7 @@ private:
|
||||
// Notice the lack of an E_BLOCK_ENDER_CHEST here; its because ender chests can totally be pushed/pulled in MCS :)
|
||||
case E_BLOCK_FURNACE:
|
||||
case E_BLOCK_LIT_FURNACE:
|
||||
case E_BLOCK_INVERTED_DAYLIGHT_SENSOR:
|
||||
case E_BLOCK_HOPPER:
|
||||
case E_BLOCK_JUKEBOX:
|
||||
case E_BLOCK_MOB_SPAWNER:
|
||||
@@ -115,7 +117,9 @@ private:
|
||||
case E_BLOCK_NOTE_BLOCK:
|
||||
case E_BLOCK_OBSIDIAN:
|
||||
case E_BLOCK_PISTON_EXTENSION:
|
||||
case E_BLOCK_STANDING_BANNER:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_WALL_BANNER:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/** This interface is used to decouple block handlers from the cPluginManager dependancy through cWorld.
|
||||
|
||||
|
||||
|
||||
|
||||
/** This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
|
||||
The block handlers call this interface, which is then implemented by the specific classes that
|
||||
the caller provides.
|
||||
*/
|
||||
@@ -10,5 +14,10 @@ class cBlockPluginInterface
|
||||
public:
|
||||
virtual ~cBlockPluginInterface() {}
|
||||
|
||||
virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
|
||||
virtual bool CallHookBlockToPickups(cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../World.h"
|
||||
#include "BlockSlab.h"
|
||||
|
||||
|
||||
|
||||
@@ -16,11 +17,33 @@ public:
|
||||
: cBlockHandler(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
|
||||
if (a_RelY <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
// Check if the slab is turned up side down
|
||||
if ((BelowBlockMeta & 0x08) == 0x08)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Chunk.h"
|
||||
#include "MetaRotator.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "BlockSlab.h"
|
||||
|
||||
|
||||
|
||||
@@ -44,6 +45,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
// Reset meta to zero
|
||||
@@ -59,7 +61,28 @@ public:
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
return ((a_RelY > 0) && cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
|
||||
if (a_RelY <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
// Check if the slab is turned up side down
|
||||
if ((BelowBlockMeta & 0x08) == 0x08)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
}
|
||||
BLOCKTYPE Type = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
|
||||
|
||||
return ((Type == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(Type));
|
||||
return ((Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../Items/ItemHandler.h"
|
||||
#include "Root.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
|
||||
#include "BlockID.h"
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +18,14 @@ public:
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_COBBLESTONE, 1, 0));
|
||||
if (a_BlockMeta == E_META_STONE_STONE)
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_COBBLESTONE, 1, 0));
|
||||
return;
|
||||
}
|
||||
a_Pickups.push_back(cItem(E_BLOCK_STONE, 1, a_BlockMeta));
|
||||
}
|
||||
} ;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
+39
-11
@@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "ChunkInterface.h"
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +11,7 @@
|
||||
class cBlockTallGrassHandler :
|
||||
public cBlockHandler
|
||||
{
|
||||
typedef cBlockHandler super;
|
||||
public:
|
||||
cBlockTallGrassHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
@@ -26,32 +28,58 @@ public:
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
// Drop seeds, sometimes
|
||||
MTRand r1;
|
||||
if (r1.randInt(10) == 5)
|
||||
cFastRandom Random;
|
||||
if (Random.NextInt(8) == 0)
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_ITEM_SEEDS, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||
virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
|
||||
if ((!a_Player->IsGameModeCreative()) && (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SHEARS))
|
||||
if (a_CanDrop && (a_Digger != NULL) && (a_Digger->GetEquippedWeapon().m_ItemType == E_ITEM_SHEARS))
|
||||
{
|
||||
cItems Pickups;
|
||||
Pickups.Add(E_BLOCK_TALL_GRASS, 1, Meta);
|
||||
a_WorldInterface.SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ);
|
||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
cItems Drops;
|
||||
Drops.Add(m_BlockType, 1, Meta);
|
||||
|
||||
a_Player->UseEquippedItem();
|
||||
// Allow plugins to modify the pickups:
|
||||
a_BlockPluginInterface.CallHookBlockToPickups(a_Digger, a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta, Drops);
|
||||
|
||||
// Spawn the pickups:
|
||||
if (!Drops.empty())
|
||||
{
|
||||
MTRand r1;
|
||||
|
||||
// Mid-block position first
|
||||
double MicroX, MicroY, MicroZ;
|
||||
MicroX = a_BlockX + 0.5;
|
||||
MicroY = a_BlockY + 0.5;
|
||||
MicroZ = a_BlockZ + 0.5;
|
||||
|
||||
// Add random offset second
|
||||
MicroX += r1.rand(1) - 0.5;
|
||||
MicroZ += r1.rand(1) - 0.5;
|
||||
|
||||
a_WorldInterface.SpawnItemPickups(Drops, MicroX, MicroY, MicroZ);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_CanDrop);
|
||||
}
|
||||
|
||||
|
||||
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_AIR));
|
||||
if (a_RelY <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
|
||||
return IsBlockTypeOfDirt(BelowBlock);
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
+52
-64
@@ -24,32 +24,23 @@ public:
|
||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||
) override
|
||||
{
|
||||
// Find proper placement of torch
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
|
||||
a_ChunkInterface.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
|
||||
|
||||
if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
|
||||
if (!CanBePlacedOn(Block, Meta, a_BlockFace)) // Try to preserve original direction
|
||||
{
|
||||
a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
|
||||
// Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
|
||||
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
|
||||
a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Set a_BlockFace to a valid direction which will be converted later to a metadata
|
||||
if (a_BlockFace == BLOCK_FACE_NONE)
|
||||
{
|
||||
// Client wouldn't have sent anything anyway, but whatever
|
||||
// No attachable face found - don't place the torch
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not top or bottom faces, try to preserve whatever face was clicked
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
|
||||
if (!CanBePlacedOn(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace))
|
||||
{
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
|
||||
// Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
|
||||
a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
|
||||
if (a_BlockFace == BLOCK_FACE_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a_BlockType = m_BlockType;
|
||||
a_BlockMeta = DirectionToMetaData(a_BlockFace);
|
||||
@@ -97,44 +88,59 @@ public:
|
||||
}
|
||||
|
||||
|
||||
static bool CanBePlacedOn(BLOCKTYPE a_BlockType, eBlockFace a_BlockFace)
|
||||
static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace)
|
||||
{
|
||||
if (!cBlockInfo::FullyOccupiesVoxel(a_BlockType))
|
||||
switch (a_BlockType)
|
||||
{
|
||||
return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright (for glass, etc.); exceptions won't even be sent by client, no need to handle
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
case E_BLOCK_END_PORTAL_FRAME:
|
||||
case E_BLOCK_SOULSAND:
|
||||
{
|
||||
// Exceptional vanilla behaviour
|
||||
return true;
|
||||
}
|
||||
case E_BLOCK_GLASS:
|
||||
case E_BLOCK_STAINED_GLASS:
|
||||
case E_BLOCK_FENCE:
|
||||
case E_BLOCK_NETHER_BRICK_FENCE:
|
||||
case E_BLOCK_COBBLESTONE_WALL:
|
||||
{
|
||||
// Torches can only be placed on top of these blocks
|
||||
return (a_BlockFace == BLOCK_FACE_YP);
|
||||
}
|
||||
case E_BLOCK_STONE_SLAB:
|
||||
case E_BLOCK_WOODEN_SLAB:
|
||||
{
|
||||
// Toches can be placed on the top of these slabs only if the occupy the top half of the voxel
|
||||
return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08));
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
|
||||
{
|
||||
// Torches can be placed on all sides of full blocks except the bottom
|
||||
return (a_BlockFace != BLOCK_FACE_YM);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure
|
||||
/** Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure */
|
||||
static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions
|
||||
{
|
||||
eBlockFace Face = static_cast<eBlockFace>(i);
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, true);
|
||||
BLOCKTYPE BlockInQuestion = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
BLOCKTYPE BlockInQuestion;
|
||||
NIBBLETYPE BlockInQuestionMeta;
|
||||
a_ChunkInterface.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockInQuestion, BlockInQuestionMeta);
|
||||
|
||||
// If on a block that can only hold a torch if torch is standing on it, return that face
|
||||
if (
|
||||
((BlockInQuestion == E_BLOCK_GLASS) ||
|
||||
(BlockInQuestion == E_BLOCK_FENCE) ||
|
||||
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
|
||||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) &&
|
||||
(Face == BLOCK_FACE_TOP)
|
||||
)
|
||||
if (CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face))
|
||||
{
|
||||
return Face;
|
||||
}
|
||||
else if (cBlockInfo::FullyOccupiesVoxel(BlockInQuestion) && (i != BLOCK_FACE_BOTTOM))
|
||||
{
|
||||
// Otherwise, if block in that direction is torch placeable and we haven't gotten to it via the bottom face, return that face
|
||||
return Face;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset coords in preparation for next iteration
|
||||
@@ -148,34 +154,16 @@ public:
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
eBlockFace Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
|
||||
AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
|
||||
BLOCKTYPE BlockInQuestion;
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockInQuestion);
|
||||
|
||||
if (
|
||||
(BlockInQuestion == E_BLOCK_GLASS) ||
|
||||
(BlockInQuestion == E_BLOCK_STAINED_GLASS) ||
|
||||
(BlockInQuestion == E_BLOCK_FENCE) ||
|
||||
(BlockInQuestion == E_BLOCK_SOULSAND) ||
|
||||
(BlockInQuestion == E_BLOCK_MOB_SPAWNER) ||
|
||||
(BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
|
||||
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
|
||||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
|
||||
)
|
||||
{
|
||||
// Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
|
||||
// No need to check for upright orientation, it was done when the torch was placed
|
||||
return true;
|
||||
}
|
||||
else if (!cBlockInfo::FullyOccupiesVoxel(BlockInQuestion))
|
||||
BLOCKTYPE BlockInQuestion;
|
||||
NIBBLETYPE BlockInQuestionMeta;
|
||||
if (!a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockInQuestion, BlockInQuestionMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ public:
|
||||
|
||||
virtual void 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
|
||||
{
|
||||
if (m_BlockType == E_BLOCK_IRON_TRAPDOOR)
|
||||
{
|
||||
// Iron doors can only be toggled by redstone, not by right-clicking
|
||||
return;
|
||||
}
|
||||
|
||||
// Flip the ON bit on/off using the XOR bitwise operation
|
||||
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x04);
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
|
||||
|
||||
+26
-8
@@ -23,10 +23,6 @@ public:
|
||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||
) override
|
||||
{
|
||||
UNUSED(a_Player);
|
||||
UNUSED(a_CursorX);
|
||||
UNUSED(a_CursorY);
|
||||
UNUSED(a_CursorZ);
|
||||
// TODO: Disallow placement where the vine doesn't attach to something properly
|
||||
BLOCKTYPE BlockType = 0;
|
||||
NIBBLETYPE BlockMeta;
|
||||
@@ -80,7 +76,21 @@ public:
|
||||
/// Returns true if the specified block type is good for vines to attach to
|
||||
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
return ((a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType));
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_GLASS:
|
||||
case E_BLOCK_STAINED_GLASS:
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
{
|
||||
// You can't attach a vine to this solid blocks.
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return cBlockInfo::IsSolid(a_BlockType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +148,7 @@ public:
|
||||
{
|
||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
DropBlock(a_ChunkInterface, *a_Chunk.GetWorld(), a_PluginInterface, NULL, BlockX, a_RelY, BlockZ);
|
||||
DropBlock(a_ChunkInterface, *a_Chunk.GetWorld(), a_PluginInterface, nullptr, BlockX, a_RelY, BlockZ);
|
||||
}
|
||||
a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
|
||||
return;
|
||||
@@ -166,23 +176,31 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
{
|
||||
UNUSED(a_ChunkInterface);
|
||||
UNUSED(a_WorldInterface);
|
||||
UNUSED(a_BlockPluginInterface);
|
||||
|
||||
// Vine cannot grow down if at the bottom:
|
||||
if (a_RelY < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Grow one block down, if possible:
|
||||
BLOCKTYPE Block;
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, Block);
|
||||
if (Block == E_BLOCK_AIR)
|
||||
{
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
|
||||
if (!a_BlockPluginInterface.CallHookBlockSpread(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
|
||||
{
|
||||
a_Chunk.UnboundedRelSetBlock(a_RelX, a_RelY - 1, a_RelZ, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
|
||||
|
||||
@@ -7,6 +7,6 @@ public:
|
||||
virtual ~cBroadcastInterface() {}
|
||||
|
||||
virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
|
||||
virtual void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) = 0;
|
||||
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) = 0;
|
||||
virtual void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) = 0;
|
||||
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr) = 0;
|
||||
};
|
||||
|
||||
@@ -45,7 +45,6 @@ SET (HDRS
|
||||
BlockGlowstone.h
|
||||
BlockGravel.h
|
||||
BlockHandler.h
|
||||
BlockHayBale.h
|
||||
BlockHopper.h
|
||||
BlockIce.h
|
||||
BlockLadder.h
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "ChunkInterface.h"
|
||||
#include "ChunkMap.h"
|
||||
#include "BlockHandler.h"
|
||||
#include "WorldInterface.h"
|
||||
#include "WorldInterface.h"
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user