summaryrefslogtreecommitdiffstats
path: root/source/UI
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-05-30 10:40:13 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-05-30 10:40:13 +0200
commit191479cd81d4f5dc6bc31a1d0b023528b2a62d3f (patch)
tree6ae50c41a69a85c8f7f25e5249615a00307ba03b /source/UI
parentFixed previous commit (diff)
downloadcuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar.gz
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar.bz2
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar.lz
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar.xz
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.tar.zst
cuberite-191479cd81d4f5dc6bc31a1d0b023528b2a62d3f.zip
Diffstat (limited to 'source/UI')
-rw-r--r--source/UI/SlotArea.cpp14
-rw-r--r--source/UI/SlotArea.h14
-rw-r--r--source/UI/Window.cpp209
-rw-r--r--source/UI/Window.h70
4 files changed, 283 insertions, 24 deletions
diff --git a/source/UI/SlotArea.cpp b/source/UI/SlotArea.cpp
index 1886c515c..0d26edbb7 100644
--- a/source/UI/SlotArea.cpp
+++ b/source/UI/SlotArea.cpp
@@ -232,7 +232,7 @@ cSlotAreaChest::cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow)
-const cItem * cSlotAreaChest::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
// a_SlotNum ranges from 0 to 26, use that to index the chest entity's inventory directly:
return &(m_Chest->GetSlot(a_SlotNum));
@@ -265,7 +265,7 @@ cSlotAreaDoubleChest::cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEnti
-const cItem * cSlotAreaDoubleChest::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaDoubleChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
// a_SlotNum ranges from 0 to 53, use that to index the correct chest's inventory:
if (a_SlotNum < 27)
@@ -486,7 +486,7 @@ cSlotAreaDropSpenser::cSlotAreaDropSpenser(cDropSpenserEntity * a_DropSpenser, c
-const cItem * cSlotAreaDropSpenser::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaDropSpenser::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
return &(m_DropSpenser->GetSlot(a_SlotNum));
}
@@ -545,7 +545,7 @@ void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a
-const cItem * cSlotAreaFurnace::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaFurnace::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
// a_SlotNum ranges from 0 to 2, query the items from the underlying furnace:
return m_Furnace->GetSlot(a_SlotNum);
@@ -595,7 +595,7 @@ void cSlotAreaInventoryBase::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAc
-const cItem * cSlotAreaInventoryBase::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaInventoryBase::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
// a_SlotNum ranges from 0 to 35, map that to the player's inventory slots according to the internal offset
return &a_Player.GetInventory().GetSlot(a_SlotNum + m_SlotOffset);
@@ -669,9 +669,9 @@ cSlotAreaTemporary::cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow)
-const cItem * cSlotAreaTemporary::GetSlot(int a_SlotNum, cPlayer & a_Player)
+const cItem * cSlotAreaTemporary::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
- cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID());
+ cItemMap::const_iterator itr = m_Items.find(a_Player.GetUniqueID());
if (itr == m_Items.end())
{
LOGERROR("cSlotAreaTemporary: player \"%s\" not found for slot %d!", a_Player.GetName().c_str(), a_SlotNum);
diff --git a/source/UI/SlotArea.h b/source/UI/SlotArea.h
index 8358f5316..cdf14baad 100644
--- a/source/UI/SlotArea.h
+++ b/source/UI/SlotArea.h
@@ -32,7 +32,7 @@ public:
int GetNumSlots(void) const { return m_NumSlots; }
/// Called to retrieve an item in the specified slot for the specified player. Must return a valid cItem.
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) = 0;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const = 0;
/// Called to set an item in the specified slot for the specified player
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) = 0;
@@ -78,7 +78,7 @@ public:
// Creative inventory's click handling is somewhat different from survival inventory's, handle that here:
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
@@ -154,7 +154,7 @@ public:
cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow);
// cSlotArea overrides:
- virtual const cItem * GetSlot (int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot (int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot (int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
virtual void OnPlayerAdded (cPlayer & a_Player) override;
virtual void OnPlayerRemoved(cPlayer & a_Player) override;
@@ -221,7 +221,7 @@ class cSlotAreaChest :
public:
cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow);
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
@@ -238,7 +238,7 @@ class cSlotAreaDoubleChest :
public:
cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow);
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
@@ -258,7 +258,7 @@ class cSlotAreaDropSpenser :
public:
cSlotAreaDropSpenser(cDropSpenserEntity * a_DropSpenser, cWindow & a_ParentWindow);
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
@@ -278,7 +278,7 @@ public:
cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow);
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
- virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
protected:
diff --git a/source/UI/Window.cpp b/source/UI/Window.cpp
index c2ce4127e..57a565a05 100644
--- a/source/UI/Window.cpp
+++ b/source/UI/Window.cpp
@@ -22,13 +22,13 @@ char cWindow::m_WindowIDCounter = 1;
-cWindow::cWindow(cWindow::WindowType a_WindowType, const AString & a_WindowTitle)
- : m_WindowID(1 + (m_WindowIDCounter++ % 127))
- , m_WindowType(a_WindowType)
- , m_WindowTitle(a_WindowTitle)
- , m_Owner(NULL)
- , m_IsDestroyed(false)
- , m_ShouldDistributeToHotbarFirst(true)
+cWindow::cWindow(cWindow::WindowType a_WindowType, const AString & a_WindowTitle) :
+ m_WindowID((++m_WindowIDCounter) % 127),
+ m_WindowType(a_WindowType),
+ m_WindowTitle(a_WindowTitle),
+ m_Owner(NULL),
+ m_IsDestroyed(false),
+ m_ShouldDistributeToHotbarFirst(true)
{
if (a_WindowType == Inventory)
{
@@ -67,6 +67,40 @@ int cWindow::GetNumSlots(void) const
+const cItem * cWindow::GetSlot(cPlayer & a_Player, int a_SlotNum) const
+{
+ // Return the item at the specified slot for the specified player
+ int LocalSlotNum = 0;
+ const cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum);
+ if (Area == NULL)
+ {
+ LOGWARNING("%s: requesting item from an invalid SlotArea (SlotNum %d), returning NULL.", __FUNCTION__, a_SlotNum);
+ return NULL;
+ }
+ return Area->GetSlot(LocalSlotNum, a_Player);
+}
+
+
+
+
+
+void cWindow::SetSlot(cPlayer & a_Player, int a_SlotNum, const cItem & a_Item)
+{
+ // Set the item to the specified slot for the specified player
+ int LocalSlotNum = 0;
+ cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum);
+ if (Area == NULL)
+ {
+ LOGWARNING("%s: requesting write to an invalid SlotArea (SlotNum %d), ignoring.", __FUNCTION__, a_SlotNum);
+ return;
+ }
+ Area->SetSlot(LocalSlotNum, a_Player, a_Item);
+}
+
+
+
+
+
void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const
{
a_Slots.clear();
@@ -102,7 +136,7 @@ void cWindow::Clicked(
{
if (a_WindowID != m_WindowID)
{
- LOG("WRONG WINDOW ID! (exp %d, got %d) received from \"%s\"", m_WindowID, a_WindowID, a_Player.GetName().c_str());
+ LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str());
return;
}
@@ -126,6 +160,12 @@ void cWindow::Clicked(
// Nothing needed
return;
}
+ case caLeftPaintBegin: OnPaintBegin (a_Player); return;
+ case caRightPaintBegin: OnPaintBegin (a_Player); return;
+ case caLeftPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return;
+ case caRightPaintProgress: OnPaintProgress(a_Player, a_SlotNum); return;
+ case caLeftPaintEnd: OnLeftPaintEnd (a_Player); return;
+ case caRightPaintEnd: OnRightPaintEnd(a_Player); return;
}
if (a_SlotNum < 0)
@@ -353,6 +393,159 @@ void cWindow::Destroy(void)
+cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum)
+{
+ if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots()))
+ {
+ LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1);
+ ASSERT(!"Invalid SlotNum");
+ return NULL;
+ }
+
+ // Iterate through all the SlotAreas, find the correct one
+ int LocalSlotNum = a_GlobalSlotNum;
+ for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
+ {
+ if (LocalSlotNum < (*itr)->GetNumSlots())
+ {
+ a_LocalSlotNum = LocalSlotNum;
+ return *itr;
+ }
+ LocalSlotNum -= (*itr)->GetNumSlots();
+ } // for itr - m_SlotAreas[]
+
+ // We shouldn't be here - the check at the beginnning should prevent this. Log and assert
+ LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum);
+ ASSERT(!"Invalid GetNumSlots");
+ return NULL;
+}
+
+
+
+
+
+const cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const
+{
+ if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots()))
+ {
+ LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1);
+ ASSERT(!"Invalid SlotNum");
+ return NULL;
+ }
+
+ // Iterate through all the SlotAreas, find the correct one
+ int LocalSlotNum = a_GlobalSlotNum;
+ for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
+ {
+ if (LocalSlotNum < (*itr)->GetNumSlots())
+ {
+ a_LocalSlotNum = LocalSlotNum;
+ return *itr;
+ }
+ LocalSlotNum -= (*itr)->GetNumSlots();
+ } // for itr - m_SlotAreas[]
+
+ // We shouldn't be here - the check at the beginnning should prevent this. Log and assert
+ LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum);
+ ASSERT(!"Invalid GetNumSlots");
+ return NULL;
+}
+
+
+
+
+
+void cWindow::OnPaintBegin(cPlayer & a_Player)
+{
+ // Prepares the internal structures for inventory painting from the specified player
+ a_Player.ClearInventoryPaintSlots();
+}
+
+
+
+
+
+void cWindow::OnPaintProgress(cPlayer & a_Player, int a_SlotNum)
+{
+ // Add the slot to the internal structures for inventory painting by the specified player
+ a_Player.AddInventoryPaintSlot(a_SlotNum);
+}
+
+
+
+
+
+void cWindow::OnLeftPaintEnd(cPlayer & a_Player)
+{
+ // Process the entire action stored in the internal structures for inventory painting
+ // distribute as many items as possible
+
+ const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots();
+ cItem ToDistribute(a_Player.GetDraggingItem());
+
+ if ((size_t)(ToDistribute.m_ItemCount) < SlotNums.size())
+ {
+ LOGWARNING("%s: Distributing less items (%d) than slots (%u)", __FUNCTION__, (int)ToDistribute.m_ItemCount, SlotNums.size());
+ // This doesn't seem to happen with the 1.5.1 client, so we don't worry about it for now
+ }
+
+ // Distribute to individual slots, keep track of how many items were actually distributed (full stacks etc.)
+ int NumDistributed = 0;
+ int ToEachSlot = (int)ToDistribute.m_ItemCount / SlotNums.size();
+ for (cSlotNums::const_iterator itr = SlotNums.begin(), end = SlotNums.end(); itr != end; ++itr)
+ {
+ int LocalSlotNum = 0;
+ cSlotArea * Area = GetSlotArea(*itr, LocalSlotNum);
+ if (Area == NULL)
+ {
+ LOGWARNING("%s: Bad SlotArea for slot %d", __FUNCTION__, *itr);
+ continue;
+ }
+
+ // Modify the item at the slot
+ cItem AtSlot(*Area->GetSlot(LocalSlotNum, a_Player));
+ int MaxStack = ItemHandler(AtSlot.m_ItemType)->GetMaxStackSize();
+ if (AtSlot.IsEmpty())
+ {
+ // Empty, just move all of it there:
+ cItem ToStore(ToDistribute);
+ ToStore.m_ItemCount = std::min(ToEachSlot, (int)MaxStack);
+ Area->SetSlot(LocalSlotNum, a_Player, ToStore);
+ NumDistributed += ToStore.m_ItemCount;
+ }
+ else
+ {
+ int CanStore = std::min(ToEachSlot, (int)MaxStack - AtSlot.m_ItemCount);
+ AtSlot.m_ItemCount += CanStore;
+ Area->SetSlot(LocalSlotNum, a_Player, AtSlot);
+ NumDistributed += CanStore;
+ }
+ } // for itr - SlotNums[]
+
+ // Remove the items distributed from the dragging item:
+ a_Player.GetDraggingItem().m_ItemCount -= NumDistributed;
+ if (a_Player.GetDraggingItem().m_ItemCount == 0)
+ {
+ a_Player.GetDraggingItem().Empty();
+ }
+
+ SendWholeWindow(*a_Player.GetClientHandle());
+}
+
+
+
+
+
+void cWindow::OnRightPaintEnd(cPlayer & a_Player)
+{
+ // Process the entire action stored in the internal structures for inventory painting
+ // distribute one item into each slot
+}
+
+
+
+
+
void cWindow::SendWholeWindow(cClientHandle & a_Client)
{
a_Client.SendWholeInventory(*this);
diff --git a/source/UI/Window.h b/source/UI/Window.h
index 86ea1849b..ae06ecf6a 100644
--- a/source/UI/Window.h
+++ b/source/UI/Window.h
@@ -9,7 +9,7 @@
#pragma once
-#include "../Item.h"
+#include "../ItemGrid.h"
@@ -31,6 +31,8 @@ typedef std::vector<cSlotArea *> cSlotAreas;
+// tolua_begin
+
/**
Represents a UI window.
@@ -39,6 +41,7 @@ When there's no player using a window, it is destroyed.
A window consists of several areas of slots with similar functionality - for example the crafting grid area, or
the inventory area. Each area knows what its slots are (GetSlot() function) and can handle mouse clicks.
The window acts only as a top-level container for those areas, redirecting the click events to the correct areas.
+Inventory painting, introduced in 1.5, is handled by the window, too
*/
class cWindow
{
@@ -58,22 +61,35 @@ public:
Hopper = 9,
};
+ // tolua_end
+
static const int c_NumInventorySlots = 36;
cWindow(WindowType a_WindowType, const AString & a_WindowTitle);
virtual ~cWindow();
char GetWindowID(void) const { return m_WindowID; }
- int GetWindowType(void) const { return m_WindowType; }
+ int GetWindowType(void) const { return m_WindowType; } // tolua_export
cWindowOwner * GetOwner(void) { return m_Owner; }
void SetOwner( cWindowOwner * a_Owner ) { m_Owner = a_Owner; }
int GetNumSlots(void) const;
+ // tolua_begin
+
+ /// Returns the item at the specified slot for the specified player. Returns NULL if invalid SlotNum requested
+ const cItem * GetSlot(cPlayer & a_Player, int a_SlotNum) const;
+
+ /// Sets the item to the specified slot for the specified player
+ void SetSlot(cPlayer & a_Player, int a_SlotNum, const cItem & a_Item);
+
+ // tolua_end
+
/// Fills a_Slots with the slots read from m_SlotAreas[], for the specified player
void GetSlots(cPlayer & a_Player, cItems & a_Slots) const;
+ /// Handles a click event from a player
void Clicked(
cPlayer & a_Player, int a_WindowID,
short a_SlotNum, eClickAction a_ClickAction,
@@ -87,8 +103,12 @@ public:
void BroadcastWholeWindow(void);
void BroadcastInventoryProgress(short a_Progressbar, short a_Value);
+ // tolua_begin
+
const AString & GetWindowTitle() const { return m_WindowTitle; }
void SetWindowTitle(const AString & a_WindowTitle ) { m_WindowTitle = a_WindowTitle; }
+
+ // tolua_end
void OwnerDestroyed(void);
@@ -125,6 +145,31 @@ protected:
static char m_WindowIDCounter;
void Destroy(void);
+
+ /** Returns the correct slot area for the specified window-global SlotNum
+ Also returns the area-local SlotNum corresponding to the GlobalSlotNum
+ If the global SlotNum is out of range, returns NULL
+ */
+ cSlotArea * GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum);
+
+ /** Returns the correct slot area for the specified window-global SlotNum
+ Also returns the area-local SlotNum corresponding to the GlobalSlotNum
+ If the global SlotNum is out of range, returns NULL.
+ Const version.
+ */
+ const cSlotArea * GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const;
+
+ /// Prepares the internal structures for inventory painting from the specified player
+ void OnPaintBegin(cPlayer & a_Player);
+
+ /// Adds the slot to the internal structures for inventory painting by the specified player
+ void OnPaintProgress(cPlayer & a_Player, int a_SlotNum);
+
+ /// Processes the entire action stored in the internal structures for inventory painting; distributes as many items as possible
+ void OnLeftPaintEnd(cPlayer & a_Player);
+
+ /// Processes the entire action stored in the internal structures for inventory painting; distributes one item into each slot
+ void OnRightPaintEnd(cPlayer & a_Player);
} ;
@@ -196,3 +241,24 @@ protected:
+
+// tolua_begin
+
+/// A window that has been created by a Lua plugin and is handled entirely by that plugin
+class cLuaWindow :
+ public cWindow
+{
+public:
+ /// Create a window of the specified type, with a slot grid of a_SlotsX * a_SlotsY size
+ cLuaWindow(cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString & a_Title);
+
+ // tolua_end
+
+protected:
+ /// Contents of the non-inventory part
+ cItemGrid m_Contents;
+} ;
+
+
+
+