diff options
Diffstat (limited to 'src/UI/SlotArea.cpp')
-rw-r--r-- | src/UI/SlotArea.cpp | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp index 1450294a4..bb597b2c9 100644 --- a/src/UI/SlotArea.cpp +++ b/src/UI/SlotArea.cpp @@ -1678,25 +1678,59 @@ void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player) { cItem Item = *GetSlot(0, a_Player); - if (cItem::IsEnchantable(Item.m_ItemType) && Item.m_Enchantments.IsEmpty()) + if (!cItem::IsEnchantable(Item.m_ItemType) || !Item.m_Enchantments.IsEmpty()) { - int Bookshelves = std::min(GetBookshelvesCount(*a_Player.GetWorld()), 15); + return; + } - auto & Random = GetRandomProvider(); - int Base = (Random.RandInt(1, 8) + (Bookshelves / 2) + Random.RandInt(0, Bookshelves)); - int TopSlot = std::max(Base / 3, 1); - int MiddleSlot = (Base * 2) / 3 + 1; - int BottomSlot = std::max(Base, Bookshelves * 2); + // Pseudocode found at: https://minecraft.gamepedia.com/Enchanting_mechanics + const auto Bookshelves = std::min(GetBookshelvesCount(*a_Player.GetWorld()), 15U); - m_ParentWindow.SetProperty(0, static_cast<short>(TopSlot), a_Player); - m_ParentWindow.SetProperty(1, static_cast<short>(MiddleSlot), a_Player); - m_ParentWindow.SetProperty(2, static_cast<short>(BottomSlot), a_Player); - } - else + // A PRNG initialised using the player's enchantment seed. + auto Random = a_Player.GetEnchantmentRandomProvider(); + + // Calculate the levels for the offered enchantment options: + const auto Base = (Random.RandInt(1U, 8U) + (Bookshelves / 2) + Random.RandInt(0U, Bookshelves)); + const std::array<unsigned int, 3> OptionLevels { - m_ParentWindow.SetProperty(0, 0, a_Player); - m_ParentWindow.SetProperty(1, 0, a_Player); - m_ParentWindow.SetProperty(2, 0, a_Player); + std::max(Base / 3, 1U), + (Base * 2) / 3 + 1, + std::max(Base, Bookshelves * 2) + }; + + // Properties set according to: https://wiki.vg/Protocol#Window_Property + // Fake a "seed" for the client to draw Standard Galactic Alphabet glyphs: + m_ParentWindow.SetProperty(3, Random.RandInt<short>(), a_Player); + + // Calculate an enchanting possibility for each option (top, middle and bottom) and send details to window: + for (short i = 0; i != OptionLevels.size(); i++) + { + // A copy of the item. + cItem EnchantedItem = Item.CopyOne(); + + // Enchant based on the number of levels: + EnchantedItem.EnchantByXPLevels(OptionLevels[i], Random); + + LOGD("Generated enchanted item %d with enchantments: %s", i, EnchantedItem.m_Enchantments.ToString()); + + // Send the level requirement for the enchantment option: + m_ParentWindow.SetProperty(i, static_cast<short>(OptionLevels[i]), a_Player); + + // Get the first enchantment ID, which must exist: + ASSERT(EnchantedItem.m_Enchantments.begin() != EnchantedItem.m_Enchantments.end()); + const short EnchantmentID = static_cast<short>(EnchantedItem.m_Enchantments.begin()->first); + + // Send the enchantment ID of the first enchantment on our item: + m_ParentWindow.SetProperty(4 + i, EnchantmentID, a_Player); + + const short EnchantmentLevel = static_cast<short>(EnchantedItem.m_Enchantments.GetLevel(EnchantmentID)); + ASSERT(EnchantmentLevel > 0); + + // Send the level for the first enchantment on our item: + m_ParentWindow.SetProperty(7 + i, EnchantmentLevel, a_Player); + + // Store the item we've enchanted as an option to be retrieved later: + m_EnchantedItemOptions[i] = std::move(EnchantedItem); } } @@ -1704,9 +1738,8 @@ void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player) -int cSlotAreaEnchanting::GetBookshelvesCount(cWorld & a_World) +unsigned cSlotAreaEnchanting::GetBookshelvesCount(cWorld & a_World) { - int Bookshelves = 0; cBlockArea Area; Area.Read(a_World, m_BlockPos - Vector3i(2, 0, 2), m_BlockPos + Vector3i(2, 1, 2)); @@ -1751,6 +1784,8 @@ int cSlotAreaEnchanting::GetBookshelvesCount(cWorld & a_World) { 1, 1, 0, 1, 1, 1 }, // Bookcase at {1, 1, 0}, air at {1, 1, 1} }; + unsigned Bookshelves = 0; + for (size_t i = 0; i < ARRAYCOUNT(CheckCoords); i++) { if ( @@ -1769,6 +1804,16 @@ int cSlotAreaEnchanting::GetBookshelvesCount(cWorld & a_World) +cItem cSlotAreaEnchanting::SelectEnchantedOption(size_t a_EnchantOption) +{ + ASSERT(a_EnchantOption < m_EnchantedItemOptions.size()); + return std::move(m_EnchantedItemOptions[a_EnchantOption]); +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cSlotAreaEnderChest: |