From c52f299e724bf893944553ac3aeedf7bf0a58241 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 2 Jan 2022 11:56:36 +0000 Subject: Handlers: update item and block handlers (#5371) + Resend blocks when server rejects placement because in a block * Fix chest handler not invoked, fixes #5367 * Fix comparator handler not invoked * Update some naming --- src/Blocks/BlockEnderChest.h | 40 ++++++ src/Blocks/BlockEnderchest.h | 44 ------- src/Blocks/BlockHandler.cpp | 42 +++---- src/Blocks/BlockRedstone.h | 70 ----------- src/Blocks/BlockRedstoneWire.h | 70 +++++++++++ src/Blocks/BlockSugarCane.h | 140 +++++++++++++++++++++ src/Blocks/BlockSugarcane.h | 140 --------------------- src/Blocks/BlockVine.h | 271 ----------------------------------------- src/Blocks/BlockVines.h | 271 +++++++++++++++++++++++++++++++++++++++++ src/Blocks/CMakeLists.txt | 8 +- 10 files changed, 546 insertions(+), 550 deletions(-) create mode 100644 src/Blocks/BlockEnderChest.h delete mode 100644 src/Blocks/BlockEnderchest.h delete mode 100644 src/Blocks/BlockRedstone.h create mode 100644 src/Blocks/BlockRedstoneWire.h create mode 100644 src/Blocks/BlockSugarCane.h delete mode 100644 src/Blocks/BlockSugarcane.h delete mode 100644 src/Blocks/BlockVine.h create mode 100644 src/Blocks/BlockVines.h (limited to 'src/Blocks') diff --git a/src/Blocks/BlockEnderChest.h b/src/Blocks/BlockEnderChest.h new file mode 100644 index 000000000..2e0da0f17 --- /dev/null +++ b/src/Blocks/BlockEnderChest.h @@ -0,0 +1,40 @@ + +#pragma once + +#include "Mixins.h" + + + + +class cBlockEnderChestHandler final : + public cYawRotator +{ + using Super = cYawRotator; + +public: + + using Super::Super; + +private: + + virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override + { + // Only drop something when mined with a pickaxe: + if ( + (a_Tool != nullptr) && + ItemCategory::IsPickaxe(a_Tool->m_ItemType) + ) + { + // Only drop self when mined with a silk-touch pickaxe: + if (a_Tool->m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0) + { + return cItem(E_BLOCK_ENDER_CHEST); + } + + return cItem(E_BLOCK_OBSIDIAN, 8); + } + + return {}; + } + +}; diff --git a/src/Blocks/BlockEnderchest.h b/src/Blocks/BlockEnderchest.h deleted file mode 100644 index aae16ccec..000000000 --- a/src/Blocks/BlockEnderchest.h +++ /dev/null @@ -1,44 +0,0 @@ - -#pragma once - -#include "Mixins.h" - - - - -class cBlockEnderchestHandler final : - public cYawRotator -{ - using Super = cYawRotator; - -public: - - using Super::Super; - -private: - - virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override - { - // Only drop something when mined with a pickaxe: - if ( - (a_Tool != nullptr) && - ItemCategory::IsPickaxe(a_Tool->m_ItemType) - ) - { - // Only drop self when mined with a silk-touch pickaxe: - if (a_Tool->m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0) - { - return cItem(E_BLOCK_ENDER_CHEST); - } - - return cItem(E_BLOCK_OBSIDIAN, 8); - } - - return {}; - } - -}; - - - - diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 2ce7904ab..937f800fd 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -33,7 +33,7 @@ #include "BlockDropSpenser.h" #include "BlockEnchantingTable.h" #include "BlockEndPortalFrame.h" -#include "BlockEnderchest.h" +#include "BlockEnderChest.h" #include "BlockEntity.h" #include "BlockFarmland.h" #include "BlockFence.h" @@ -75,7 +75,7 @@ #include "BlockPumpkin.h" #include "BlockQuartz.h" #include "BlockRail.h" -#include "BlockRedstone.h" +#include "BlockRedstoneWire.h" #include "BlockRedstoneLamp.h" #include "BlockRedstoneOre.h" #include "BlockRedstoneRepeater.h" @@ -91,14 +91,14 @@ #include "BlockStairs.h" #include "BlockStems.h" #include "BlockStone.h" -#include "BlockSugarcane.h" +#include "BlockSugarCane.h" #include "BlockTNT.h" #include "BlockTallGrass.h" #include "BlockTorch.h" #include "BlockTrapdoor.h" #include "BlockTripwire.h" #include "BlockTripwireHook.h" -#include "BlockVine.h" +#include "BlockVines.h" #include "BlockWallSign.h" #include "BlockWorkbench.h" @@ -215,14 +215,14 @@ namespace constexpr cBlockStairsHandler BlockBirchWoodStairsHandler (E_BLOCK_BIRCH_WOOD_STAIRS); constexpr cBlockGlazedTerracottaHandler BlockBlackGlazedTerracottaHandler (E_BLOCK_BLACK_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockBlackShulkerBoxHandler (E_BLOCK_BLACK_SHULKER_BOX); - constexpr cDefaultBlockHandler BlockBlockOfCoalHandler (E_BLOCK_BLOCK_OF_COAL); - constexpr cDefaultBlockHandler BlockBlockOfRedstoneHandler (E_BLOCK_BLOCK_OF_REDSTONE); + constexpr cDefaultBlockHandler BlockCoalBlockHandler (E_BLOCK_BLOCK_OF_COAL); + constexpr cDefaultBlockHandler BlockRedstoneBlockHandler (E_BLOCK_BLOCK_OF_REDSTONE); constexpr cBlockGlazedTerracottaHandler BlockBlueGlazedTerracottaHandler (E_BLOCK_BLUE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockBlueShulkerBoxHandler (E_BLOCK_BLUE_SHULKER_BOX); constexpr cDefaultBlockHandler BlockBoneBlockHandler (E_BLOCK_BONE_BLOCK); constexpr cBlockBookShelfHandler BlockBookcaseHandler (E_BLOCK_BOOKCASE); constexpr cBlockBrewingStandHandler BlockBrewingStandHandler (E_BLOCK_BREWING_STAND); - constexpr cDefaultBlockHandler BlockBrickHandler (E_BLOCK_BRICK); + constexpr cDefaultBlockHandler BlockBricksHandler (E_BLOCK_BRICK); constexpr cBlockStairsHandler BlockBrickStairsHandler (E_BLOCK_BRICK_STAIRS); constexpr cBlockGlazedTerracottaHandler BlockBrownGlazedTerracottaHandler (E_BLOCK_BROWN_GLAZED_TERRACOTTA); constexpr cBlockMushroomHandler BlockBrownMushroomHandler (E_BLOCK_BROWN_MUSHROOM); @@ -274,7 +274,7 @@ namespace constexpr cDefaultBlockHandler BlockEndPortalHandler (E_BLOCK_END_PORTAL); constexpr cDefaultBlockHandler BlockEndRodHandler (E_BLOCK_END_ROD); constexpr cDefaultBlockHandler BlockEndStoneHandler (E_BLOCK_END_STONE); - constexpr cBlockEnderchestHandler BlockEnderChestHandler (E_BLOCK_ENDER_CHEST); + constexpr cBlockEnderChestHandler BlockEnderChestHandler (E_BLOCK_ENDER_CHEST); constexpr cBlockFarmlandHandler BlockFarmlandHandler (E_BLOCK_FARMLAND); constexpr cBlockFenceHandler BlockFenceHandler (E_BLOCK_FENCE); constexpr cBlockFireHandler BlockFireHandler (E_BLOCK_FIRE); @@ -339,7 +339,7 @@ namespace constexpr cDefaultBlockHandler BlockMossyCobblestoneHandler (E_BLOCK_MOSSY_COBBLESTONE); constexpr cBlockMyceliumHandler BlockMyceliumHandler (E_BLOCK_MYCELIUM); constexpr cBlockFenceHandler BlockNetherBrickFenceHandler (E_BLOCK_NETHER_BRICK_FENCE); - constexpr cDefaultBlockHandler BlockNetherBrickHandler (E_BLOCK_NETHER_BRICK); + constexpr cDefaultBlockHandler BlockNetherBricksHandler (E_BLOCK_NETHER_BRICK); constexpr cBlockStairsHandler BlockNetherBrickStairsHandler (E_BLOCK_NETHER_BRICK_STAIRS); constexpr cBlockPortalHandler BlockNetherPortalHandler (E_BLOCK_NETHER_PORTAL); constexpr cDefaultOreHandler BlockNetherQuartzOreHandler (E_BLOCK_NETHER_QUARTZ_ORE); @@ -380,7 +380,7 @@ namespace constexpr cBlockRailHandler BlockRailHandler (E_BLOCK_RAIL); constexpr cBlockGlazedTerracottaHandler BlockRedGlazedTerracottaHandler (E_BLOCK_RED_GLAZED_TERRACOTTA); constexpr cBlockMushroomHandler BlockRedMushroomHandler (E_BLOCK_RED_MUSHROOM); - constexpr cDefaultBlockHandler BlockRedNetherBrickHandler (E_BLOCK_RED_NETHER_BRICK); + constexpr cDefaultBlockHandler BlockRedNetherBricksHandler (E_BLOCK_RED_NETHER_BRICK); constexpr cBlockFlowerHandler BlockRedRoseHandler (E_BLOCK_RED_ROSE); constexpr cDefaultBlockHandler BlockRedSandstoneHandler (E_BLOCK_RED_SANDSTONE); constexpr cBlockSlabHandler BlockRedSandstoneSlabHandler (E_BLOCK_RED_SANDSTONE_SLAB); @@ -393,7 +393,7 @@ namespace constexpr cBlockRedstoneRepeaterHandler BlockRedstoneRepeaterOnHandler (E_BLOCK_REDSTONE_REPEATER_ON); constexpr cBlockRedstoneTorchHandler BlockRedstoneTorchOffHandler (E_BLOCK_REDSTONE_TORCH_OFF); constexpr cBlockRedstoneTorchHandler BlockRedstoneTorchOnHandler (E_BLOCK_REDSTONE_TORCH_ON); - constexpr cBlockRedstoneHandler BlockRedstoneWireHandler (E_BLOCK_REDSTONE_WIRE); + constexpr cBlockRedstoneWireHandler BlockRedstoneWireHandler (E_BLOCK_REDSTONE_WIRE); constexpr cBlockCommandBlockHandler BlockRepeatingCommandBlockHandler (E_BLOCK_REPEATING_COMMAND_BLOCK); constexpr cBlockSandHandler BlockSandHandler (E_BLOCK_SAND); constexpr cDefaultBlockHandler BlockSandstoneHandler (E_BLOCK_SANDSTONE); @@ -425,15 +425,15 @@ namespace constexpr cBlockSlabHandler BlockStoneSlabHandler (E_BLOCK_STONE_SLAB); constexpr cDefaultBlockHandler BlockStructureBlockHandler (E_BLOCK_STRUCTURE_BLOCK); constexpr cDefaultBlockHandler BlockStructureVoidHandler (E_BLOCK_STRUCTURE_VOID); - constexpr cBlockSugarcaneHandler BlockSugarcaneHandler (E_BLOCK_SUGARCANE); + constexpr cBlockSugarCaneHandler BlockSugarCaneHandler (E_BLOCK_SUGARCANE); constexpr cBlockTallGrassHandler BlockTallGrassHandler (E_BLOCK_TALL_GRASS); - constexpr cBlockTNTHandler BlockTntHandler (E_BLOCK_TNT); + constexpr cBlockTNTHandler BlockTNTHandler (E_BLOCK_TNT); constexpr cBlockTorchHandler BlockTorchHandler (E_BLOCK_TORCH); constexpr cBlockTrapdoorHandler BlockTrapdoorHandler (E_BLOCK_TRAPDOOR); constexpr cBlockChestHandler BlockTrappedChestHandler (E_BLOCK_TRAPPED_CHEST); constexpr cBlockTripwireHandler BlockTripwireHandler (E_BLOCK_TRIPWIRE); constexpr cBlockTripwireHookHandler BlockTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK); - constexpr cBlockVineHandler BlockVinesHandler (E_BLOCK_VINES); + constexpr cBlockVinesHandler BlockVinesHandler (E_BLOCK_VINES); constexpr cBlockBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER); constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN); constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER); @@ -655,14 +655,14 @@ const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) case E_BLOCK_BIRCH_WOOD_STAIRS: return BlockBirchWoodStairsHandler; case E_BLOCK_BLACK_GLAZED_TERRACOTTA: return BlockBlackGlazedTerracottaHandler; case E_BLOCK_BLACK_SHULKER_BOX: return BlockBlackShulkerBoxHandler; - case E_BLOCK_BLOCK_OF_COAL: return BlockBlockOfCoalHandler; - case E_BLOCK_BLOCK_OF_REDSTONE: return BlockBlockOfRedstoneHandler; + case E_BLOCK_BLOCK_OF_COAL: return BlockCoalBlockHandler; + case E_BLOCK_BLOCK_OF_REDSTONE: return BlockRedstoneBlockHandler; case E_BLOCK_BLUE_GLAZED_TERRACOTTA: return BlockBlueGlazedTerracottaHandler; case E_BLOCK_BLUE_SHULKER_BOX: return BlockBlueShulkerBoxHandler; case E_BLOCK_BONE_BLOCK: return BlockBoneBlockHandler; case E_BLOCK_BOOKCASE: return BlockBookcaseHandler; case E_BLOCK_BREWING_STAND: return BlockBrewingStandHandler; - case E_BLOCK_BRICK: return BlockBrickHandler; + case E_BLOCK_BRICK: return BlockBricksHandler; case E_BLOCK_BRICK_STAIRS: return BlockBrickStairsHandler; case E_BLOCK_BROWN_GLAZED_TERRACOTTA: return BlockBrownGlazedTerracottaHandler; case E_BLOCK_BROWN_MUSHROOM: return BlockBrownMushroomHandler; @@ -779,7 +779,7 @@ const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) case E_BLOCK_MOSSY_COBBLESTONE: return BlockMossyCobblestoneHandler; case E_BLOCK_MYCELIUM: return BlockMyceliumHandler; case E_BLOCK_NETHERRACK: return BlockNetherrackHandler; - case E_BLOCK_NETHER_BRICK: return BlockNetherBrickHandler; + case E_BLOCK_NETHER_BRICK: return BlockNetherBricksHandler; case E_BLOCK_NETHER_BRICK_FENCE: return BlockNetherBrickFenceHandler; case E_BLOCK_NETHER_BRICK_STAIRS: return BlockNetherBrickStairsHandler; case E_BLOCK_NETHER_PORTAL: return BlockNetherPortalHandler; @@ -829,7 +829,7 @@ const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) case E_BLOCK_REDSTONE_WIRE: return BlockRedstoneWireHandler; case E_BLOCK_RED_GLAZED_TERRACOTTA: return BlockRedGlazedTerracottaHandler; case E_BLOCK_RED_MUSHROOM: return BlockRedMushroomHandler; - case E_BLOCK_RED_NETHER_BRICK: return BlockRedNetherBrickHandler; + case E_BLOCK_RED_NETHER_BRICK: return BlockRedNetherBricksHandler; case E_BLOCK_RED_ROSE: return BlockRedRoseHandler; case E_BLOCK_RED_SANDSTONE: return BlockRedSandstoneHandler; case E_BLOCK_RED_SANDSTONE_SLAB: return BlockRedSandstoneSlabHandler; @@ -867,9 +867,9 @@ const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) case E_BLOCK_STONE_SLAB: return BlockStoneSlabHandler; case E_BLOCK_STRUCTURE_BLOCK: return BlockStructureBlockHandler; case E_BLOCK_STRUCTURE_VOID: return BlockStructureVoidHandler; - case E_BLOCK_SUGARCANE: return BlockSugarcaneHandler; + case E_BLOCK_SUGARCANE: return BlockSugarCaneHandler; case E_BLOCK_TALL_GRASS: return BlockTallGrassHandler; - case E_BLOCK_TNT: return BlockTntHandler; + case E_BLOCK_TNT: return BlockTNTHandler; case E_BLOCK_TORCH: return BlockTorchHandler; case E_BLOCK_TRAPDOOR: return BlockTrapdoorHandler; case E_BLOCK_TRAPPED_CHEST: return BlockTrappedChestHandler; diff --git a/src/Blocks/BlockRedstone.h b/src/Blocks/BlockRedstone.h deleted file mode 100644 index d77ff151a..000000000 --- a/src/Blocks/BlockRedstone.h +++ /dev/null @@ -1,70 +0,0 @@ - -#pragma once - -#include "BlockHandler.h" -#include "BlockSlab.h" - - - - - -class cBlockRedstoneHandler final : - public cBlockHandler -{ - using Super = cBlockHandler; - -public: - - using Super::Super; - -private: - - virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override - { - if (a_Position.y <= 0) - { - return false; - } - - BLOCKTYPE BelowBlock; - NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_Position.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(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override - { - return cItem(E_ITEM_REDSTONE_DUST, 1, 0); - } - - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override - { - UNUSED(a_Meta); - return 0; - } -} ; - - - - diff --git a/src/Blocks/BlockRedstoneWire.h b/src/Blocks/BlockRedstoneWire.h new file mode 100644 index 000000000..3976afa90 --- /dev/null +++ b/src/Blocks/BlockRedstoneWire.h @@ -0,0 +1,70 @@ + +#pragma once + +#include "BlockHandler.h" +#include "BlockSlab.h" + + + + + +class cBlockRedstoneWireHandler final : + public cBlockHandler +{ + using Super = cBlockHandler; + +public: + + using Super::Super; + +private: + + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override + { + if (a_Position.y <= 0) + { + return false; + } + + BLOCKTYPE BelowBlock; + NIBBLETYPE BelowBlockMeta; + a_Chunk.GetBlockTypeMeta(a_Position.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(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override + { + return cItem(E_ITEM_REDSTONE_DUST, 1, 0); + } + + + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override + { + UNUSED(a_Meta); + return 0; + } +} ; + + + + diff --git a/src/Blocks/BlockSugarCane.h b/src/Blocks/BlockSugarCane.h new file mode 100644 index 000000000..cffe667e5 --- /dev/null +++ b/src/Blocks/BlockSugarCane.h @@ -0,0 +1,140 @@ + +#pragma once + +#include "BlockPlant.h" + + + + + +class cBlockSugarCaneHandler final : + public cBlockPlant +{ + using Super = cBlockPlant; + +public: + + using Super::Super; + +private: + + virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override + { + return cItem(E_ITEM_SUGARCANE, 1, 0); + } + + + + + + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override + { + if (a_Position.y <= 0) + { + return false; + } + + switch (a_Chunk.GetBlock(a_Position.addedY(-1))) + { + case E_BLOCK_DIRT: + case E_BLOCK_GRASS: + case E_BLOCK_FARMLAND: + case E_BLOCK_SAND: + { + static const Vector3i Coords[] = + { + {-1, -1, 0}, + { 1, -1, 0}, + { 0, -1, -1}, + { 0, -1, 1}, + } ; + for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) + { + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta)) + { + // Too close to the edge, cannot simulate + return true; + } + if (IsBlockWater(BlockType) || (BlockType == E_BLOCK_FROSTED_ICE)) + { + return true; + } + } // for i - Coords[] + // Not directly neighboring a water block + return false; + } + case E_BLOCK_SUGARCANE: + { + return true; + } + } + return false; + } + + + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override + { + UNUSED(a_Meta); + return 7; + } + + + + + + virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override + { + // Check the total height of the sugarcane blocks here: + int top = a_RelPos.y + 1; + while ( + (top < cChunkDef::Height) && + (a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_SUGARCANE) + ) + { + ++top; + } + int bottom = a_RelPos.y - 1; + while ( + (bottom > 0) && + (a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_SUGARCANE) + ) + { + --bottom; + } + + // Grow by at most a_NumStages, but no more than max height: + auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top - bottom)); + Vector3i topPos(a_RelPos.x, top, a_RelPos.z); + for (int i = 0; i < toGrow; i++) + { + if (a_Chunk.GetBlock(topPos.addedY(i)) == E_BLOCK_AIR) + { + a_Chunk.SetBlock(topPos.addedY(i), E_BLOCK_SUGARCANE, 0); + } + else + { + return i; + } + } // for i + return toGrow; + } + + virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override + { + // Only allow growing if there's an air block above: + if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR)) + { + return Super::CanGrow(a_Chunk, a_RelPos); + } + return paStay; + } +} ; + + + + diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h deleted file mode 100644 index bf5ae5e73..000000000 --- a/src/Blocks/BlockSugarcane.h +++ /dev/null @@ -1,140 +0,0 @@ - -#pragma once - -#include "BlockPlant.h" - - - - - -class cBlockSugarcaneHandler final : - public cBlockPlant -{ - using Super = cBlockPlant; - -public: - - using Super::Super; - -private: - - virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override - { - return cItem(E_ITEM_SUGARCANE, 1, 0); - } - - - - - - virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override - { - if (a_Position.y <= 0) - { - return false; - } - - switch (a_Chunk.GetBlock(a_Position.addedY(-1))) - { - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_FARMLAND: - case E_BLOCK_SAND: - { - static const Vector3i Coords[] = - { - {-1, -1, 0}, - { 1, -1, 0}, - { 0, -1, -1}, - { 0, -1, 1}, - } ; - for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta)) - { - // Too close to the edge, cannot simulate - return true; - } - if (IsBlockWater(BlockType) || (BlockType == E_BLOCK_FROSTED_ICE)) - { - return true; - } - } // for i - Coords[] - // Not directly neighboring a water block - return false; - } - case E_BLOCK_SUGARCANE: - { - return true; - } - } - return false; - } - - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override - { - UNUSED(a_Meta); - return 7; - } - - - - - - virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override - { - // Check the total height of the sugarcane blocks here: - int top = a_RelPos.y + 1; - while ( - (top < cChunkDef::Height) && - (a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_SUGARCANE) - ) - { - ++top; - } - int bottom = a_RelPos.y - 1; - while ( - (bottom > 0) && - (a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_SUGARCANE) - ) - { - --bottom; - } - - // Grow by at most a_NumStages, but no more than max height: - auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top - bottom)); - Vector3i topPos(a_RelPos.x, top, a_RelPos.z); - for (int i = 0; i < toGrow; i++) - { - if (a_Chunk.GetBlock(topPos.addedY(i)) == E_BLOCK_AIR) - { - a_Chunk.SetBlock(topPos.addedY(i), E_BLOCK_SUGARCANE, 0); - } - else - { - return i; - } - } // for i - return toGrow; - } - - virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override - { - // Only allow growing if there's an air block above: - if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR)) - { - return Super::CanGrow(a_Chunk, a_RelPos); - } - return paStay; - } -} ; - - - - diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h deleted file mode 100644 index da4d6dfc3..000000000 --- a/src/Blocks/BlockVine.h +++ /dev/null @@ -1,271 +0,0 @@ -#pragma once - -#include "BlockHandler.h" - - - - - -class cBlockVineHandler final : - public cBlockHandler -{ - using Super = cBlockHandler; - -public: - - using Super::Super; - -private: - - static const NIBBLETYPE VINE_LOST_SUPPORT = 16; - static const NIBBLETYPE VINE_UNCHANGED = 17; - - - virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override - { - return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT; - } - - - virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override - { - // Only drops self when using shears, otherwise drops nothing: - if ((a_Tool == nullptr) || (a_Tool->m_ItemType != E_ITEM_SHEARS)) - { - return {}; - } - return cItem(E_BLOCK_VINES, 1, 0); - } - - - - - - static char MetaDataToDirection(NIBBLETYPE a_MetaData) - { - switch (a_MetaData) - { - case 0x1: return BLOCK_FACE_NORTH; - case 0x4: return BLOCK_FACE_SOUTH; - case 0x8: return BLOCK_FACE_WEST; - case 0x2: return BLOCK_FACE_EAST; - default: return BLOCK_FACE_TOP; - } - } - - - - - - /** Returns true if the specified block type is good for vines to attach to */ - static bool IsBlockAttachable(BLOCKTYPE a_BlockType) - { - switch (a_BlockType) - { - case E_BLOCK_CHEST: - case E_BLOCK_ENDER_CHEST: - case E_BLOCK_GLASS: - case E_BLOCK_PISTON: - case E_BLOCK_PISTON_EXTENSION: - case E_BLOCK_REDSTONE_REPEATER_OFF: - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_STAINED_GLASS: - case E_BLOCK_STICKY_PISTON: - case E_BLOCK_TRAPPED_CHEST: - { - // You can't attach a vine to this solid blocks. - return false; - } - default: - { - return cBlockInfo::IsSolid(a_BlockType); - } - } - } - - - - - - /** Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current vine meta. - Returns special values for a vine that can continue to exist unchanged, or must die completely. */ - static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta) - { - static const struct - { - int x, z; - NIBBLETYPE Bit; - } Coords[] = - { - { 0, 1, 1}, // south, ZP - {-1, 0, 2}, // west, XM - { 0, -1, 4}, // north, ZM - { 1, 0, 8}, // east, XP - } ; - - NIBBLETYPE MaxMeta = 0; - for (auto & Coord : Coords) - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - auto checkPos = a_Position.addedXZ(Coord.x, Coord.z); - if ( - a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) && - IsBlockAttachable(BlockType) - ) - { - MaxMeta |= Coord.Bit; - } - } - - // Check if vine above us, add its meta to MaxMeta: - if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES)) - { - MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1)); - } - - NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal. - if (Common != a_CurrentMeta) - { - bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1))); - if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine. - { - return VINE_LOST_SUPPORT; - } - - return Common; - } - - return VINE_UNCHANGED; - } - - - - - - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override - { - a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) - { - - const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos); - const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position)); - - if (MaxMeta == VINE_UNCHANGED) - { - return false; - } - - // There is a neighbor missing, need to update the meta or even destroy the block. - - if (MaxMeta == VINE_LOST_SUPPORT) - { - // The vine just lost all its support, destroy the block: - a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0); - } - else - { - // It lost some of its support, set it to what remains (SetBlock to notify neighbors): - a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta); - } - - return false; - }); - } - - - - - - virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override - { - return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType); - } - - - - - - virtual void OnUpdate( - cChunkInterface & a_ChunkInterface, - cWorldInterface & a_WorldInterface, - cBlockPluginInterface & a_PluginInterface, - cChunk & a_Chunk, - const Vector3i a_RelPos - ) const override - { - UNUSED(a_ChunkInterface); - UNUSED(a_WorldInterface); - - // Vine cannot grow down if at the bottom: - auto GrowPos = a_RelPos.addedY(-1); - if (!cChunkDef::IsValidHeight(GrowPos.y)) - { - return; - } - - // Grow one block down, if possible: - BLOCKTYPE Block; - a_Chunk.UnboundedRelGetBlockType(GrowPos, Block); - if (Block == E_BLOCK_AIR) - { - auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos); - if (!a_PluginInterface.CallHookBlockSpread(WorldPos.x, WorldPos.y, WorldPos.z, ssVineSpread)) - { - a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos)); - } - } - } - - - - - - virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override - { - return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right - } - - - - - - virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override - { - return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left - } - - - - - - virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override - { - // Bits 2 and 4 stay, bits 1 and 3 swap - return static_cast((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2)); - } - - - - - - virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override - { - // Bits 1 and 3 stay, bits 2 and 4 swap - return static_cast((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2)); - } - - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override - { - UNUSED(a_Meta); - return 7; - } -} ; - - - - diff --git a/src/Blocks/BlockVines.h b/src/Blocks/BlockVines.h new file mode 100644 index 000000000..d6eccd552 --- /dev/null +++ b/src/Blocks/BlockVines.h @@ -0,0 +1,271 @@ +#pragma once + +#include "BlockHandler.h" + + + + + +class cBlockVinesHandler final : + public cBlockHandler +{ + using Super = cBlockHandler; + +public: + + using Super::Super; + +private: + + static const NIBBLETYPE VINE_LOST_SUPPORT = 16; + static const NIBBLETYPE VINE_UNCHANGED = 17; + + + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override + { + return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT; + } + + + virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override + { + // Only drops self when using shears, otherwise drops nothing: + if ((a_Tool == nullptr) || (a_Tool->m_ItemType != E_ITEM_SHEARS)) + { + return {}; + } + return cItem(E_BLOCK_VINES, 1, 0); + } + + + + + + static char MetaDataToDirection(NIBBLETYPE a_MetaData) + { + switch (a_MetaData) + { + case 0x1: return BLOCK_FACE_NORTH; + case 0x4: return BLOCK_FACE_SOUTH; + case 0x8: return BLOCK_FACE_WEST; + case 0x2: return BLOCK_FACE_EAST; + default: return BLOCK_FACE_TOP; + } + } + + + + + + /** Returns true if the specified block type is good for vines to attach to */ + static bool IsBlockAttachable(BLOCKTYPE a_BlockType) + { + switch (a_BlockType) + { + case E_BLOCK_CHEST: + case E_BLOCK_ENDER_CHEST: + case E_BLOCK_GLASS: + case E_BLOCK_PISTON: + case E_BLOCK_PISTON_EXTENSION: + case E_BLOCK_REDSTONE_REPEATER_OFF: + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_STAINED_GLASS: + case E_BLOCK_STICKY_PISTON: + case E_BLOCK_TRAPPED_CHEST: + { + // You can't attach a vine to this solid blocks. + return false; + } + default: + { + return cBlockInfo::IsSolid(a_BlockType); + } + } + } + + + + + + /** Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current vine meta. + Returns special values for a vine that can continue to exist unchanged, or must die completely. */ + static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta) + { + static const struct + { + int x, z; + NIBBLETYPE Bit; + } Coords[] = + { + { 0, 1, 1}, // south, ZP + {-1, 0, 2}, // west, XM + { 0, -1, 4}, // north, ZM + { 1, 0, 8}, // east, XP + } ; + + NIBBLETYPE MaxMeta = 0; + for (auto & Coord : Coords) + { + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + auto checkPos = a_Position.addedXZ(Coord.x, Coord.z); + if ( + a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) && + IsBlockAttachable(BlockType) + ) + { + MaxMeta |= Coord.Bit; + } + } + + // Check if vine above us, add its meta to MaxMeta: + if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES)) + { + MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1)); + } + + NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal. + if (Common != a_CurrentMeta) + { + bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1))); + if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine. + { + return VINE_LOST_SUPPORT; + } + + return Common; + } + + return VINE_UNCHANGED; + } + + + + + + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override + { + a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) + { + + const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos); + const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position)); + + if (MaxMeta == VINE_UNCHANGED) + { + return false; + } + + // There is a neighbor missing, need to update the meta or even destroy the block. + + if (MaxMeta == VINE_LOST_SUPPORT) + { + // The vine just lost all its support, destroy the block: + a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0); + } + else + { + // It lost some of its support, set it to what remains (SetBlock to notify neighbors): + a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta); + } + + return false; + }); + } + + + + + + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override + { + return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType); + } + + + + + + virtual void OnUpdate( + cChunkInterface & a_ChunkInterface, + cWorldInterface & a_WorldInterface, + cBlockPluginInterface & a_PluginInterface, + cChunk & a_Chunk, + const Vector3i a_RelPos + ) const override + { + UNUSED(a_ChunkInterface); + UNUSED(a_WorldInterface); + + // Vine cannot grow down if at the bottom: + auto GrowPos = a_RelPos.addedY(-1); + if (!cChunkDef::IsValidHeight(GrowPos.y)) + { + return; + } + + // Grow one block down, if possible: + BLOCKTYPE Block; + a_Chunk.UnboundedRelGetBlockType(GrowPos, Block); + if (Block == E_BLOCK_AIR) + { + auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos); + if (!a_PluginInterface.CallHookBlockSpread(WorldPos.x, WorldPos.y, WorldPos.z, ssVineSpread)) + { + a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos)); + } + } + } + + + + + + virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override + { + return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right + } + + + + + + virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override + { + return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left + } + + + + + + virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override + { + // Bits 2 and 4 stay, bits 1 and 3 swap + return static_cast((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2)); + } + + + + + + virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override + { + // Bits 1 and 3 stay, bits 2 and 4 swap + return static_cast((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2)); + } + + + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override + { + UNUSED(a_Meta); + return 7; + } +} ; + + + + diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt index f69350c30..a7dd7b675 100644 --- a/src/Blocks/CMakeLists.txt +++ b/src/Blocks/CMakeLists.txt @@ -34,7 +34,7 @@ target_sources( BlockDoor.h BlockDropSpenser.h BlockEnchantingTable.h - BlockEnderchest.h + BlockEnderChest.h BlockEndPortalFrame.h BlockEntity.h BlockFarmland.h @@ -80,7 +80,7 @@ target_sources( BlockPumpkin.h BlockQuartz.h BlockRail.h - BlockRedstone.h + BlockRedstoneWire.h BlockRedstoneLamp.h BlockRedstoneOre.h BlockRedstoneRepeater.h @@ -96,14 +96,14 @@ target_sources( BlockStairs.h BlockStems.h BlockStone.h - BlockSugarcane.h + BlockSugarCane.h BlockTNT.h BlockTallGrass.h BlockTorch.h BlockTrapdoor.h BlockTripwire.h BlockTripwireHook.h - BlockVine.h + BlockVines.h BlockWallSign.h BlockWorkbench.h BroadcastInterface.h -- cgit v1.2.3