summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Blocks/BlockEnchantmentTable.h37
-rw-r--r--src/Blocks/BlockHandler.cpp2
-rw-r--r--src/ClientHandle.cpp23
-rw-r--r--src/ClientHandle.h5
-rw-r--r--src/Enchantments.cpp775
-rw-r--r--src/Enchantments.h41
-rw-r--r--src/FastRandom.cpp10
-rw-r--r--src/FastRandom.h3
-rw-r--r--src/Item.cpp153
-rw-r--r--src/Item.h7
-rw-r--r--src/Protocol/Protocol125.cpp16
-rw-r--r--src/Protocol/Protocol125.h1
-rw-r--r--src/Protocol/Protocol17x.cpp13
-rw-r--r--src/Protocol/Protocol17x.h1
-rw-r--r--src/UI/SlotArea.cpp305
-rw-r--r--src/UI/SlotArea.h32
-rw-r--r--src/UI/Window.cpp60
-rw-r--r--src/UI/Window.h34
18 files changed, 1509 insertions, 9 deletions
diff --git a/src/Blocks/BlockEnchantmentTable.h b/src/Blocks/BlockEnchantmentTable.h
new file mode 100644
index 000000000..81d2cb9a0
--- /dev/null
+++ b/src/Blocks/BlockEnchantmentTable.h
@@ -0,0 +1,37 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+#include "../UI/Window.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+class cBlockEnchantmentTableHandler :
+ public cBlockHandler
+{
+public:
+ cBlockEnchantmentTableHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
+ {
+ cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->OpenWindow(Window);
+ }
+
+
+ virtual bool IsUseable(void) override
+ {
+ return true;
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 4a29ff628..a764c6f44 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -25,6 +25,7 @@
#include "BlockDirt.h"
#include "BlockDoor.h"
#include "BlockDropSpenser.h"
+#include "BlockEnchantmentTable.h"
#include "BlockEnderchest.h"
#include "BlockEntity.h"
#include "BlockFarmland.h"
@@ -119,6 +120,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_DOUBLE_WOODEN_SLAB: return new cBlockDoubleSlabHandler (a_BlockType);
case E_BLOCK_DROPPER: return new cBlockDropSpenserHandler (a_BlockType);
case E_BLOCK_EMERALD_ORE: return new cBlockOreHandler (a_BlockType);
+ case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler ( );
case E_BLOCK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 07e91f59a..c7805e4de 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -2729,4 +2729,27 @@ void cClientHandle::SocketClosed(void)
+void cClientHandle::HandleEnchantItem(Byte & WindowID, Byte & Enchantment)
+{
+ cEnchantingWindow * Window = (cEnchantingWindow*)m_Player->GetWindow();
+ cItem Item = *Window->m_SlotArea->GetSlot(0, *m_Player);
+ int BaseEnchantmentLevel = Window->GetPropertyValue(Enchantment);
+
+ if (Item.EnchantByXPLevels(BaseEnchantmentLevel))
+ {
+ if (m_Player->IsGameModeCreative() || m_Player->DeltaExperience(-m_Player->XpForLevel(BaseEnchantmentLevel)) >= 0)
+ {
+ Window->m_SlotArea->SetSlot(0, *m_Player, Item);
+ Window->SendSlot(*m_Player, Window->m_SlotArea, 0);
+ Window->BroadcastWholeWindow();
+
+ Window->SetProperty(0, 0, *m_Player);
+ Window->SetProperty(1, 0, *m_Player);
+ Window->SetProperty(2, 0, *m_Player);
+ }
+ }
+}
+
+
+
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 12e0256de..3d01d8034 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -18,6 +18,8 @@
#include "ByteBuffer.h"
#include "Scoreboard.h"
#include "Map.h"
+#include "Enchantments.h"
+#include "UI/SlotArea.h"
@@ -244,6 +246,9 @@ public:
/** Called when the player moves into a different world; queues sreaming the new chunks */
void MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket);
+ /** Called when the player will enchant a Item */
+ void HandleEnchantItem(Byte & WindowID, Byte & Enchantment);
+
private:
/** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
diff --git a/src/Enchantments.cpp b/src/Enchantments.cpp
index 9d4e23e0a..dad92dc91 100644
--- a/src/Enchantments.cpp
+++ b/src/Enchantments.cpp
@@ -5,6 +5,7 @@
#include "Globals.h"
#include "Enchantments.h"
#include "WorldStorage/FastNBT.h"
+#include "FastRandom.h"
@@ -218,7 +219,781 @@ bool cEnchantments::operator !=(const cEnchantments & a_Other) const
+void cEnchantments::AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, int a_EnchantmentLevel)
+{
+ if (ItemCategory::IsSword(a_ItemType))
+ {
+ // Sharpness
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4);
+ }
+ else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1);
+ }
+
+ // Smite
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1);
+ }
+
+ // Bane of Arthropods
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1);
+ }
+
+ // Knockback
+ if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1);
+ }
+
+ // Fire Aspect
+ if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1);
+ }
+
+ // Looting
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1);
+ }
+ }
+
+ else if (ItemCategory::IsTool(a_ItemType))
+ {
+ // Efficiency
+ if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1);
+ }
+
+ // Silk Touch
+ if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1);
+ }
+
+ // Fortune
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1);
+ }
+ }
+
+ else if (ItemCategory::IsArmor(a_ItemType))
+ {
+ // Protection
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1);
+ }
+
+ // Fire Protection
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1);
+ }
+
+ // Blast Protection
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1);
+ }
+
+ // Projectile Protection
+ if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1);
+ }
+
+ // Thorns
+ if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3);
+ }
+ else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1);
+ }
+
+
+ if (ItemCategory::IsHelmet(a_ItemType))
+ {
+ // Respiration
+ if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3);
+ }
+ else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1);
+ }
+
+ // Aqua Affinity
+ if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1);
+ }
+ }
+
+ else if (ItemCategory::IsBoots(a_ItemType))
+ {
+ // Feather Fall
+ if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4);
+ }
+ else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
+ }
+ }
+ }
+
+ else if (a_ItemType == E_ITEM_BOW)
+ {
+ // Power
+ if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1);
+ }
+
+ // Punch
+ if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1);
+ }
+
+ // Flame and Infinity
+ if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1);
+ }
+ }
+
+ else if (a_ItemType == E_ITEM_FISHING_ROD)
+ {
+ // Luck of the Sea and Lure
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1);
+ }
+ }
+
+ else if (a_ItemType == E_ITEM_BOOK)
+ {
+ // All Enchantments
+
+ // Sharpness
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4);
+ }
+ else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1);
+ }
+
+ // Smite
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1);
+ }
+
+ // Bane of Arthropods
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1);
+ }
+
+ // Knockback
+ if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1);
+ }
+
+ // Fire Aspect
+ if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1);
+ }
+
+ // Looting
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1);
+ }
+
+ // Efficiency
+ if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1);
+ }
+
+ // Silk Touch
+ if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1);
+ }
+
+ // Fortune
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1);
+ }
+
+ // Protection
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1);
+ }
+
+ // Fire Protection
+ if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1);
+ }
+
+ // Blast Protection
+ if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1);
+ }
+
+ // Projectile Protection
+ if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3);
+ }
+ else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2);
+ }
+ else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1);
+ }
+
+ // Thorns
+ if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3);
+ }
+ else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1);
+ }
+
+ // Respiration
+ if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3);
+ }
+ else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2);
+ }
+ else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1);
+ }
+
+ // Aqua Affinity
+ if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1);
+ }
+
+ // Feather Fall
+ if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4);
+ }
+ else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
+ }
+
+ // Power
+ if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4);
+ }
+ else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3);
+ }
+ else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2);
+ }
+ else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1);
+ }
+
+ // Punch
+ if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2);
+ }
+ else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1);
+ }
+
+ // Flame and Infinity
+ if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1);
+ }
+
+ // Luck of the Sea and Lure
+ if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3);
+ }
+ else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2);
+ }
+ else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1);
+ AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1);
+ }
+ }
+
+ // Unbreaking
+ if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 3);
+ }
+ else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 63))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 2);
+ }
+ else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55))
+ {
+ AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 1);
+ }
+}
+
+
+
+
+
+void cEnchantments::AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, int a_EnchantmentLevel)
+{
+ cWeightedEnchantment weightedenchantment;
+ weightedenchantment.m_Weight = a_Weight;
+ cEnchantments enchantment;
+ enchantment.SetLevel(a_EnchantmentID, a_EnchantmentLevel);
+ weightedenchantment.m_Enchantments = enchantment;
+ a_Enchantments.push_back(weightedenchantment);
+}
+
+
+
+
+
+void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID)
+{
+ for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
+ {
+ if ((*it).m_Enchantments.GetLevel(a_EnchantmentID) > 0)
+ {
+ a_Enchantments.erase(it);
+ break;
+ }
+ }
+}
+
+
+
+
+void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment)
+{
+ for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
+ {
+ if ((*it).m_Enchantments == a_Enchantment)
+ {
+ a_Enchantments.erase(it);
+ break;
+ }
+ }
+}
+
+
+
+
+
+void cEnchantments::CheckEnchantmentConflictsFromVector(cWeightedEnchantments & a_Enchantments, cEnchantments a_FirstEnchantment)
+{
+ if (a_FirstEnchantment.GetLevel(cEnchantments::enchProtection) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFireProtection) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBlastProtection) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchProjectileProtection) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection);
+ }
+
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSharpness) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSmite) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBaneOfArthropods) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness);
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSilkTouch) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFortune);
+ }
+ else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFortune) > 0)
+ {
+ RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSilkTouch);
+ }
+}
+
+
+
+
+
+cEnchantments cEnchantments::GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments)
+{
+ cFastRandom Random;
+
+ int AllWeights = 0;
+ for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
+ {
+ AllWeights += (*it).m_Weight;
+ }
+ int RandomNumber = Random.GenerateRandomInteger(0, AllWeights - 1);
+ for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it)
+ {
+ RandomNumber -= (*it).m_Weight;
+ if (RandomNumber < 0)
+ {
+ return (*it).m_Enchantments;
+ }
+ }
+
+ return cEnchantments();
+}
diff --git a/src/Enchantments.h b/src/Enchantments.h
index f77b535d8..a376d27cf 100644
--- a/src/Enchantments.h
+++ b/src/Enchantments.h
@@ -8,6 +8,7 @@
#pragma once
+#include "Defines.h"
#include "WorldStorage/EnchantmentSerializer.h"
@@ -18,6 +19,11 @@ class cFastNBTWriter;
class cParsedNBT;
+// fwd:
+struct cWeightedEnchantment;
+
+typedef std::vector<cWeightedEnchantment> cWeightedEnchantments;
+
@@ -28,6 +34,8 @@ mapping each enchantment's id onto its level. ID may be either a number or the e
Level value of 0 means no such enchantment, and it will not be stored in the m_Enchantments.
Serialization will never put zero-level enchantments into the stringspec and will always use numeric IDs.
*/
+
+
// tolua_begin
class cEnchantments
{
@@ -61,7 +69,7 @@ public:
enchLuckOfTheSea = 61,
enchLure = 62,
} ;
-
+
/// Creates an empty enchantments container
cEnchantments(void);
@@ -91,9 +99,27 @@ public:
/// Returns true if a_Other contains exactly the same enchantments and levels
bool operator ==(const cEnchantments & a_Other) const;
-
+
// tolua_end
+
+ /** Add enchantment weights from item to the vector */
+ static void AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, int a_EnchantmentLevel);
+
+ /** Add a enchantment with weight to the vector */
+ static void AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, int a_EnchantmentLevel);
+ /** Remove the entire enchantment (with weight) from the vector */
+ static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID);
+
+ /** Remove the entire enchantment (with weight) from the vector */
+ static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment);
+
+ /** Check enchantment conflicts from enchantments from the vector */
+ static void CheckEnchantmentConflictsFromVector(cWeightedEnchantments & a_Enchantments, cEnchantments a_FirstEnchantment);
+
+ /** Gets random enchantment from Vector and returns it */
+ static cEnchantments GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments);
+
/// Returns true if a_Other doesn't contain exactly the same enchantments and levels
bool operator !=(const cEnchantments & a_Other) const;
@@ -102,7 +128,7 @@ public:
/// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments)
friend void EnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx);
-
+
protected:
/// Maps enchantment ID -> enchantment level
typedef std::map<int, int> cMap;
@@ -114,3 +140,12 @@ protected:
+// Define the cWeightedEnchantment struct for the Enchanting System to store the EnchantmentWeights:
+struct cWeightedEnchantment
+{
+ int m_Weight;
+ cEnchantments m_Enchantments;
+};
+
+
+
diff --git a/src/FastRandom.cpp b/src/FastRandom.cpp
index e6634bb0d..c45261947 100644
--- a/src/FastRandom.cpp
+++ b/src/FastRandom.cpp
@@ -172,3 +172,13 @@ float cFastRandom::NextFloat(float a_Range, int a_Salt)
+
+int cFastRandom::GenerateRandomInteger(int a_Begin, int a_End)
+{
+ cFastRandom Random;
+ return Random.NextInt(a_End - a_Begin + 1) + a_Begin;
+}
+
+
+
+
diff --git a/src/FastRandom.h b/src/FastRandom.h
index bf70822cf..567198a31 100644
--- a/src/FastRandom.h
+++ b/src/FastRandom.h
@@ -43,6 +43,9 @@ public:
/// Returns a random float in the range [0 .. a_Range]; a_Range must be less than 1M; a_Salt is additional source of randomness
float NextFloat(float a_Range, int a_Salt);
+
+ /** Returns a random int in the range [a_Begin .. a_End] */
+ int GenerateRandomInteger(int a_Begin, int a_End);
protected:
int m_Seed;
diff --git a/src/Item.cpp b/src/Item.cpp
index 856b68be6..f92efcb39 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -5,6 +5,8 @@
#include "json/json.h"
#include "Items/ItemHandler.h"
+#include "FastRandom.h"
+
@@ -209,6 +211,157 @@ bool cItem::IsEnchantable(short item)
+int cItem::GetEnchantability()
+{
+ int Enchantability = 0;
+
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_SWORD: Enchantability = 15; break;
+ case E_ITEM_WOODEN_PICKAXE: Enchantability = 15; break;
+ case E_ITEM_WOODEN_SHOVEL: Enchantability = 15; break;
+ case E_ITEM_WOODEN_AXE: Enchantability = 15; break;
+ case E_ITEM_WOODEN_HOE: Enchantability = 15; break;
+
+ case E_ITEM_LEATHER_CAP: Enchantability = 15; break;
+ case E_ITEM_LEATHER_TUNIC: Enchantability = 15; break;
+ case E_ITEM_LEATHER_PANTS: Enchantability = 15; break;
+ case E_ITEM_LEATHER_BOOTS: Enchantability = 15; break;
+
+ case E_ITEM_STONE_SWORD: Enchantability = 5; break;
+ case E_ITEM_STONE_PICKAXE: Enchantability = 5; break;
+ case E_ITEM_STONE_SHOVEL: Enchantability = 5; break;
+ case E_ITEM_STONE_AXE: Enchantability = 5; break;
+ case E_ITEM_STONE_HOE: Enchantability = 5; break;
+
+ case E_ITEM_IRON_HELMET: Enchantability = 9; break;
+ case E_ITEM_IRON_CHESTPLATE: Enchantability = 9; break;
+ case E_ITEM_IRON_LEGGINGS: Enchantability = 9; break;
+ case E_ITEM_IRON_BOOTS: Enchantability = 9; break;
+
+ case E_ITEM_IRON_SWORD: Enchantability = 14; break;
+ case E_ITEM_IRON_PICKAXE: Enchantability = 14; break;
+ case E_ITEM_IRON_SHOVEL: Enchantability = 14; break;
+ case E_ITEM_IRON_AXE: Enchantability = 14; break;
+ case E_ITEM_IRON_HOE: Enchantability = 14; break;
+
+ case E_ITEM_CHAIN_HELMET: Enchantability = 12; break;
+ case E_ITEM_CHAIN_CHESTPLATE: Enchantability = 12; break;
+ case E_ITEM_CHAIN_LEGGINGS: Enchantability = 12; break;
+ case E_ITEM_CHAIN_BOOTS: Enchantability = 12; break;
+
+ case E_ITEM_DIAMOND_HELMET: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_CHESTPLATE: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_LEGGINGS: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_BOOTS: Enchantability = 10; break;
+
+ case E_ITEM_DIAMOND_SWORD: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_PICKAXE: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_SHOVEL: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_AXE: Enchantability = 10; break;
+ case E_ITEM_DIAMOND_HOE: Enchantability = 10; break;
+
+ case E_ITEM_GOLD_HELMET: Enchantability = 25; break;
+ case E_ITEM_GOLD_CHESTPLATE: Enchantability = 25; break;
+ case E_ITEM_GOLD_LEGGINGS: Enchantability = 25; break;
+ case E_ITEM_GOLD_BOOTS: Enchantability = 25; break;
+
+ case E_ITEM_GOLD_SWORD: Enchantability = 22; break;
+ case E_ITEM_GOLD_PICKAXE: Enchantability = 22; break;
+ case E_ITEM_GOLD_SHOVEL: Enchantability = 22; break;
+ case E_ITEM_GOLD_AXE: Enchantability = 22; break;
+ case E_ITEM_GOLD_HOE: Enchantability = 22; break;
+
+ case E_ITEM_FISHING_ROD: Enchantability = 1; break;
+ case E_ITEM_BOW: Enchantability = 1; break;
+ case E_ITEM_BOOK: Enchantability = 1; break;
+ }
+
+ return Enchantability;
+}
+
+
+
+
+
+bool cItem::EnchantByXPLevels(int a_NumXPLevels)
+{
+ if (!cItem::IsEnchantable(m_ItemType) && (m_ItemType != E_ITEM_BOOK))
+ {
+ return false;
+ }
+
+ int Enchantability = GetEnchantability();
+
+ cFastRandom Random;
+ int ModifiedEnchantmentLevel = a_NumXPLevels + (int)Random.NextFloat((float)Enchantability / 4) + (int)Random.NextFloat((float)Enchantability / 4) + 1;
+ float RandomBonus = 1.0F + (Random.NextFloat(1) + Random.NextFloat(1) - 1.0F) * 0.15F;
+ int FinalEnchantmentLevel = (int)(ModifiedEnchantmentLevel * RandomBonus + 0.5F);
+
+ cWeightedEnchantments enchantments;
+ cEnchantments::AddItemEnchantmentWeights(enchantments, m_ItemType, FinalEnchantmentLevel);
+
+ if (m_ItemType == E_ITEM_BOOK)
+ {
+ m_ItemType = E_ITEM_ENCHANTED_BOOK;
+ }
+
+ cEnchantments Enchantment1 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ m_Enchantments.AddFromString(Enchantment1.ToString());
+ cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment1);
+
+ // Checking for conflicting enchantments
+ cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment1);
+
+ float NewEnchantmentLevel = (float)a_NumXPLevels;
+
+ // Next Enchantment (Second)
+ NewEnchantmentLevel = NewEnchantmentLevel / 2;
+ float SecondEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
+ if ((Random.NextFloat(100) > SecondEnchantmentChance) || (enchantments.size() == 0))
+ {
+ return false;
+ }
+
+ cEnchantments Enchantment2 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ m_Enchantments.AddFromString(Enchantment2.ToString());
+ cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment2);
+
+ // Checking for conflicting enchantments
+ cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment2);
+
+ // Next Enchantment (Third)
+ NewEnchantmentLevel = NewEnchantmentLevel / 2;
+ float ThirdEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
+ if ((Random.NextFloat(100) > ThirdEnchantmentChance) || (enchantments.size() == 0))
+ {
+ return false;
+ }
+
+ cEnchantments Enchantment3 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ m_Enchantments.AddFromString(Enchantment3.ToString());
+ cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment3);
+
+ // Checking for conflicting enchantments
+ cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment3);
+
+ // Next Enchantment (Fourth)
+ NewEnchantmentLevel = NewEnchantmentLevel / 2;
+ float FourthEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
+ if ((Random.NextFloat(100) > FourthEnchantmentChance) || (enchantments.size() == 0))
+ {
+ return false;
+ }
+ cEnchantments Enchantment4 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ m_Enchantments.AddFromString(Enchantment4.ToString());
+
+ return true;
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cItems:
diff --git a/src/Item.h b/src/Item.h
index 910ecb382..00316c188 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -175,6 +175,13 @@ public:
/** Returns true if the specified item type is enchantable (as per 1.2.5 protocol requirements) */
static bool IsEnchantable(short a_ItemType); // tolua_export
+ /** Returns the enchantability of the item. When the item hasn't a enchantability, it will returns 0 */
+ int GetEnchantability(); // tolua_export
+
+ /** Enchants the item using the specified number of XP levels.
+ Returns true if item enchanted, false if not. */
+ bool EnchantByXPLevels(int a_NumXPLevels); // tolua_export
+
// tolua_begin
short m_ItemType;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index af1b1c604..9b8db0b7b 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -96,6 +96,7 @@ enum
PACKET_INVENTORY_WHOLE = 0x68,
PACKET_WINDOW_PROPERTY = 0x69,
PACKET_CREATIVE_INVENTORY_ACTION = 0x6B,
+ PACKET_ENCHANT_ITEM = 0x6C,
PACKET_UPDATE_SIGN = 0x82,
PACKET_ITEM_DATA = 0x83,
PACKET_PLAYER_LIST_ITEM = 0xC9,
@@ -1278,6 +1279,7 @@ int cProtocol125::ParsePacket(unsigned char a_PacketType)
case PACKET_SLOT_SELECTED: return ParseSlotSelected();
case PACKET_UPDATE_SIGN: return ParseUpdateSign();
case PACKET_USE_ENTITY: return ParseUseEntity();
+ case PACKET_ENCHANT_ITEM: return ParseEnchantItem();
case PACKET_WINDOW_CLICK: return ParseWindowClick();
case PACKET_WINDOW_CLOSE: return ParseWindowClose();
}
@@ -1639,6 +1641,20 @@ int cProtocol125::ParseUseEntity(void)
+int cProtocol125::ParseEnchantItem(void)
+{
+ HANDLE_PACKET_READ(ReadByte, Byte, WindowID);
+ HANDLE_PACKET_READ(ReadByte, Byte, Enchantment);
+
+ m_Client->HandleEnchantItem(WindowID, Enchantment);
+
+ return PARSE_OK;
+}
+
+
+
+
+
int cProtocol125::ParseWindowClick(void)
{
HANDLE_PACKET_READ(ReadChar, char, WindowID);
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 16f31bd0e..89e64f386 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -143,6 +143,7 @@ protected:
virtual int ParseSlotSelected (void);
virtual int ParseUpdateSign (void);
virtual int ParseUseEntity (void);
+ virtual int ParseEnchantItem (void);
virtual int ParseWindowClick (void);
virtual int ParseWindowClose (void);
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 403046760..36f770df7 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1580,6 +1580,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
case 0x0f: // Confirm transaction - not used in MCS
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
+ case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true;
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true;
case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true;
@@ -2044,6 +2045,18 @@ void cProtocol172::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer)
+void cProtocol172::HandlePacketEnchantItem(cByteBuffer & a_ByteBuffer)
+{
+ HANDLE_READ(a_ByteBuffer, ReadByte, Byte, WindowID);
+ HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Enchantment);
+
+ m_Client->HandleEnchantItem(WindowID, Enchantment);
+}
+
+
+
+
+
void cProtocol172::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadChar, char, WindowID);
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 5cafc4722..6a3e81eff 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -280,6 +280,7 @@ protected:
void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer);
void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer);
void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer);
+ void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 88977e005..5f74b4fa3 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -13,6 +13,8 @@
#include "Window.h"
#include "../CraftingRecipes.h"
#include "../Root.h"
+#include "../FastRandom.h"
+#include "../BlockArea.h"
@@ -145,6 +147,7 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
FreeSlots = 0;
}
int Filling = (FreeSlots > DraggingItem.m_ItemCount) ? DraggingItem.m_ItemCount : FreeSlots;
+
Slot.m_ItemCount += (char)Filling;
DraggingItem.m_ItemCount -= (char)Filling;
if (DraggingItem.m_ItemCount <= 0)
@@ -167,7 +170,6 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
{
m_ParentWindow.BroadcastWholeWindow();
}
-
}
@@ -593,6 +595,307 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cSlotAreaEnchanting:
+
+cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow) :
+ cSlotAreaTemporary(1, a_ParentWindow)
+{
+ a_ParentWindow.m_SlotArea = this;
+}
+
+
+
+
+
+void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
+{
+ ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
+
+ bool bAsync = false;
+ if (GetSlot(a_SlotNum, a_Player) == NULL)
+ {
+ LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
+ return;
+ }
+
+ switch (a_ClickAction)
+ {
+ case caShiftLeftClick:
+ case caShiftRightClick:
+ {
+ ShiftClicked(a_Player, a_SlotNum, a_ClickedItem);
+ return;
+ }
+
+ case caDblClick:
+ {
+ DblClicked(a_Player, a_SlotNum);
+ return;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ cItem Slot(*GetSlot(a_SlotNum, a_Player));
+ if (!Slot.IsSameType(a_ClickedItem))
+ {
+ LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
+ LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
+ LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
+ bAsync = true;
+ }
+ cItem & DraggingItem = a_Player.GetDraggingItem();
+ switch (a_ClickAction)
+ {
+ case caRightClick:
+ {
+ // Right-clicked
+ if (DraggingItem.IsEmpty())
+ {
+ DraggingItem = Slot.CopyOne();
+ Slot.Empty();
+ break;
+ }
+
+ if (Slot.IsEmpty())
+ {
+ Slot = DraggingItem.CopyOne();
+ DraggingItem.m_ItemCount -= 1;
+ if (DraggingItem.m_ItemCount <= 0)
+ {
+ DraggingItem.Empty();
+ }
+ }
+ else if ((!DraggingItem.IsEqual(Slot)) && (DraggingItem.m_ItemCount == 1))
+ {
+ // Swap contents
+ cItem tmp(DraggingItem);
+ DraggingItem = Slot;
+ Slot = tmp;
+ }
+ break;
+ }
+
+ case caLeftClick:
+ {
+ // Left-clicked
+ if (DraggingItem.IsEmpty())
+ {
+ DraggingItem = Slot.CopyOne();
+ Slot.Empty();
+ break;
+ }
+
+ if (DraggingItem.IsEqual(Slot))
+ {
+ // Do nothing
+ break;
+ }
+
+ if (!Slot.IsEmpty())
+ {
+ if (DraggingItem.m_ItemCount == 1)
+ {
+ // Swap contents
+ cItem tmp(DraggingItem);
+ DraggingItem = Slot;
+ Slot = tmp;
+ }
+ }
+ else
+ {
+ Slot = DraggingItem.CopyOne();
+ DraggingItem.m_ItemCount -= 1;
+ if (DraggingItem.m_ItemCount <= 0)
+ {
+ DraggingItem.Empty();
+ }
+ }
+ break;
+ }
+ default:
+ {
+ LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction));
+ m_ParentWindow.BroadcastWholeWindow();
+ return;
+ }
+ } // switch (a_ClickAction
+
+ SetSlot(a_SlotNum, a_Player, Slot);
+ if (bAsync)
+ {
+ m_ParentWindow.BroadcastWholeWindow();
+ }
+ UpdateResult(a_Player);
+}
+
+
+
+
+
+void cSlotAreaEnchanting::DblClicked(cPlayer & a_Player, int a_SlotNum)
+{
+ cItem & Dragging = a_Player.GetDraggingItem();
+ if ((!Dragging.IsEmpty()) || (a_SlotNum != 0))
+ {
+ return;
+ }
+
+ cItem Item = *GetSlot(0, a_Player);
+ if (!m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, false))
+ {
+ m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, true);
+ }
+}
+
+
+
+
+
+void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots)
+{
+ const cItem * Slot = GetSlot(0, a_Player);
+ if (!Slot->IsEmpty())
+ {
+ return;
+ }
+
+ if (a_Apply)
+ {
+ SetSlot(0, a_Player, a_ItemStack.CopyOne());
+ }
+ a_ItemStack.m_ItemCount -= 1;
+ if (a_ItemStack.m_ItemCount <= 0)
+ {
+ a_ItemStack.Empty();
+ }
+
+ UpdateResult(a_Player);
+}
+
+
+
+
+
+void cSlotAreaEnchanting::OnPlayerRemoved(cPlayer & a_Player)
+{
+ // Toss the item in the enchanting slot
+ TossItems(a_Player, 0, 1);
+
+ super::OnPlayerRemoved(a_Player);
+}
+
+
+
+
+
+void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player)
+{
+ cItem Item = *GetSlot(0, a_Player);
+
+ if (Item.IsEmpty() || !Item.m_Enchantments.IsEmpty())
+ {
+ m_ParentWindow.SetProperty(0, 0, a_Player);
+ m_ParentWindow.SetProperty(1, 0, a_Player);
+ m_ParentWindow.SetProperty(2, 0, a_Player);
+ }
+ else if (cItem::IsEnchantable(Item.m_ItemType) || Item.m_ItemType == E_ITEM_BOOK)
+ {
+ int Bookshelves = std::min(GetBookshelvesCount(a_Player.GetWorld()), 15);
+
+ cFastRandom Random;
+ int base = (Random.GenerateRandomInteger(1, 8) + floor(Bookshelves / 2) + Random.GenerateRandomInteger(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, topSlot, a_Player);
+ m_ParentWindow.SetProperty(1, middleSlot, a_Player);
+ m_ParentWindow.SetProperty(2, bottomSlot, a_Player);
+ }
+ else
+ {
+ m_ParentWindow.SetProperty(0, 0, a_Player);
+ m_ParentWindow.SetProperty(1, 0, a_Player);
+ m_ParentWindow.SetProperty(2, 0, a_Player);
+ }
+}
+
+
+
+
+
+int cSlotAreaEnchanting::GetBookshelvesCount(cWorld * a_World)
+{
+ int PosX, PosY, PosZ;
+ ((cEnchantingWindow*)&m_ParentWindow)->GetBlockPos(PosX, PosY, PosZ);
+
+ int Bookshelves = 0;
+ cBlockArea Area;
+ Area.Read(a_World, PosX - 2, PosX + 2, PosY, PosY + 1, PosZ - 2, PosZ + 2);
+
+ static const struct
+ {
+ int m_BookX, m_BookY, m_BookZ; // Coords to check for bookcases
+ int m_AirX, m_AirY, m_AirZ; // Coords to check for air; if not air, the bookcase won't be counted
+ } CheckCoords[] =
+ {
+ { 0, 0, 0, 1, 0, 1 }, // Bookcase at {0, 0, 0}, air at {1, 0, 1}
+ { 0, 0, 1, 1, 0, 1 }, // Bookcase at {0, 0, 1}, air at {1, 0, 1}
+ { 0, 0, 2, 1, 0, 2 }, // Bookcase at {0, 0, 2}, air at {1, 0, 2}
+ { 0, 0, 3, 1, 0, 3 }, // Bookcase at {0, 0, 3}, air at {1, 0, 3}
+ { 0, 0, 4, 1, 0, 3 }, // Bookcase at {0, 0, 4}, air at {1, 0, 3}
+ { 1, 0, 4, 1, 0, 3 }, // Bookcase at {1, 0, 4}, air at {1, 0, 3}
+ { 2, 0, 4, 2, 0, 3 }, // Bookcase at {2, 0, 4}, air at {2, 0, 3}
+ { 3, 0, 4, 3, 0, 3 }, // Bookcase at {3, 0, 4}, air at {3, 0, 3}
+ { 4, 0, 4, 3, 0, 3 }, // Bookcase at {4, 0, 4}, air at {3, 0, 3}
+ { 4, 0, 3, 3, 0, 3 }, // Bookcase at {4, 0, 3}, air at {3, 0, 3}
+ { 4, 0, 2, 3, 0, 2 }, // Bookcase at {4, 0, 2}, air at {3, 0, 2}
+ { 4, 0, 1, 3, 0, 1 }, // Bookcase at {4, 0, 1}, air at {3, 0, 1}
+ { 4, 0, 0, 3, 0, 1 }, // Bookcase at {4, 0, 0}, air at {3, 0, 1}
+ { 3, 0, 0, 3, 0, 1 }, // Bookcase at {3, 0, 0}, air at {3, 0, 1}
+ { 2, 0, 0, 2, 0, 1 }, // Bookcase at {2, 0, 0}, air at {2, 0, 1}
+ { 1, 0, 0, 1, 0, 1 }, // Bookcase at {1, 0, 0}, air at {1, 0, 1}
+
+ { 0, 1, 0, 1, 1, 1 }, // Bookcase at {0, 1, 0}, air at {1, 1, 1}
+ { 0, 1, 1, 1, 1, 1 }, // Bookcase at {0, 1, 1}, air at {1, 1, 1}
+ { 0, 1, 2, 1, 1, 2 }, // Bookcase at {0, 1, 2}, air at {1, 1, 2}
+ { 0, 1, 3, 1, 1, 3 }, // Bookcase at {0, 1, 3}, air at {1, 1, 3}
+ { 0, 1, 4, 1, 1, 3 }, // Bookcase at {0, 1, 4}, air at {1, 1, 3}
+ { 1, 1, 4, 1, 1, 3 }, // Bookcase at {1, 1, 4}, air at {1, 1, 3}
+ { 2, 1, 4, 2, 1, 3 }, // Bookcase at {2, 1, 4}, air at {2, 1, 3}
+ { 3, 1, 4, 3, 1, 3 }, // Bookcase at {3, 1, 4}, air at {3, 1, 3}
+ { 4, 1, 4, 3, 1, 3 }, // Bookcase at {4, 1, 4}, air at {3, 1, 3}
+ { 4, 1, 3, 3, 1, 3 }, // Bookcase at {4, 1, 3}, air at {3, 1, 3}
+ { 4, 1, 2, 3, 1, 2 }, // Bookcase at {4, 1, 2}, air at {3, 1, 2}
+ { 4, 1, 1, 3, 1, 1 }, // Bookcase at {4, 1, 1}, air at {3, 1, 1}
+ { 4, 1, 0, 3, 1, 1 }, // Bookcase at {4, 1, 0}, air at {3, 1, 1}
+ { 3, 1, 0, 3, 1, 1 }, // Bookcase at {3, 1, 0}, air at {3, 1, 1}
+ { 2, 1, 0, 2, 1, 1 }, // Bookcase at {2, 1, 0}, air at {2, 1, 1}
+ { 1, 1, 0, 1, 1, 1 }, // Bookcase at {1, 1, 0}, air at {1, 1, 1}
+ };
+
+ for (size_t i = 0; i < ARRAYCOUNT(CheckCoords); i++)
+ {
+ if (
+ (Area.GetRelBlockType(CheckCoords[i].m_AirX, CheckCoords[i].m_AirY, CheckCoords[i].m_AirZ) == E_BLOCK_AIR) && // There's air in the checkspot
+ (Area.GetRelBlockType(CheckCoords[i].m_BookX, CheckCoords[i].m_BookY, CheckCoords[i].m_BookZ) == E_BLOCK_BOOKCASE) // There's bookcase in the wanted place
+ )
+ {
+ Bookshelves++;
+ }
+ } // for i - CheckCoords
+
+ return Bookshelves;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnderChest:
cSlotAreaEnderChest::cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow) :
diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h
index 25b367cff..bab1098bb 100644
--- a/src/UI/SlotArea.h
+++ b/src/UI/SlotArea.h
@@ -19,6 +19,8 @@ class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cCraftingRecipe;
+class cEnchantingWindow;
+class cWorld;
@@ -66,7 +68,7 @@ public:
/// If a_CollectFullStacks is false, slots with full stacks are skipped while collecting.
/// Returns true if full stack has been collected in a_Dragging, false if there's space remaining to fill.
virtual bool CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks);
-
+
protected:
int m_NumSlots;
cWindow & m_ParentWindow;
@@ -252,6 +254,34 @@ protected:
+class cSlotAreaEnchanting :
+ public cSlotAreaTemporary
+{
+ typedef cSlotAreaTemporary super;
+
+public:
+ cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow);
+
+ // cSlotArea overrides:
+ virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
+ virtual void DblClicked(cPlayer & a_Player, int a_SlotNum) override;
+ virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
+
+ // cSlotAreaTemporary overrides:
+ 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);
+
+protected:
+ /** Handles a click in the item slot. */
+ void UpdateResult(cPlayer & a_Player);
+};
+
+
+
+
+
class cSlotAreaChest :
public cSlotArea
{
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index aae7b99a3..0a78578fc 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -805,6 +805,66 @@ cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cEnchantingWindow:
+
+cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
+ cWindow(wtEnchantment, "Enchant"),
+ m_BlockX(a_BlockX),
+ m_BlockY(a_BlockY),
+ m_BlockZ(a_BlockZ)
+{
+ m_SlotAreas.push_back(new cSlotAreaEnchanting(*this));
+ m_SlotAreas.push_back(new cSlotAreaInventory(*this));
+ m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
+}
+
+
+
+
+
+void cEnchantingWindow::SetProperty(int a_Property, int a_Value)
+{
+ m_PropertyValue[a_Property] = a_Value;
+
+ super::SetProperty(a_Property, a_Value);
+}
+
+
+
+
+
+void cEnchantingWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Player)
+{
+ m_PropertyValue[a_Property] = a_Value;
+
+ super::SetProperty(a_Property, a_Value, a_Player);
+}
+
+
+
+
+
+int cEnchantingWindow::GetPropertyValue(int a_Property)
+{
+ return m_PropertyValue[a_Property];
+}
+
+
+
+
+
+void cEnchantingWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
+{
+ a_PosX = m_BlockX;
+ a_PosY = m_BlockY;
+ a_PosZ = m_BlockZ;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cChestWindow:
cChestWindow::cChestWindow(cChestEntity * a_Chest) :
diff --git a/src/UI/Window.h b/src/UI/Window.h
index 030182888..1ca67bfd8 100644
--- a/src/UI/Window.h
+++ b/src/UI/Window.h
@@ -136,11 +136,11 @@ public:
void SetWindowTitle(const AString & a_WindowTitle ) { m_WindowTitle = a_WindowTitle; }
/// Sends the UpdateWindowProperty (0x69) packet to all clients of the window
- void SetProperty(int a_Property, int a_Value);
+ virtual void SetProperty(int a_Property, int a_Value);
/// Sends the UpdateWindowPropert(0x69) packet to the specified player
- void SetProperty(int a_Property, int a_Value, cPlayer & a_Player);
-
+ virtual void SetProperty(int a_Property, int a_Value, cPlayer & a_Player);
+
// tolua_end
void OwnerDestroyed(void);
@@ -165,7 +165,7 @@ public:
/// Used by cSlotAreas to send individual slots to clients, a_RelativeSlotNum is the slot number relative to a_SlotArea
void SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum);
-
+
protected:
cSlotAreas m_SlotAreas;
@@ -231,6 +231,32 @@ public:
+class cEnchantingWindow :
+ public cWindow
+{
+ typedef cWindow super;
+public:
+ cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
+ virtual void SetProperty(int a_Property, int a_Value, cPlayer & a_Player) override;
+ virtual void SetProperty(int a_Property, int a_Value) override;
+
+ /** Return the Value of a Property */
+ int GetPropertyValue(int a_Property);
+
+ /** Set the Position Values to the Position of the Enchantment Table */
+ void GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ);
+
+ cSlotArea * m_SlotArea;
+
+protected:
+ int m_PropertyValue[3];
+ int m_BlockX, m_BlockY, m_BlockZ;
+};
+
+
+
+
+
class cFurnaceWindow :
public cWindow
{