diff --git a/src/Blocks/BlockGlowstone.h b/src/Blocks/BlockGlowstone.h index d43581a4d..930509e0a 100644 --- a/src/Blocks/BlockGlowstone.h +++ b/src/Blocks/BlockGlowstone.h @@ -6,7 +6,6 @@ - class cBlockGlowstoneHandler : public cBlockHandler { @@ -25,8 +24,10 @@ private: } else { - // TODO: Handle the Fortune enchantment here - return cItem(E_ITEM_GLOWSTONE_DUST, GetRandomProvider().RandInt(2, 4), 0); + unsigned int DropNum = GetRandomProvider().RandInt(2, 4 + ToolFortuneLevel(a_Tool)); + // cap the dropnum to the max amount of 4 + DropNum = std::min(DropNum, 4); + return cItem(E_ITEM_GLOWSTONE_DUST, DropNum, 0); } } diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 67cef6cd5..4272bc607 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -649,6 +649,22 @@ bool cBlockHandler::ToolHasSilkTouch(const cItem * a_Tool) +unsigned int cBlockHandler::ToolFortuneLevel(const cItem * a_Tool) +{ + if (a_Tool != nullptr) + { + return a_Tool->m_Enchantments.GetLevel(cEnchantments::enchFortune); + } + else // Not a tool + { + return 0; + } +} + + + + + const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) { // Switch on the block type, as an enumeration diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index 447fc7dc6..8d595cc4a 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -230,6 +230,10 @@ public: Helper used in many ConvertToPickups() implementations. */ static bool ToolHasSilkTouch(const cItem * a_Tool); + /** Returns the fortune level of a tool, if it is a valid tool. + Can be used in ConvertToPickups() implementations. */ + static unsigned int ToolFortuneLevel(const cItem * a_Tool); + // Gets the blockhandler for the given block type. static const cBlockHandler & For(BLOCKTYPE a_BlockType); diff --git a/src/Blocks/BlockOre.h b/src/Blocks/BlockOre.h index e329a5781..6c01a6a27 100644 --- a/src/Blocks/BlockOre.h +++ b/src/Blocks/BlockOre.h @@ -3,10 +3,6 @@ #include "BlockHandler.h" - - - - class cBlockOreHandler: public cBlockHandler { @@ -31,17 +27,20 @@ private: } } - // TODO: Handle the Fortune enchantment here auto & random = GetRandomProvider(); + const unsigned int FortuneLevel = ToolFortuneLevel(a_Tool); + // Clamp to 10 to prevent server crash if thing are mined with extremely high level fortune pick + const unsigned int DropMult = std::clamp(FloorC(random.RandReal(FortuneLevel + 2.0)), 1, 10); + switch (m_BlockType) { - case E_BLOCK_LAPIS_ORE: return cItem(E_ITEM_DYE, random.RandInt(4, 8), 4); - case E_BLOCK_REDSTONE_ORE: return cItem(E_ITEM_REDSTONE_DUST, random.RandInt(4, 5), 0); - case E_BLOCK_REDSTONE_ORE_GLOWING: return cItem(E_ITEM_REDSTONE_DUST, random.RandInt(4, 5), 0); - case E_BLOCK_DIAMOND_ORE: return cItem(E_ITEM_DIAMOND); - case E_BLOCK_EMERALD_ORE: return cItem(E_ITEM_EMERALD); - case E_BLOCK_COAL_ORE: return cItem(E_ITEM_COAL); - case E_BLOCK_NETHER_QUARTZ_ORE: return cItem(E_ITEM_NETHER_QUARTZ); + case E_BLOCK_LAPIS_ORE: return cItem(E_ITEM_DYE, DropMult * random.RandInt(4, 9), 4); + case E_BLOCK_REDSTONE_ORE: // handled by next case (glowing redstone), no dropMult + case E_BLOCK_REDSTONE_ORE_GLOWING: return cItem(E_ITEM_REDSTONE_DUST, random.RandInt(4, 5 + FortuneLevel), 0); + case E_BLOCK_DIAMOND_ORE: return cItem(E_ITEM_DIAMOND, DropMult); + case E_BLOCK_EMERALD_ORE: return cItem(E_ITEM_EMERALD, DropMult); + case E_BLOCK_COAL_ORE: return cItem(E_ITEM_COAL, DropMult); + case E_BLOCK_NETHER_QUARTZ_ORE: return cItem(E_ITEM_NETHER_QUARTZ, DropMult); case E_BLOCK_CLAY: return cItem(E_ITEM_CLAY, 4); default: { diff --git a/src/Blocks/BlockSeaLantern.h b/src/Blocks/BlockSeaLantern.h index c24476e0b..1fab10a11 100644 --- a/src/Blocks/BlockSeaLantern.h +++ b/src/Blocks/BlockSeaLantern.h @@ -6,7 +6,6 @@ - class cBlockSeaLanternHandler : public cBlockHandler { @@ -20,8 +19,18 @@ private: virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) const override { - // Reset meta to 0 - // TODO: Handle the Fortune enchantment - return cItem(E_ITEM_PRISMARINE_CRYSTALS, GetRandomProvider().RandInt(2, 3), 0); + // Drop self only when using silk-touch: + if (ToolHasSilkTouch(a_Tool)) + { + return cItem(E_BLOCK_SEA_LANTERN, 1, 0); + } + else + { + unsigned int DropNum = GetRandomProvider().RandInt(2, 3 + ToolFortuneLevel(a_Tool)); + // cap the dropnum to the max amount of 5 + DropNum = std::min(DropNum, 5); + // Reset meta to 0 + return cItem(E_ITEM_PRISMARINE_CRYSTALS, DropNum, 0); + } } } ;