diff options
author | KingCol13 <48412633+KingCol13@users.noreply.github.com> | 2020-10-01 23:33:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-01 23:33:32 +0200 |
commit | 8947147c25e2640519897bfdc8807e97ee291d70 (patch) | |
tree | 63eca1e5bd8ad29ac9beba5a780d466c9bb13849 /src/UI | |
parent | Add SetBlockMeta warning in documentation (#4943) (diff) | |
download | cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar.gz cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar.bz2 cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar.lz cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar.xz cuberite-8947147c25e2640519897bfdc8807e97ee291d70.tar.zst cuberite-8947147c25e2640519897bfdc8807e97ee291d70.zip |
Diffstat (limited to 'src/UI')
-rw-r--r-- | src/UI/EnchantingWindow.cpp | 18 | ||||
-rw-r--r-- | src/UI/EnchantingWindow.h | 23 | ||||
-rw-r--r-- | src/UI/SlotArea.cpp | 79 | ||||
-rw-r--r-- | src/UI/SlotArea.h | 10 |
4 files changed, 93 insertions, 37 deletions
diff --git a/src/UI/EnchantingWindow.cpp b/src/UI/EnchantingWindow.cpp index 4ce4bebb3..15d27fc63 100644 --- a/src/UI/EnchantingWindow.cpp +++ b/src/UI/EnchantingWindow.cpp @@ -28,13 +28,12 @@ cEnchantingWindow::cEnchantingWindow(Vector3i a_BlockPos, const AString & a_Titl void cEnchantingWindow::SetProperty(short a_Property, short a_Value, cPlayer & a_Player) { - if ((a_Property < 0) || (static_cast<size_t>(a_Property) >= ARRAYCOUNT(m_PropertyValue))) + ASSERT(a_Property >= 0); + if (static_cast<size_t>(a_Property) < m_PropertyValue.size()) { - ASSERT(!"a_Property is invalid"); - return; + m_PropertyValue[a_Property] = a_Value; } - m_PropertyValue[a_Property] = a_Value; Super::SetProperty(a_Property, a_Value, a_Player); } @@ -44,13 +43,12 @@ void cEnchantingWindow::SetProperty(short a_Property, short a_Value, cPlayer & a void cEnchantingWindow::SetProperty(short a_Property, short a_Value) { - if ((a_Property < 0) || (static_cast<size_t>(a_Property) >= ARRAYCOUNT(m_PropertyValue))) + ASSERT(a_Property >= 0); + if (static_cast<size_t>(a_Property) < m_PropertyValue.size()) { - ASSERT(!"a_Property is invalid"); - return; + m_PropertyValue[a_Property] = a_Value; } - m_PropertyValue[a_Property] = a_Value; Super::SetProperty(a_Property, a_Value); } @@ -58,9 +56,9 @@ void cEnchantingWindow::SetProperty(short a_Property, short a_Value) -short cEnchantingWindow::GetPropertyValue(short a_Property) +short cEnchantingWindow::GetProperty(short a_Property) { - if ((a_Property < 0) || (static_cast<size_t>(a_Property) >= ARRAYCOUNT(m_PropertyValue))) + if ((a_Property < 0) || (static_cast<size_t>(a_Property) >= m_PropertyValue.size())) { ASSERT(!"a_Property is invalid"); return 0; diff --git a/src/UI/EnchantingWindow.h b/src/UI/EnchantingWindow.h index 4de5ed00c..2b32f078a 100644 --- a/src/UI/EnchantingWindow.h +++ b/src/UI/EnchantingWindow.h @@ -15,6 +15,12 @@ +class cSlotAreaEnchanting; + + + + + class cEnchantingWindow: public cWindow { @@ -24,22 +30,23 @@ public: cEnchantingWindow(Vector3i a_BlockPos, const AString & a_Title); + /** Sends enchantment properties to the client. + If the property represents a level requirement, stores it for later GetProperty retrieval. */ virtual void SetProperty(short a_Property, short a_Value, cPlayer & a_Player) override; + /** Sends enchantment properties to the client. + If the property represents a level requirement, stores it for later GetProperty retrieval. */ virtual void SetProperty(short a_Property, short a_Value) override; - /** Return the value of a property */ - short GetPropertyValue(short a_Property); + /** Return the level requirement of the given enchantment slot. */ + short GetProperty(short a_Property); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; - cSlotArea * m_SlotArea; + cSlotAreaEnchanting * m_SlotArea; protected: - short m_PropertyValue[3]; + + std::array<short, 3> m_PropertyValue; Vector3i m_BlockPos; }; - - - - 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: diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h index d363a72e6..acf8c404b 100644 --- a/src/UI/SlotArea.h +++ b/src/UI/SlotArea.h @@ -397,14 +397,20 @@ public: virtual void OnPlayerAdded (cPlayer & a_Player) override; virtual void OnPlayerRemoved(cPlayer & a_Player) override; - /* Get the count of bookshelves who stand in the near of the enchanting table */ - int GetBookshelvesCount(cWorld & a_World); + /* Get the number of bookshelves which are near the enchanting table */ + unsigned GetBookshelvesCount(cWorld & a_World); + + /* Return the enchanted item matching the chosen option (0, 1, 2) + Ownership of the cItem is transferred to the caller. */ + cItem SelectEnchantedOption(size_t a_EnchantOption); protected: + /** Handles a click in the item slot. */ void UpdateResult(cPlayer & a_Player); Vector3i m_BlockPos; + std::array<cItem, 3> m_EnchantedItemOptions; }; |