diff options
Diffstat (limited to '')
58 files changed, 1397 insertions, 654 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h index f113f7905..ad6d216cd 100644 --- a/src/Blocks/BlockAnvil.h +++ b/src/Blocks/BlockAnvil.h @@ -35,21 +35,34 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ); + cWindow * Window = new cAnvilWindow(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); a_Player.OpenWindow(*Window); return true; } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta)) + if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta)) { return false; } @@ -58,11 +71,19 @@ public: return true; } + + + + virtual bool IsUseable() override { return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 8b349ef5e..6d50e8c41 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -15,7 +15,11 @@ -void cBlockBedHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) +void cBlockBedHandler::OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + const Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta +) { auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03); if ((a_OldBlockMeta & 0x08) != 0) @@ -50,87 +54,97 @@ void cBlockBedHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterf -bool cBlockBedHandler::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) +bool cBlockBedHandler::OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos +) { - Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ); + // Sleeping in bed only allowed in Overworld, beds explode elsewhere: if (a_WorldInterface.GetDimension() != dimOverworld) { - a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords); + auto PosCopy = a_BlockPos; + a_WorldInterface.DoExplosionAt(5, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, true, esBed, &PosCopy); + return true; } - else if (!((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458))) // Source: https://minecraft.gamepedia.com/Bed#Sleeping + + // Sleeping is allowed only during night: + // TODO: Also during thunderstorms + if (!((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458))) // Source: https://minecraft.gamepedia.com/Bed#Sleeping { a_Player.SendMessageFailure("You can only sleep at night"); + return true; + } + + // Check if the bed is occupied: + auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); + if ((Meta & 0x04) == 0x04) + { + a_Player.SendMessageFailure("This bed is occupied"); + return true; + } + + // Cannot sleep if there are hostile mobs nearby: + auto FindMobs = [](cEntity & a_Entity) + { + return ( + (a_Entity.GetEntityType() == cEntity::etMonster) && + (static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile) + ); + }; + if (!a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(a_Player.GetPosition() - Vector3i(0, 5, 0), 8, 10), FindMobs)) + { + a_Player.SendMessageFailure("You may not rest now, there are monsters nearby"); + return true; + } + + // Broadcast the "Use bed" for the pillow block: + if ((Meta & 0x8) == 0x8) + { + // Is pillow + a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, a_BlockPos); } else { - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(Coords); - if ((Meta & 0x4) == 0x4) + // Is foot end + VERIFY((Meta & 0x04) != 0x04); // Occupied flag should never be set, else our compilator (intended) is broken + + auto PillowPos = a_BlockPos + MetaDataToDirection(Meta & 0x03); + if (a_ChunkInterface.GetBlock(PillowPos) == E_BLOCK_BED) // Must always use pillow location for sleeping { - a_Player.SendMessageFailure("This bed is occupied"); + a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, PillowPos); } - else - { - auto FindMobs = [](cEntity & a_Entity) - { - return ( - (a_Entity.GetEntityType() == cEntity::etMonster) && - (static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile) - ); - }; + } - if (!a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(a_Player.GetPosition() - Vector3i(0, 5, 0), 8, 10), FindMobs)) - { - a_Player.SendMessageFailure("You may not rest now, there are monsters nearby"); - } - else + // Occupy the bed: + a_Player.SetBedPos(a_BlockPos); + SetBedOccupationState(a_ChunkInterface, a_Player.GetLastBedPos(), true); + a_Player.SetIsInBed(true); + a_Player.SendMessageSuccess("Home position set successfully"); + + // Fast-forward the time if all players in the world are in their beds: + auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer) + { + if (!a_OtherPlayer.IsInBed()) + { + return true; + } + return false; + }; + if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester)) + { + a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer) { - Vector3i PillowDirection(0, 0, 0); - - if ((Meta & 0x8) == 0x8) - { - // Is pillow - a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, { a_BlockX, a_BlockY, a_BlockZ }); - } - else - { - // Is foot end - VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken - - PillowDirection = MetaDataToDirection(Meta & 0x3); - if (a_ChunkInterface.GetBlock(Coords + PillowDirection) == E_BLOCK_BED) // Must always use pillow location for sleeping - { - a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{a_BlockX, a_BlockY, a_BlockZ} + PillowDirection); - } - } - - a_Player.SetBedPos(Coords); - SetBedOccupationState(a_ChunkInterface, a_Player.GetLastBedPos(), true); - a_Player.SetIsInBed(true); - a_Player.SendMessageSuccess("Home position set successfully"); - - auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer) - { - if (!a_OtherPlayer.IsInBed()) - { - return true; - } - return false; - }; - - if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester)) - { - a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer) - { - cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false); - a_OtherPlayer.SetIsInBed(false); - return false; - } - ); - a_WorldInterface.SetTimeOfDay(0); - a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta & 0x0b); // Clear the "occupied" bit of the bed's block - } + cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false); + a_OtherPlayer.SetIsInBed(false); + return false; } - } + ); + a_WorldInterface.SetTimeOfDay(0); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta & 0x0b); // Clear the "occupied" bit of the bed's block } return true; } diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h index 6793585b8..418d44ca5 100644 --- a/src/Blocks/BlockBed.h +++ b/src/Blocks/BlockBed.h @@ -32,10 +32,30 @@ public: // Overrides: - virtual void OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) override; - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override; - virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override; - virtual void OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange) override; + virtual void OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + const Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + ) override; + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, + const Vector3i a_ClickedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos + ) override; + + virtual cItems ConvertToPickups( + NIBBLETYPE a_BlockMeta, + cBlockEntity * a_BlockEntity, + const cEntity * a_Digger, + const cItem * a_Tool + ) override; + + virtual void OnPlacedByPlayer( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, + const sSetBlock & a_BlockChange + ) override; diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h index e7bd9b957..150ae6633 100644 --- a/src/Blocks/BlockBigFlower.h +++ b/src/Blocks/BlockBigFlower.h @@ -9,7 +9,7 @@ -class cBlockBigFlowerHandler : +class cBlockBigFlowerHandler: public cBlockHandler { using Super = cBlockHandler; @@ -95,15 +95,15 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, BlockType, BlockMeta); + a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BlockType, BlockMeta); return IsBlockTypeOfDirt(BlockType) || ((BlockType == E_BLOCK_BIG_FLOWER) && !IsMetaTopPart(BlockMeta)); } @@ -112,7 +112,7 @@ public: - virtual void OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) override + virtual void OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) override { if ((a_OldBlockMeta & 0x8) != 0) { diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h index c09dec56c..945c39b03 100644 --- a/src/Blocks/BlockButton.h +++ b/src/Blocks/BlockButton.h @@ -24,36 +24,40 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - Vector3i Pos(a_BlockX, a_BlockY, a_BlockZ); - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(Pos); - - Vector3d SoundPos(Pos); + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); - // If button is already on do nothing + // If button is already on, do nothing: if (Meta & 0x08) { return false; } - // Set p the ON bit to on + // Set the ON bit to on Meta |= 0x08; - a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta, false); - a_WorldInterface.WakeUpSimulators(Pos); - a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.stone_button.click_on", SoundPos, 0.5f, 0.6f); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta, false); + a_WorldInterface.WakeUpSimulators(a_BlockPos); + a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.stone_button.click_on", a_BlockPos, 0.5f, 0.6f); // Queue a button reset (unpress) auto TickDelay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? 20 : 30; - a_Player.GetWorld()->ScheduleTask(TickDelay, [SoundPos, Pos, this](cWorld & a_World) + a_Player.GetWorld()->ScheduleTask(TickDelay, [a_BlockPos, this](cWorld & a_World) { - if (a_World.GetBlock(Pos) == m_BlockType) + if (a_World.GetBlock(a_BlockPos) == m_BlockType) { // Block hasn't change in the meantime; set its meta - a_World.SetBlockMeta(Pos.x, Pos.y, Pos.z, a_World.GetBlockMeta(Pos) & 0x07, false); - a_World.WakeUpSimulators(Pos); - a_World.BroadcastSoundEffect("block.stone_button.click_off", SoundPos, 0.5f, 0.5f); + a_World.SetBlockMeta(a_BlockPos, a_World.GetBlockMeta(a_BlockPos) & 0x07, false); + a_World.WakeUpSimulators(a_BlockPos); + a_World.BroadcastSoundEffect("block.stone_button.click_off", a_BlockPos, 0.5f, 0.5f); } } ); @@ -61,23 +65,38 @@ public: return true; } + + + + virtual bool IsUseable(void) override { return true; } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_BlockFace); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); return true; } + + + + + /** Converts the block face of the neighbor to which the button is attached, to the block meta for this button. */ inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) @@ -97,6 +116,11 @@ public: UNREACHABLE("Unsupported block face"); } + + + + + /** Converts the block meta of this button into a block face of the neighbor to which the button is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) @@ -115,24 +139,39 @@ public: } } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override - { - NIBBLETYPE Meta; - a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta); - 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) && (cBlockInfo::FullyOccupiesVoxel(BlockIsOn)); + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override + { + auto Meta = a_Chunk.GetMeta(a_RelPos); + auto SupportRelPos = AddFaceDirection(a_RelPos, BlockMetaDataToBlockFace(Meta), true); + if (!cChunkDef::IsValidHeight(SupportRelPos.y)) + { + return false; + } + BLOCKTYPE SupportBlockType; + a_Chunk.UnboundedRelGetBlockType(SupportRelPos, SupportBlockType); + + return cBlockInfo::FullyOccupiesVoxel(SupportBlockType); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); return 0; } - /** Extracts the ON bit from metadata and returns if true if it is set */ + + + + + /** Extracts the ON bit from metadata. */ static bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return ((a_BlockMeta & 0x8) == 0x8); diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h index db65ea15f..0c3577898 100644 --- a/src/Blocks/BlockCactus.h +++ b/src/Blocks/BlockCactus.h @@ -23,13 +23,13 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - BLOCKTYPE Surface = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ); + BLOCKTYPE Surface = a_Chunk.GetBlock(a_RelPos.addedY(-1)); if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS)) { // Cactus can only be placed on sand and itself @@ -37,22 +37,19 @@ public: } // Check surroundings. Cacti may ONLY be surrounded by non-solid blocks - static const struct + static const Vector3i Coords[] = { - int x, z; - } Coords[] = - { - {-1, 0}, - { 1, 0}, - { 0, -1}, - { 0, 1}, - } ; + {-1, 0, 0}, + { 1, 0, 0}, + { 0, 0, -1}, + { 0, 0, 1}, + }; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if ( - a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta) && + a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[i], BlockType, BlockMeta) && ( cBlockInfo::IsSolid(BlockType) || (BlockType == E_BLOCK_LAVA) || diff --git a/src/Blocks/BlockCake.h b/src/Blocks/BlockCake.h index e30a79db1..dbcce5f17 100644 --- a/src/Blocks/BlockCake.h +++ b/src/Blocks/BlockCake.h @@ -20,9 +20,16 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if (!a_Player.Feed(2, 0.4)) { @@ -31,11 +38,11 @@ public: if (Meta >= 5) { - a_ChunkInterface.DigBlock(a_WorldInterface, {a_BlockX, a_BlockY, a_BlockZ}); + a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos); } else { - a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, Meta + 1); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta + 1); } return true; } diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h index 9f315caa8..41e84c47b 100644 --- a/src/Blocks/BlockCarpet.h +++ b/src/Blocks/BlockCarpet.h @@ -14,14 +14,14 @@ -class cBlockCarpetHandler : +class cBlockCarpetHandler: public cBlockHandler { using Super = cBlockHandler; public: - cBlockCarpetHandler(BLOCKTYPE a_BlockType) : + cBlockCarpetHandler(BLOCKTYPE a_BlockType): Super(a_BlockType) { } @@ -31,9 +31,11 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { @@ -46,9 +48,9 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return (a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR); + return (a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) != E_BLOCK_AIR); } diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h index 28c1dfda8..da7c43860 100644 --- a/src/Blocks/BlockCauldron.h +++ b/src/Blocks/BlockCauldron.h @@ -32,9 +32,16 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); auto EquippedItem = a_Player.GetEquippedItem(); switch (EquippedItem.m_ItemType) { @@ -42,7 +49,7 @@ public: { if (Meta == 3) { - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0); + a_ChunkInterface.SetBlockMeta(a_BlockPos, 0); // Give new bucket, filled with fluid when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { @@ -55,7 +62,7 @@ public: { if (Meta < 3) { - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 3); + a_ChunkInterface.SetBlockMeta(a_BlockPos, 3); // Give empty bucket back when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { @@ -68,7 +75,7 @@ public: { if (Meta > 0) { - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, --Meta); + a_ChunkInterface.SetBlockMeta(a_BlockPos, --Meta); // Give new potion when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { @@ -82,8 +89,8 @@ public: // Refill cauldron with water bottles. if ((Meta < 3) && (EquippedItem.m_ItemDamage == 0)) { - a_ChunkInterface.SetBlockMeta(Vector3i(a_BlockX, a_BlockY, a_BlockZ), ++Meta); - // Give empty bottle when the gamemode is not creative: + a_ChunkInterface.SetBlockMeta(Vector3i(a_BlockPos), ++Meta); + // Give back an empty bottle when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_GLASS_BOTTLE)); diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h index aeb687abb..d28ea81fd 100644 --- a/src/Blocks/BlockChest.h +++ b/src/Blocks/BlockChest.h @@ -27,14 +27,16 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - // Is there a doublechest already next to this block? - if (!CanBeAt(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ)) + // Cannot place right next to double-chest: + if (!CanBeAt(a_ChunkInterface, a_PlacedBlockPos)) { // Yup, cannot form a triple-chest, refuse: return false; @@ -42,13 +44,13 @@ public: // Try to read double-chest information: cBlockArea Area; - if (!Area.Read(a_ChunkInterface, a_BlockX - 1, a_BlockX + 1, a_BlockY, a_BlockY, a_BlockZ - 1, a_BlockZ + 1)) + if (!Area.Read(a_ChunkInterface, a_PlacedBlockPos - Vector3i(1, 0, 1), a_PlacedBlockPos + Vector3i(1, 0, 1))) { return false; } // Get meta as if this was a single-chest: - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta)) + if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta)) { return false; } @@ -80,21 +82,20 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; - int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; - return CanBeAt(a_ChunkInterface, BlockX, a_RelY, BlockZ); + auto BlockPos = a_Chunk.RelativeToAbsolute(a_RelPos); + return CanBeAt(a_ChunkInterface, BlockPos); } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { cBlockArea Area; - if (!Area.Read(a_ChunkInterface, a_BlockX - 2, a_BlockX + 2, a_BlockY, a_BlockY, a_BlockZ - 2, a_BlockZ + 2)) + if (!Area.Read(a_ChunkInterface, a_BlockPos - Vector3i(2, 0, 2), a_BlockPos + Vector3i(2, 0, 2))) { // Cannot read the surroundings, probably at the edge of loaded chunks. Disallow. return false; diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h index 74b7c3caa..955a2e3fc 100644 --- a/src/Blocks/BlockCocoaPod.h +++ b/src/Blocks/BlockCocoaPod.h @@ -22,16 +22,15 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - eBlockFace BlockFace = MetaToBlockFace(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ)); - AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockFace, true); - + // Check that we're attached to a jungle log block: + eBlockFace BlockFace = MetaToBlockFace(a_Chunk.GetMeta(a_RelPos)); + auto LogPos = AddFaceDirection(a_RelPos, BlockFace, true); BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta); - - return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x3) == E_META_LOG_JUNGLE)); + a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta); + return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x03) == E_META_LOG_JUNGLE)); } diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index 5e6b3eaa6..a2f2d430d 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -21,45 +21,114 @@ public: { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); - Meta ^= 0x04; // Toggle 3rd (addition / subtraction) bit with XOR - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); + // Toggle the 3rd bit (addition / subtraction): + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); + Meta ^= 0x04; + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); return true; } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { UNUSED(a_ChunkInterface); - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + UNUSED(a_BlockFace); + + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual bool IsUseable(void) override { return true; } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR)); + if (a_RelPos.y <= 0) + { + return false; + } + + BLOCKTYPE BelowBlock; + NIBBLETYPE BelowBlockMeta; + a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); + + if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) + { + return true; + } + else if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) + { + // Check if the slab is turned up side down + if ((BelowBlockMeta & 0x08) == 0x08) + { + return true; + } + } + return false; } + + + + virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override { return cItem(E_ITEM_COMPARATOR, 1, 0); } + + + + inline static bool IsInSubtractionMode(NIBBLETYPE a_Meta) { return ((a_Meta & 0x4) == 0x4); } + + + + inline static bool IsOn(NIBBLETYPE a_Meta) { return ((a_Meta & 0x8) == 0x8); } + + + + inline static Vector3i GetSideCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta, bool a_bInverse) { if (!a_bInverse) @@ -98,6 +167,10 @@ public: return a_Position; } + + + + inline static Vector3i GetRearCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta) { switch (a_Meta) @@ -117,6 +190,10 @@ public: return a_Position; } + + + + inline static Vector3i GetFrontCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta) { switch (a_Meta) @@ -136,6 +213,10 @@ public: return a_Position; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h index 4622d1ad5..05bb0d2f1 100644 --- a/src/Blocks/BlockCrops.h +++ b/src/Blocks/BlockCrops.h @@ -108,13 +108,15 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND)); + return ((a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_FARMLAND)); } + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockDeadBush.h b/src/Blocks/BlockDeadBush.h index 52c9ac594..9eb0c8e84 100644 --- a/src/Blocks/BlockDeadBush.h +++ b/src/Blocks/BlockDeadBush.h @@ -31,14 +31,14 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ); + BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelPos.addedY(-1)); switch (BelowBlock) { case E_BLOCK_CLAY: diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp index bb694e5b2..fcc4ddbe6 100644 --- a/src/Blocks/BlockDoor.cpp +++ b/src/Blocks/BlockDoor.cpp @@ -40,15 +40,20 @@ void cBlockDoorHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInter -bool cBlockDoorHandler::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) +bool cBlockDoorHandler::OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos +) { UNUSED(a_WorldInterface); UNUSED(a_BlockFace); - UNUSED(a_CursorX); - UNUSED(a_CursorY); - UNUSED(a_CursorZ); + UNUSED(a_CursorPos); - switch (a_ChunkInterface.GetBlock({a_BlockX, a_BlockY, a_BlockZ})) + switch (a_ChunkInterface.GetBlock(a_BlockPos)) { default: { @@ -61,14 +66,14 @@ bool cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_OAK_DOOR: { - ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); - a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, {a_BlockX, a_BlockY, a_BlockZ}, 0, a_Player.GetClientHandle()); + ChangeDoor(a_ChunkInterface, a_BlockPos); + a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); break; } // Prevent iron door from opening on player click case E_BLOCK_IRON_DOOR: { - OnCancelRightClick(a_ChunkInterface, a_WorldInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + OnCancelRightClick(a_ChunkInterface, a_WorldInterface, a_Player, a_BlockPos, a_BlockFace); break; } } @@ -80,22 +85,29 @@ bool cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac -void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) +void cBlockDoorHandler::OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace +) { UNUSED(a_ChunkInterface); + UNUSED(a_BlockFace); - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); - if (Meta & 0x8) + if (Meta & 0x08) { - // Current block is top of the door - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, a_Player); + // Current block is top of the door, send the bottom part: + a_WorldInterface.SendBlockTo(a_BlockPos.addedY(-1), a_Player); } else { - // Current block is bottom of the door - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, a_Player); + // Current block is bottom of the door, send the top part: + a_WorldInterface.SendBlockTo(a_BlockPos.addedY(1), a_Player); } } diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h index 48c761d05..a32649961 100644 --- a/src/Blocks/BlockDoor.h +++ b/src/Blocks/BlockDoor.h @@ -20,37 +20,63 @@ public: cBlockDoorHandler(BLOCKTYPE a_BlockType); - virtual void OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) override; - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override; - virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override; + virtual void OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + ) override; + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override; + + virtual void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) 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, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { // If clicking a bottom face, place the door one block lower: - if (a_BlockFace == BLOCK_FACE_BOTTOM) + auto PlacedPos = a_PlacedBlockPos; + if (a_ClickedBlockFace == BLOCK_FACE_BOTTOM) { - a_BlockY--; + PlacedPos.y--; } if ( - !CanReplaceBlock(a_ChunkInterface.GetBlock({a_BlockX, a_BlockY, a_BlockZ})) || - !CanReplaceBlock(a_ChunkInterface.GetBlock({a_BlockX, a_BlockY + 1, a_BlockZ})) + !CanReplaceBlock(a_ChunkInterface.GetBlock(PlacedPos)) || + !CanReplaceBlock(a_ChunkInterface.GetBlock(PlacedPos.addedY(1))) ) { return false; } - return Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta); + return Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, PlacedPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta); } virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) override; @@ -93,11 +119,19 @@ public: return true; } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return ((a_RelY > 0) && CanBeOn(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ), a_Chunk.GetMeta(a_RelX, a_RelY - 1, a_RelZ))); + return ((a_RelPos.y > 0) && CanBeOn(a_Chunk.GetBlock(a_RelPos.addedY(-1)), a_Chunk.GetMeta(a_RelPos.addedY(-1)))); } + + + + /** Returns true if door can be placed on the specified block type. */ static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { @@ -188,9 +222,9 @@ public: /** Returns true iff the door at the specified coords is open. The coords may point to either the top part or the bottom part of the door. */ - static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { - NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos); return ((Meta & 0x04) != 0); } @@ -201,17 +235,17 @@ public: /** Returns the complete meta composed from the both parts of the door as (TopMeta << 4) | BottomMeta The coords may point to either part of the door. The returned value has bit 3 (0x08) set iff the coords point to the top part of the door. - Fails gracefully for (invalid) doors on the world's top and bottom. */ - static NIBBLETYPE GetCompleteDoorMeta(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + Fails silently for (invalid) doors on the world's top and bottom. */ + static NIBBLETYPE GetCompleteDoorMeta(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); + NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if ((Meta & 0x08) != 0) { // The coords are pointing at the top part of the door - if (a_BlockY > 0) + if (a_BlockPos.y > 0) { - NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY - 1, a_BlockZ}); + NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(-1)); return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4)); } // This is the top part of the door at the bottommost layer of the world, there's no bottom: @@ -220,9 +254,9 @@ public: else { // The coords are pointing at the bottom part of the door - if (a_BlockY < cChunkDef::Height - 1) + if (a_BlockPos.y < cChunkDef::Height - 1) { - NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY + 1, a_BlockZ}); + NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(1)); return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4)); } // This is the bottom part of the door at the topmost layer of the world, there's no top: @@ -235,15 +269,15 @@ public: /** Sets the door to the specified state. If the door is already in that state, does nothing. */ - static void SetOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open) + static void SetOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos, bool a_Open) { - BLOCKTYPE Block = a_ChunkInterface.GetBlock({a_BlockX, a_BlockY, a_BlockZ}); + BLOCKTYPE Block = a_ChunkInterface.GetBlock(a_BlockPos); if (!IsDoorBlockType(Block)) { return; } - NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos); bool IsOpened = ((Meta & 0x04) != 0); if (IsOpened == a_Open) { @@ -255,14 +289,14 @@ public: if ((Meta & 0x08) == 0) { // The block is the bottom part of the door - a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, NewMeta); + a_ChunkInterface.SetBlockMeta(a_BlockPos, NewMeta); } else { // The block is the top part of the door, set the meta to the corresponding top part - if (a_BlockY > 0) + if (a_BlockPos.y > 0) { - a_ChunkInterface.SetBlockMeta({a_BlockX, a_BlockY - 1, a_BlockZ}, NewMeta); + a_ChunkInterface.SetBlockMeta(a_BlockPos.addedY(-1), NewMeta); } } } @@ -272,9 +306,9 @@ public: /** Changes the door at the specified coords from open to close or vice versa */ - static void ChangeDoor(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + static void ChangeDoor(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { - SetOpen(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, !IsOpen(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ)); + SetOpen(a_ChunkInterface, a_BlockPos, !IsOpen(a_ChunkInterface, a_BlockPos)); } diff --git a/src/Blocks/BlockEnchantmentTable.h b/src/Blocks/BlockEnchantmentTable.h index bfb0f521c..a981cf7a7 100644 --- a/src/Blocks/BlockEnchantmentTable.h +++ b/src/Blocks/BlockEnchantmentTable.h @@ -9,27 +9,49 @@ -class cBlockEnchantmentTableHandler : +class cBlockEnchantmentTableHandler: public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockEnchantmentTableHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockEnchantmentTableHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ); + cWindow * Window = new cEnchantingWindow(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); a_Player.OpenWindow(*Window); return true; } + + + + virtual bool IsUseable(void) override { return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockEndPortalFrame.h b/src/Blocks/BlockEndPortalFrame.h index c35d13929..be67bb4f9 100644 --- a/src/Blocks/BlockEndPortalFrame.h +++ b/src/Blocks/BlockEndPortalFrame.h @@ -7,22 +7,26 @@ -class cBlockEndPortalFrameHandler : +class cBlockEndPortalFrameHandler: public cMetaRotator<cBlockHandler, 0x03, - E_META_END_PORTAL_FRAME_ZM, - E_META_END_PORTAL_FRAME_XP, - E_META_END_PORTAL_FRAME_ZP, - E_META_END_PORTAL_FRAME_XM + E_META_END_PORTAL_FRAME_ZM, + E_META_END_PORTAL_FRAME_XP, + E_META_END_PORTAL_FRAME_ZP, + E_META_END_PORTAL_FRAME_XM > { -public: - cBlockEndPortalFrameHandler(BLOCKTYPE a_BlockType): - cMetaRotator<cBlockHandler, 0x03, + using Super = cMetaRotator< + cBlockHandler, 0x03, E_META_END_PORTAL_FRAME_ZM, E_META_END_PORTAL_FRAME_XP, E_META_END_PORTAL_FRAME_ZP, E_META_END_PORTAL_FRAME_XM - >(a_BlockType) + >; + +public: + + cBlockEndPortalFrameHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } @@ -31,9 +35,11 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { diff --git a/src/Blocks/BlockEntity.h b/src/Blocks/BlockEntity.h index 8e7f92913..9fbb77a1f 100644 --- a/src/Blocks/BlockEntity.h +++ b/src/Blocks/BlockEntity.h @@ -28,9 +28,16 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockX, a_BlockY, a_BlockZ); + return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); } diff --git a/src/Blocks/BlockFence.h b/src/Blocks/BlockFence.h index 96a3d8d96..25ac85eed 100644 --- a/src/Blocks/BlockFence.h +++ b/src/Blocks/BlockFence.h @@ -10,21 +10,28 @@ -class cBlockFenceHandler : +class cBlockFenceHandler: public cBlockHandler { + using Super = cBlockHandler; + public: + // These are the min and max coordinates (X and Z) for a straight fence. // 0.4 and 0.6 are really just guesses, but they seem pretty good. // (0.4 to 0.6 is a fence that's 0.2 wide, down the center of the block) const double MIN_COORD = 0.4; const double MAX_COORD = 0.6; - cBlockFenceHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + cBlockFenceHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } + + + + virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) override { bool XMSolid = cBlockInfo::IsSolid(a_XM); @@ -76,9 +83,20 @@ public: return PlacementBox; } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - auto LeashKnot = cLeashKnot::FindKnotAtPos(*a_Player.GetWorld(), { a_BlockX, a_BlockY, a_BlockZ }); + auto LeashKnot = cLeashKnot::FindKnotAtPos(*a_Player.GetWorld(), a_BlockPos); auto KnotAlreadyExists = (LeashKnot != nullptr); if (KnotAlreadyExists) @@ -89,7 +107,7 @@ public: // New knot? needs to init and produce sound effect else { - auto NewLeashKnot = cpp14::make_unique<cLeashKnot>(a_BlockFace, Vector3i{a_BlockX, a_BlockY, a_BlockZ}); + auto NewLeashKnot = cpp14::make_unique<cLeashKnot>(a_BlockFace, a_BlockPos); auto NewLeashKnotPtr = NewLeashKnot.get(); NewLeashKnotPtr->TiePlayersLeashedMobs(a_Player, KnotAlreadyExists); @@ -112,11 +130,25 @@ public: return true; } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual bool IsUseable(void) override { return true; diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h index 5d89ae021..bba308230 100644 --- a/src/Blocks/BlockFenceGate.h +++ b/src/Blocks/BlockFenceGate.h @@ -20,36 +20,65 @@ public: { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}); + NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta(a_BlockPos); NIBBLETYPE NewMetaData = YawToMetaData(a_Player.GetYaw()); OldMetaData ^= 4; // Toggle the gate if ((OldMetaData & 1) == (NewMetaData & 1)) { // Standing in front of the gate - apply new direction - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, (OldMetaData & 4) | (NewMetaData & 3)); + a_ChunkInterface.SetBlockMeta(a_BlockPos, (OldMetaData & 4) | (NewMetaData & 3)); } else { // Standing aside - use last direction - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, OldMetaData); + a_ChunkInterface.SetBlockMeta(a_BlockPos, OldMetaData); } - a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, {a_BlockX, a_BlockY, a_BlockZ}, 0, a_Player.GetClientHandle()); + a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); return true; } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual bool IsUseable(void) override { return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h index d88891d75..714ff9cab 100644 --- a/src/Blocks/BlockFlower.h +++ b/src/Blocks/BlockFlower.h @@ -7,12 +7,15 @@ -class cBlockFlowerHandler : +class cBlockFlowerHandler: public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockFlowerHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockFlowerHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } @@ -30,11 +33,15 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)); + return ((a_RelPos.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelPos.addedY(-1)))); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockGrass.h b/src/Blocks/BlockGrass.h index 374fcceed..51a321b35 100644 --- a/src/Blocks/BlockGrass.h +++ b/src/Blocks/BlockGrass.h @@ -90,30 +90,31 @@ public: // Y Coord out of range continue; } - auto chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Pos); - if (chunk == nullptr) + auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Pos); + if (Chunk == nullptr) { // Unloaded chunk continue; } - chunk->GetBlockTypeMeta(Pos, DestBlock, DestMeta); + Chunk->GetBlockTypeMeta(Pos, DestBlock, DestMeta); if ((DestBlock != E_BLOCK_DIRT) || (DestMeta != E_META_DIRT_NORMAL)) { // Not a regular dirt block continue; } - BLOCKTYPE Above = chunk->GetBlock(AbovePos); - NIBBLETYPE light = std::max(chunk->GetBlockLight(AbovePos), chunk->GetTimeAlteredLight(chunk->GetSkyLight(AbovePos))); - if ((light > 4) && - cBlockInfo::IsTransparent(Above) && - (!IsBlockLava(Above)) && - (!IsBlockWaterOrIce(Above)) + auto AboveDestPos = Pos.addedY(1); + auto AboveBlockType = Chunk->GetBlock(AboveDestPos); + auto Light = std::max(Chunk->GetBlockLight(AboveDestPos), Chunk->GetTimeAlteredLight(Chunk->GetSkyLight(AboveDestPos))); + if ((Light > 4) && + cBlockInfo::IsTransparent(AboveBlockType) && + (!IsBlockLava(AboveBlockType)) && + (!IsBlockWaterOrIce(AboveBlockType)) ) { - auto absPos = chunk->RelativeToAbsolute(Pos); - if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*chunk->GetWorld(), absPos.x, absPos.y, absPos.z, ssGrassSpread)) + auto AbsPos = Chunk->RelativeToAbsolute(Pos); + if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), AbsPos.x, AbsPos.y, AbsPos.z, ssGrassSpread)) { - chunk->FastSetBlock(Pos, E_BLOCK_GRASS, 0); + Chunk->FastSetBlock(Pos, E_BLOCK_GRASS, 0); } } } // for i - repeat twice diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index f1df4db44..5d6609836 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -406,8 +406,9 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType) bool cBlockHandler::GetPlacementBlockTypeMeta( cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + const Vector3i a_ClickedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) { @@ -437,7 +438,7 @@ void cBlockHandler::OnUpdate( void cBlockHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange) { - OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockChange.GetPos(), a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta); + OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockChange.GetAbsolutePos(), a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta); } @@ -509,7 +510,7 @@ cItems cBlockHandler::ConvertToPickups( -bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk) +bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) { return true; } @@ -554,10 +555,10 @@ bool cBlockHandler::DoesDropOnUnsuitable(void) -/* default functionality: only test for height, since we assume full voxels with varying height */ -bool cBlockHandler::IsInsideBlock(Vector3d a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) +bool cBlockHandler::IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) { - return a_Position.y < cBlockInfo::GetBlockHeight(a_BlockType); + // Default functionality: Test the height, since we assume full voxels with varying height + return (a_RelPosition.y < cBlockInfo::GetBlockHeight(m_BlockType)); } @@ -584,7 +585,7 @@ void cBlockHandler::Check( cChunk & a_Chunk ) { - if (!CanBeAt(a_ChunkInterface, a_RelPos.x, a_RelPos.y, a_RelPos.z, a_Chunk)) + if (!CanBeAt(a_ChunkInterface, a_RelPos, a_Chunk)) { if (DoesDropOnUnsuitable()) { diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index f4a7fc674..a582b8dc2 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -44,19 +44,28 @@ public: blocktype of the minus-X neighbor, the positive-X neighbor, etc. */ virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP); - /** Called before a block is placed into a world. + /** Called before a block is placed into a world by player, by cItemHandler::GetPlacementBlockTypeMeta(). The handler should return true to allow placement, false to refuse. - Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block. - Called by cItemHandler::GetPlacementBlockTypeMeta() if the item is a block */ + a_PlacedBlockPos is the coords of the block being placed + a_ClickedBlockFace is the face of the neighbor block clicked by the client to place this block. + a_CursorPos is the position of the cursor within the neighbor's face + The descendant handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block. + The default handler uses the stored block type and meta copied from the lowest 4 bits of the player's equipped item's damage value. */ virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ); /** Called by cWorld::SetBlock() after the block has been set */ - virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); + virtual void OnPlaced( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta + ); /** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */ virtual void OnPlacedByPlayer( @@ -118,18 +127,37 @@ public: cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ + const Vector3i a_BlockPos ) { } - /** Called if the user right clicks the block and the block is useable - returns true if the use was successful, return false to use the block as a "normal" block */ - virtual bool 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) { return false; } + /** Called when the user right clicks the block and the block is useable. + a_CursorPos is the cursor position within the clicked block face. + Returns true if the use was successful, return false to use the block as a "normal" block */ + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) + { + return false; + } /** Called when a right click to this block is cancelled. - It forces the server to send the real state of a block to the client to prevent client assuming the operation is successfull */ - virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) {} + Descendants should force the server to send the real state of a block to the client to prevent client assuming the operation was successfull. */ + virtual void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) + { + } /** Returns the pickups that would result if the block was mined by a_Digger using a_Tool. Doesn't do any actual block change / mining, only calculates the pickups. @@ -145,41 +173,37 @@ 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); + virtual bool CanBeAt( + cChunkInterface & a_ChunkInterface, + const Vector3i a_RelPos, + const cChunk & a_Chunk + ); /** Checks whether the block has an effect on growing the plant */ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) { return false; } - /** Checks if the block can be placed at this point. - Default: CanBeAt(...) - 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 to check whether this block supports a rclk action. If it returns true, OnUse() is called */ virtual bool IsUseable(void); /** Indicates whether the client will click through this block. - For example digging a fire will hit the block below the fire so fire is clicked through - */ + For example digging a fire will hit the block below the fire so fire is clicked through. */ virtual bool IsClickedThrough(void); /** Checks if the player can build "inside" this block. For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision @param a_Pos Position of the block @param a_Player Player trying to build on the block - @param a_Meta Meta value of the block currently at a_Pos - */ - virtual bool DoesIgnoreBuildCollision(cChunkInterface & ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta); + @param a_Meta Meta value of the block currently at a_Pos */ + virtual bool DoesIgnoreBuildCollision(cChunkInterface & ChunkInterface, const Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta); /** Returns if this block drops if it gets destroyed by an unsuitable situation. Default: true */ virtual bool DoesDropOnUnsuitable(void); - /** Tests if a_Position is inside the block where a_Position is relative to the origin of the block - Note that this is considered from a "top-down" perspective i.e. empty spaces on the bottom of a block don't matter */ - virtual bool IsInsideBlock(Vector3d a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta); + /** Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the block. + Coords in a_RelPosition are guaranteed to be in the [0..1] range. */ + virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta); /** Called when one of the neighbors gets set; equivalent to MC block update. By default drops (DropBlockAsPickup() / SetBlock()) if the position is no longer suitable (CanBeAt(), DoesDropOnUnsuitable()), diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h index a8d59440d..cb1ddf7d1 100644 --- a/src/Blocks/BlockHopper.h +++ b/src/Blocks/BlockHopper.h @@ -24,16 +24,18 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; // Convert the blockface into meta: - switch (a_BlockFace) + switch (a_ClickedBlockFace) { case BLOCK_FACE_BOTTOM: a_BlockMeta = E_META_HOPPER_FACING_YM; break; case BLOCK_FACE_TOP: a_BlockMeta = E_META_HOPPER_FACING_YM; break; diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h index c141faeb4..3f38d2c0c 100644 --- a/src/Blocks/BlockLadder.h +++ b/src/Blocks/BlockLadder.h @@ -8,7 +8,7 @@ -class cBlockLadderHandler : +class cBlockLadderHandler: public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04> > { using Super = cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>>; @@ -25,24 +25,26 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - if (!LadderCanBePlacedAt(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)) + // Try finding a suitable neighbor block face for the ladder; start with the given one. + if (!LadderCanBePlacedAt(a_ChunkInterface, a_PlacedBlockPos, a_ClickedBlockFace)) { - a_BlockFace = FindSuitableBlockFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); - - if (a_BlockFace == BLOCK_FACE_BOTTOM) + a_ClickedBlockFace = FindSuitableBlockFace(a_ChunkInterface, a_PlacedBlockPos); + if (a_ClickedBlockFace == BLOCK_FACE_NONE) { return false; } } a_BlockType = m_BlockType; - a_BlockMeta = DirectionToMetaData(a_BlockFace); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); return true; } @@ -50,9 +52,10 @@ public: - static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction) + /** Converts the block face of the neighbor to which the ladder is attached to the ladder block's meta. */ + static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) { - switch (a_Direction) + switch (a_NeighborBlockFace) { case BLOCK_FACE_ZM: return 0x2; case BLOCK_FACE_ZP: return 0x3; @@ -65,14 +68,15 @@ public: return 0x2; } } - UNREACHABLE("Unsupported block face"); + UNREACHABLE("Unsupported neighbor block face"); } - static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData) + /** Converts the ladder block's meta to the block face of the neighbor to which the ladder is attached. */ + static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) { switch (a_MetaData) { @@ -88,47 +92,51 @@ public: - /** Finds a suitable Direction for the Ladder. Returns BLOCK_FACE_BOTTOM on failure */ - static eBlockFace FindSuitableBlockFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + /** Finds a suitable block face value for the Ladder. + The returned value is the block face of the neighbor of the specified block to which a ladder at a_LadderPos can be attached. + Returns BLOCK_FACE_NONE if no valid location is found */ + static eBlockFace FindSuitableBlockFace(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos) { for (int FaceInt = BLOCK_FACE_ZM; FaceInt <= BLOCK_FACE_XP; FaceInt++) { eBlockFace Face = static_cast<eBlockFace>(FaceInt); - if (LadderCanBePlacedAt(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, Face)) + if (LadderCanBePlacedAt(a_ChunkInterface, a_LadderPos, Face)) { return Face; } } - return BLOCK_FACE_BOTTOM; + return BLOCK_FACE_NONE; } - static bool LadderCanBePlacedAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) + /** Returns true if the ladder in the specified position will be supported by its neghbor through the specified neighbor's blockface. */ + static bool LadderCanBePlacedAt(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos, eBlockFace a_NeighborBlockFace) { - if ((a_BlockFace == BLOCK_FACE_BOTTOM) || (a_BlockFace == BLOCK_FACE_TOP)) + if ( + (a_NeighborBlockFace == BLOCK_FACE_NONE) || + (a_NeighborBlockFace == BLOCK_FACE_BOTTOM) || + (a_NeighborBlockFace == BLOCK_FACE_TOP) + ) { return false; } - AddFaceDirection( a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); - - return cBlockInfo::IsSolid(a_ChunkInterface.GetBlock({a_BlockX, a_BlockY, a_BlockZ})); + auto NeighborPos = AddFaceDirection(a_LadderPos, a_NeighborBlockFace, true); + return cBlockInfo::IsSolid(a_ChunkInterface.GetBlock(NeighborPos)); } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - // TODO: Use AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison - eBlockFace BlockFace = 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 LadderCanBePlacedAt(a_ChunkInterface, BlockX, a_RelY, BlockZ, BlockFace); + auto NeighborBlockFace = MetaDataToBlockFace(a_Chunk.GetMeta(a_RelPos)); + auto LadderAbsPos = a_Chunk.RelativeToAbsolute(a_RelPos); + return LadderCanBePlacedAt(a_ChunkInterface, LadderAbsPos, NeighborBlockFace); } diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h index 8425b6620..4a682322d 100644 --- a/src/Blocks/BlockLever.h +++ b/src/Blocks/BlockLever.h @@ -6,14 +6,14 @@ #include "BlockSlab.h" -class cBlockLeverHandler : +class cBlockLeverHandler: public cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, false> { using Super = cMetaRotator<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, false>; public: - cBlockLeverHandler(BLOCKTYPE a_BlockType) : + cBlockLeverHandler(BLOCKTYPE a_BlockType): Super(a_BlockType) { } @@ -22,15 +22,21 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ); // Flip the ON bit on / off using the XOR bitwise operation - NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(Coords) ^ 0x08); + NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08); - a_ChunkInterface.SetBlockMeta(Coords.x, Coords.y, Coords.z, Meta); - a_WorldInterface.WakeUpSimulators(Coords); - a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", Vector3d(Coords), 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); + a_WorldInterface.WakeUpSimulators(a_BlockPos); + a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", a_BlockPos, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); return true; } @@ -58,14 +64,16 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - a_BlockMeta = LeverDirectionToMetaData(a_BlockFace); + a_BlockMeta = LeverDirectionToMetaData(a_ClickedBlockFace); return true; } @@ -73,6 +81,7 @@ public: + /** Converts the block face of the neighbor to which the lever is attached to the lever block's meta. */ inline static NIBBLETYPE LeverDirectionToMetaData(eBlockFace a_Dir) { // Determine lever direction: @@ -93,6 +102,7 @@ public: + /** Converts the leve block's meta to the block face of the neighbor to which the lever is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) @@ -117,34 +127,33 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); - - eBlockFace Face = BlockMetaDataToBlockFace(Meta); - - AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true); - - if ((a_RelY < 0) || (a_RelY >= cChunkDef::Height -1)) + // Find the type of block the lever is attached to: + auto Meta = a_Chunk.GetMeta(a_RelPos); + auto NeighborFace = BlockMetaDataToBlockFace(Meta); + auto NeighborPos = AddFaceDirection(a_RelPos, NeighborFace, true); + if (!cChunkDef::IsValidHeight(NeighborPos.y)) + { + return false; + } + BLOCKTYPE NeighborBlockType; + if (!a_Chunk.UnboundedRelGetBlock(NeighborPos, NeighborBlockType, Meta)) { return false; } - BLOCKTYPE BlockIsOn; - a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockIsOn, Meta); - - - if (cBlockInfo::FullyOccupiesVoxel(BlockIsOn)) + // Allow any full block or the "good" side of a half-slab: + if (cBlockInfo::FullyOccupiesVoxel(NeighborBlockType)) { return true; } - else if (cBlockSlabHandler::IsAnySlabType(BlockIsOn)) + else if (cBlockSlabHandler::IsAnySlabType(NeighborBlockType)) { - // Check if the slab is turned up side down - if (((Meta & 0x08) == 0x08) && (Face == BLOCK_FACE_TOP)) - { - return true; - } + return ( + (((Meta & 0x08) == 0x08) && (NeighborFace == BLOCK_FACE_TOP)) || + (((Meta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) + ); } return false; diff --git a/src/Blocks/BlockLilypad.h b/src/Blocks/BlockLilypad.h index c51eb0a3d..8ffc8fd20 100644 --- a/src/Blocks/BlockLilypad.h +++ b/src/Blocks/BlockLilypad.h @@ -19,6 +19,10 @@ public: { } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); @@ -26,15 +30,19 @@ public: } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if ((a_RelY < 1) || (a_RelY >= cChunkDef::Height)) + auto UnderPos = a_RelPos.addedY(-1); + if (!cChunkDef::IsValidHeight(UnderPos.y)) { return false; } BLOCKTYPE UnderType; NIBBLETYPE UnderMeta; - a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, UnderType, UnderMeta); + a_Chunk.GetBlockTypeMeta(UnderPos, UnderType, UnderMeta); return ( (((UnderType == E_BLOCK_STATIONARY_WATER) || (UnderType == E_BLOCK_WATER)) && (UnderMeta == 0)) || // A water source is below (UnderType == E_BLOCK_ICE) || (UnderType == E_BLOCK_FROSTED_ICE) // Or (frosted) ice diff --git a/src/Blocks/BlockMobSpawner.h b/src/Blocks/BlockMobSpawner.h index c8a1c5696..78fa9ec31 100644 --- a/src/Blocks/BlockMobSpawner.h +++ b/src/Blocks/BlockMobSpawner.h @@ -8,22 +8,38 @@ -class cBlockMobSpawnerHandler : +class cBlockMobSpawnerHandler: public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockMobSpawnerHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockMobSpawnerHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockX, a_BlockY, a_BlockZ); + return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); } + + + virtual bool IsUseable() override { return true; diff --git a/src/Blocks/BlockMushroom.h b/src/Blocks/BlockMushroom.h index f44fbdc07..e40031465 100644 --- a/src/Blocks/BlockMushroom.h +++ b/src/Blocks/BlockMushroom.h @@ -7,6 +7,7 @@ +/** Handler for the small (singleblock) mushrooms. */ class cBlockMushroomHandler: public cClearMetaOnDrop<cBlockHandler> { @@ -19,18 +20,26 @@ public: { } + + + + // TODO: Add Mushroom Spread - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } // TODO: Cannot be at too much daylight - switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)) + switch (a_Chunk.GetBlock(a_RelPos.addedY(-1))) { case E_BLOCK_GLASS: case E_BLOCK_CACTUS: @@ -45,6 +54,10 @@ public: return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h index 40ab1d886..86e348cf1 100644 --- a/src/Blocks/BlockNetherWart.h +++ b/src/Blocks/BlockNetherWart.h @@ -8,7 +8,7 @@ -class cBlockNetherWartHandler : +class cBlockNetherWartHandler: public cBlockPlant<false> { using Super = cBlockPlant<false>; @@ -64,10 +64,10 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, 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)); + return ((a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_SOULSAND)); } diff --git a/src/Blocks/BlockPlanks.h b/src/Blocks/BlockPlanks.h index 556f700ee..ea7d91398 100644 --- a/src/Blocks/BlockPlanks.h +++ b/src/Blocks/BlockPlanks.h @@ -7,18 +7,28 @@ -class cBlockPlanksHandler : public cBlockHandler +class cBlockPlanksHandler: + public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockPlanksHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockPlanksHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { @@ -27,6 +37,10 @@ public: return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { switch (a_Meta) diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h index 3f5d87155..c18da10be 100644 --- a/src/Blocks/BlockPortal.h +++ b/src/Blocks/BlockPortal.h @@ -7,25 +7,33 @@ -class cBlockPortalHandler : +class cBlockPortalHandler: public cBlockHandler { + using Super = cBlockHandler; public: - cBlockPortalHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockPortalHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - // We set to zero so MCS doesn't stop you from building weird portals like vanilla does + // We set meta to zero so Cuberite doesn't stop a Creative-mode player from building custom portal shapes // CanBeAt doesn't do anything if meta is zero - // We set to zero because the client sends meta = 2 to the server (it calculates rotation itself) + // We set to zero because the client sends meta = 1 or 2 to the server (it calculates rotation itself) a_BlockType = m_BlockType; a_BlockMeta = 0; @@ -67,14 +75,14 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if ((a_RelY <= 0) || (a_RelY >= cChunkDef::Height - 1)) + if ((a_RelPos.y <= 0) || (a_RelPos.y >= cChunkDef::Height - 1)) { return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1 } - switch (a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ)) + switch (a_Chunk.GetMeta(a_RelPos)) { case 0x1: { @@ -91,8 +99,7 @@ public: for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; - a_Chunk.UnboundedRelGetBlockType(a_RelX + Direction.x, a_RelY + Direction.y, a_RelZ + Direction.z, Block); - + a_Chunk.UnboundedRelGetBlockType(a_RelPos + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; @@ -115,8 +122,7 @@ public: for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; - a_Chunk.UnboundedRelGetBlockType(a_RelX + Direction.x, a_RelY + Direction.y, a_RelZ + Direction.z, Block); - + a_Chunk.UnboundedRelGetBlockType(a_RelPos + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; @@ -128,6 +134,10 @@ public: return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h index bac93675e..445ec9ff6 100644 --- a/src/Blocks/BlockPressurePlate.h +++ b/src/Blocks/BlockPressurePlate.h @@ -18,15 +18,19 @@ public: { } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY - 1 <= 0) + if (a_RelPos.y <= 1) { return false; } // TODO: check if the block is upside-down slab or upside-down stairs - BLOCKTYPE Block = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ); + auto Block = a_Chunk.GetBlock(a_RelPos.addedY(-1)); switch (Block) { case E_BLOCK_ACACIA_FENCE: @@ -47,6 +51,10 @@ public: } } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h index c87240cf1..27d6b9984 100644 --- a/src/Blocks/BlockQuartz.h +++ b/src/Blocks/BlockQuartz.h @@ -7,42 +7,57 @@ -class cBlockQuartzHandler : public cBlockHandler +class cBlockQuartzHandler: + public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockQuartzHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockQuartzHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - NIBBLETYPE Meta = static_cast<NIBBLETYPE>(a_Player.GetEquippedItem().m_ItemDamage); + auto Meta = static_cast<NIBBLETYPE>(a_Player.GetEquippedItem().m_ItemDamage); - if (Meta != E_META_QUARTZ_PILLAR) // Check if the block is a pillar block. + // Pillar block needs additional direction in the metadata: + if (Meta != E_META_QUARTZ_PILLAR) { a_BlockMeta = Meta; return true; } - - a_BlockMeta = BlockFaceToMetaData(a_BlockFace, Meta); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); return true; } - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_QuartzMeta) + + + + + /** Converts the block face of the pillar block's "base" to the block's metadata. */ + inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_YM: case BLOCK_FACE_YP: { - return a_QuartzMeta; // Top or bottom, just return original + return E_META_QUARTZ_PILLAR; // Top or bottom } case BLOCK_FACE_ZP: @@ -57,15 +72,17 @@ public: return 0x3; // East or west } - case BLOCK_FACE_NONE: + default: { - ASSERT(!"Unhandled block face!"); - return a_QuartzMeta; // No idea, give a special meta (all sides the same) + return E_META_QUARTZ_PILLAR; } } - UNREACHABLE("Unsupported block face"); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 7ee98d576..f5cd7d8a2 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -28,21 +28,26 @@ public: { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - Vector3i Pos{ a_BlockX, a_BlockY, a_BlockZ }; - a_BlockMeta = FindMeta(a_ChunkInterface, Pos); - return a_Player.GetWorld()->DoWithChunkAt(Pos, - [this, Pos, &a_ChunkInterface](cChunk & a_Chunk) + a_BlockMeta = FindMeta(a_ChunkInterface, a_PlacedBlockPos); + return a_Player.GetWorld()->DoWithChunkAt(a_PlacedBlockPos, + [this, a_PlacedBlockPos, &a_ChunkInterface](cChunk & a_Chunk) { - auto RelPos = cChunkDef::AbsoluteToRelative(Pos); - return CanBeAt(a_ChunkInterface, RelPos.x, RelPos.y, RelPos.z, a_Chunk); + auto RelPos = cChunkDef::AbsoluteToRelative(a_PlacedBlockPos); + return CanBeAt(a_ChunkInterface, RelPos, a_Chunk); } ); } @@ -111,18 +116,18 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - if (!cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))) + if (!cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelPos.addedY(-1)))) { return false; } - NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); + NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelPos); switch (Meta) { case E_META_RAIL_ASCEND_XP: @@ -132,19 +137,16 @@ public: { // Mapping between the meta and the neighbors that need checking Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero - static const struct - { - int x, z; - } Coords[] = + static const Vector3i Coords[] = { - { 1, 0}, // east, XP - {-1, 0}, // west, XM - { 0, -1}, // north, ZM - { 0, 1}, // south, ZP + { 1, 0, 0}, // east, XP + {-1, 0, 0}, // west, XM + { 0, 0, -1}, // north, ZM + { 0, 0, 1}, // south, ZP } ; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[Meta].x, a_RelY, a_RelZ + Coords[Meta].z, BlockType, BlockMeta)) + if (!a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[Meta], BlockType, BlockMeta)) { // Too close to the edge, cannot simulate return true; @@ -155,6 +157,10 @@ public: return true; } + + + + NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos) { NIBBLETYPE Meta = 0; diff --git a/src/Blocks/BlockRedstone.h b/src/Blocks/BlockRedstone.h index 14621948e..e91c605db 100644 --- a/src/Blocks/BlockRedstone.h +++ b/src/Blocks/BlockRedstone.h @@ -8,7 +8,7 @@ -class cBlockRedstoneHandler : +class cBlockRedstoneHandler: public cBlockHandler { using Super = cBlockHandler; @@ -20,16 +20,20 @@ public: { } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, BelowBlock, BelowBlockMeta); + a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { @@ -46,11 +50,19 @@ public: return false; } + + + + virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override { return cItem(E_ITEM_REDSTONE_DUST, 1, 0); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockRedstoneOre.h b/src/Blocks/BlockRedstoneOre.h index 4b570ab73..9042d7cc6 100644 --- a/src/Blocks/BlockRedstoneOre.h +++ b/src/Blocks/BlockRedstoneOre.h @@ -17,31 +17,39 @@ public: using Super::Super; // Inherit constructor from base + + + + virtual bool OnUse( - cChunkInterface & a_ChunkInterface, - cWorldInterface & a_WorldInterface, - cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, + const Vector3i a_BlockPos, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ + const Vector3i a_CursorPos ) override { - Vector3i BlockPos{a_BlockX, a_BlockY, a_BlockZ}; - a_ChunkInterface.SetBlock(BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); + a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); return false; } + + + + virtual void OnDigging( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ + const Vector3i a_BlockPos ) override { - Vector3i BlockPos{a_BlockX, a_BlockY, a_BlockZ}; - a_ChunkInterface.SetBlock(BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); + a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); } + + + + virtual bool IsUseable() override { return true; @@ -61,6 +69,10 @@ public: using Super::Super; // Inherit constructor from base + + + + virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h index 25aa9b795..e0b748821 100644 --- a/src/Blocks/BlockRedstoneRepeater.h +++ b/src/Blocks/BlockRedstoneRepeater.h @@ -23,33 +23,63 @@ public: { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, ((a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}) + 0x04) & 0x0f)); + // Increment the delay setting: + a_ChunkInterface.SetBlockMeta(a_BlockPos, ((a_ChunkInterface.GetBlockMeta(a_BlockPos) + 0x04) & 0x0f)); return true; } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { UNUSED(a_ChunkInterface); - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual bool IsUseable(void) override { return true; } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY - 1, a_RelZ, BelowBlock, BelowBlockMeta); + a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { @@ -66,17 +96,29 @@ public: return false; } + + + + virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override { return cItem(E_ITEM_REDSTONE_REPEATER, 1, 0); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); return 11; } + + + + inline static Vector3i GetLeftCoordinateOffset(NIBBLETYPE a_Meta) { switch (a_Meta & E_META_REDSTONE_REPEATER_FACING_MASK) // We only want the direction (bottom) bits @@ -95,11 +137,18 @@ public: } } + + + inline static Vector3i GetFrontCoordinateOffset(NIBBLETYPE a_Meta) { return -GetRearCoordinateOffset(a_Meta); } + + + + inline static Vector3i GetRearCoordinateOffset(NIBBLETYPE a_Meta) { switch (a_Meta & E_META_REDSTONE_REPEATER_FACING_MASK) // We only want the direction (bottom) bits diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h index 370353882..86397d806 100644 --- a/src/Blocks/BlockSapling.h +++ b/src/Blocks/BlockSapling.h @@ -34,9 +34,9 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)); + return (a_RelPos.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelPos.addedY(-1))); } diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h index 5854f334c..b94b9f8f3 100644 --- a/src/Blocks/BlockSideways.h +++ b/src/Blocks/BlockSideways.h @@ -27,15 +27,17 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; NIBBLETYPE Meta = static_cast<NIBBLETYPE>(a_Player.GetEquippedItem().m_ItemDamage); - a_BlockMeta = BlockFaceToMetaData(a_BlockFace, Meta); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace, Meta); return true; } diff --git a/src/Blocks/BlockSignPost.h b/src/Blocks/BlockSignPost.h index 45fa7cad4..f493cb355 100644 --- a/src/Blocks/BlockSignPost.h +++ b/src/Blocks/BlockSignPost.h @@ -32,17 +32,21 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - BLOCKTYPE Type = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ); - + BLOCKTYPE Type = a_Chunk.GetBlock(a_RelPos.addedY(-1)); return ((Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type)); } + + + + + /** Converts the (player) rotation to placed-signpost block meta. */ static NIBBLETYPE RotationToMetaData(double a_Rotation) { a_Rotation += 180 + (180 / 16); // So it's not aligned with axis @@ -56,16 +60,28 @@ public: return (static_cast<char>(a_Rotation)) % 16; } + + + + virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override { return (a_Meta + 4) & 0x0f; } + + + + virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override { return (a_Meta + 12) & 0x0f; } + + + + virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override { // Mirrors signs over the XY plane (North-South Mirroring) @@ -75,6 +91,10 @@ public: return (a_Meta < 0x08) ? (0x08 - a_Meta) : (0x18 - a_Meta); } + + + + virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override { // Mirrors signs over the YZ plane (East-West Mirroring) @@ -84,6 +104,10 @@ public: return 0x0f - a_Meta; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h index bd9c0299a..c59dc6f06 100644 --- a/src/Blocks/BlockSlab.h +++ b/src/Blocks/BlockSlab.h @@ -44,9 +44,11 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { @@ -54,18 +56,18 @@ public: NIBBLETYPE Meta = static_cast<NIBBLETYPE>(a_Player.GetEquippedItem().m_ItemDamage); // Set the correct metadata based on player equipped item (i.e. a_BlockMeta not initialised yet) - switch (a_BlockFace) + switch (a_ClickedBlockFace) { case BLOCK_FACE_TOP: { // Bottom half slab block - a_BlockMeta = Meta & 0x7; + a_BlockMeta = Meta & 0x07; break; } case BLOCK_FACE_BOTTOM: { // Top half slab block - a_BlockMeta = Meta | 0x8; + a_BlockMeta = Meta | 0x08; break; } case BLOCK_FACE_EAST: @@ -73,15 +75,15 @@ public: case BLOCK_FACE_SOUTH: case BLOCK_FACE_WEST: { - if (a_CursorY > 7) + if (a_CursorPos.y > 7) { // Cursor at top half of block, place top slab - a_BlockMeta = Meta | 0x8; break; + a_BlockMeta = Meta | 0x08; break; } else { // Cursor at bottom half of block, place bottom slab - a_BlockMeta = Meta & 0x7; break; + a_BlockMeta = Meta & 0x07; break; } } case BLOCK_FACE_NONE: return false; @@ -89,10 +91,10 @@ public: // 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}))) + if (IsAnySlabType(a_ChunkInterface.GetBlock(a_PlacedBlockPos))) { a_BlockType = GetDoubleSlabType(m_BlockType); - a_BlockMeta = a_BlockMeta & 0x7; + a_BlockMeta = a_BlockMeta & 0x07; } return true; @@ -117,7 +119,13 @@ public: - virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override + virtual void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player.GetEquippedItem().m_ItemType != static_cast<short>(m_BlockType))) { @@ -125,7 +133,7 @@ public: } // Sends the slab back to the client. It's to refuse a doubleslab placement. */ - a_Player.GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_Player.GetWorld()->SendBlockTo(a_BlockPos, a_Player); } @@ -222,13 +230,13 @@ public: - virtual bool IsInsideBlock(Vector3d a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) override + virtual bool IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) override { - if (a_BlockMeta & 0x8) // top half + if (a_BlockMeta & 0x08) // top half { return true; } - return cBlockHandler::IsInsideBlock(a_Position, a_BlockType, a_BlockMeta); + return cBlockHandler::IsInsideBlock(a_Position, a_BlockMeta); } } ; @@ -236,7 +244,7 @@ public: -class cBlockDoubleSlabHandler : +class cBlockDoubleSlabHandler: public cBlockHandler { using Super = cBlockHandler; diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h index 4972e61fe..9b9ee85c0 100644 --- a/src/Blocks/BlockSnow.h +++ b/src/Blocks/BlockSnow.h @@ -10,30 +10,40 @@ class cBlockSnowHandler : public cBlockHandler { + using Super = cBlockHandler; + public: + enum { FullBlockMeta = 7 // Meta value of a full-height snow block }; - cBlockSnowHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockSnowHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; + // Check if incrementing existing snow height: BLOCKTYPE BlockBeforePlacement; NIBBLETYPE MetaBeforePlacement; - a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, BlockBeforePlacement, MetaBeforePlacement); - + a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockBeforePlacement, MetaBeforePlacement); if ((BlockBeforePlacement == E_BLOCK_SNOW) && (MetaBeforePlacement < FullBlockMeta)) { // Only increment if: @@ -45,16 +55,19 @@ public: // First time placement, check placement is valid a_BlockMeta = 0; - BLOCKTYPE BlockBelow; NIBBLETYPE MetaBelow; return ( - (a_BlockY > 0) && - a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY - 1, a_BlockZ}, BlockBelow, MetaBelow) && + (a_PlacedBlockPos.y > 0) && + a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos.addedY(-1), BlockBelow, MetaBelow) && CanBeOn(BlockBelow, MetaBelow) ); } + + + + virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override { if ((a_Player.GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < FullBlockMeta)) @@ -97,35 +110,47 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY > 0) + if (a_RelPos.y <= 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); - - return CanBeOn(BlockBelow, MetaBelow); + return false; } - - return false; + auto BelowPos = a_RelPos.addedY(-1); + auto BlockBelow = a_Chunk.GetBlock(BelowPos); + auto MetaBelow = a_Chunk.GetMeta(BelowPos); + return CanBeOn(BlockBelow, MetaBelow); } + + + + virtual bool DoesDropOnUnsuitable(void) override { return false; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); return 14; } - virtual bool IsInsideBlock(Vector3d a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) override + + + + + virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) override { - return a_Position.y < (cBlockInfo::GetBlockHeight(a_BlockType) * (a_BlockMeta & 0x07)); + return a_RelPosition.y < (cBlockInfo::GetBlockHeight(m_BlockType) * (a_BlockMeta & 0x07)); } + private: /** Returns true if snow can be placed on top of a block with the given type and meta. */ diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h index c9e36d535..d616f5d67 100644 --- a/src/Blocks/BlockStairs.h +++ b/src/Blocks/BlockStairs.h @@ -17,25 +17,27 @@ public: cBlockStairsHandler(BLOCKTYPE a_BlockType): Super(a_BlockType) { - } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { UNUSED(a_ChunkInterface); - UNUSED(a_BlockX); - UNUSED(a_BlockY); - UNUSED(a_BlockZ); - UNUSED(a_CursorX); - UNUSED(a_CursorZ); + UNUSED(a_PlacedBlockPos); + UNUSED(a_CursorPos); a_BlockType = m_BlockType; a_BlockMeta = RotationToMetaData(a_Player.GetYaw()); - switch (a_BlockFace) + switch (a_ClickedBlockFace) { case BLOCK_FACE_TOP: break; case BLOCK_FACE_BOTTOM: a_BlockMeta = a_BlockMeta | 0x4; break; // When placing onto a bottom face, always place an upside-down stairs block @@ -45,7 +47,7 @@ public: case BLOCK_FACE_WEST: { // When placing onto a sideways face, check cursor, if in top half, make it an upside-down stairs block - if (a_CursorY > 8) + if (a_CursorPos.y > 8) { a_BlockMeta |= 0x4; } @@ -56,6 +58,10 @@ public: return true; } + + + + static NIBBLETYPE RotationToMetaData(double a_Rotation) { a_Rotation += 90 + 45; // So its not aligned with axis @@ -81,12 +87,20 @@ public: } } + + + + virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override { // Toggle bit 3: return (a_Meta & 0x0b) | ((~a_Meta) & 0x04); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); @@ -114,12 +128,16 @@ public: } } + + + + /** EXCEPTION a.k.a. why is this removed: This collision-detection is actually more accurate than the client, but since the client itself sends inaccurate / sparse data, it's easier to just err on the side of the client and keep the two in sync by assuming that if a player hit ANY of the stair's bounding cube, it counts as the ground. */ #if 0 - bool IsInsideBlock(const Vector3d & a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) + bool IsInsideBlock(Vector3d a_RelPosition, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) { if (a_BlockMeta & 0x4) // upside down { @@ -127,19 +145,19 @@ public: } else if ((a_BlockMeta & 0x3) == 0) // tall side is east (+X) { - return a_Position.y < ((a_Position.x > 0.5) ? 1.0 : 0.5); + return (a_RelPosition.y < ((a_RelPosition.x > 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 1) // tall side is west (-X) { - return a_Position.y < ((a_Position.x < 0.5) ? 1.0 : 0.5); + return (a_RelPosition.y < ((a_RelPosition.x < 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 2) // tall side is south (+Z) { - return a_Position.y < ((a_Position.z > 0.5) ? 1.0 : 0.5); + return (a_RelPosition.y < ((a_RelPosition.z > 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 3) // tall side is north (-Z) { - return a_Position.y < ((a_Position.z < 0.5) ? 1.0 : 0.5); + return (a_RelPosition.y < ((a_RelPosition.z < 0.5) ? 1.0 : 0.5)); } return false; } diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h index bf0d7ce41..0e4b01c5a 100644 --- a/src/Blocks/BlockStems.h +++ b/src/Blocks/BlockStems.h @@ -36,9 +36,9 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND)); + return ((a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_FARMLAND)); } diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h index f45b312a8..fa153bd28 100644 --- a/src/Blocks/BlockSugarcane.h +++ b/src/Blocks/BlockSugarcane.h @@ -32,36 +32,32 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)) + switch (a_Chunk.GetBlock(a_RelPos.addedY(-1))) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_FARMLAND: case E_BLOCK_SAND: { - static const struct + static const Vector3i Coords[] = { - int x, z; - } Coords[] = - { - {-1, 0}, - { 1, 0}, - { 0, -1}, - { 0, 1}, + {-1, -1, 0}, + { 1, -1, 0}, + { 0, -1, -1}, + { 0, -1, 1}, } ; - a_RelY -= 1; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta)) + if (!a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[i], BlockType, BlockMeta)) { // Too close to the edge, cannot simulate return true; diff --git a/src/Blocks/BlockTNT.h b/src/Blocks/BlockTNT.h index d8b50335a..fafa289da 100644 --- a/src/Blocks/BlockTNT.h +++ b/src/Blocks/BlockTNT.h @@ -10,17 +10,34 @@ class cBlockTNTHandler : public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockTNTHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockTNTHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h index d09e9d496..4cf115efd 100644 --- a/src/Blocks/BlockTallGrass.h +++ b/src/Blocks/BlockTallGrass.h @@ -54,14 +54,14 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - if (a_RelY <= 0) + if (a_RelPos.y <= 0) { return false; } - BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ); + BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelPos.addedY(-1)); return IsBlockTypeOfDirt(BelowBlock); } diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index 93ca5e40d..e2a2dfcc9 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -8,7 +8,7 @@ -class cBlockTorchHandler : +class cBlockTorchHandler: public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>> { using Super = cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>>; @@ -20,39 +20,46 @@ public: { } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { - BLOCKTYPE Block; - NIBBLETYPE Meta; - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block - a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, Block, Meta); - - if (!CanBePlacedOn(Block, Meta, a_BlockFace)) // Try to preserve original direction + BLOCKTYPE ClickedBlockType; + NIBBLETYPE ClickedBlockMeta; + auto ClickedBlockPos = AddFaceDirection(a_PlacedBlockPos, a_ClickedBlockFace, true); + a_ChunkInterface.GetBlockTypeMeta(ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); + if (!CanBePlacedOn(ClickedBlockType, ClickedBlockMeta, a_ClickedBlockFace)) { - // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face - - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block - a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Set a_BlockFace to a valid direction which will be converted later to a metadata - if (a_BlockFace == BLOCK_FACE_NONE) + // Couldn't be placed on whatever face was clicked, last ditch resort - find another face + a_ClickedBlockFace = FindSuitableFace(a_ChunkInterface, a_PlacedBlockPos); // Set a_BlockFace to a valid direction which will be converted later to a metadata + if (a_ClickedBlockFace == BLOCK_FACE_NONE) { // No attachable face found - don't place the torch return false; } } - a_BlockType = m_BlockType; - a_BlockMeta = DirectionToMetaData(a_BlockFace); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); return true; } - inline static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction) + + + + + /** Converts the block face of the neighbor to which the torch is attached, to the torch block's meta. */ + inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) { - switch (a_Direction) + switch (a_NeighborBlockFace) { case BLOCK_FACE_BOTTOM: ASSERT(!"Shouldn't be getting this face"); return 0; case BLOCK_FACE_TOP: return E_META_TORCH_FLOOR; @@ -69,7 +76,12 @@ public: return 0x0; } - inline static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData) + + + + + /** Converts the torch block's meta to the block face of the neighbor to which the torch is attached. */ + inline static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) { switch (a_MetaData) { @@ -88,6 +100,11 @@ public: return BLOCK_FACE_TOP; } + + + + + /** Returns true if the torch can be placed on the specified block's face. */ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace) { switch (a_BlockType) @@ -115,7 +132,7 @@ public: case E_BLOCK_STONE_SLAB: case E_BLOCK_WOODEN_SLAB: { - // Toches can be placed on the top of these slabs only if the occupy the top half of the voxel + // Toches can be placed only on the top of top-half-slabs return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08)); } case E_BLOCK_OAK_WOOD_STAIRS: @@ -146,45 +163,52 @@ public: } } - /** Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure */ - static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + + + + + /** Returns a suitable neighbor's blockface to place the torch at the specified pos + Returns BLOCK_FACE_NONE on failure */ + static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, const Vector3i a_TorchPos) { - for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions + for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all faces { - eBlockFace Face = static_cast<eBlockFace>(i); - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, true); - BLOCKTYPE BlockInQuestion; - NIBBLETYPE BlockInQuestionMeta; - a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, BlockInQuestion, BlockInQuestionMeta); - - if (CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face)) + auto Face = static_cast<eBlockFace>(i); + auto NeighborPos = AddFaceDirection(a_TorchPos, Face, true); + BLOCKTYPE NeighborBlockType; + NIBBLETYPE NeighborBlockMeta; + a_ChunkInterface.GetBlockTypeMeta(NeighborPos, NeighborBlockType, NeighborBlockMeta); + if (CanBePlacedOn(NeighborBlockType, NeighborBlockMeta, Face)) { return Face; } - else - { - // Reset coords in preparation for next iteration - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, false); - } } return BLOCK_FACE_NONE; } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override - { - eBlockFace Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ)); - AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true); - BLOCKTYPE BlockInQuestion; - NIBBLETYPE BlockInQuestionMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockInQuestion, BlockInQuestionMeta)) + + + + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override + { + auto Face = MetaDataToBlockFace(a_Chunk.GetMeta(a_RelPos)); + auto NeighborRelPos = AddFaceDirection(a_RelPos, Face, true); + BLOCKTYPE NeighborBlockType; + NIBBLETYPE NeighborBlockMeta; + if (!a_Chunk.UnboundedRelGetBlock(NeighborRelPos, NeighborBlockType, NeighborBlockMeta)) { + // Neighbor in an unloaded chunk, bail out without changint this. return false; } - return CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face); + return CanBePlacedOn(NeighborBlockType, NeighborBlockMeta, Face); } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h index 0ad2c64f5..f0c821764 100644 --- a/src/Blocks/BlockTrapdoor.h +++ b/src/Blocks/BlockTrapdoor.h @@ -32,7 +32,14 @@ public: - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { if (m_BlockType == E_BLOCK_IRON_TRAPDOOR) { @@ -41,36 +48,56 @@ public: } // Flip the ON bit on / off using the XOR bitwise operation - NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}) ^ 0x04); - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); - a_WorldInterface.GetBroadcastManager().BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, { a_BlockX, a_BlockY, a_BlockZ }, 0, a_Player.GetClientHandle()); + NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x04); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); + a_WorldInterface.GetBroadcastManager().BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); return true; } - 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 void OnCancelRightClick( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace + ) override { UNUSED(a_ChunkInterface); - a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player); + a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } + + + + virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_BlockFace); + a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - if (a_CursorY > 7) + if (a_CursorPos.y > 7) { a_BlockMeta |= 0x8; } return true; } + + + + inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) @@ -90,6 +117,10 @@ public: UNREACHABLE("Unsupported block face"); } + + + + inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x3) @@ -106,6 +137,10 @@ public: } } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h index 797034ea0..766c0e404 100644 --- a/src/Blocks/BlockTripwireHook.h +++ b/src/Blocks/BlockTripwireHook.h @@ -24,14 +24,16 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { a_BlockType = m_BlockType; - a_BlockMeta = DirectionToMetadata(a_BlockFace); + a_BlockMeta = DirectionToMetadata(a_ClickedBlockFace); return true; } @@ -79,16 +81,17 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - NIBBLETYPE Meta; - a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta); - - AddFaceDirection(a_RelX, a_RelY, a_RelZ, MetadataToDirection(Meta), true); - BLOCKTYPE BlockIsOn; - a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn); - - return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn)); + auto Meta = a_Chunk.GetMeta(a_RelPos); + auto NeighborPos = AddFaceDirection(a_RelPos, MetadataToDirection(Meta), true); + if (!cChunkDef::IsValidHeight(NeighborPos.y)) + { + return false; + } + BLOCKTYPE NeighborBlockType; + a_Chunk.UnboundedRelGetBlockType(a_RelPos, NeighborBlockType); + return cBlockInfo::FullyOccupiesVoxel(NeighborBlockType); } diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h index f8328f046..2cf6e985c 100644 --- a/src/Blocks/BlockVine.h +++ b/src/Blocks/BlockVine.h @@ -23,23 +23,25 @@ public: virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { // TODO: Disallow placement where the vine doesn't attach to something properly BLOCKTYPE BlockType = 0; NIBBLETYPE BlockMeta; - a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, BlockType, BlockMeta); + a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockType, BlockMeta); if (BlockType == m_BlockType) { - a_BlockMeta = BlockMeta | DirectionToMetaData(a_BlockFace); + a_BlockMeta = BlockMeta | DirectionToMetaData(a_ClickedBlockFace); } else { - a_BlockMeta = DirectionToMetaData(a_BlockFace); + a_BlockMeta = DirectionToMetaData(a_ClickedBlockFace); } a_BlockType = m_BlockType; return true; diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h index 551107d88..87c0355a9 100644 --- a/src/Blocks/BlockWallSign.h +++ b/src/Blocks/BlockWallSign.h @@ -33,39 +33,45 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override + virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override { - int BlockX = (a_Chunk.GetPosX() * cChunkDef::Width) + a_RelX; - int BlockZ = (a_Chunk.GetPosZ() * cChunkDef::Width) + a_RelZ; - GetBlockCoordsBehindTheSign(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ), BlockX, BlockZ); - BLOCKTYPE Type = a_ChunkInterface.GetBlock({BlockX, a_RelY, BlockZ}); - - return ((Type == E_BLOCK_WALLSIGN) || (Type == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(Type)); + auto NeighborPos = a_RelPos + GetOffsetBehindTheSign(a_Chunk.GetMeta(a_RelPos)); + BLOCKTYPE NeighborType; + if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType)) + { + // The neighbor is not accessible (unloaded chunk), bail out without changing this + return true; + } + return ((NeighborType == E_BLOCK_WALLSIGN) || (NeighborType == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(NeighborType)); } - static void GetBlockCoordsBehindTheSign(NIBBLETYPE a_BlockMeta, int & a_BlockX, int & a_BlockZ) + /** Returns the offset from the sign coords to the block to which the wallsign is attached, based on the wallsign's block meta. + Asserts / returns a zero vector on wrong meta. */ + static Vector3i GetOffsetBehindTheSign(NIBBLETYPE a_BlockMeta) { switch (a_BlockMeta) { - case 2: a_BlockZ++; break; - case 3: a_BlockZ--; break; - case 4: a_BlockX++; break; - case 5: a_BlockX--; break; - default: break; + case 2: return Vector3i( 0, 0, 1); + case 3: return Vector3i( 0, 0, -1); + case 4: return Vector3i( 1, 0, 0); + case 5: return Vector3i(-1, 0, 0); } + ASSERT(!"Invalid wallsign block meta"); + return Vector3i(); } - static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction) + /** Converts the block face of the neighbor to which the wallsign is attached to the wallsign block's meta. */ + static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) { - switch (a_Direction) + switch (a_NeighborBlockFace) { case BLOCK_FACE_ZM: return 0x02; case BLOCK_FACE_ZP: return 0x03; diff --git a/src/Blocks/BlockWorkbench.h b/src/Blocks/BlockWorkbench.h index c5eb48657..608754158 100644 --- a/src/Blocks/BlockWorkbench.h +++ b/src/Blocks/BlockWorkbench.h @@ -12,24 +12,46 @@ class cBlockWorkbenchHandler: public cBlockHandler { + using Super = cBlockHandler; + public: - cBlockWorkbenchHandler(BLOCKTYPE a_BlockType) - : cBlockHandler(a_BlockType) + + cBlockWorkbenchHandler(BLOCKTYPE a_BlockType): + Super(a_BlockType) { } - virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + + + + + virtual bool OnUse( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cPlayer & a_Player, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos + ) override { - cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ); + cWindow * Window = new cCraftingWindow(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); a_Player.OpenWindow(*Window); return true; } + + + + virtual bool IsUseable(void) override { return true; } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); diff --git a/src/Blocks/Mixins.h b/src/Blocks/Mixins.h index cddbb4850..7e581c876 100644 --- a/src/Blocks/Mixins.h +++ b/src/Blocks/Mixins.h @@ -189,7 +189,8 @@ public: cYawRotator(BLOCKTYPE a_BlockType): Super(a_BlockType) - {} + { + } @@ -197,13 +198,14 @@ public: virtual bool GetPlacementBlockTypeMeta( cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + const Vector3i a_BlockPos, + eBlockFace a_BlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { NIBBLETYPE BaseMeta; - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, BaseMeta)) + if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockPos, a_BlockFace, a_CursorPos, a_BlockType, BaseMeta)) { return false; } @@ -259,25 +261,29 @@ class cPitchYawRotator: public cYawRotator<Base, BitMask, North, East, South, West> { using Super = cYawRotator<Base, BitMask, North, East, South, West>; + public: cPitchYawRotator(BLOCKTYPE a_BlockType): Super(a_BlockType) - {} + { + } virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, + cChunkInterface & a_ChunkInterface, + cPlayer & a_Player, + const Vector3i a_PlacedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta ) override { NIBBLETYPE BaseMeta; - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, BaseMeta)) + if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, BaseMeta)) { return false; } diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index 0967e2bb8..2a39ffbc2 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -60,6 +60,12 @@ public: /** Sends the block on those coords to the player */ virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer & a_Player) = 0; + /** Sends the block on those coords to the player */ + inline void SendBlockTo(const Vector3i a_BlockPos, cPlayer & a_Player) + { + SendBlockTo(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Player); + } + /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ virtual bool ForEachPlayer(cPlayerListCallback a_Callback) = 0; |