Enchanting table shows detail on hover. Enchanting is deterministic. (#4937)
* Use lapis for enchanting, subtract correct number of levels, ClientHandle now selects from pregenerated list. Co-authored-by: Tiger Wang <ziwei.tiger@outlook.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// Pseudocode found at: https://minecraft.gamepedia.com/Enchanting_mechanics
|
||||
const auto Bookshelves = std::min(GetBookshelvesCount(*a_Player.GetWorld()), 15U);
|
||||
|
||||
// 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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user