1
0

Merge pull request #387 from mc-server/trapdoors

Trapdoors, redstone fixes, and snow
This commit is contained in:
Mattes D 2013-11-30 07:20:27 -08:00
commit 2bbe5046e9
23 changed files with 445 additions and 379 deletions

View File

@ -2095,10 +2095,6 @@
RelativePath="..\src\Blocks\BlockBrewingStand.h"
>
</File>
<File
RelativePath="..\src\Blocks\BlockButton.cpp"
>
</File>
<File
RelativePath="..\src\Blocks\BlockButton.h"
>
@ -2127,10 +2123,6 @@
RelativePath="..\src\Blocks\BlockCobWeb.h"
>
</File>
<File
RelativePath="..\src\Blocks\BlockComparator.cpp"
>
</File>
<File
RelativePath="..\src\Blocks\BlockComparator.h"
>
@ -2231,10 +2223,6 @@
RelativePath="..\src\blocks\BlockLeaves.h"
>
</File>
<File
RelativePath="..\src\Blocks\BlockLever.cpp"
>
</File>
<File
RelativePath="..\src\Blocks\BlockLever.h"
>
@ -2283,10 +2271,6 @@
RelativePath="..\src\Blocks\BlockRail.h"
>
</File>
<File
RelativePath="..\src\blocks\BlockRedstone.cpp"
>
</File>
<File
RelativePath="..\src\blocks\BlockRedstone.h"
>
@ -2295,10 +2279,6 @@
RelativePath="..\src\blocks\BlockRedstoneOre.h"
>
</File>
<File
RelativePath="..\src\blocks\BlockRedstoneRepeater.cpp"
>
</File>
<File
RelativePath="..\src\blocks\BlockRedstoneRepeater.h"
>
@ -2351,6 +2331,10 @@
RelativePath="..\src\blocks\BlockTorch.h"
>
</File>
<File
RelativePath="..\src\Blocks\BlockTrapdoor.h"
>
</File>
<File
RelativePath="..\src\blocks\BlockVine.h"
>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug profiled|Win32">
@ -185,6 +185,7 @@
<ResourceCompile Include="MCServer.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\Blocks\BlockTrapdoor.h" />
<ClInclude Include="resource_MCServer.h" />
<ClInclude Include="..\src\Authenticator.h" />
<ClInclude Include="..\src\BlockArea.h" />
@ -794,14 +795,9 @@
<ClCompile Include="..\src\Generating\StructGen.cpp" />
<ClCompile Include="..\src\Generating\Trees.cpp" />
<ClCompile Include="..\src\Blocks\BlockBed.cpp" />
<ClCompile Include="..\src\Blocks\BlockButton.cpp" />
<ClCompile Include="..\src\Blocks\BlockComparator.cpp" />
<ClCompile Include="..\src\blocks\BlockDoor.cpp" />
<ClCompile Include="..\src\blocks\BlockHandler.cpp" />
<ClCompile Include="..\src\Blocks\BlockLever.cpp" />
<ClCompile Include="..\src\blocks\BlockPiston.cpp" />
<ClCompile Include="..\src\blocks\BlockRedstone.cpp" />
<ClCompile Include="..\src\blocks\BlockRedstoneRepeater.cpp" />
<ClCompile Include="..\src\items\ItemHandler.cpp" />
<ClCompile Include="..\src\Protocol\ChunkDataSerializer.cpp" />
<ClCompile Include="..\src\Protocol\Protocol125.cpp" />

View File

@ -942,6 +942,9 @@
<ClInclude Include="..\src\HTTPServer\NameValueParser.h">
<Filter>Source Files\HTTPServer</Filter>
</ClInclude>
<ClInclude Include="..\src\Blocks\BlockTrapdoor.h">
<Filter>Source Files\Blocks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\webadmin\template.html">
@ -1555,30 +1558,15 @@
<ClCompile Include="..\src\Blocks\BlockBed.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\Blocks\BlockButton.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\Blocks\BlockComparator.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\blocks\BlockDoor.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\blocks\BlockHandler.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\Blocks\BlockLever.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\blocks\BlockPiston.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\blocks\BlockRedstone.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\blocks\BlockRedstoneRepeater.cpp">
<Filter>Source Files\Blocks</Filter>
</ClCompile>
<ClCompile Include="..\src\items\ItemHandler.cpp">
<Filter>Source Files\Items</Filter>
</ClCompile>
@ -1666,9 +1654,6 @@
<ClCompile Include="..\src\HTTPServer\NameValueParser.cpp">
<Filter>Source Files\HTTPServer</Filter>
</ClCompile>
<ClCompile Include="..\source\BlockEntities\BlockEntity.cpp">
<Filter>Source Files\BlockEntities</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\MCServer\API.txt">

View File

@ -174,7 +174,7 @@ enum ENUM_BLOCK_ID
E_BLOCK_NEW_LEAVES = 161, // Acacia and Dark Oak IDs in Minecraft 1.7.x
E_BLOCK_NEW_LOG = 162,
E_BLOCK_ACACIA_WOOD_STAIRS = 163,
E_BLOCK_DARK_OAK_WOOD_STAIRS = 164, /////////////////////////////////
E_BLOCK_DARK_OAK_WOOD_STAIRS = 164,
E_BLOCK_HAY_BALE = 170,
E_BLOCK_CARPET = 171,
E_BLOCK_HARDENED_CLAY = 172,
@ -188,7 +188,6 @@ enum ENUM_BLOCK_ID
E_BLOCK_MAX_TYPE_ID = E_BLOCK_NUMBER_OF_TYPES - 1, ///< Maximum BlockType number used
// Synonym or ID compatibility
E_BLOCK_YELLOW_FLOWER = E_BLOCK_DANDELION,
E_BLOCK_RED_ROSE = E_BLOCK_FLOWER,
E_BLOCK_LOCKED_CHEST = E_BLOCK_STAINED_GLASS,

View File

@ -1,32 +0,0 @@
#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 the XOR bitwise operation
NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
// Queue a button reset (unpress)
a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30);
}

View File

@ -10,9 +10,23 @@ class cBlockButtonHandler :
public cBlockHandler
{
public:
cBlockButtonHandler(BLOCKTYPE a_BlockType);
cBlockButtonHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(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 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
{
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
// Queue a button reset (unpress)
a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
@ -51,10 +65,10 @@ public:
{
switch (a_BlockFace)
{
case BLOCK_FACE_ZM: { return 0x4; }
case BLOCK_FACE_ZP: { return 0x3; }
case BLOCK_FACE_XM: { return 0x2; }
case BLOCK_FACE_XP: { return 0x1; }
case BLOCK_FACE_ZM: return 0x4;
case BLOCK_FACE_ZP: return 0x3;
case BLOCK_FACE_XM: return 0x2;
case BLOCK_FACE_XP: return 0x1;
default:
{
ASSERT(!"Unhandled block face!");

View File

@ -1,53 +0,0 @@
#include "Globals.h"
#include "BlockComparator.h"
#include "BlockRedstoneRepeater.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 = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}

View File

@ -2,6 +2,7 @@
#pragma once
#include "BlockHandler.h"
#include "BlockRedstoneRepeater.h"
@ -11,10 +12,18 @@ 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;
cBlockComparatorHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(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 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 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);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
@ -41,7 +50,12 @@ public:
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;
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}
virtual const char * GetStepSound(void) override

View File

@ -61,6 +61,7 @@
#include "BlockSugarcane.h"
#include "BlockTallGrass.h"
#include "BlockTorch.h"
#include "BlockTrapdoor.h"
#include "BlockVine.h"
#include "BlockWood.h"
#include "BlockWorkbench.h"
@ -193,6 +194,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_SUGARCANE: return new cBlockSugarcaneHandler (a_BlockType);
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType);
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType);
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);

View File

@ -98,7 +98,10 @@ public:
*/
virtual bool DoesIgnoreBuildCollision(void);
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
/// <summary>Similar to DoesIgnoreBuildCollision(void), but is used for cases where block meta/player item-in-hand is needed to determine collision (thin snow)</summary>
virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) { return DoesIgnoreBuildCollision(); }
/// <summary>Returns if this block drops if it gets destroyed by an unsuitable situation. Default: true</summary>
virtual bool DoesDropOnUnsuitable(void);
/** Called when one of the neighbors gets set; equivalent to MC block update.
@ -107,26 +110,30 @@ public:
*/
virtual void Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk);
/// Returns the meta for a block after rotating it counter-clockwise from the specified meta. Default: no change
/// <summary>Rotates a given block meta counter-clockwise. Default: no change</summary>
/// <returns>Block meta following rotation</returns>
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) { return a_Meta; }
/// Returns the meta for a block after rotating it clockwise from the specified meta. Default: no change
/// <summary>Rotates a given block meta clockwise. Default: no change</summary>
/// <returns>Block meta following rotation</returns>
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) { return a_Meta; }
/// Returns the meta for a block after mirroring it around the XY plane. Default: no change
/// <summary>Mirros a given block meta around the XY plane. Default: no change</summary>
/// <returns>Block meta following mirroring</returns>
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) { return a_Meta; }
/// Returns the meta for a block after mirroring it around the XZ plane. Default: no change
/// <summary>Mirros a given block meta around the XZ plane. Default: no change</summary>
/// <returns>Block meta following mirroring</returns>
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) { return a_Meta; }
/// Returns the meta for a block after mirroring it around the YZ plane. Default: no change
/// <summary>Mirros a given block meta around the YZ plane. Default: no change</summary>
/// <returns>Block meta following mirroring</returns>
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) { return a_Meta; }
/// Get the blockhandler for a specific block id
/// <summary>Get the blockhandler for a specific block id</summary>
static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockType);
/// Deletes all initialised block handlers
/// <summary>Deletes all initialised block handlers</summary>
static void Deinit();
protected:

View File

@ -1,31 +0,0 @@
#include "Globals.h"
#include "BlockLever.h"
#include "../Entities/Player.h"
#include "../Simulator/RedstoneSimulator.h"
cBlockLeverHandler::cBlockLeverHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
void cBlockLeverHandler::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 the XOR bitwise operation
NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
}

View File

@ -10,9 +10,19 @@ class cBlockLeverHandler :
public cBlockHandler
{
public:
cBlockLeverHandler(BLOCKTYPE a_BlockType);
cBlockLeverHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(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 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
{
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08);
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override

View File

@ -1,27 +0,0 @@
#include "Globals.h"
#include "BlockRedstone.h"
#include "../Item.h"
#include "../World.h"
cBlockRedstoneHandler::cBlockRedstoneHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
void cBlockRedstoneHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Nothing needed yet
}

View File

@ -12,9 +12,10 @@ class cBlockRedstoneHandler :
public cBlockHandler
{
public:
cBlockRedstoneHandler(BLOCKTYPE a_BlockType);
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
cBlockRedstoneHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override

View File

@ -1,50 +0,0 @@
#include "Globals.h"
#include "BlockRedstoneRepeater.h"
#include "../Entities/Player.h"
cBlockRedstoneRepeaterHandler::cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Nothing needed yet
}
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->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f));
}
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
)
{
a_BlockType = m_BlockType;
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}

View File

@ -11,10 +11,29 @@ class cBlockRedstoneRepeaterHandler :
public cBlockHandler
{
public:
cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType);
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(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 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 = RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}
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
{
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f));
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
@ -36,14 +55,6 @@ 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;
virtual const char * GetStepSound(void) override
{
return "step.wood";

View File

@ -25,21 +25,37 @@ public:
) 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
BLOCKTYPE BlockBeforePlacement;
NIBBLETYPE MetaBeforePlacement;
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockBeforePlacement, MetaBeforePlacement);
if ((BlockBeforePlacement == E_BLOCK_SNOW) && (MetaBeforePlacement < 7))
{
Meta++;
// Only increment if:
// A snow block was already there (not first time placement) AND
// Height is smaller than 7, the maximum possible height
MetaBeforePlacement++;
}
a_BlockMeta = Meta;
a_BlockMeta = MetaBeforePlacement;
return true;
}
virtual bool DoesIgnoreBuildCollision(void) override
virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override
{
return true;
if ((a_Player->GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < 7))
{
return true; // If a player is holding a (thin) snow block and it's size can be increased, return collision ignored
}
if (a_Meta == 0)
{
return true; // If at normal snowfall height (lowest), we ignore collision
}
return false;
}
@ -51,7 +67,19 @@ public:
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return (a_RelY > 0) && g_BlockIsSnowable[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)];
if (a_RelY > 0)
{
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
NIBBLETYPE MetaBelow = a_Chunk.GetMeta(a_RelX, a_RelY - 1, a_RelZ);
if (g_BlockIsSnowable[BlockBelow] || ((BlockBelow == E_BLOCK_SNOW) && (MetaBelow == 7)))
{
// If block below is snowable, or it is a thin slow block and has a meta of 7 (full thin snow block), say yay
return true;
}
}
return false;
}

View File

@ -47,8 +47,28 @@ public:
return true;
}
// TODO: step sound
virtual const char * GetStepSound(void) override
{
if (
(m_BlockType == E_BLOCK_WOODEN_STAIRS) ||
(m_BlockType == E_BLOCK_SPRUCE_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_JUNGLE_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_ACACIA_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_BIRCH_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_DARK_OAK_WOOD_STAIRS)
)
{
return "step.wood";
}
return "step.stone";
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{

View File

@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
#include "../MersenneTwister.h"
#include "../World.h"

108
src/Blocks/BlockTrapdoor.h Normal file
View File

@ -0,0 +1,108 @@
#pragma once
#include "BlockHandler.h"
class cBlockTrapdoorHandler :
public cBlockHandler
{
public:
cBlockTrapdoorHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual const char * GetStepSound(void) override
{
return "step.wood";
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
virtual bool IsUseable(void) override
{
return true;
}
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)
{
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x04);
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
}
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);
/* TODO: fix CursorY issues and uncomment this
if (a_CursorY > 7)
{
a_BlockMeta |= 0x8;
}
*/
return true;
}
inline static NIBBLETYPE BlockFaceToMetaData(char a_BlockFace)
{
switch (a_BlockFace)
{
case BLOCK_FACE_ZP: return 0x1;
case BLOCK_FACE_ZM: return 0x0;
case BLOCK_FACE_XP: return 0x3;
case BLOCK_FACE_XM: return 0x2;
default:
{
ASSERT(!"Unhandled block face!");
return 0x0;
}
}
}
inline static NIBBLETYPE BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x3)
{
case 0x0: return BLOCK_FACE_ZM;
case 0x1: return BLOCK_FACE_ZP;
case 0x2: return BLOCK_FACE_XM;
case 0x3: return BLOCK_FACE_XP;
default:
{
ASSERT(!"Unhandled block meta!");
return BLOCK_FACE_NONE;
}
}
}
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]);
}
};

View File

@ -891,14 +891,14 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
else
{
// Check if the block ignores build collision (water, grass etc.):
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(ClickedBlock);
if (Handler->DoesIgnoreBuildCollision())
if (
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() ||
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(m_Player, ClickedBlockMeta)
)
{
Handler->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(ClickedBlock)->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
}
BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
else
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
@ -908,7 +908,9 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
return;
}
BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
NIBBLETYPE PlaceMeta;
BLOCKTYPE PlaceBlock;
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta);
// Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
// No need to do combinability (dblslab) checks, client will do that here.
@ -918,10 +920,13 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, c
}
else
{
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
if (
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() &&
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(m_Player, PlaceMeta)
)
{
// Tried to place a block *into* another?
// Happens when you place a block aiming at side of block like torch or stem
// Happens when you place a block aiming at side of block with a torch on it or stem beside it
return;
}
}

View File

@ -76,15 +76,6 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
{
BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z);
if (!IsAllowedBlock(BlockType))
{
dataitr = ChunkData.erase(dataitr);
continue;
}
// Check to see if PoweredBlocks have invalid items (source is air or unpowered)
for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();)
{
@ -95,7 +86,10 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
BLOCKTYPE SourceBlockType;
NIBBLETYPE SourceBlockMeta;
a_Chunk->UnboundedRelGetBlock(RelX, Change.a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta);
if (!a_Chunk->UnboundedRelGetBlock(RelX, Change.a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta))
{
continue;
}
if (SourceBlockType != Change.a_SourceBlock)
{
@ -132,8 +126,13 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
BLOCKTYPE SourceBlockType;
NIBBLETYPE SourceBlockMeta;
BLOCKTYPE MiddleBlockType;
a_Chunk->UnboundedRelGetBlock(RelX, Change.a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta);
a_Chunk->UnboundedRelGetBlockType(MidRelX, Change.a_MiddlePos.y, MidRelZ, MiddleBlockType);
if (
!a_Chunk->UnboundedRelGetBlock(RelX, Change.a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) ||
!a_Chunk->UnboundedRelGetBlockType(MidRelX, Change.a_MiddlePos.y, MidRelZ, MiddleBlockType)
)
{
continue;
}
if (SourceBlockType != Change.a_SourceBlock)
{
@ -161,7 +160,16 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
}
}
// PoweredBlock list was fine, now to the actual handling
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
{
BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z);
if (!IsAllowedBlock(BlockType))
{
dataitr = ChunkData.erase(dataitr);
continue;
}
// PoweredBlock and LinkedPoweredBlock list was fine, now to the actual handling
int a_X = BaseX + dataitr->x;
int a_Z = BaseZ + dataitr->z;
switch (BlockType)
@ -169,6 +177,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(a_X, dataitr->y, a_Z); break;
case E_BLOCK_LEVER: HandleRedstoneLever(a_X, dataitr->y, a_Z); break;
case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_TORCH_OFF:
@ -406,7 +415,9 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
if (SurroundMeta > 1) // Wires of power 1 or 0 cannot transfer power TO ME, don't bother checking
{
if (SurroundMeta > MyMeta) // Does surrounding wire have a higher power level than self?
// Does surrounding wire have a higher power level than self?
// >= to fix a bug where wires bordering each other with the same power level will appear (in terms of meta) to power each other, when they aren't actually in the powered list
if (SurroundMeta >= MyMeta)
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, SurroundMeta - 1);
}
@ -555,7 +566,7 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int
void cRedstoneSimulator::HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ)
{
cPiston Piston(&m_World);
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
if (IsPistonPowered(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness)
{
Piston.ExtendPiston(a_BlockX, a_BlockY, a_BlockZ);
}
@ -717,6 +728,22 @@ void cRedstoneSimulator::HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BL
void cRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ)
{
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x4);
}
else
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0xB); // Take into account that the fourth bit is needed for trapdoors too
}
}
bool cRedstoneSimulator::AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
{
for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
@ -747,7 +774,8 @@ bool cRedstoneSimulator::AreCoordsPowered(int a_BlockX, int a_BlockY, int a_Bloc
bool cRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
{
// Check through powered blocks list
// Repeaters cannot be powered by any face except their back; verify that this is true for a source
for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
{
sPoweredBlocks & Change = *itr;
@ -780,7 +808,6 @@ bool cRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_Blo
}
}
// Check linked powered list, 'middle' blocks
for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
{
sLinkedPoweredBlocks & Change = *itr;
@ -817,6 +844,53 @@ bool cRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_Blo
bool cRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
{
// Pistons cannot be powered through their front face; this function verifies that a source meets this requirement
int OldX = a_BlockX, OldY = a_BlockY, OldZ = a_BlockZ;
for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
{
sPoweredBlocks & Change = *itr;
if (!Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Meta); // Piston meta is based on what direction they face, so we can do this
if (!Change.a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
return true;
}
a_BlockX = OldX;
a_BlockY = OldY;
a_BlockZ = OldZ;
}
for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
{
sLinkedPoweredBlocks & Change = *itr;
if (!Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Meta);
if (!Change.a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
return true;
}
a_BlockX = OldX;
a_BlockY = OldY;
a_BlockZ = OldZ;
}
return false; // Source was in front of the piston's front face
}
void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType)
{
@ -1086,7 +1160,6 @@ void cRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_B
void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock)
{
if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR) { return; } // Don't set air, fixes some bugs (wires powering themselves)
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { return; } // Check for duplicates
sPoweredBlocks RC;
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
@ -1107,7 +1180,6 @@ void cRedstoneSimulator::SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a
)
{
if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR) { return; } // Don't set air, fixes some bugs (wires powering themselves)
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) { return; } // Check for duplicates
if (!IsViableMiddleBlock(m_World.GetBlock(a_MiddleX, a_MiddleY, a_MiddleZ))) { return; } // See if middle block is viable
sLinkedPoweredBlocks RC;

View File

@ -93,6 +93,8 @@ private:
void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ);
/// <summary>Handles activator, detector, and powered rails</summary>
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
/// <summary>Handles trapdoors</summary>
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
/* ===================== */
/* ====== Helper functions ====== */
@ -109,6 +111,8 @@ private:
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
/// <summary>Returns if a repeater is powered</summary>
bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
/// <summary>Returns if a piston is powered</summary>
bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
/// <summary>Returns if lever metadata marks it as emitting power</summary>
bool IsLeverOn(NIBBLETYPE a_BlockMeta);