summaryrefslogtreecommitdiffstats
path: root/src/UI
diff options
context:
space:
mode:
Diffstat (limited to 'src/UI')
-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
4 files changed, 425 insertions, 6 deletions
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 419d919bd..2d58388b1 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();
}
-
}
@@ -594,6 +596,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) + (int)floor((float)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
{