summaryrefslogtreecommitdiffstats
path: root/src/UI
diff options
context:
space:
mode:
Diffstat (limited to 'src/UI')
-rw-r--r--src/UI/EnchantingWindow.cpp18
-rw-r--r--src/UI/EnchantingWindow.h23
-rw-r--r--src/UI/SlotArea.cpp79
-rw-r--r--src/UI/SlotArea.h10
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;
};