summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2014-03-10 19:36:55 +0100
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2014-03-10 19:36:55 +0100
commitcc2d8052383d64ffe21e53a7ec401ed7ee345fcd (patch)
tree55571ea694182bf2c00f055a275be2df5ada703f /src/Blocks
parentShrapnel now configurable (diff)
parentFixed #778 - stack overflow.com (diff)
downloadcuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar.gz
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar.bz2
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar.lz
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar.xz
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.tar.zst
cuberite-cc2d8052383d64ffe21e53a7ec401ed7ee345fcd.zip
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockBed.h5
-rw-r--r--src/Blocks/BlockButton.h5
-rw-r--r--src/Blocks/BlockChest.h5
-rw-r--r--src/Blocks/BlockComparator.h12
-rw-r--r--src/Blocks/BlockDoor.cpp25
-rw-r--r--src/Blocks/BlockDoor.h59
-rw-r--r--src/Blocks/BlockDropSpenser.h19
-rw-r--r--src/Blocks/BlockEnderchest.h6
-rw-r--r--src/Blocks/BlockFenceGate.h12
-rw-r--r--src/Blocks/BlockFlowerPot.h83
-rw-r--r--src/Blocks/BlockHandler.cpp56
-rw-r--r--src/Blocks/BlockHandler.h27
-rw-r--r--src/Blocks/BlockMobHead.h5
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h9
-rw-r--r--src/Blocks/BlockStairs.h76
-rw-r--r--src/Blocks/BlockTNT.h32
-rw-r--r--src/Blocks/BlockTorch.h67
-rw-r--r--src/Blocks/BlockTrapdoor.h10
-rw-r--r--src/Blocks/BlockVine.h24
-rw-r--r--src/Blocks/ChunkInterface.cpp2
-rw-r--r--src/Blocks/MetaRotater.h120
-rw-r--r--src/Blocks/WorldInterface.h3
22 files changed, 361 insertions, 301 deletions
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index caec2b56f..6daa94730 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -4,6 +4,7 @@
#include "BlockHandler.h"
#include "ChunkInterface.h"
#include "WorldInterface.h"
+#include "MetaRotater.h"
#include "../Entities/Player.h"
@@ -11,11 +12,11 @@
class cBlockBedHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockBedHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01,true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 2db9b7ec7..740cbe3c4 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -2,16 +2,17 @@
#include "BlockHandler.h"
#include "Chunk.h"
+#include "MetaRotater.h"
class cBlockButtonHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
{
public:
cBlockButtonHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index 02ecc4346..30588d8fc 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -4,17 +4,18 @@
#include "BlockEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
+#include "MetaRotater.h"
class cBlockChestHandler :
- public cBlockEntityHandler
+ public cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
{
public:
cBlockChestHandler(BLOCKTYPE a_BlockType)
- : cBlockEntityHandler(a_BlockType)
+ : cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index aba390d9d..e570ff302 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -3,17 +3,18 @@
#include "BlockHandler.h"
#include "BlockRedstoneRepeater.h"
+#include "MetaRotater.h"
class cBlockComparatorHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>
{
public:
cBlockComparatorHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>(a_BlockType)
{
}
@@ -26,6 +27,13 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index 2ff5c1c37..4e38ef334 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -9,7 +9,7 @@
cBlockDoorHandler::cBlockDoorHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : super(a_BlockType)
{
}
@@ -55,6 +55,29 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac
+void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+{
+ UNUSED(a_ChunkInterface);
+
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (Meta & 8)
+ {
+ // Current block is top of the door
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, a_Player);
+ }
+ else
+ {
+ // Current block is bottom of the door
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, a_Player);
+ }
+}
+
+
+
+
+
void cBlockDoorHandler::OnPlacedByPlayer(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index ef0dbb787..981774c17 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -4,18 +4,21 @@
#include "BlockHandler.h"
#include "../Entities/Player.h"
#include "Chunk.h"
+#include "MetaRotater.h"
class cBlockDoorHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true>
{
+ typedef cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true> super;
public:
cBlockDoorHandler(BLOCKTYPE a_BlockType);
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
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;
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override;
virtual const char * GetStepSound(void) override;
@@ -167,6 +170,60 @@ public:
}
+ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
+ {
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaRotateCCW(a_Meta);
+ }
+ }
+
+
+
+ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
+ {
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaRotateCW(a_Meta);
+ }
+ }
+
+
+
+ virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
+ {
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaMirrorXY(a_Meta);
+ }
+ }
+
+
+
+ virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
+ {
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaMirrorYZ(a_Meta);
+ }
+ }
+
} ;
diff --git a/src/Blocks/BlockDropSpenser.h b/src/Blocks/BlockDropSpenser.h
index 30d347ec9..7e0ad0e55 100644
--- a/src/Blocks/BlockDropSpenser.h
+++ b/src/Blocks/BlockDropSpenser.h
@@ -6,17 +6,18 @@
#pragma once
#include "../Piston.h"
+#include "MetaRotater.h"
class cBlockDropSpenserHandler :
- public cBlockEntityHandler
+ public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockDropSpenserHandler(BLOCKTYPE a_BlockType) :
- cBlockEntityHandler(a_BlockType)
+ cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
@@ -34,6 +35,20 @@ public:
a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetYaw(), a_Player->GetPitch());
return true;
}
+
+ virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
+ {
+ // Bit 0x08 is a flag. Lowest three bits are position. 0x08 == 1000
+ NIBBLETYPE OtherMeta = a_Meta & 0x08;
+ // Mirrors defined by by a table. (Source, mincraft.gamepedia.com) 0x07 == 0111
+ switch (a_Meta & 0x07)
+ {
+ case 0x00: return 0x01 + OtherMeta; // Down -> Up
+ case 0x01: return 0x00 + OtherMeta; // Up -> Down
+ }
+ // Not Facing Up or Down; No change.
+ return a_Meta;
+ }
} ;
diff --git a/src/Blocks/BlockEnderchest.h b/src/Blocks/BlockEnderchest.h
index b4b0b995d..97cf484fb 100644
--- a/src/Blocks/BlockEnderchest.h
+++ b/src/Blocks/BlockEnderchest.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockEntity.h"
-
+#include "MetaRotater.h"
class cBlockEnderchestHandler :
- public cBlockEntityHandler
+ public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockEnderchestHandler(BLOCKTYPE a_BlockType)
- : cBlockEntityHandler(a_BlockType)
+ : cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index fb984f345..e3162bbd6 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotater.h"
class cBlockFenceGateHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockFenceGateHandler(BLOCKTYPE a_BlockType) :
- cBlockHandler(a_BlockType)
+ cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
@@ -48,6 +48,12 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual bool IsUseable(void) override
{
return true;
diff --git a/src/Blocks/BlockFlowerPot.h b/src/Blocks/BlockFlowerPot.h
index 4de85f629..fc75ef638 100644
--- a/src/Blocks/BlockFlowerPot.h
+++ b/src/Blocks/BlockFlowerPot.h
@@ -2,101 +2,24 @@
#pragma once
#include "BlockHandler.h"
+#include "BlockEntity.h"
class cBlockFlowerPotHandler :
- public cBlockHandler
+ public cBlockEntityHandler
{
public:
cBlockFlowerPotHandler(BLOCKTYPE a_BlockType) :
- cBlockHandler(a_BlockType)
+ cBlockEntityHandler(a_BlockType)
{
}
-
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(E_ITEM_FLOWER_POT, 1, 0));
- if (a_BlockMeta == 0)
- {
- return;
- }
- cItem Plant;
- switch (a_BlockMeta)
- {
- case 1: Plant = cItem(E_BLOCK_RED_ROSE, 1, 0); break;
- case 2: Plant = cItem(E_BLOCK_YELLOW_FLOWER, 1, 0); break;
- case 3: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_APPLE); break;
- case 4: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_CONIFER); break;
- case 5: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_BIRCH); break;
- case 6: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_JUNGLE); break;
- case 7: Plant = cItem(E_BLOCK_RED_MUSHROOM, 1, 0); break;
- case 8: Plant = cItem(E_BLOCK_BROWN_MUSHROOM, 1, 0); break;
- case 9: Plant = cItem(E_BLOCK_CACTUS, 1, 0); break;
- case 10: Plant = cItem(E_BLOCK_DEAD_BUSH, 1, 0); break;
- case 11: Plant = cItem(E_BLOCK_TALL_GRASS, 1, E_META_TALL_GRASS_FERN); break;
- default: return;
- }
- a_Pickups.push_back(Plant);
- }
-
-
- void OnUse(cWorld * a_World, cWorldInterface * a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
- {
- NIBBLETYPE Meta = a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ );
- if (Meta != 0)
- {
- // Already filled
- return;
- }
-
- switch (a_Player->GetEquippedItem().m_ItemType)
- {
- case E_BLOCK_RED_ROSE: Meta = 1; break;
- case E_BLOCK_YELLOW_FLOWER: Meta = 2; break;
- case E_BLOCK_SAPLING:
- {
- switch (a_Player->GetEquippedItem().m_ItemDamage)
- {
- case E_META_SAPLING_APPLE: Meta = 3; break;
- case E_META_SAPLING_CONIFER: Meta = 4; break;
- case E_META_SAPLING_BIRCH: Meta = 5; break;
- case E_META_SAPLING_JUNGLE: Meta = 6; break;
- }
- break;
- }
- case E_BLOCK_RED_MUSHROOM: Meta = 7; break;
- case E_BLOCK_BROWN_MUSHROOM: Meta = 8; break;
- case E_BLOCK_CACTUS: Meta = 9; break;
- case E_BLOCK_DEAD_BUSH: Meta = 10; break;
- case E_BLOCK_TALL_GRASS:
- {
- if (a_Player->GetEquippedItem().m_ItemDamage == E_META_TALL_GRASS_FERN)
- {
- Meta = 11;
- }
- else
- {
- return;
- }
- break;
- }
- }
-
- if (a_Player->GetGameMode() != gmCreative)
- {
- a_Player->GetInventory().RemoveOneEquippedItem();
- }
- a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
- }
-
-
- virtual bool IsUseable(void) override
- {
- return true;
}
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 834727c9a..aa97b2ca9 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -57,6 +57,7 @@
#include "BlockRedstoneLamp.h"
#include "BlockRedstoneRepeater.h"
#include "BlockRedstoneTorch.h"
+#include "BlockTNT.h"
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSideways.h"
@@ -77,33 +78,6 @@
-bool cBlockHandler::m_HandlerInitialized = false;
-cBlockHandler * cBlockHandler::m_BlockHandler[256];
-
-
-
-
-
-cBlockHandler * cBlockHandler::GetBlockHandler(BLOCKTYPE a_BlockType)
-{
- if (!m_HandlerInitialized)
- {
- // We have to initialize
- memset(m_BlockHandler, 0, sizeof(m_BlockHandler));
- m_HandlerInitialized = true;
- }
- if (m_BlockHandler[a_BlockType] != NULL)
- {
- return m_BlockHandler[a_BlockType];
- }
-
- return m_BlockHandler[a_BlockType] = CreateBlockHandler(a_BlockType);
-}
-
-
-
-
-
cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
{
switch(a_BlockType)
@@ -172,6 +146,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE 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_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_NEW_LEAVES: return new cBlockNewLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
@@ -192,7 +167,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_REDSTONE_REPEATER_ON: return new cBlockRedstoneRepeaterHandler(a_BlockType);
case E_BLOCK_REDSTONE_TORCH_OFF: return new cBlockRedstoneTorchHandler (a_BlockType);
case E_BLOCK_REDSTONE_TORCH_ON: return new cBlockRedstoneTorchHandler (a_BlockType);
- case E_BLOCK_REDSTONE_WIRE: return new cBlockRedstoneHandler (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_SAND: return new cBlockSandHandler (a_BlockType);
@@ -212,6 +187,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (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_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType);
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
@@ -231,20 +207,6 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
-void cBlockHandler::Deinit()
-{
- for (int i = 0; i < 256; i++)
- {
- delete m_BlockHandler[i];
- }
- memset(m_BlockHandler, 0, sizeof(m_BlockHandler)); // Don't leave any dangling pointers around, just in case
- m_HandlerInitialized = false;
-}
-
-
-
-
-
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
{
m_BlockType = a_BlockType;
@@ -329,7 +291,7 @@ void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_Bl
{
if ((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height))
{
- GetBlockHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
+ cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
}
}
@@ -361,6 +323,14 @@ void cBlockHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface &
+void cBlockHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+{
+}
+
+
+
+
+
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index a2913d7f8..3a3efb3cc 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -23,6 +23,8 @@ class cBlockHandler
{
public:
cBlockHandler(BLOCKTYPE a_BlockType);
+
+ virtual ~cBlockHandler() {}
/// Called when the block gets ticked either by a random tick or by a queued tick.
/// Note that the coords are chunk-relative!
@@ -69,6 +71,9 @@ public:
/// Called if the user right clicks the block and the block is useable
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);
+ /** Called when a Right Click to this Block is cancelled */
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
+
/// <summary>Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents</summary>
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
@@ -136,30 +141,14 @@ public:
/// <returns>Block meta following mirroring</returns>
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) { return a_Meta; }
- /// <summary>Get the blockhandler for a specific block id</summary>
- static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockType);
-
- /// <summary>Deletes all initialised block handlers</summary>
- static void Deinit();
-
protected:
BLOCKTYPE m_BlockType;
// Creates a new blockhandler for the given block type. For internal use only, use ::GetBlockHandler() instead.
- static cBlockHandler *CreateBlockHandler(BLOCKTYPE a_BlockType);
- static cBlockHandler *m_BlockHandler[256];
- static bool m_HandlerInitialized; //used to detect if the blockhandlers are initialized
-};
-
+ static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType);
-
-
-
-// Shortcut to get the blockhandler for a specific block
-inline cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
-{
- return cBlockHandler::GetBlockHandler(a_BlockType);
-}
+ friend class cBlockInfo;
+};
diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h
index 6a00c3acd..2b128f13b 100644
--- a/src/Blocks/BlockMobHead.h
+++ b/src/Blocks/BlockMobHead.h
@@ -29,7 +29,7 @@ public:
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
{
- class cCallback : public cMobHeadBlockCallback
+ class cCallback : public cMobHeadCallback
{
cPlayer * m_Player;
NIBBLETYPE m_OldBlockMeta;
@@ -45,6 +45,7 @@ public:
a_MobHeadEntity->SetType(static_cast<eMobHeadType>(m_OldBlockMeta));
a_MobHeadEntity->SetRotation(static_cast<eMobHeadRotation>(Rotation));
+ a_MobHeadEntity->GetWorld()->BroadcastBlockEntity(a_MobHeadEntity->GetPosX(), a_MobHeadEntity->GetPosY(), a_MobHeadEntity->GetPosZ(), m_Player->GetClientHandle());
return false;
}
@@ -59,7 +60,7 @@ public:
a_BlockMeta = a_BlockFace;
cWorld * World = (cWorld *) &a_WorldInterface;
- World->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
+ World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
}
} ;
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index eb0918acf..1e2a86949 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -29,7 +29,7 @@ public:
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
-
+
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
{
@@ -37,6 +37,13 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index c1887bc46..ea8405597 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotater.h"
class cBlockStairsHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>
{
public:
cBlockStairsHandler(BLOCKTYPE a_BlockType) :
- cBlockHandler(a_BlockType)
+ cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>(a_BlockType)
{
}
@@ -25,6 +25,14 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
+ UNUSED(a_ChunkInterface);
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ UNUSED(a_CursorX);
+ UNUSED(a_CursorY);
+ UNUSED(a_CursorZ);
+ UNUSED(a_BlockMeta);
a_BlockType = m_BlockType;
a_BlockMeta = RotationToMetaData(a_Player->GetYaw());
switch (a_BlockFace)
@@ -96,54 +104,6 @@ public:
}
- virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
- {
- // Bits 3 and 4 stay, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x0c);
- switch (a_Meta & 0x03)
- {
- case 0x00: return TopBits | 0x03; // East -> North
- case 0x01: return TopBits | 0x02; // West -> South
- case 0x02: return TopBits | 0x00; // South -> East
- case 0x03: return TopBits | 0x01; // North -> West
- }
- // Not reachable, but to avoid a compiler warning:
- return 0;
- }
-
-
- virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
- {
- // Bits 3 and 4 stay, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x0c);
- switch (a_Meta & 0x03)
- {
- case 0x00: return TopBits | 0x02; // East -> South
- case 0x01: return TopBits | 0x03; // West -> North
- case 0x02: return TopBits | 0x01; // South -> West
- case 0x03: return TopBits | 0x00; // North -> East
- }
- // Not reachable, but to avoid a compiler warning:
- return 0;
- }
-
-
- virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
- {
- // Bits 3 and 4 stay, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x0c);
- switch (a_Meta & 0x03)
- {
- case 0x00: return TopBits | 0x00; // East -> East
- case 0x01: return TopBits | 0x01; // West -> West
- case 0x02: return TopBits | 0x03; // South -> North
- case 0x03: return TopBits | 0x02; // North -> South
- }
- // Not reachable, but to avoid a compiler warning:
- return 0;
- }
-
-
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Toggle bit 3:
@@ -151,20 +111,6 @@ public:
}
- virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
- {
- // Bits 3 and 4 stay, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x0c);
- switch (a_Meta & 0x03)
- {
- case 0x00: return TopBits | 0x01; // East -> West
- case 0x01: return TopBits | 0x00; // West -> East
- case 0x02: return TopBits | 0x02; // South -> South
- case 0x03: return TopBits | 0x03; // North -> North
- }
- // Not reachable, but to avoid a compiler warning:
- return 0;
- }
} ;
diff --git a/src/Blocks/BlockTNT.h b/src/Blocks/BlockTNT.h
new file mode 100644
index 000000000..283a03730
--- /dev/null
+++ b/src/Blocks/BlockTNT.h
@@ -0,0 +1,32 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockTNTHandler :
+ public cBlockHandler
+{
+public:
+ cBlockTNTHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index 84bbb37ec..d32c77629 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -2,17 +2,17 @@
#include "BlockHandler.h"
#include "../Chunk.h"
-
+#include "MetaRotater.h"
class cBlockTorchHandler :
- public cBlockHandler
+ public cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>
{
public:
cBlockTorchHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>(a_BlockType)
{
}
@@ -185,67 +185,6 @@ public:
{
return "step.wood";
}
-
-
- virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
- {
- // Bit 4 stays, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x08);
- switch (a_Meta & 0x07)
- {
- case 0x01: return TopBits | 0x04; // East -> North
- case 0x02: return TopBits | 0x03; // West -> South
- case 0x03: return TopBits | 0x01; // South -> East
- case 0x04: return TopBits | 0x02; // North -> West
- default: return a_Meta; // Floor -> Floor
- }
- }
-
-
- virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
- {
- // Bit 4 stays, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x08);
- switch (a_Meta & 0x07)
- {
- case 0x01: return TopBits | 0x03; // East -> South
- case 0x02: return TopBits | 0x04; // West -> North
- case 0x03: return TopBits | 0x02; // South -> West
- case 0x04: return TopBits | 0x01; // North -> East
- default: return a_Meta; // Floor -> Floor
- }
- }
-
-
- virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
- {
- // Bit 4 stays, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x08);
- switch (a_Meta & 0x07)
- {
- case 0x03: return TopBits | 0x04; // South -> North
- case 0x04: return TopBits | 0x03; // North -> South
- default: return a_Meta; // Keep the rest
- }
- }
-
-
- // Mirroring around the XZ plane doesn't make sense for floor torches,
- // the others stay the same, so let's keep all the metas the same.
- // The base class does tht for us, no need to override MetaMirrorXZ()
-
-
- virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
- {
- // Bit 4 stays, the rest is swapped around according to a table:
- NIBBLETYPE TopBits = (a_Meta & 0x08);
- switch (a_Meta & 0x07)
- {
- case 0x01: return TopBits | 0x02; // East -> West
- case 0x02: return TopBits | 0x01; // West -> East
- default: return a_Meta; // Keep the rest
- }
- }
} ;
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 70a369e69..9bae92c4d 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -36,8 +36,16 @@ public:
{
// 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);
+
+ cWorld * World = (cWorld *) &a_WorldInterface;
+ World->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
+ }
+
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
virtual bool GetPlacementBlockTypeMeta(
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index d8c114284..708583e70 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -1,8 +1,7 @@
-
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotater.h"
@@ -24,6 +23,10 @@ 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;
@@ -162,11 +165,17 @@ public:
return false;
}
- virtual void OnUpdate(cWorld * a_World, int X, int Y, int Z)
+ virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
- if (a_World->GetBlock(X, Y - 1, Z) == E_BLOCK_AIR)
+ UNUSED(a_ChunkInterface);
+ UNUSED(a_WorldInterface);
+ UNUSED(a_BlockPluginInterface);
+
+ BLOCKTYPE Block;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, Block);
+ if (Block == E_BLOCK_AIR)
{
- a_World->SetBlock(X, Y - 1, Z, E_BLOCK_VINES, a_World->GetBlockMeta(X, Y, Z));
+ a_Chunk.UnboundedRelSetBlock(a_RelX, a_RelY - 1, a_RelZ, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
}
}
@@ -180,8 +189,8 @@ public:
{
return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
}
-
-
+
+
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
// Bits 2 and 4 stay, bits 1 and 3 swap
@@ -194,6 +203,7 @@ public:
// Bits 1 and 3 stay, bits 2 and 4 swap
return ((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
}
+
} ;
diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp
index b2dda19f4..540581ae7 100644
--- a/src/Blocks/ChunkInterface.cpp
+++ b/src/Blocks/ChunkInterface.cpp
@@ -6,7 +6,7 @@
bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, int a_X, int a_Y, int a_Z)
{
- cBlockHandler *Handler = cBlockHandler::GetBlockHandler(GetBlock(a_X, a_Y, a_Z));
+ cBlockHandler * Handler = cBlockInfo::GetHandler(GetBlock(a_X, a_Y, a_Z));
Handler->OnDestroyed(*this, a_WorldInterface, a_X, a_Y, a_Z);
return m_ChunkMap->DigBlock(a_X, a_Y, a_Z);
}
diff --git a/src/Blocks/MetaRotater.h b/src/Blocks/MetaRotater.h
new file mode 100644
index 000000000..dde88e6db
--- /dev/null
+++ b/src/Blocks/MetaRotater.h
@@ -0,0 +1,120 @@
+// MetaRotater.h
+
+// Provides a mixin for rotations and reflections
+
+#pragma once
+
+// MSVC generates warnings for the templated AssertIfNotMatched parameter conditions, so disable it:
+#ifdef _MSC_VER
+ #pragma warning(disable: 4127) // Conditional expression is constant
+#endif
+
+
+
+
+
+/*
+Provides a mixin for rotations and reflections following the standard pattern of apply mask then use case.
+
+Usage:
+Inherit from this class providing your base class as Base, the BitMask for the direction bits in bitmask and the masked value for the directions in North, East, South, West. There is also an aptional parameter AssertIfNotMatched. Set this if it is invalid for a block to exist in any other state.
+*/
+
+template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched = false>
+class cMetaRotater : public Base
+{
+public:
+
+ cMetaRotater(BLOCKTYPE a_BlockType) :
+ Base(a_BlockType)
+ {}
+
+ virtual ~cMetaRotater() {}
+
+ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override;
+ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override;
+ virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override;
+ virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override;
+};
+
+
+
+
+
+template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCW(NIBBLETYPE a_Meta)
+{
+ NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
+ switch (a_Meta & BitMask)
+ {
+ case South: return West | OtherMeta;
+ case West: return North | OtherMeta;
+ case North: return East | OtherMeta;
+ case East: return South | OtherMeta;
+ }
+ if (AssertIfNotMatched)
+ {
+ ASSERT(!"Invalid Meta value");
+ }
+ return a_Meta;
+}
+
+
+
+
+
+template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCCW(NIBBLETYPE a_Meta)
+{
+ NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
+ switch (a_Meta & BitMask)
+ {
+ case South: return East | OtherMeta;
+ case East: return North | OtherMeta;
+ case North: return West | OtherMeta;
+ case West: return South | OtherMeta;
+ }
+ if (AssertIfNotMatched)
+ {
+ ASSERT(!"Invalid Meta value");
+ }
+ return a_Meta;
+}
+
+
+
+
+
+template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorXY(NIBBLETYPE a_Meta)
+{
+ NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
+ switch (a_Meta & BitMask)
+ {
+ case South: return North | OtherMeta;
+ case North: return South | OtherMeta;
+ }
+ // Not Facing North or South; No change.
+ return a_Meta;
+}
+
+
+
+
+
+template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
+NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorYZ(NIBBLETYPE a_Meta)
+{
+ NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
+ switch (a_Meta & BitMask)
+ {
+ case West: return East | OtherMeta;
+ case East: return West | OtherMeta;
+ }
+ // Not Facing East or West; No change.
+ return a_Meta;
+}
+
+
+
+
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index b6f2f55a7..e59b00eff 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -27,4 +27,7 @@ public:
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0;
+
+ /** Sends the block on those coords to the player */
+ virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player) = 0;
};