From 8947147c25e2640519897bfdc8807e97ee291d70 Mon Sep 17 00:00:00 2001 From: KingCol13 <48412633+KingCol13@users.noreply.github.com> Date: Fri, 2 Oct 2020 00:33:32 +0300 Subject: 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 --- src/ClientHandle.cpp | 88 +++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 50 deletions(-) (limited to 'src/ClientHandle.cpp') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 27b34eeec..848190127 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -768,79 +768,67 @@ void cClientHandle::HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment) if (a_Enchantment > 2) { LOGWARNING("%s attempt to crash the server with invalid enchanting selection (%u)!", GetUsername().c_str(), a_Enchantment); - Kick("Invalid enchanting!"); + Kick("Selected invalid enchantment - hacked client?"); return; } - // Bail out if something's wrong with the window + // Bail out if something's wrong with the window: if ( (m_Player->GetWindow() == nullptr) || (m_Player->GetWindow()->GetWindowID() != a_WindowID) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtEnchantment) ) { + Kick("Enchantment with invalid window - hacked client?"); return; } cEnchantingWindow * Window = static_cast(m_Player->GetWindow()); - auto Item = *Window->m_SlotArea->GetSlot(0, *m_Player); // A copy of the item to be enchanted. - short BaseEnchantmentLevel = Window->GetPropertyValue(a_Enchantment); + const auto BaseEnchantmentLevel = Window->GetProperty(a_Enchantment); - if (!Item.EnchantByXPLevels(BaseEnchantmentLevel)) - { - // Item wasn't enchantable: - return; - } - - const auto SetEnchantAndBroadcast = [this, &Item, Window] - { - // Set the item slot to our new enchanted item: - Window->m_SlotArea->SetSlot(0, *m_Player, Item); - Window->BroadcastWholeWindow(); - - // Remove enchantment choices: - Window->SetProperty(0, 0, *m_Player); - Window->SetProperty(1, 0, *m_Player); - Window->SetProperty(2, 0, *m_Player); - }; - - // Creative players can always enchant: - if (m_Player->IsGameModeCreative()) + // Survival players must be checked they can afford enchantment and have lapis removed: + if (!m_Player->IsGameModeCreative()) { - SetEnchantAndBroadcast(); - return; - } + const auto XpRequired = m_Player->XpForLevel(BaseEnchantmentLevel); + auto LapisStack = *Window->m_SlotArea->GetSlot(1, *m_Player); // A copy of the lapis stack. + const auto LapisRequired = a_Enchantment + 1; - const auto XpRequired = m_Player->XpForLevel(BaseEnchantmentLevel); - auto LapisStack = *Window->m_SlotArea->GetSlot(1, *m_Player); // A copy of the lapis stack. - const auto LapisRequired = a_Enchantment + 1; + // Only allow enchantment if the player has sufficient levels and lapis to enchant: + if ((m_Player->GetCurrentXp() >= XpRequired) && (LapisStack.m_ItemCount >= LapisRequired)) + { + /** We need to reduce the player's level by the number of lapis required. + However we need to keep the resulting percentage filled the same. */ - // Only allow enchantment if the player has sufficient levels and lapis to enchant: - if ((m_Player->GetCurrentXp() >= XpRequired) && (LapisStack.m_ItemCount >= LapisRequired)) - { - /* - We need to reduce the player's level by the number of lapis required. - However we need to keep the resulting percentage filled the same. - */ + const auto TargetLevel = m_Player->GetXpLevel() - LapisRequired; + const auto CurrentFillPercent = m_Player->GetXpPercentage(); - const auto TargetLevel = m_Player->GetXpLevel() - LapisRequired; - const auto CurrentFillPercent = m_Player->GetXpPercentage(); + // The experience to remove in order to reach the start (0% fill) of the target level. + const auto DeltaForLevel = -m_Player->GetCurrentXp() + m_Player->XpForLevel(TargetLevel); - // The experience to remove in order to reach the start (0% fill) of the target level. - const auto DeltaForLevel = -m_Player->GetCurrentXp() + m_Player->XpForLevel(TargetLevel); + // The experience to add to get the same fill percent. + const auto DeltaForPercent = CurrentFillPercent * (m_Player->XpForLevel(TargetLevel + 1) - m_Player->XpForLevel(TargetLevel)); - // The experience to add to get the same fill percent. - const auto DeltaForPercent = CurrentFillPercent * (m_Player->XpForLevel(TargetLevel + 1) - m_Player->XpForLevel(TargetLevel)); + // Apply the experience delta: + m_Player->DeltaExperience(DeltaForLevel + DeltaForPercent); - // Apply the experience delta: - m_Player->DeltaExperience(DeltaForLevel + DeltaForPercent); + // Now reduce the lapis in our stack and send it back: + LapisStack.AddCount(-LapisRequired); + Window->m_SlotArea->SetSlot(1, *m_Player, LapisStack); + } + else + { + // Not creative and can't afford enchantment, so exit: + Kick("Selected unavailable enchantment - hacked client?"); + return; + } + } - // Now reduce the lapis in our stack and send it back: - LapisStack.AddCount(-LapisRequired); - Window->m_SlotArea->SetSlot(1, *m_Player, LapisStack); + // Retrieve the enchanted item corresponding to our chosen option (top, middle, bottom) + cItem EnchantedItem = Window->m_SlotArea->SelectEnchantedOption(a_Enchantment); - SetEnchantAndBroadcast(); - } + // Set the item slot to our new enchanted item: + Window->m_SlotArea->SetSlot(0, *m_Player, EnchantedItem); + m_Player->PermuteEnchantmentSeed(); } -- cgit v1.2.3