summaryrefslogtreecommitdiffstats
path: root/source/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'source/Blocks')
-rw-r--r--source/Blocks/BlockBed.h6
-rw-r--r--source/Blocks/BlockButton.cpp39
-rw-r--r--source/Blocks/BlockButton.h69
-rw-r--r--source/Blocks/BlockCactus.h6
-rw-r--r--source/Blocks/BlockComparator.cpp53
-rw-r--r--source/Blocks/BlockComparator.h55
-rw-r--r--source/Blocks/BlockCrops.h14
-rw-r--r--source/Blocks/BlockDeadBush.h12
-rw-r--r--source/Blocks/BlockDoor.cpp7
-rw-r--r--source/Blocks/BlockDoor.h86
-rw-r--r--source/Blocks/BlockDropSpenser.h2
-rw-r--r--source/Blocks/BlockFarmland.h44
-rw-r--r--source/Blocks/BlockFenceGate.h34
-rw-r--r--source/Blocks/BlockFlower.h12
-rw-r--r--source/Blocks/BlockHandler.cpp51
-rw-r--r--source/Blocks/BlockHandler.h8
-rw-r--r--source/Blocks/BlockLever.cpp14
-rw-r--r--source/Blocks/BlockLever.h8
-rw-r--r--source/Blocks/BlockMushroom.h12
-rw-r--r--source/Blocks/BlockMycelium.h5
-rw-r--r--source/Blocks/BlockPlanks.h41
-rw-r--r--source/Blocks/BlockPumpkin.h60
-rw-r--r--source/Blocks/BlockRedstone.h11
-rw-r--r--source/Blocks/BlockRedstoneRepeater.cpp17
-rw-r--r--source/Blocks/BlockRedstoneRepeater.h21
-rw-r--r--source/Blocks/BlockSapling.h12
-rw-r--r--source/Blocks/BlockSign.h6
-rw-r--r--source/Blocks/BlockSnow.h24
-rw-r--r--source/Blocks/BlockStairs.h1
-rw-r--r--source/Blocks/BlockSugarcane.h6
-rw-r--r--source/Blocks/BlockTorch.h104
-rw-r--r--source/Blocks/BlockVine.h6
-rw-r--r--source/Blocks/BlockWood.h45
33 files changed, 657 insertions, 234 deletions
diff --git a/source/Blocks/BlockBed.h b/source/Blocks/BlockBed.h
index 0bf1cfc0f..8a289b22c 100644
--- a/source/Blocks/BlockBed.h
+++ b/source/Blocks/BlockBed.h
@@ -37,12 +37,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop() override
- {
- return false;
- }
-
-
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
diff --git a/source/Blocks/BlockButton.cpp b/source/Blocks/BlockButton.cpp
new file mode 100644
index 000000000..1011f9351
--- /dev/null
+++ b/source/Blocks/BlockButton.cpp
@@ -0,0 +1,39 @@
+
+#include "Globals.h"
+#include "BlockButton.h"
+
+
+
+
+
+cBlockButtonHandler::cBlockButtonHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+{
+}
+
+
+
+
+
+void cBlockButtonHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
+{
+ // Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off.
+ NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f);
+ a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
+
+ if (Meta & 0x08)
+ {
+ a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
+ }
+ else
+ {
+ a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.5f);
+ }
+
+ // Queue a button reset (unpress), with a GetBlock to prevent duplication of buttons (press, break, wait for reset)
+ a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 25);
+}
+
+
+
+
diff --git a/source/Blocks/BlockButton.h b/source/Blocks/BlockButton.h
new file mode 100644
index 000000000..e3f655bfa
--- /dev/null
+++ b/source/Blocks/BlockButton.h
@@ -0,0 +1,69 @@
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockButtonHandler :
+ public cBlockHandler
+{
+public:
+ cBlockButtonHandler(BLOCKTYPE a_BlockType);
+
+ virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ // Reset meta to 0
+ a_Pickups.push_back(cItem(m_BlockType == E_BLOCK_WOODEN_BUTTON ? E_BLOCK_WOODEN_BUTTON : E_BLOCK_STONE_BUTTON, 1, 0));
+ }
+
+
+ virtual bool IsUseable(void) override
+ {
+ return true;
+ }
+
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ a_BlockMeta = BlockFaceToMetaData(a_BlockFace);
+ return true;
+ }
+
+
+ virtual const char * GetStepSound(void) override
+ {
+ return m_BlockType == E_BLOCK_WOODEN_BUTTON ? "step.wood" : "step.stone";
+ }
+
+
+ inline static NIBBLETYPE BlockFaceToMetaData(char a_BlockFace)
+ {
+ switch (a_BlockFace)
+ {
+ case BLOCK_FACE_ZP: { return 0x4; }
+ case BLOCK_FACE_ZM: { return 0x3; }
+ case BLOCK_FACE_XP: { return 0x2; }
+ case BLOCK_FACE_XM: { return 0x1; }
+ default:
+ {
+ ASSERT(!"Unhandled block face!");
+ return 0x0; // No idea, give a special meta (button in centre of block)
+ }
+ }
+ }
+} ;
+
+
+
+
diff --git a/source/Blocks/BlockCactus.h b/source/Blocks/BlockCactus.h
index 1d123bc0a..4147ad473 100644
--- a/source/Blocks/BlockCactus.h
+++ b/source/Blocks/BlockCactus.h
@@ -63,12 +63,6 @@ public:
return true;
}
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
diff --git a/source/Blocks/BlockComparator.cpp b/source/Blocks/BlockComparator.cpp
new file mode 100644
index 000000000..b4e5a55d0
--- /dev/null
+++ b/source/Blocks/BlockComparator.cpp
@@ -0,0 +1,53 @@
+
+#include "Globals.h"
+#include "BlockComparator.h"
+#include "../Simulator/RedstoneSimulator.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+cBlockComparatorHandler::cBlockComparatorHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+{
+}
+
+
+
+
+
+void cBlockComparatorHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ // Nothing needed yet
+}
+
+
+
+
+
+void cBlockComparatorHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
+{
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ Meta ^= 0x04; // Toggle 3rd (addition/subtraction) bit with XOR
+ a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
+}
+
+
+
+
+bool cBlockComparatorHandler::GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+)
+{
+ a_BlockType = m_BlockType;
+ a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
+ return true;
+}
+
+
+
+
diff --git a/source/Blocks/BlockComparator.h b/source/Blocks/BlockComparator.h
new file mode 100644
index 000000000..cb2941d3c
--- /dev/null
+++ b/source/Blocks/BlockComparator.h
@@ -0,0 +1,55 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockComparatorHandler :
+ public cBlockHandler
+{
+public:
+ cBlockComparatorHandler(BLOCKTYPE a_BlockType);
+ virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
+
+ virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ // Reset meta to 0
+ a_Pickups.push_back(cItem(E_ITEM_COMPARATOR, 1, 0));
+ }
+
+
+ virtual bool IsUseable(void) override
+ {
+ return true;
+ }
+
+
+ virtual bool CanBeAt(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 bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override;
+
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+} ;
+
+
+
+
diff --git a/source/Blocks/BlockCrops.h b/source/Blocks/BlockCrops.h
index 4bc76fd50..e7b320eac 100644
--- a/source/Blocks/BlockCrops.h
+++ b/source/Blocks/BlockCrops.h
@@ -20,12 +20,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop() override
- {
- return false;
- }
-
-
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_Meta) override
{
MTRand rand;
@@ -84,10 +78,16 @@ public:
void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- if (Meta < 7)
+ NIBBLETYPE Light = a_World->GetBlockBlockLight(a_BlockX, a_BlockY, a_BlockZ);
+
+ if ((Meta < 7) && (Light > 8))
{
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_CROPS, ++Meta);
}
+ else if (Light < 9)
+ {
+ a_World->DigBlock(a_BlockX, a_BlockY, a_BlockZ);
+ }
}
diff --git a/source/Blocks/BlockDeadBush.h b/source/Blocks/BlockDeadBush.h
index 379e8e5df..14617d006 100644
--- a/source/Blocks/BlockDeadBush.h
+++ b/source/Blocks/BlockDeadBush.h
@@ -28,18 +28,6 @@ public:
{
return (a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_SAND);
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
} ;
diff --git a/source/Blocks/BlockDoor.cpp b/source/Blocks/BlockDoor.cpp
index 02cbd28e2..e71ccd368 100644
--- a/source/Blocks/BlockDoor.cpp
+++ b/source/Blocks/BlockDoor.cpp
@@ -3,7 +3,6 @@
#include "BlockDoor.h"
#include "../Item.h"
#include "../World.h"
-#include "../Doors.h"
#include "../Entities/Player.h"
@@ -26,7 +25,7 @@ void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY
if (OldMeta & 8)
{
// Was upper part of door
- if (cDoors::IsDoor(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
+ if (IsDoor(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
{
a_World->FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
}
@@ -34,7 +33,7 @@ void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY
else
{
// Was lower part
- if (cDoors::IsDoor(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
+ if (IsDoor(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
{
a_World->FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0);
}
@@ -49,7 +48,7 @@ void cBlockDoorHandler::OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX
{
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR)
{
- cDoors::ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ);
+ ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ);
}
}
diff --git a/source/Blocks/BlockDoor.h b/source/Blocks/BlockDoor.h
index 4978fee38..03a79d47d 100644
--- a/source/Blocks/BlockDoor.h
+++ b/source/Blocks/BlockDoor.h
@@ -3,7 +3,6 @@
#include "BlockHandler.h"
#include "../World.h"
-#include "../Doors.h"
#include "../Entities/Player.h"
@@ -43,7 +42,7 @@ public:
}
a_BlockType = m_BlockType;
- a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation());
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
return true;
}
@@ -68,12 +67,6 @@ public:
}
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
-
-
virtual bool CanBeAt(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));
@@ -98,6 +91,83 @@ public:
}
return false;
}
+
+
+ /// Converts the player's yaw to placed door's blockmeta
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 90 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
+
+
+ /// Returns true if the specified blocktype is any kind of door
+ inline static bool IsDoor(BLOCKTYPE a_Block)
+ {
+ return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
+ }
+
+
+ /// Returns the metadata for the opposite door state (open vs closed)
+ static NIBBLETYPE ChangeStateMetaData(NIBBLETYPE a_MetaData)
+ {
+ return a_MetaData ^ 4;
+ }
+
+
+ /// Changes the door at the specified coords from open to close or vice versa
+ static void ChangeDoor(cWorld * a_World, int a_X, int a_Y, int a_Z)
+ {
+ NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ a_World->SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData(OldMetaData));
+
+ if (OldMetaData & 8)
+ {
+ // Current block is top of the door
+ BLOCKTYPE BottomBlock = a_World->GetBlock(a_X, a_Y - 1, a_Z);
+ NIBBLETYPE BottomMeta = a_World->GetBlockMeta(a_X, a_Y - 1, a_Z);
+
+ if (IsDoor(BottomBlock) && !(BottomMeta & 8))
+ {
+ a_World->SetBlockMeta(a_X, a_Y - 1, a_Z, ChangeStateMetaData(BottomMeta));
+ }
+ }
+ else
+ {
+ // Current block is bottom of the door
+ BLOCKTYPE TopBlock = a_World->GetBlock(a_X, a_Y + 1, a_Z);
+ NIBBLETYPE TopMeta = a_World->GetBlockMeta(a_X, a_Y + 1, a_Z);
+
+ if (IsDoor(TopBlock) && (TopMeta & 8))
+ {
+ a_World->SetBlockMeta(a_X, a_Y + 1, a_Z, ChangeStateMetaData(TopMeta));
+ }
+ }
+ }
+
+
} ;
diff --git a/source/Blocks/BlockDropSpenser.h b/source/Blocks/BlockDropSpenser.h
index e5572da8a..b7f20825d 100644
--- a/source/Blocks/BlockDropSpenser.h
+++ b/source/Blocks/BlockDropSpenser.h
@@ -31,7 +31,7 @@ public:
a_BlockType = m_BlockType;
// FIXME: Do not use cPiston class for dispenser placement!
- a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0);
+ a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), a_Player->GetPitch());
return true;
}
} ;
diff --git a/source/Blocks/BlockFarmland.h b/source/Blocks/BlockFarmland.h
index 6cab1fa38..7bc71f7f3 100644
--- a/source/Blocks/BlockFarmland.h
+++ b/source/Blocks/BlockFarmland.h
@@ -30,30 +30,38 @@ public:
virtual void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
- // TODO: Rain hydrates farmland, too. Check world weather, don't search for water if raining.
- // NOTE: The desert biomes do not get precipitation, so another check needs to be made.
+ bool Found = false;
- // Search for water in a close proximity:
- // Ref.: http://www.minecraftwiki.net/wiki/Farmland#Hydrated_Farmland_Tiles
- cBlockArea Area;
- if (!Area.Read(a_World, a_BlockX - 4, a_BlockX + 4, a_BlockY, a_BlockY + 1, a_BlockZ - 4, a_BlockZ + 4))
+ int Biome = a_World->GetBiomeAt(a_BlockX, a_BlockZ);
+ if (a_World->IsWeatherWet() && (Biome != biDesert) && (Biome != biDesertHills))
{
- // Too close to the world edge, cannot check surroudnings; don't tick at all
- return;
+ // Rain hydrates farmland, too, except in Desert biomes.
+ Found = true;
}
- bool Found = false;
- int NumBlocks = Area.GetBlockCount();
- BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
- for (int i = 0; i < NumBlocks; i++)
+ else
{
- if (
- (BlockTypes[i] == E_BLOCK_WATER) ||
- (BlockTypes[i] == E_BLOCK_STATIONARY_WATER)
- )
+ // Search for water in a close proximity:
+ // Ref.: http://www.minecraftwiki.net/wiki/Farmland#Hydrated_Farmland_Tiles
+ cBlockArea Area;
+ if (!Area.Read(a_World, a_BlockX - 4, a_BlockX + 4, a_BlockY, a_BlockY + 1, a_BlockZ - 4, a_BlockZ + 4))
{
- Found = true;
- break;
+ // Too close to the world edge, cannot check surroudnings; don't tick at all
+ return;
}
+
+ int NumBlocks = Area.GetBlockCount();
+ BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
+ for (int i = 0; i < NumBlocks; i++)
+ {
+ if (
+ (BlockTypes[i] == E_BLOCK_WATER) ||
+ (BlockTypes[i] == E_BLOCK_STATIONARY_WATER)
+ )
+ {
+ Found = true;
+ break;
+ }
+ } // for i - BlockTypes[]
}
NIBBLETYPE BlockMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
diff --git a/source/Blocks/BlockFenceGate.h b/source/Blocks/BlockFenceGate.h
index d6f8aa85f..6423a7cb0 100644
--- a/source/Blocks/BlockFenceGate.h
+++ b/source/Blocks/BlockFenceGate.h
@@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../Doors.h"
@@ -26,7 +25,7 @@ public:
) override
{
a_BlockType = m_BlockType;
- a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
return true;
}
@@ -34,7 +33,7 @@ public:
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- NIBBLETYPE NewMetaData = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
+ NIBBLETYPE NewMetaData = PlayerYawToMetaData(a_Player->GetRotation());
OldMetaData ^= 4; // Toggle the gate
if ((OldMetaData & 1) == (NewMetaData & 1))
{
@@ -53,6 +52,35 @@ public:
{
return true;
}
+
+
+ /// Converts the player's yaw to placed gate's blockmeta
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 360 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
} ;
diff --git a/source/Blocks/BlockFlower.h b/source/Blocks/BlockFlower.h
index 952901ba5..421e2d5d8 100644
--- a/source/Blocks/BlockFlower.h
+++ b/source/Blocks/BlockFlower.h
@@ -30,18 +30,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return true;
- }
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
-
-
virtual const char * GetStepSound(void) override
{
return "step.grass";
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index 5134c1103..e59fee8ee 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -7,12 +7,14 @@
#include "../PluginManager.h"
#include "BlockBed.h"
#include "BlockBrewingStand.h"
+#include "BlockButton.h"
#include "BlockCactus.h"
#include "BlockCarpet.h"
#include "BlockCauldron.h"
#include "BlockChest.h"
#include "BlockCloth.h"
#include "BlockCobWeb.h"
+#include "BlockComparator.h"
#include "BlockCrops.h"
#include "BlockDeadBush.h"
#include "BlockDirt.h"
@@ -41,6 +43,8 @@
#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
+#include "BlockPlanks.h"
+#include "BlockPumpkin.h"
#include "BlockRail.h"
#include "BlockRedstone.h"
#include "BlockRedstoneRepeater.h"
@@ -108,6 +112,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_CAULDRON: return new cBlockCauldronHandler (a_BlockType);
case E_BLOCK_CHEST: return new cBlockChestHandler (a_BlockType);
case E_BLOCK_COAL_ORE: return new cBlockOreHandler (a_BlockType);
+ case E_BLOCK_ACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType);
case E_BLOCK_COBBLESTONE: return new cBlockStoneHandler (a_BlockType);
case E_BLOCK_COBBLESTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType);
@@ -122,7 +127,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType);
case E_BLOCK_EMERALD_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
- case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler;
+ case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler ( );
case E_BLOCK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
case E_BLOCK_FIRE: return new cBlockFireHandler (a_BlockType);
case E_BLOCK_FLOWER_POT: return new cBlockFlowerPotHandler (a_BlockType);
@@ -134,6 +139,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_GRAVEL: return new cBlockGravelHandler (a_BlockType);
case E_BLOCK_HOPPER: return new cBlockHopperHandler (a_BlockType);
case E_BLOCK_ICE: return new cBlockIceHandler (a_BlockType);
+ case E_BLOCK_INACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType);
case E_BLOCK_IRON_DOOR: return new cBlockDoorHandler (a_BlockType);
case E_BLOCK_IRON_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_JUKEBOX: return new cBlockEntityHandler (a_BlockType);
@@ -151,10 +157,12 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
- case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler ();
- case E_BLOCK_PLANKS: return new cBlockWoodHandler (a_BlockType);
+ case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler ( );
+ case E_BLOCK_PLANKS: return new cBlockPlanksHandler (a_BlockType);
+ case E_BLOCK_PUMPKIN: return new cBlockPumpkinHandler (a_BlockType);
+ case E_BLOCK_JACK_O_LANTERN: return new cBlockPumpkinHandler (a_BlockType);
case E_BLOCK_PUMPKIN_STEM: return new cBlockStemsHandler (a_BlockType);
- case E_BLOCK_QUARTZ_STAIR: return new cBlockStairsHandler (a_BlockType);
+ case E_BLOCK_QUARTZ_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_POTATOES: return new cBlockCropsHandler (a_BlockType);
case E_BLOCK_POWERED_RAIL: return new cBlockRailHandler (a_BlockType);
@@ -178,6 +186,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_STICKY_PISTON: return new cBlockPistonHandler (a_BlockType);
case E_BLOCK_STONE: return new cBlockStoneHandler (a_BlockType);
case E_BLOCK_STONE_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
+ case E_BLOCK_STONE_BUTTON: return new cBlockButtonHandler (a_BlockType);
case E_BLOCK_STONE_SLAB: return new cBlockSlabHandler (a_BlockType);
case E_BLOCK_SUGARCANE: return new cBlockSugarcaneHandler (a_BlockType);
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType);
@@ -185,6 +194,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE 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);
+ case E_BLOCK_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType);
case E_BLOCK_WOODEN_DOOR: return new cBlockDoorHandler (a_BlockType);
case E_BLOCK_WOODEN_SLAB: return new cBlockSlabHandler (a_BlockType);
case E_BLOCK_WOODEN_STAIRS: return new cBlockStairsHandler (a_BlockType);
@@ -351,7 +361,20 @@ void cBlockHandler::DropBlock(cWorld * a_World, cEntity * a_Digger, int a_BlockX
if (!Pickups.empty())
{
- a_World->SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ);
+ MTRand r1;
+
+ // Mid-block position first
+ double MicroX, MicroY, MicroZ;
+ MicroX = a_BlockX + 0.5;
+ MicroY = a_BlockY + 0.5;
+ MicroZ = a_BlockZ + 0.5;
+
+ // Add random offset second (this causes pickups to spawn inside blocks most times, it's a little buggy)
+ //MicroX += (int)(r1.randInt(16) + r1.randInt(16) - 16);
+ //MicroY += (int)(r1.randInt(16) + r1.randInt(16) - 16);
+ //MicroZ += (int)(r1.randInt(16) + r1.randInt(16) - 16);
+
+ a_World->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ);
}
}
@@ -404,24 +427,6 @@ bool cBlockHandler::DoesIgnoreBuildCollision(void)
-bool cBlockHandler::DoesAllowBlockOnTop(void)
-{
- return true;
-}
-
-
-
-
-
-bool cBlockHandler::CanBePlacedOnSide(void)
-{
- return true;
-}
-
-
-
-
-
bool cBlockHandler::DoesDropOnUnsuitable(void)
{
return true;
diff --git a/source/Blocks/BlockHandler.h b/source/Blocks/BlockHandler.h
index 228ce174b..0487505ee 100644
--- a/source/Blocks/BlockHandler.h
+++ b/source/Blocks/BlockHandler.h
@@ -83,10 +83,7 @@ public:
NOTE: This call doesn't actually place the block
*/
// virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
-
- /// Called when the player tries to place a block on top of this block (Only if he aims directly on this block); return false to disallow
- virtual bool DoesAllowBlockOnTop(void);
-
+
/// Called to check whether this block supports a rclk action. If it returns true, OnUse() is called
virtual bool IsUseable(void);
@@ -99,9 +96,6 @@ public:
For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
*/
virtual bool DoesIgnoreBuildCollision(void);
-
- /// Indicates this block can be placed on the side of other blocks. Default: true
- virtual bool CanBePlacedOnSide(void);
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
virtual bool DoesDropOnUnsuitable(void);
diff --git a/source/Blocks/BlockLever.cpp b/source/Blocks/BlockLever.cpp
index f2ca1805a..a9bd6c990 100644
--- a/source/Blocks/BlockLever.cpp
+++ b/source/Blocks/BlockLever.cpp
@@ -1,8 +1,6 @@
#include "Globals.h"
#include "BlockLever.h"
-#include "../Item.h"
-#include "../World.h"
#include "../Entities/Player.h"
#include "../Simulator/RedstoneSimulator.h"
@@ -23,7 +21,8 @@ void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX,
{
// Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off.
NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f);
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta);
+
+ a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
if (Meta & 0x08)
{
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
@@ -37,12 +36,3 @@ void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX,
-
-void cBlockLeverHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
-{
- OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NONE, 8, 8, 8);
-}
-
-
-
-
diff --git a/source/Blocks/BlockLever.h b/source/Blocks/BlockLever.h
index 362cf563e..5553170e2 100644
--- a/source/Blocks/BlockLever.h
+++ b/source/Blocks/BlockLever.h
@@ -1,7 +1,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../World.h"
#include "../Simulator/RedstoneSimulator.h"
@@ -14,7 +13,6 @@ class cBlockLeverHandler :
public:
cBlockLeverHandler(BLOCKTYPE a_BlockType);
- virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
@@ -42,12 +40,6 @@ public:
a_BlockMeta = cRedstoneSimulator::LeverDirectionToMetaData(a_BlockFace);
return true;
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockMushroom.h b/source/Blocks/BlockMushroom.h
index b3b23e2ba..2846a6317 100644
--- a/source/Blocks/BlockMushroom.h
+++ b/source/Blocks/BlockMushroom.h
@@ -46,18 +46,6 @@ public:
}
return true;
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockMycelium.h b/source/Blocks/BlockMycelium.h
index 0ed7162ac..7f897c72a 100644
--- a/source/Blocks/BlockMycelium.h
+++ b/source/Blocks/BlockMycelium.h
@@ -20,6 +20,11 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_DIRT, 1, 0));
}
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.gravel";
+ }
} ;
diff --git a/source/Blocks/BlockPlanks.h b/source/Blocks/BlockPlanks.h
new file mode 100644
index 000000000..f3b8dbfb6
--- /dev/null
+++ b/source/Blocks/BlockPlanks.h
@@ -0,0 +1,41 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockPlanksHandler : public cBlockHandler
+{
+public:
+ cBlockPlanksHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
+ a_BlockMeta = Meta;
+ return true;
+ }
+
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+} ;
+
+
+
+
diff --git a/source/Blocks/BlockPumpkin.h b/source/Blocks/BlockPumpkin.h
new file mode 100644
index 000000000..76abc6818
--- /dev/null
+++ b/source/Blocks/BlockPumpkin.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+class cBlockPumpkinHandler :
+ public cBlockHandler
+{
+public:
+ cBlockPumpkinHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ a_BlockMeta = PlayerYawToMetaData(a_Player->GetRotation());
+ return true;
+ }
+
+ inline static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
+ {
+ ASSERT((a_Yaw >= -180) && (a_Yaw < 180));
+
+ a_Yaw += 180 + 45;
+ if (a_Yaw > 360)
+ {
+ a_Yaw -= 360;
+ }
+ if ((a_Yaw >= 0) && (a_Yaw < 90))
+ {
+ return 0x0;
+ }
+ else if ((a_Yaw >= 180) && (a_Yaw < 270))
+ {
+ return 0x2;
+ }
+ else if ((a_Yaw >= 90) && (a_Yaw < 180))
+ {
+ return 0x1;
+ }
+ else
+ {
+ return 0x3;
+ }
+ }
+
+} ;
+
+
+
+
diff --git a/source/Blocks/BlockRedstone.h b/source/Blocks/BlockRedstone.h
index ae0466937..f28f3f2d6 100644
--- a/source/Blocks/BlockRedstone.h
+++ b/source/Blocks/BlockRedstone.h
@@ -16,11 +16,6 @@ public:
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
@@ -33,12 +28,6 @@ public:
// Reset meta to 0
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1));
}
-
-
- virtual bool CanBePlacedOnSide(void) override
- {
- return false;
- }
} ;
diff --git a/source/Blocks/BlockRedstoneRepeater.cpp b/source/Blocks/BlockRedstoneRepeater.cpp
index 3bc879435..72ea21012 100644
--- a/source/Blocks/BlockRedstoneRepeater.cpp
+++ b/source/Blocks/BlockRedstoneRepeater.cpp
@@ -1,9 +1,8 @@
#include "Globals.h"
#include "BlockRedstoneRepeater.h"
-#include "../Item.h"
-#include "../World.h"
#include "../Simulator/RedstoneSimulator.h"
+#include "../Entities/Player.h"
@@ -29,16 +28,22 @@ void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_BlockX, i
void cBlockRedstoneRepeaterHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
- a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f));
+ a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f));
}
-
-void cBlockRedstoneRepeaterHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
+bool cBlockRedstoneRepeaterHandler::GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+)
{
- OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NONE, 8, 8, 8);
+ a_BlockType = m_BlockType;
+ a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
+ return true;
}
diff --git a/source/Blocks/BlockRedstoneRepeater.h b/source/Blocks/BlockRedstoneRepeater.h
index f3e250963..958841a34 100644
--- a/source/Blocks/BlockRedstoneRepeater.h
+++ b/source/Blocks/BlockRedstoneRepeater.h
@@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../World.h"
@@ -15,7 +14,6 @@ public:
cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType);
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
@@ -32,22 +30,19 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
virtual bool CanBeAt(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 bool CanBePlacedOnSide(void) override
- {
- return false;
- }
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override;
+
virtual const char * GetStepSound(void) override
{
diff --git a/source/Blocks/BlockSapling.h b/source/Blocks/BlockSapling.h
index 17ef4984f..fff2fa88b 100644
--- a/source/Blocks/BlockSapling.h
+++ b/source/Blocks/BlockSapling.h
@@ -29,12 +29,6 @@ public:
{
return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
@@ -50,12 +44,6 @@ public:
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x08);
}
}
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockSign.h b/source/Blocks/BlockSign.h
index e6426180f..7fbe61893 100644
--- a/source/Blocks/BlockSign.h
+++ b/source/Blocks/BlockSign.h
@@ -23,12 +23,6 @@ public:
{
a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0));
}
-
-
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockSnow.h b/source/Blocks/BlockSnow.h
index bdd9f0b87..b8d48362c 100644
--- a/source/Blocks/BlockSnow.h
+++ b/source/Blocks/BlockSnow.h
@@ -15,8 +15,28 @@ public:
: cBlockHandler(a_BlockType)
{
}
-
-
+
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ NIBBLETYPE Meta = a_World->GetBlockMeta(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
+
+ if ((Meta < 7) && (Meta != 0)) // Is height at maximum (7) or at mininum (0)? Don't do anything if so
+ {
+ Meta++;
+ }
+
+ a_BlockMeta = Meta;
+ return true;
+ }
+
+
virtual bool DoesIgnoreBuildCollision(void) override
{
return true;
diff --git a/source/Blocks/BlockStairs.h b/source/Blocks/BlockStairs.h
index 485ebda1a..8d259eee3 100644
--- a/source/Blocks/BlockStairs.h
+++ b/source/Blocks/BlockStairs.h
@@ -53,7 +53,6 @@ public:
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
a_Rotation += 90 + 45; // So its not aligned with axis
- NIBBLETYPE result = 0x0;
if (a_Rotation > 360)
{
a_Rotation -= 360;
diff --git a/source/Blocks/BlockSugarcane.h b/source/Blocks/BlockSugarcane.h
index 9d66d6be6..28a60df80 100644
--- a/source/Blocks/BlockSugarcane.h
+++ b/source/Blocks/BlockSugarcane.h
@@ -77,12 +77,6 @@ public:
{
a_World->GrowSugarcane(a_BlockX, a_BlockY, a_BlockZ, 1);
}
-
-
- virtual bool CanBePlacedOnSide() override
- {
- return false;
- }
virtual const char * GetStepSound(void) override
diff --git a/source/Blocks/BlockTorch.h b/source/Blocks/BlockTorch.h
index 3a50cab77..a52b373cb 100644
--- a/source/Blocks/BlockTorch.h
+++ b/source/Blocks/BlockTorch.h
@@ -24,16 +24,31 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
- // Find proper placement. Use the player-supplied one as the default, but fix if not okay:
- if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
+ // Find proper placement of torch
+
+ if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
{
- a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
-
- if (a_BlockFace == BLOCK_FACE_BOTTOM)
+ a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
+ if (a_BlockFace == BLOCK_FACE_NONE)
{
+ // Client wouldn't have sent anything anyway, but whatever
return false;
}
}
+ else
+ {
+ // Not top or bottom faces, try to preserve whatever face was clicked
+ if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
+ {
+ // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
+ a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
+ if (a_BlockFace == BLOCK_FACE_NONE)
+ {
+ return false;
+ }
+ }
+ }
+
a_BlockType = m_BlockType;
a_BlockMeta = DirectionToMetaData(a_BlockFace);
return true;
@@ -100,51 +115,54 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return true;
- }
-
-
- static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_Direction)
+ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_BlockFace)
{
- if ( g_BlockIsSolid[a_BlockType] ) {
- return (a_Direction == 0x1); // allow only direction "standing on floor"
+ if ( !g_BlockIsTorchPlaceable[a_BlockType] )
+ {
+ return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright
}
- else {
- return g_BlockIsSolid[a_BlockType];
+ else
+ {
+ return true;
}
}
static bool TorchCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
- // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead
- // How to propagate that change up?
- // Simon: The easiest way is to calculate the position two times, shouldn�t cost much cpu power :)
-
- if (a_BlockFace == BLOCK_FACE_BOTTOM)
- {
- return false;
- }
-
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
-
return CanBePlacedOn(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace);
}
- /// Finds a suitable Face for the Torch. Returns BLOCK_FACE_BOTTOM on failure
+ /// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure
static char FindSuitableFace(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (int i = 1; i <= 5; i++)
+ for (int i = 0; i <= 5; i++)
{
- if (TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, i))
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, true);
+ BLOCKTYPE BlockInQuestion = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (
+ ((BlockInQuestion == E_BLOCK_GLASS) ||
+ (BlockInQuestion == E_BLOCK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) &&
+ (i == BLOCK_FACE_TOP)
+ )
+ {
+ return i;
+ }
+ else if ((g_BlockIsTorchPlaceable[BlockInQuestion]) && (i != BLOCK_FACE_BOTTOM))
{
return i;
}
+ else
+ {
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, i, false);
+ }
}
- return BLOCK_FACE_BOTTOM;
+ return BLOCK_FACE_NONE;
}
@@ -163,11 +181,33 @@ public:
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- // TODO: Use AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison
char Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
- return TorchCanBePlacedAt(a_Chunk.GetWorld(), BlockX, a_RelY, BlockZ, Face);
+
+ AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
+ BLOCKTYPE BlockInQuestion;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockInQuestion);
+
+ if (
+ (BlockInQuestion == E_BLOCK_GLASS) ||
+ (BlockInQuestion == E_BLOCK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
+ )
+ {
+ // Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
+ // No need to check for upright orientation, it was done when the torch was placed
+ return true;
+ }
+ else if ( !g_BlockIsTorchPlaceable[BlockInQuestion] )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
diff --git a/source/Blocks/BlockVine.h b/source/Blocks/BlockVine.h
index 37d9f1a45..2c9f67cab 100644
--- a/source/Blocks/BlockVine.h
+++ b/source/Blocks/BlockVine.h
@@ -151,12 +151,6 @@ public:
}
- virtual bool DoesAllowBlockOnTop(void) override
- {
- return false;
- }
-
-
virtual const char * GetStepSound(void) override
{
return "step.grass";
diff --git a/source/Blocks/BlockWood.h b/source/Blocks/BlockWood.h
index 4e2246506..cb5ee995a 100644
--- a/source/Blocks/BlockWood.h
+++ b/source/Blocks/BlockWood.h
@@ -15,6 +15,51 @@ public:
{
}
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+ NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
+ a_BlockMeta = BlockFaceToMetaData(a_BlockFace, Meta);
+ return true;
+ }
+
+
+ inline static NIBBLETYPE BlockFaceToMetaData(char a_BlockFace, NIBBLETYPE a_WoodMeta)
+ {
+ switch (a_BlockFace)
+ {
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
+ {
+ return a_WoodMeta; // Top or bottom, just return original
+ }
+
+ case BLOCK_FACE_ZP:
+ case BLOCK_FACE_ZM:
+ {
+ return a_WoodMeta | 0x8; // North or south
+ }
+
+ case BLOCK_FACE_XP:
+ case BLOCK_FACE_XM:
+ {
+ return a_WoodMeta | 0x4; // East or west
+ }
+
+ default:
+ {
+ ASSERT(!"Unhandled block face!");
+ return a_WoodMeta | 0xC; // No idea, give a special meta (all sides bark)
+ }
+ }
+ }
+
virtual const char * GetStepSound(void) override
{