summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockAnvil.h27
-rw-r--r--src/Blocks/BlockBed.h13
-rw-r--r--src/Blocks/BlockBigFlower.h131
-rw-r--r--src/Blocks/BlockButton.h6
-rw-r--r--src/Blocks/BlockCauldron.h2
-rw-r--r--src/Blocks/BlockChest.h7
-rw-r--r--src/Blocks/BlockComparator.h6
-rw-r--r--src/Blocks/BlockCrops.h12
-rw-r--r--src/Blocks/BlockDirt.h18
-rw-r--r--src/Blocks/BlockDoor.cpp84
-rw-r--r--src/Blocks/BlockDoor.h72
-rw-r--r--src/Blocks/BlockDropSpenser.h6
-rw-r--r--src/Blocks/BlockEnchantmentTable.h37
-rw-r--r--src/Blocks/BlockEnderchest.h6
-rw-r--r--src/Blocks/BlockFarmland.h4
-rw-r--r--src/Blocks/BlockFenceGate.h6
-rw-r--r--src/Blocks/BlockFire.h41
-rw-r--r--src/Blocks/BlockFluid.h8
-rw-r--r--src/Blocks/BlockFurnace.h8
-rw-r--r--src/Blocks/BlockHandler.cpp15
-rw-r--r--src/Blocks/BlockHandler.h3
-rw-r--r--src/Blocks/BlockHopper.h21
-rw-r--r--src/Blocks/BlockLadder.h4
-rw-r--r--src/Blocks/BlockLeaves.h26
-rw-r--r--src/Blocks/BlockLever.h37
-rw-r--r--src/Blocks/BlockLilypad.h28
-rw-r--r--src/Blocks/BlockMobHead.h142
-rw-r--r--src/Blocks/BlockNetherWart.h15
-rw-r--r--src/Blocks/BlockPluginInterface.h6
-rw-r--r--src/Blocks/BlockPortal.h14
-rw-r--r--src/Blocks/BlockPumpkin.h6
-rw-r--r--src/Blocks/BlockRail.h138
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h6
-rw-r--r--src/Blocks/BlockSign.h35
-rw-r--r--src/Blocks/BlockSlab.h61
-rw-r--r--src/Blocks/BlockStairs.h15
-rw-r--r--src/Blocks/BlockStems.h3
-rw-r--r--src/Blocks/BlockTallGrass.h24
-rw-r--r--src/Blocks/BlockTorch.h6
-rw-r--r--src/Blocks/BlockTrapdoor.h6
-rw-r--r--src/Blocks/BlockVine.h10
-rw-r--r--src/Blocks/CMakeLists.txt1
-rw-r--r--src/Blocks/MetaRotator.h (renamed from src/Blocks/MetaRotater.h)16
43 files changed, 890 insertions, 242 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index 9f5f84be0..35a356678 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -18,10 +18,19 @@ public:
{
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(E_BLOCK_ANVIL, 1, a_BlockMeta >> 2));
}
+
+
+ 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
+ {
+ cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->OpenWindow(Window);
+ }
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
@@ -31,27 +40,23 @@ public:
) override
{
a_BlockType = m_BlockType;
-
- int Direction = (int)floor(a_Player->GetYaw() * 4.0 / 360.0 + 0.5) & 0x3;
- int RawMeta = a_BlockMeta >> 2;
-
- Direction++;
- Direction %= 4;
+ NIBBLETYPE HighBits = a_BlockMeta & 0x0c; // Only highest two bits are preserved
+ int Direction = (int)floor(a_Player->GetYaw() * 4.0 / 360.0 + 1.5) & 0x3;
switch (Direction)
{
- case 0: a_BlockMeta = 0x2 | RawMeta << 2; break;
- case 1: a_BlockMeta = 0x3 | RawMeta << 2; break;
- case 2: a_BlockMeta = 0x0 | RawMeta << 2; break;
- case 3: a_BlockMeta = 0x1 | RawMeta << 2; break;
+ case 0: a_BlockMeta = 0x2 | HighBits; break;
+ case 1: a_BlockMeta = 0x3 | HighBits; break;
+ case 2: a_BlockMeta = 0x0 | HighBits; break;
+ case 3: a_BlockMeta = 0x1 | HighBits; break;
default:
{
return false;
}
}
-
return true;
}
+
virtual bool IsUseable() override
{
return true;
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index 6daa94730..51e79b888 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -4,7 +4,7 @@
#include "BlockHandler.h"
#include "ChunkInterface.h"
#include "WorldInterface.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
#include "../Entities/Player.h"
@@ -12,11 +12,11 @@
class cBlockBedHandler :
- public cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
+ public cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockBedHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01,true>(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01,true>(a_BlockType)
{
}
@@ -39,6 +39,13 @@ public:
}
+ virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
+ {
+ return true;
+ }
+
+
+
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h
new file mode 100644
index 000000000..39fd3cac8
--- /dev/null
+++ b/src/Blocks/BlockBigFlower.h
@@ -0,0 +1,131 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockBigFlowerHandler :
+ public cBlockHandler
+{
+public:
+ typedef cBlockHandler super;
+
+ cBlockBigFlowerHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ if (Meta & 0x8)
+ {
+ super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY - 1, a_BlockZ);
+ }
+ else
+ {
+ super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY, a_BlockZ);
+ }
+ }
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ NIBBLETYPE Meta = a_BlockMeta & 0x7;
+
+ if ((Meta == 2) || (Meta == 3))
+ {
+ return;
+ }
+
+ a_Pickups.push_back(cItem(E_BLOCK_BIG_FLOWER, 1, Meta));
+ }
+
+
+ virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ if (Meta & 0x8)
+ {
+ Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ);
+ }
+
+ NIBBLETYPE FlowerMeta = Meta & 0x7;
+ if (!a_Player->IsGameModeCreative())
+ {
+ if (((FlowerMeta == 2) || (FlowerMeta == 3)) && (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SHEARS))
+ {
+ MTRand r1;
+ if (r1.randInt(10) == 5)
+ {
+ cItems Pickups;
+ if (FlowerMeta == 2)
+ {
+ Pickups.Add(E_BLOCK_TALL_GRASS, 2, 1);
+ }
+ else if (FlowerMeta == 3)
+ {
+ Pickups.Add(E_BLOCK_TALL_GRASS, 2, 2);
+ }
+ a_WorldInterface.SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ);
+ }
+ a_Player->UseEquippedItem();
+ }
+ }
+ }
+
+
+ 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) && (a_RelY < cChunkDef::Height) && ((a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_AIR) || (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_BIG_FLOWER)));
+ }
+
+
+ virtual void OnPlacedByPlayer(
+ 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,
+ BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
+ ) override
+ {
+ int Meta = (((int)floor(a_Player->GetYaw() * 4.0 / 360.0 + 0.5) & 0x3) + 2) % 4;
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, 0x8 | Meta);
+ }
+
+
+ virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (OldMeta & 0x8)
+ {
+ // Was upper part of flower
+ if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) == m_BlockType)
+ {
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
+ }
+ }
+ else
+ {
+ // Was lower part
+ if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) == m_BlockType)
+ {
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0);
+ }
+ }
+ }
+
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+} ;
+
+
+
+
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 740cbe3c4..4b2f6f618 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -2,17 +2,17 @@
#include "BlockHandler.h"
#include "Chunk.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockButtonHandler :
- public cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
+ public cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
{
public:
cBlockButtonHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h
index 2e1032d2b..41b79b6c3 100644
--- a/src/Blocks/BlockCauldron.h
+++ b/src/Blocks/BlockCauldron.h
@@ -23,7 +23,7 @@ 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
{
- char Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
switch (a_Player->GetEquippedItem().m_ItemType)
{
case E_ITEM_WATER_BUCKET:
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index 30588d8fc..c9a769c75 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -4,18 +4,18 @@
#include "BlockEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockChestHandler :
- public cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
+ public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockChestHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
+ : cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
@@ -56,6 +56,7 @@ public:
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
)
{
+ // FIXME: This is unreachable, as the condition is the same as the above one
a_BlockMeta = (yaw < 0) ? 4 : 5;
return true;
}
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index e570ff302..4dd05366d 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -3,18 +3,18 @@
#include "BlockHandler.h"
#include "BlockRedstoneRepeater.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockComparatorHandler :
- public cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>
+ public cMetaRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>
{
public:
cBlockComparatorHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index ffc2b3f8b..8606cf3f3 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
+#include "../FastRandom.h"
@@ -21,7 +21,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_Meta) override
{
- MTRand rand;
+ cFastRandom rand;
if (a_Meta == 0x7)
{
@@ -31,18 +31,18 @@ public:
case E_BLOCK_CROPS:
{
a_Pickups.push_back(cItem(E_ITEM_WHEAT, 1, 0));
- a_Pickups.push_back(cItem(E_ITEM_SEEDS, 1 + (int)(rand.randInt(2) + rand.randInt(2)) / 2, 0)); // [1 .. 3] with high preference of 2
+ a_Pickups.push_back(cItem(E_ITEM_SEEDS, (char)(1 + (rand.NextInt(3) + rand.NextInt(3)) / 2), 0)); // [1 .. 3] with high preference of 2
break;
}
case E_BLOCK_CARROTS:
{
- a_Pickups.push_back(cItem(E_ITEM_CARROT, 1 + (int)(rand.randInt(2) + rand.randInt(2)) / 2, 0)); // [1 .. 3] with high preference of 2
+ a_Pickups.push_back(cItem(E_ITEM_CARROT, (char)(1 + (rand.NextInt(3) + rand.NextInt(3)) / 2), 0)); // [1 .. 3] with high preference of 2
break;
}
case E_BLOCK_POTATOES:
{
- a_Pickups.push_back(cItem(E_ITEM_POTATO, 1 + (int)(rand.randInt(2) + rand.randInt(2)) / 2, 0)); // [1 .. 3] with high preference of 2
- if (rand.randInt(20) == 0)
+ a_Pickups.push_back(cItem(E_ITEM_POTATO, (char)(1 + (rand.NextInt(3) + rand.NextInt(3)) / 2), 0)); // [1 .. 3] with high preference of 2
+ if (rand.NextInt(21) == 0)
{
// With a 5% chance, drop a poisonous potato as well
a_Pickups.push_back(cItem(E_ITEM_POISONOUS_POTATO, 1, 0));
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index a1ab74257..2d4fccbac 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
+#include "../FastRandom.h"
@@ -35,8 +35,10 @@ public:
// Grass becomes dirt if there is something on top of it:
if (a_RelY < cChunkDef::Height - 1)
{
- BLOCKTYPE Above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
- if ((!cBlockInfo::IsTransparent(Above) && !cBlockInfo::IsOneHitDig(Above)) || IsBlockWater(Above))
+ BLOCKTYPE Above;
+ NIBBLETYPE AboveMeta;
+ a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY + 1, a_RelZ, Above, AboveMeta);
+ if (!cBlockInfo::GetHandler(Above)->CanDirtGrowGrass(AboveMeta))
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
return;
@@ -44,12 +46,12 @@ public:
}
// Grass spreads to adjacent dirt blocks:
- MTRand rand; // TODO: Replace with cFastRandom
+ cFastRandom rand;
for (int i = 0; i < 2; i++) // Pick two blocks to grow to
{
- int OfsX = rand.randInt(2) - 1; // [-1 .. 1]
- int OfsY = rand.randInt(4) - 3; // [-3 .. 1]
- int OfsZ = rand.randInt(2) - 1; // [-1 .. 1]
+ int OfsX = rand.NextInt(3, a_RelX) - 1; // [-1 .. 1]
+ int OfsY = rand.NextInt(5, a_RelY) - 3; // [-3 .. 1]
+ int OfsZ = rand.NextInt(3, a_RelZ) - 1; // [-1 .. 1]
BLOCKTYPE DestBlock;
NIBBLETYPE DestMeta;
@@ -77,7 +79,7 @@ public:
BLOCKTYPE AboveDest;
NIBBLETYPE AboveMeta;
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
- if ((cBlockInfo::IsOneHitDig(AboveDest) || cBlockInfo::IsTransparent(AboveDest)) && !IsBlockWater(AboveDest))
+ if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
{
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, BlockX * cChunkDef::Width, BlockY, BlockZ * cChunkDef::Width, ssGrassSpread))
{
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index 4e38ef334..479c68153 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -110,3 +110,87 @@ const char * cBlockDoorHandler::GetStepSound(void)
+
+NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
+{
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaRotateCCW(a_Meta);
+ }
+}
+
+
+
+NIBBLETYPE cBlockDoorHandler::MetaRotateCW(NIBBLETYPE a_Meta)
+{
+ if (a_Meta & 0x08)
+ {
+ return a_Meta;
+ }
+ else
+ {
+ return super::MetaRotateCW(a_Meta);
+ }
+}
+
+
+
+NIBBLETYPE cBlockDoorHandler::MetaMirrorXY(NIBBLETYPE a_Meta)
+{
+ // Top bit (0x08) contains door panel type (Top/Bottom panel) Only Bottom panels contain position data
+ // Return a_Meta if panel is a top panel (0x08 bit is set to 1)
+
+ // Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
+ // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
+ // so the function can only see either the hinge position or orientation, but not both, at any given time. The class itself
+ // needs extra datamembers.
+ if (a_Meta & 0x08) return a_Meta;
+
+ // Holds open/closed meta data. 0x0C == 1100.
+ NIBBLETYPE OtherMeta = a_Meta & 0x0C;
+
+ // Mirrors according to a table. 0x03 == 0011.
+ switch (a_Meta & 0x03)
+ {
+ case 0x03: return 0x01 + OtherMeta; // South -> North
+ case 0x01: return 0x03 + OtherMeta; // North -> South
+ }
+
+ // Not Facing North or South; No change.
+ return a_Meta;
+}
+
+
+
+NIBBLETYPE cBlockDoorHandler::MetaMirrorYZ(NIBBLETYPE a_Meta)
+{
+ // Top bit (0x08) contains door panel type (Top/Bottom panel) Only Bottom panels contain position data
+ // Return a_Meta if panel is a top panel (0x08 bit is set to 1)
+
+ // Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
+ // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
+ // so the function can only see either the hinge position or orientation, but not both, at any given time.The class itself
+ // needs extra datamembers.
+
+ if (a_Meta & 0x08) return a_Meta;
+
+ // Holds open/closed meta data. 0x0C == 1100.
+ NIBBLETYPE OtherMeta = a_Meta & 0x0C;
+
+ // Mirrors according to a table. 0x03 == 0011.
+ switch (a_Meta & 0x03)
+ {
+ case 0x00: return 0x02 + OtherMeta; // West -> East
+ case 0x02: return 0x00 + OtherMeta; // East -> West
+ }
+
+ // Not Facing North or South; No change.
+ return a_Meta;
+}
+
+
+
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 981774c17..797fe484c 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -4,15 +4,15 @@
#include "BlockHandler.h"
#include "../Entities/Player.h"
#include "Chunk.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockDoorHandler :
- public cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true>
+ public cMetaRotator<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true>
{
- typedef cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true> super;
+ typedef cMetaRotator<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true> super;
public:
cBlockDoorHandler(BLOCKTYPE a_BlockType);
@@ -21,6 +21,10 @@ 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;
virtual const char * GetStepSound(void) override;
+ 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;
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
@@ -142,14 +146,14 @@ public:
static void ChangeDoor(cChunkInterface & a_ChunkInterface, int a_X, int a_Y, int a_Z)
{
NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta(a_X, a_Y, a_Z);
-
+
a_ChunkInterface.SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData(OldMetaData));
-
+
if (OldMetaData & 8)
{
// Current block is top of the door
BLOCKTYPE BottomBlock = a_ChunkInterface.GetBlock(a_X, a_Y - 1, a_Z);
- NIBBLETYPE BottomMeta = a_ChunkInterface.GetBlockMeta(a_X, a_Y - 1, a_Z);
+ NIBBLETYPE BottomMeta = a_ChunkInterface.GetBlockMeta(a_X, a_Y - 1, a_Z);
if (IsDoor(BottomBlock) && !(BottomMeta & 8))
{
@@ -168,62 +172,6 @@ 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 7e0ad0e55..88b61a418 100644
--- a/src/Blocks/BlockDropSpenser.h
+++ b/src/Blocks/BlockDropSpenser.h
@@ -6,18 +6,18 @@
#pragma once
#include "../Piston.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockDropSpenserHandler :
- public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
+ public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockDropSpenserHandler(BLOCKTYPE a_BlockType) :
- cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
+ cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockEnchantmentTable.h b/src/Blocks/BlockEnchantmentTable.h
new file mode 100644
index 000000000..81d2cb9a0
--- /dev/null
+++ b/src/Blocks/BlockEnchantmentTable.h
@@ -0,0 +1,37 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+#include "../UI/Window.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+class cBlockEnchantmentTableHandler :
+ public cBlockHandler
+{
+public:
+ cBlockEnchantmentTableHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ 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
+ {
+ cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->OpenWindow(Window);
+ }
+
+
+ virtual bool IsUseable(void) override
+ {
+ return true;
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockEnderchest.h b/src/Blocks/BlockEnderchest.h
index 97cf484fb..67955f8ce 100644
--- a/src/Blocks/BlockEnderchest.h
+++ b/src/Blocks/BlockEnderchest.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockEntity.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockEnderchestHandler :
- public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
+ public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockEnderchestHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
+ : cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index b720ccd14..3dd5bcd1d 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -52,9 +52,9 @@ public:
return;
}
- int NumBlocks = Area.GetBlockCount();
+ size_t NumBlocks = Area.GetBlockCount();
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
- for (int i = 0; i < NumBlocks; i++)
+ for (size_t i = 0; i < NumBlocks; i++)
{
if (
(BlockTypes[i] == E_BLOCK_WATER) ||
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index e3162bbd6..e202c6610 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockFenceGateHandler :
- public cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>
+ public cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockFenceGateHandler(BLOCKTYPE a_BlockType) :
- cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
+ cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h
index a25b87858..f9f32eb50 100644
--- a/src/Blocks/BlockFire.h
+++ b/src/Blocks/BlockFire.h
@@ -17,25 +17,27 @@ public:
}
/// Portal boundary and direction variables
- int XZP, XZM, Dir; // For wont of a better name...
+ // 2014_03_30 _X: What are these used for? Why do we need extra variables?
+ int XZP, XZM;
+ NIBBLETYPE Dir;
virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
/*
PORTAL FINDING ALGORITH
=======================
- -Get clicked base block
- -Trace upwards to find first obsidian block; aborts if anything other than obsidian or air is encountered.
- Uses this value as a reference (the 'ceiling')
- -For both directions (if one fails, try the other), BASE (clicked) block:
- -Go in one direction, only stop if a non obsidian block is encountered (abort) OR a portal border is encountered (FindObsidianCeiling returns -1)
- -If a border was encountered, go the other direction and repeat above
- -Write borders to XZP and XZM, write direction portal faces to Dir
- -Loop through boundary variables, and fill with portal blocks based on Dir with meta from Dir
+ - Get clicked base block
+ - Trace upwards to find first obsidian block; aborts if anything other than obsidian or air is encountered.
+ Uses this value as a reference (the 'ceiling')
+ - For both directions (if one fails, try the other), BASE (clicked) block:
+ - Go in one direction, only stop if a non obsidian block is encountered (abort) OR a portal border is encountered (FindObsidianCeiling returns -1)
+ - If a border was encountered, go the other direction and repeat above
+ - Write borders to XZP and XZM, write direction portal faces to Dir
+ - Loop through boundary variables, and fill with portal blocks based on Dir with meta from Dir
*/
a_BlockY--; // Because we want the block below the fire
- FindAndSetPortalFrame(a_BlockX, a_BlockY, a_BlockZ, a_ChunkInterface, a_WorldInterface); // Brought to you by Aperture Science
+ FindAndSetPortalFrame(a_BlockX, a_BlockY, a_BlockZ, a_ChunkInterface, a_WorldInterface);
}
virtual void OnDigging(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
@@ -66,7 +68,6 @@ public:
{
return 0;
}
-
for (int newY = Y + 1; newY < cChunkDef::Height; newY++)
{
@@ -82,7 +83,7 @@ public:
// This is because the frame is a solid obsidian pillar
if ((MaxY != 0) && (newY == Y + 1))
{
- return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface);
+ return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface) ? -1 /* -1 = found a frame */ : 0;
}
else
{
@@ -97,18 +98,18 @@ public:
}
/// Evaluates if coords have a valid border on top, based on MaxY
- int EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
+ bool EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
{
for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners
{
if (a_ChunkInterface.GetBlock(X, checkBorder, Z) != E_BLOCK_OBSIDIAN)
{
// Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal
- return 0;
+ return false;
}
}
// Everything was obsidian, found a border!
- return -1; // Return -1 for a frame border
+ return true;
}
/// Finds entire frame in any direction with the coordinates of a base block and fills hole with nether portal (START HERE)
@@ -167,7 +168,7 @@ public:
{
return false; // Not valid slice, no portal can be formed
}
- } XZP = X1 - 1; // Set boundary of frame interior, note that for some reason, the loop of X and the loop of Z go to different numbers, hence -1 here and -2 there
+ } XZP = X1 - 1; // Set boundary of frame interior
for (; ((a_ChunkInterface.GetBlock(X2, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X2, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM)
{
int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY);
@@ -197,13 +198,13 @@ public:
if ((Value == -1) || (ValueTwo == -1))
{
FoundFrameZP = true;
- continue;
+ break;
}
else if ((Value != MaxY) && (ValueTwo != MaxY))
{
return false;
}
- } XZP = Z1 - 2;
+ } XZP = Z1 - 1;
for (; ((a_ChunkInterface.GetBlock(X, Y, Z2) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X, Y + 1, Z2) == E_BLOCK_OBSIDIAN)); Z2--)
{
int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY);
@@ -211,13 +212,13 @@ public:
if ((Value == -1) || (ValueTwo == -1))
{
FoundFrameZM = true;
- continue;
+ break;
}
else if ((Value != MaxY) && (ValueTwo != MaxY))
{
return false;
}
- } XZM = Z2 + 2;
+ } XZM = Z2 + 1;
return (FoundFrameZP && FoundFrameZM);
}
};
diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h
index 37885e4de..d0c4ea55b 100644
--- a/src/Blocks/BlockFluid.h
+++ b/src/Blocks/BlockFluid.h
@@ -49,6 +49,12 @@ public:
}
super::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk);
}
+
+
+ virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
+ {
+ return false;
+ }
} ;
@@ -93,6 +99,7 @@ public:
// Check if it's fuel:
BLOCKTYPE BlockType;
if (
+ ((a_RelY + y < 0) || (a_RelY + y > cChunkDef::Height)) ||
!a_Chunk.UnboundedRelGetBlockType(a_RelX + x, a_RelY + y, a_RelZ + z, BlockType) ||
!cFireSimulator::IsFuel(BlockType)
)
@@ -119,6 +126,7 @@ public:
for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++)
{
if (
+ ((RelY + CrossCoords[i].y >= 0) && (RelY + CrossCoords[i].y <= cChunkDef::Height)) &&
a_Chunk.UnboundedRelGetBlockType(RelX + CrossCoords[i].x, RelY + CrossCoords[i].y, RelZ + CrossCoords[i].z, BlockType) &&
(BlockType == E_BLOCK_AIR)
)
diff --git a/src/Blocks/BlockFurnace.h b/src/Blocks/BlockFurnace.h
index 27ef2689f..a7a807957 100644
--- a/src/Blocks/BlockFurnace.h
+++ b/src/Blocks/BlockFurnace.h
@@ -4,17 +4,17 @@
#include "BlockEntity.h"
#include "../World.h"
#include "../Piston.h"
-
+#include "MetaRotator.h"
class cBlockFurnaceHandler :
- public cBlockEntityHandler
+ public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
- cBlockFurnaceHandler(BLOCKTYPE a_BlockType) :
- cBlockEntityHandler(a_BlockType)
+ cBlockFurnaceHandler(BLOCKTYPE a_BlockType)
+ : cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 4f74e2f45..304e35e84 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -8,6 +8,7 @@
#include "../Chunk.h"
#include "BlockAnvil.h"
#include "BlockBed.h"
+#include "BlockBigFlower.h"
#include "BlockBrewingStand.h"
#include "BlockButton.h"
#include "BlockCactus.h"
@@ -24,6 +25,7 @@
#include "BlockDirt.h"
#include "BlockDoor.h"
#include "BlockDropSpenser.h"
+#include "BlockEnchantmentTable.h"
#include "BlockEnderchest.h"
#include "BlockEntity.h"
#include "BlockFarmland.h"
@@ -41,6 +43,7 @@
#include "BlockIce.h"
#include "BlockLadder.h"
#include "BlockLeaves.h"
+#include "BlockLilypad.h"
#include "BlockNewLeaves.h"
#include "BlockLever.h"
#include "BlockMelon.h"
@@ -89,6 +92,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
case E_BLOCK_BED: return new cBlockBedHandler (a_BlockType);
+ case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_BREWING_STAND: return new cBlockBrewingStandHandler (a_BlockType);
case E_BLOCK_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
@@ -116,6 +120,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_DOUBLE_WOODEN_SLAB: return new cBlockDoubleSlabHandler (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_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler ( );
case E_BLOCK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
@@ -142,6 +147,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE 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_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);
@@ -394,6 +400,15 @@ bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, in
+bool cBlockHandler::CanDirtGrowGrass(NIBBLETYPE a_Meta)
+{
+ return ((cBlockInfo::IsTransparent(m_BlockType)) || (cBlockInfo::IsOneHitDig(m_BlockType)));
+}
+
+
+
+
+
bool cBlockHandler::IsUseable()
{
return false;
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index 3a3efb3cc..fb6cae729 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -85,6 +85,9 @@ public:
/// Checks if the block can stay at the specified relative coords in the chunk
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
+
+ /** Can the dirt under this block grow to grass? */
+ virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta);
/** Checks if the block can be placed at this point.
Default: CanBeAt(...)
diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h
index 59b84aa0e..a882bb077 100644
--- a/src/Blocks/BlockHopper.h
+++ b/src/Blocks/BlockHopper.h
@@ -3,16 +3,16 @@
// Declares the cBlockHopperHandler class representing the handler for the Hopper block
-
+#include "MetaRotator.h"
class cBlockHopperHandler :
- public cBlockEntityHandler
+ public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockHopperHandler(BLOCKTYPE a_BlockType)
- : cBlockEntityHandler(a_BlockType)
+ : cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
@@ -39,6 +39,21 @@ public:
}
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/BlockLadder.h b/src/Blocks/BlockLadder.h
index a3e9edc6b..a605edf3f 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -9,11 +9,11 @@
class cBlockLadderHandler :
- public cBlockHandler
+ public cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockLadderHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h
index a6d3373c1..495e849fa 100644
--- a/src/Blocks/BlockLeaves.h
+++ b/src/Blocks/BlockLeaves.h
@@ -1,6 +1,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
+#include "../FastRandom.h"
#include "../World.h"
#include "../BlockArea.h"
@@ -16,6 +16,7 @@
{ \
case E_BLOCK_LEAVES: a_Area.SetBlockType(x, y, z, (BLOCKTYPE)(E_BLOCK_SPONGE + i + 1)); break; \
case E_BLOCK_LOG: return true; \
+ case E_BLOCK_NEW_LEAVES: a_Area.SetBlockType(x, y, z, (BLOCKTYPE)(E_BLOCK_SPONGE + i + 1)); break; \
case E_BLOCK_NEW_LOG: return true; \
}
@@ -37,16 +38,18 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- MTRand rand;
+ cFastRandom rand;
// Only the first 2 bits contain the display information, the others are for growing
- if (rand.randInt(5) == 0)
+ if (rand.NextInt(6) == 0)
{
a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, a_BlockMeta & 3));
}
- if ((a_BlockMeta & 3) == E_META_SAPLING_APPLE)
+
+ // 1 % chance of dropping an apple, if the leaves' type is Apple Leaves
+ if ((a_BlockMeta & 3) == E_META_LEAVES_APPLE)
{
- if (rand.rand(100) == 0)
+ if (rand.NextInt(101) == 0)
{
a_Pickups.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
}
@@ -58,11 +61,10 @@ public:
{
cBlockHandler::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
- //0.5% chance of dropping an apple
+ // 0.5% chance of dropping an apple, if the leaves' type is Apple Leaves:
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- //check if Oak (0x1 and 0x2 bit not set)
- MTRand rand;
- if(!(Meta & 3) && rand.randInt(200) == 100)
+ cFastRandom rand;
+ if (((Meta & 3) == E_META_LEAVES_APPLE) && (rand.NextInt(201) == 100))
{
cItems Drops;
Drops.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
@@ -136,14 +138,14 @@ bool HasNearLog(cBlockArea & a_Area, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Filter the blocks into a {leaves, log, other (air)} set:
BLOCKTYPE * Types = a_Area.GetBlockTypes();
- for (int i = a_Area.GetBlockCount() - 1; i > 0; i--)
+ for (size_t i = a_Area.GetBlockCount() - 1; i > 0; i--)
{
switch (Types[i])
{
- case E_BLOCK_NEW_LEAVES:
- case E_BLOCK_NEW_LOG:
case E_BLOCK_LEAVES:
case E_BLOCK_LOG:
+ case E_BLOCK_NEW_LEAVES:
+ case E_BLOCK_NEW_LOG:
{
break;
}
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index ef6e102cd..ad2ae29e5 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -1,17 +1,18 @@
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotator.h"
class cBlockLeverHandler :
- public cBlockHandler
+ public cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false>
{
+ typedef cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false> super;
public:
cBlockLeverHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x07, 0x04, 0x02, 0x03, 0x01, false>(a_BlockType)
{
}
@@ -104,6 +105,36 @@ public:
return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
}
+
+
+ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
+ {
+ switch (a_Meta)
+ {
+ case 0x00: return 0x07; // Ceiling rotation
+ case 0x07: return 0x00;
+
+ case 0x05: return 0x06; // Ground rotation
+ case 0x06: return 0x05;
+
+ default: return super::MetaRotateCCW(a_Meta); // Wall Rotation
+ }
+ }
+
+
+ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
+ {
+ switch (a_Meta)
+ {
+ case 0x00: return 0x07; // Ceiling rotation
+ case 0x07: return 0x00;
+
+ case 0x05: return 0x06; // Ground rotation
+ case 0x06: return 0x05;
+
+ default: return super::MetaRotateCCW(a_Meta); // Wall Rotation
+ }
+ }
} ;
diff --git a/src/Blocks/BlockLilypad.h b/src/Blocks/BlockLilypad.h
new file mode 100644
index 000000000..2dd4ec768
--- /dev/null
+++ b/src/Blocks/BlockLilypad.h
@@ -0,0 +1,28 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+#include "Entities/Pickup.h"
+
+
+
+
+class cBlockLilypadHandler :
+ public cBlockHandler
+{
+public:
+ cBlockLilypadHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ // Reset meta to zero
+ a_Pickups.push_back(cItem(E_BLOCK_LILY_PAD, 1, 0));
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h
index 6aa01f986..b7629b07c 100644
--- a/src/Blocks/BlockMobHead.h
+++ b/src/Blocks/BlockMobHead.h
@@ -22,14 +22,127 @@ public:
a_Pickups.push_back(cItem(E_ITEM_HEAD, 1, 0));
}
- bool TrySpawnWither(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
+ bool TrySpawnWither(cChunkInterface & a_ChunkInterface, cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
if (a_BlockY < 2)
{
return false;
}
+
+ class cCallback : public cMobHeadCallback
+ {
+ bool m_IsWither;
+
+ virtual bool Item (cMobHeadEntity * a_MobHeadEntity)
+ {
+ m_IsWither = (a_MobHeadEntity->GetType() == SKULL_TYPE_WITHER);
+
+ return false;
+ }
+
+ public:
+ cCallback () : m_IsWither(false) {}
+
+ bool IsWither(void) const { return m_IsWither; }
+
+ void Reset(void) { m_IsWither = false; }
+
+ } CallbackA, CallbackB;
+
+ class cPlayerCallback : public cPlayerListCallback
+ {
+ Vector3f m_Pos;
+
+ virtual bool Item(cPlayer * a_Player)
+ {
+ // TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one
+ double Dist = (a_Player->GetPosition() - m_Pos).Length();
+ if (Dist < 50.0)
+ {
+ // If player is close, award achievement
+ a_Player->AwardAchievement(achSpawnWither);
+ }
+ return false;
+ }
+
+ public:
+ cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {}
+
+ } PlayerCallback(Vector3f(a_BlockX, a_BlockY, a_BlockZ));
+
+ a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, CallbackA);
+
+ if (!CallbackA.IsWither())
+ {
+ return false;
+ }
+
+ CallbackA.Reset();
+
+ BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
+ BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ);
+
+ if ((BlockY1 != E_BLOCK_SOULSAND) || (BlockY2 != E_BLOCK_SOULSAND))
+ {
+ return false;
+ }
+
+ a_World->DoWithMobHeadAt(a_BlockX - 1, a_BlockY, a_BlockZ, CallbackA);
+ a_World->DoWithMobHeadAt(a_BlockX + 1, a_BlockY, a_BlockZ, CallbackB);
+
+ BLOCKTYPE Block1 = a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ);
+ BLOCKTYPE Block2 = a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ);
+
+ if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
+ {
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
+
+ // Block entities
+ a_World->SetBlock(a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ a_World->SetBlock(a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+
+ // Spawn the wither:
+ a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);
+
+ // Award Achievement
+ a_World->ForEachPlayer(PlayerCallback);
+
+ return true;
+ }
+
+ CallbackA.Reset();
+ CallbackB.Reset();
- // TODO 2014-03-24 xdot
+ a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ - 1, CallbackA);
+ a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ + 1, CallbackB);
+
+ Block1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1);
+ Block2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1);
+
+ if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
+ {
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1, E_BLOCK_AIR, 0);
+ a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
+
+ // Block entities
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0);
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0);
+
+ // Spawn the wither:
+ a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither);
+
+ // Award Achievement
+ a_World->ForEachPlayer(PlayerCallback);
+
+ return true;
+ }
return false;
}
@@ -62,20 +175,37 @@ public:
}
public:
- cCallback (cPlayer * a_Player, NIBBLETYPE a_OldBlockMeta, NIBBLETYPE a_NewBlockMeta) :
- m_Player(a_Player),
+ cCallback (cPlayer * a_CBPlayer, NIBBLETYPE a_OldBlockMeta, NIBBLETYPE a_NewBlockMeta) :
+ m_Player(a_CBPlayer),
m_OldBlockMeta(a_OldBlockMeta),
m_NewBlockMeta(a_NewBlockMeta)
{}
};
cCallback Callback(a_Player, a_BlockMeta, static_cast<NIBBLETYPE>(a_BlockFace));
- a_BlockMeta = a_BlockFace;
+ a_BlockMeta = (NIBBLETYPE)a_BlockFace;
cWorld * World = (cWorld *) &a_WorldInterface;
World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
- TrySpawnWither(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
+ if (a_BlockMeta == SKULL_TYPE_WITHER)
+ {
+ static const Vector3i Coords[] =
+ {
+ Vector3i( 0, 0, 0),
+ Vector3i( 1, 0, 0),
+ Vector3i(-1, 0, 0),
+ Vector3i( 0, 0, 1),
+ Vector3i( 0, 0, -1),
+ };
+ for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i)
+ {
+ if (TrySpawnWither(a_ChunkInterface, World, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z))
+ {
+ break;
+ }
+ } // for i - Coords[]
+ }
}
} ;
diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h
index 923180e19..812cf906f 100644
--- a/src/Blocks/BlockNetherWart.h
+++ b/src/Blocks/BlockNetherWart.h
@@ -2,14 +2,13 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
+#include "../FastRandom.h"
#include "../World.h"
-/// Common class that takes care of carrots, potatoes and wheat
class cBlockNetherWartHandler :
public cBlockHandler
{
@@ -22,12 +21,12 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_Meta) override
{
- MTRand rand;
+ cFastRandom rand;
if (a_Meta == 0x7)
{
- // Is fully grown, drop the entire produce:
- a_Pickups.push_back(cItem(E_ITEM_NETHER_WART, 1 + (int)(rand.randInt(2) + rand.randInt(2)) / 2, 0));
+ // Fully grown, drop the entire produce:
+ a_Pickups.push_back(cItem(E_ITEM_NETHER_WART, (char)(1 + (rand.NextInt(3) + rand.NextInt(3))) / 2, 0));
}
else
{
@@ -35,18 +34,20 @@ 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
{
- NIBBLETYPE Meta = a_Chunk.GetMeta (a_RelX, a_RelY, a_RelZ);
-
+ NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
if (Meta < 7)
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_NETHER_WART, ++Meta);
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
+ // Needs to be placed on top of a Soulsand block:
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_SOULSAND));
}
} ;
diff --git a/src/Blocks/BlockPluginInterface.h b/src/Blocks/BlockPluginInterface.h
index 7428c9a7a..3a36c40b1 100644
--- a/src/Blocks/BlockPluginInterface.h
+++ b/src/Blocks/BlockPluginInterface.h
@@ -1,8 +1,14 @@
#pragma once
+/** This interface is used to decouple block handlers from the cPluginManager dependancy through cWorld.
+The block handlers call this interface, which is then implemented by the specific classes that
+the caller provides.
+*/
class cBlockPluginInterface
{
public:
+ virtual ~cBlockPluginInterface() {}
+
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;
};
diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h
index 21bcbdeea..3b8030028 100644
--- a/src/Blocks/BlockPortal.h
+++ b/src/Blocks/BlockPortal.h
@@ -2,6 +2,7 @@
#pragma once
#include "BlockHandler.h"
+#include "../Mobs/Monster.h"
@@ -38,6 +39,19 @@ public:
return; // No pickups
}
+ virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
+ {
+ cFastRandom Random;
+ if (Random.NextInt(2000) != 0)
+ {
+ return;
+ }
+
+ int PosX = a_Chunk.GetPosX() * 16 + a_RelX;
+ int PosZ = a_Chunk.GetPosZ() * 16 + a_RelZ;
+
+ a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, cMonster::mtZombiePigman);
+ }
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
diff --git a/src/Blocks/BlockPumpkin.h b/src/Blocks/BlockPumpkin.h
index 349f52605..ac2b9817a 100644
--- a/src/Blocks/BlockPumpkin.h
+++ b/src/Blocks/BlockPumpkin.h
@@ -1,16 +1,16 @@
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotator.h"
class cBlockPumpkinHandler :
- public cBlockHandler
+ public cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false>
{
public:
cBlockPumpkinHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h
index 07e9814cd..358b5ca11 100644
--- a/src/Blocks/BlockRail.h
+++ b/src/Blocks/BlockRail.h
@@ -141,7 +141,7 @@ public:
NIBBLETYPE Meta = 0;
char RailsCnt = 0;
bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
- memset(Neighbors, false, sizeof(Neighbors));
+ memset(Neighbors, 0, sizeof(Neighbors));
Neighbors[0] = (IsUnstable(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN));
Neighbors[1] = (IsUnstable(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN));
Neighbors[2] = (IsUnstable(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1) || !IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN));
@@ -431,9 +431,145 @@ public:
}
break;
}
+ default: break;
}
return true;
}
+
+
+ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
+ {
+ // Bit 0x08 is a flag when a_Meta is in the range 0x00--0x05 and 0x0A--0x0F.
+ // Bit 0x08 specifies direction when a_Meta is in the range 0x06-0x09.
+ if ((a_Meta < 0x06) || (a_Meta > 0x09))
+ {
+ // Save powered rail flag.
+ NIBBLETYPE OtherMeta = a_Meta & 0x08;
+ // Rotates according to table; 0x07 == 0111.
+ // Rails can either be flat (North/South) or Ascending (Asc. East)
+ switch (a_Meta & 0x07)
+ {
+ case 0x00: return 0x01 + OtherMeta; // North/South -> East/West
+ case 0x01: return 0x00 + OtherMeta; // East/West -> North/South
+
+ case 0x02: return 0x04 + OtherMeta; // Asc. East -> Asc. North
+ case 0x04: return 0x03 + OtherMeta; // Asc. North -> Asc. West
+ case 0x03: return 0x05 + OtherMeta; // Asc. West -> Asc. South
+ case 0x05: return 0x02 + OtherMeta; // Asc. South -> Asc. East
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ // Corner Directions
+ case 0x06: return 0x09; // Northwest Cnr. -> Southwest Cnr.
+ case 0x07: return 0x06; // Northeast Cnr. -> Northwest Cnr.
+ case 0x08: return 0x07; // Southeast Cnr. -> Northeast Cnr.
+ case 0x09: return 0x08; // Southwest Cnr. -> Southeast Cnr.
+ }
+ }
+ // To avoid a compiler warning;
+ return a_Meta;
+ }
+
+
+ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
+ {
+ // Bit 0x08 is a flag for value in the range 0x00--0x05 and specifies direction for values withint 0x006--0x09.
+ if ((a_Meta < 0x06) || (a_Meta > 0x09))
+ {
+ // Save powered rail flag.
+ NIBBLETYPE OtherMeta = a_Meta & 0x08;
+ // Rotates according to table; 0x07 == 0111.
+ // Rails can either be flat (North/South) or Ascending (Asc. East)
+ switch (a_Meta & 0x07)
+ {
+ case 0x00: return 0x01 + OtherMeta; // North/South -> East/West
+ case 0x01: return 0x00 + OtherMeta; // East/West -> North/South
+
+ case 0x02: return 0x05 + OtherMeta; // Asc. East -> Asc. South
+ case 0x05: return 0x03 + OtherMeta; // Asc. South -> Asc. West
+ case 0x03: return 0x04 + OtherMeta; // Asc. West -> Asc. North
+ case 0x04: return 0x02 + OtherMeta; // Asc. North -> Asc. East
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ // Corner Directions
+ case 0x06: return 0x07; // Northwest Cnr. -> Northeast Cnr.
+ case 0x07: return 0x08; // Northeast Cnr. -> Southeast Cnr.
+ case 0x08: return 0x09; // Southeast Cnr. -> Southwest Cnr.
+ case 0x09: return 0x06; // Southwest Cnr. -> Northwest Cnr.
+ }
+ }
+ // To avoid a compiler warning;
+ return a_Meta;
+ }
+
+
+ virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
+ {
+ // Bit 0x08 is a flag for value in the range 0x00--0x05 and specifies direction for values withint 0x006--0x09.
+ if ((a_Meta < 0x06) || (a_Meta > 0x09))
+ {
+ // Save powered rail flag.
+ NIBBLETYPE OtherMeta = a_Meta & 0x08;
+ // Mirrors according to table; 0x07 == 0111.
+ // Rails can either be flat (North/South) or Ascending (Asc. East)
+ switch (a_Meta & 0x07)
+ {
+ case 0x05: return 0x04 + OtherMeta; // Asc. South -> Asc. North
+ case 0x04: return 0x05 + OtherMeta; // Asc. North -> Asc. South
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ // Corner Directions
+ case 0x06: return 0x09; // Northwest Cnr. -> Southwest Cnr.
+ case 0x07: return 0x08; // Northeast Cnr. -> Southeast Cnr.
+ case 0x08: return 0x07; // Southeast Cnr. -> Northeast Cnr.
+ case 0x09: return 0x06; // Southwest Cnr. -> Northwest Cnr.
+ }
+ }
+ // To avoid a compiler warning;
+ return a_Meta;
+ }
+
+
+ virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
+ {
+ // Bit 0x08 is a flag for value in the range 0x00--0x05 and specifies direction for values withint 0x006--0x09.
+ if ((a_Meta < 0x06) || (a_Meta > 0x09))
+ {
+ // Save powered rail flag.
+ NIBBLETYPE OtherMeta = a_Meta & 0x08;
+ // Mirrors according to table; 0x07 == 0111.
+ // Rails can either be flat (North/South) or Ascending (Asc. East)
+ switch (a_Meta & 0x07)
+ {
+ case 0x02: return 0x03 + OtherMeta; // Asc. East -> Asc. West
+ case 0x03: return 0x02 + OtherMeta; // Asc. West -> Asc. East
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ // Corner Directions
+ case 0x06: return 0x07; // Northwest Cnr. -> Northeast Cnr.
+ case 0x07: return 0x06; // Northeast Cnr. -> Northwest Cnr.
+ case 0x08: return 0x09; // Southeast Cnr. -> Southwest Cnr.
+ case 0x09: return 0x08; // Southwest Cnr. -> Southeast Cnr.
+ }
+ }
+ // To avoid a compiler warning;
+ return a_Meta;
+ }
} ;
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index 1e2a86949..fe6cd21b9 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -3,17 +3,17 @@
#include "BlockHandler.h"
#include "Chunk.h"
-
+#include "MetaRotator.h"
class cBlockRedstoneRepeaterHandler :
- public cBlockHandler
+ public cMetaRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>
{
public:
cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockSign.h b/src/Blocks/BlockSign.h
index cd0c02a40..9d6fede21 100644
--- a/src/Blocks/BlockSign.h
+++ b/src/Blocks/BlockSign.h
@@ -31,7 +31,7 @@ public:
}
- static char RotationToMetaData(double a_Rotation)
+ static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
a_Rotation += 180 + (180 / 16); // So it's not aligned with axis
if (a_Rotation > 360)
@@ -45,7 +45,7 @@ public:
}
- static char DirectionToMetaData(eBlockFace a_Direction)
+ static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
{
switch (a_Direction)
{
@@ -71,6 +71,37 @@ public:
{
a_Player->GetClientHandle()->SendEditSign(a_BlockX, a_BlockY, a_BlockZ);
}
+
+
+ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
+ {
+ return (++a_Meta) & 0x0F;
+ }
+
+
+ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
+ {
+ return (--a_Meta) & 0x0F;
+ }
+
+ virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
+ {
+ // Mirrors signs over the XY plane (North-South Mirroring)
+
+ // There are 16 meta values which correspond to different directions.
+ // These values are equated to angles on a circle; 0x08 = 180 degrees.
+ return (a_Meta < 0x08) ? 0x08 + a_Meta : 0x08 - a_Meta;
+ }
+
+
+ virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
+ {
+ // Mirrors signs over the YZ plane (East-West Mirroring)
+
+ // There are 16 meta values which correspond to different directions.
+ // These values are equated to angles on a circle; 0x10 = 360 degrees.
+ return 0x10 - a_Meta;
+ }
} ;
diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h
index 7cd2c97b2..80841b094 100644
--- a/src/Blocks/BlockSlab.h
+++ b/src/Blocks/BlockSlab.h
@@ -11,8 +11,7 @@
#include "BlockHandler.h"
#include "../Items/ItemHandler.h"
-
-
+#include "Root.h"
@@ -40,41 +39,9 @@ public:
) override
{
a_BlockType = m_BlockType;
- BLOCKTYPE Type = (BLOCKTYPE) (a_Player->GetEquippedItem().m_ItemType);
NIBBLETYPE Meta = (NIBBLETYPE) a_Player->GetEquippedItem().m_ItemDamage;
- // HandlePlaceBlock wants a cItemHandler pointer thing, so let's give it one
- cItemHandler * ItemHandler = cItemHandler::GetItemHandler(GetDoubleSlabType(Type));
-
- // Check if the block at the coordinates is a slab. Eligibility for combining has already been processed in ClientHandle
- if (IsAnySlabType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ)))
- {
- // Call the function in ClientHandle that places a block when the client sends the packet,
- // so that plugins may interfere with the placement.
-
- if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
- {
- // Top and bottom faces need no parameter modification
- a_Player->GetClientHandle()->HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
- }
- else
- {
- // The other faces need to distinguish between top and bottom cursor positions
- if (a_CursorY > 7)
- {
- // Edit the call to use BLOCK_FACE_BOTTOM, otherwise it places incorrectly
- a_Player->GetClientHandle()->HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_TOP, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
- }
- else
- {
- // Edit the call to use BLOCK_FACE_TOP, otherwise it places incorrectly
- a_Player->GetClientHandle()->HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_BOTTOM, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
- }
- }
- return false; // Cancel the event, because dblslabs were already placed, nothing else needed
- }
-
- // Place the single-slab with correct metas:
+ // Set the correct metadata based on player equipped item (i.e. a_BlockMeta not initialised yet)
switch (a_BlockFace)
{
case BLOCK_FACE_TOP:
@@ -105,7 +72,16 @@ public:
a_BlockMeta = Meta & 0x7; break;
}
}
+ case BLOCK_FACE_NONE: return false;
} // switch (a_BlockFace)
+
+ // Check if the block at the coordinates is a single slab. Eligibility for combining has already been processed in ClientHandle
+ // Changed to-be-placed to a double slab if we are clicking on a single slab, as opposed to placing one for the first time
+ if (IsAnySlabType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ)))
+ {
+ a_BlockType = GetDoubleSlabType(m_BlockType);
+ }
+
return true;
}
@@ -121,6 +97,12 @@ public:
return "";
}
+
+ virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
+ {
+ return ((a_Meta & 0x8) != 0);
+ }
+
/// Returns true if the specified blocktype is one of the slabs handled by this handler
static bool IsAnySlabType(BLOCKTYPE a_BlockType)
@@ -184,6 +166,15 @@ public:
ASSERT(!"Unhandled double slab type!");
return "";
}
+
+
+ virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
+ {
+ NIBBLETYPE OtherMeta = a_Meta & 0x07; // Contains unrelated meta data.
+
+ // 8th bit is up/down. 1 right-side-up, 0 is up-side-down.
+ return (a_Meta & 0x08) ? 0x00 + OtherMeta : 0x01 + OtherMeta;
+ }
} ;
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index ea8405597..a49fda5ae 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockStairsHandler :
- public cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>
+ public cMetaRotator<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>
{
public:
cBlockStairsHandler(BLOCKTYPE a_BlockType) :
- cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>(a_BlockType)
+ cMetaRotator<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>(a_BlockType)
{
}
@@ -30,9 +30,7 @@ public:
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)
@@ -51,10 +49,12 @@ public:
}
break;
}
+ case BLOCK_FACE_NONE: return false;
}
return true;
}
+
virtual const char * GetStepSound(void) override
{
if (
@@ -77,6 +77,11 @@ public:
// Reset meta to 0
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
+
+ virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
+ {
+ return true;
+ }
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index 705436345..b726a0901 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -17,9 +17,10 @@ public:
{
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- int ItemType = (m_BlockType == E_BLOCK_MELON_STEM) ? E_ITEM_MELON_SEEDS : E_ITEM_PUMPKIN_SEEDS;
+ short ItemType = (m_BlockType == E_BLOCK_MELON_STEM) ? E_ITEM_MELON_SEEDS : E_ITEM_PUMPKIN_SEEDS;
a_Pickups.push_back(cItem(ItemType, 1, 0));
}
diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h
index b8af1f1da..ba1f2e0f6 100644
--- a/src/Blocks/BlockTallGrass.h
+++ b/src/Blocks/BlockTallGrass.h
@@ -15,14 +15,14 @@ public:
: cBlockHandler(a_BlockType)
{
}
-
-
+
+
virtual bool DoesIgnoreBuildCollision(void) override
{
return true;
}
-
-
+
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Drop seeds, sometimes
@@ -34,11 +34,25 @@ public:
}
+ virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
+ if ((!a_Player->IsGameModeCreative()) && (a_Player->GetEquippedItem().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);
+ }
+ a_Player->UseEquippedItem();
+ }
+
+
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));
}
-
+
virtual const char * GetStepSound(void) override
{
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index d32c77629..8ddec8de1 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -2,17 +2,17 @@
#include "BlockHandler.h"
#include "../Chunk.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
class cBlockTorchHandler :
- public cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>
+ public cMetaRotator<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>
{
public:
cBlockTorchHandler(BLOCKTYPE a_BlockType)
- : cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 9bae92c4d..6a36ab874 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-
+#include "MetaRotator.h"
class cBlockTrapdoorHandler :
- public cBlockHandler
+ public cMetaRotator<cBlockHandler, 0x03, 0x01, 0x02, 0x00, 0x03, false>
{
public:
cBlockTrapdoorHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x03, 0x01, 0x02, 0x00, 0x03, false>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index d096c81a8..7bb9dc484 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -1,7 +1,7 @@
#pragma once
#include "BlockHandler.h"
-#include "MetaRotater.h"
+#include "MetaRotator.h"
@@ -83,7 +83,7 @@ public:
static const struct
{
int x, z;
- int Bit;
+ NIBBLETYPE Bit;
} Coords[] =
{
{ 0, 1, 1}, // south, ZP
@@ -91,7 +91,7 @@ public:
{ 0, -1, 4}, // north, ZM
{ 1, 0, 8}, // east, XP
} ;
- int res = 0;
+ NIBBLETYPE res = 0;
for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
{
BLOCKTYPE BlockType;
@@ -197,14 +197,14 @@ public:
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
// Bits 2 and 4 stay, bits 1 and 3 swap
- return ((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
+ return (NIBBLETYPE)((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
}
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
{
// Bits 1 and 3 stay, bits 2 and 4 swap
- return ((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
+ return (NIBBLETYPE)((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
}
} ;
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index 082ff41ac..4b8c745ad 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -6,6 +6,7 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
file(GLOB SOURCE
"*.cpp"
+ "*.h"
)
add_library(Blocks ${SOURCE})
diff --git a/src/Blocks/MetaRotater.h b/src/Blocks/MetaRotator.h
index dde88e6db..899c583e1 100644
--- a/src/Blocks/MetaRotater.h
+++ b/src/Blocks/MetaRotator.h
@@ -1,4 +1,4 @@
-// MetaRotater.h
+// MetaRotator.h
// Provides a mixin for rotations and reflections
@@ -21,15 +21,15 @@ Inherit from this class providing your base class as Base, the BitMask for the d
*/
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched = false>
-class cMetaRotater : public Base
+class cMetaRotator : public Base
{
public:
- cMetaRotater(BLOCKTYPE a_BlockType) :
+ cMetaRotator(BLOCKTYPE a_BlockType) :
Base(a_BlockType)
{}
- virtual ~cMetaRotater() {}
+ virtual ~cMetaRotator() {}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override;
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override;
@@ -42,7 +42,7 @@ public:
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 cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
@@ -64,7 +64,7 @@ NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatc
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 cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
@@ -86,7 +86,7 @@ NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatc
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 cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorXY(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
@@ -103,7 +103,7 @@ NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatc
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 cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorYZ(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)