Cuberite
A lightweight, fast and extensible game server for Minecraft
LuaWindow.cpp
Go to the documentation of this file.
1 // LuaWindow.cpp
2 
3 // Implements the cLuaWindow class representing a virtual window that plugins may create and open for the player
4 
5 #include "Globals.h"
6 #include "LuaWindow.h"
7 #include "../Entities/Player.h"
8 #include "../UI/SlotArea.h"
9 #include "PluginLua.h"
10 #include "lua/src/lauxlib.h" // Needed for LUA_REFNIL
11 #include "../Root.h"
12 #include "../ClientHandle.h"
13 
14 
15 
16 
18 // cLuaWindow:
19 
20 cLuaWindow::cLuaWindow(cLuaState & a_LuaState, cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString & a_Title) :
21  Super(a_WindowType, a_Title),
22  m_Contents(a_SlotsX, a_SlotsY),
23  m_LuaState(a_LuaState.QueryCanonLuaState())
24 {
25  ASSERT(m_LuaState != nullptr); // We must have a valid Lua state; this assert fails only if there was no Canon Lua state
26 
27  m_Contents.AddListener(*this);
28  m_SlotAreas.push_back(new cSlotAreaItemGrid(m_Contents, *this));
29 
30  // If appropriate, add an Armor slot area:
31  switch (a_WindowType)
32  {
35  {
36  m_SlotAreas.push_back(new cSlotAreaArmor(*this));
37  break;
38  }
39  default:
40  {
41  break;
42  }
43  }
44  m_SlotAreas.push_back(new cSlotAreaInventory(*this));
45  m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
46 }
47 
48 
49 
50 
51 
53 {
55 
56  // Close open lua window from players, to avoid dangling pointers
57  cRoot::Get()->ForEachPlayer([this](cPlayer & a_Player)
58  {
59  if (a_Player.GetWindow() == this)
60  {
61  a_Player.CloseWindow(false);
62  }
63  return false;
64  }
65  );
66 
67  // Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's
68  // destructor, when the member is already gone.
69  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
70  {
71  delete *itr;
72  }
73  m_SlotAreas.clear();
74 
75  ASSERT(m_OpenedBy.empty());
76 }
77 
78 
79 
80 
81 
83 {
84  // Only one Lua state can be a cLuaWindow object callback:
85  ASSERT(a_OnClicked->IsSameLuaState(*m_LuaState));
86 
87  // Store the new reference, releasing the old one if appropriate:
88  m_OnClicked = std::move(a_OnClicked);
89 }
90 
91 
92 
93 
94 
96 {
97  // Only one Lua state can be a cLuaWindow object callback:
98  ASSERT(a_OnClosing->IsSameLuaState(*m_LuaState));
99 
100  // Store the new reference, releasing the old one if appropriate:
101  m_OnClosing = std::move(a_OnClosing);
102 }
103 
104 
105 
106 
107 
109 {
110  // Only one Lua state can be a cLuaWindow object callback:
111  ASSERT(a_OnSlotChanged->IsSameLuaState(*m_LuaState));
112 
113  // Store the new reference, releasing the old one if appropriate:
114  m_OnSlotChanged = std::move(a_OnSlotChanged);
115 }
116 
117 
118 
119 
120 
122 {
123  // If the first player is opening the window, create a Lua Reference to the window object so that Lua will not GC it until the last player closes the window:
124  if (m_PlayerCount == 0)
125  {
127  }
128 
129  ++m_PlayerCount;
130  Super::OpenedByPlayer(a_Player);
131 }
132 
133 
134 
135 
136 
137 bool cLuaWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
138 {
139  // First notify the plugin through the registered callback:
140  if (m_OnClosing != nullptr)
141  {
142  bool res;
143  if (
144  m_OnClosing->Call(this, &a_Player, a_CanRefuse, cLuaState::Return, res) && // The callback succeeded
145  res // The callback says not to close the window
146  )
147  {
148  // The callback disagrees (the higher levels check the CanRefuse flag compliance)
149  return false;
150  }
151  }
152 
153  // If the last player has closed the window, release the Lua reference, so that Lua may GC the object:
154  --m_PlayerCount;
155  if (m_PlayerCount == 0)
156  {
157  m_LuaRef.UnRef();
158  }
159 
160  return Super::ClosedByPlayer(a_Player, a_CanRefuse);
161 }
162 
163 
164 
165 
166 
168 {
169  Super::Destroy();
170 
171  // Lua will take care of this object, it will garbage-collect it, so we must not delete it!
172  m_IsDestroyed = false;
173 }
174 
175 
176 
177 
178 
179 void cLuaWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
180 {
181  cSlotAreas Areas;
182  for (auto && Area : m_SlotAreas)
183  {
184  if (Area != a_ClickedArea)
185  {
186  Areas.push_back(Area);
187  }
188  }
189 
190  Super::DistributeStackToAreas(a_ItemStack, a_Player, Areas, a_ShouldApply, false);
191 }
192 
193 
194 
195 
196 
197 void cLuaWindow::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
198 {
199  if (a_ItemGrid != &m_Contents)
200  {
201  ASSERT(!"Invalid ItemGrid in callback");
202  return;
203  }
204 
205  // If an OnSlotChanged callback has been registered, call it:
206  if (m_OnSlotChanged != nullptr)
207  {
208  m_OnSlotChanged->Call(this, a_SlotNum);
209  }
210 }
211 
212 
213 
214 
215 
216 void cLuaWindow::Clicked(cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
217 {
218  if (m_OnClicked != nullptr)
219  {
220  // Plugin can stop a click
221  bool res;
222  if (m_OnClicked->Call(this, &a_Player, a_SlotNum, a_ClickAction, a_ClickedItem, cLuaState::Return, res) && res)
223  {
224  // Tell the client the actual state of the window
225  a_Player.GetClientHandle()->SendInventorySlot(-1, -1, a_Player.GetDraggingItem());
227  return;
228  }
229  }
230 
231  cWindow::Clicked(a_Player, a_WindowID, a_SlotNum, a_ClickAction, a_ClickedItem);
232 }
233 
234 
235 
236 
Handles the main inventory of each player, excluding the armor and hotbar.
Definition: SlotArea.h:117
void CreateFromObject(cLuaState &a_LuaState, T &&a_Object)
Creates a Lua reference to the specified object instance in the specified Lua state.
Definition: LuaState.h:194
virtual void Clicked(cPlayer &a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem &a_ClickedItem)
Handles a click event from a player.
Definition: Window.cpp:199
virtual ~cLuaWindow() override
Definition: LuaWindow.cpp:52
cWindow * GetWindow(void)
Definition: Player.h:239
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse) override
Called when a player closes this window; notifies all slot areas.
Definition: LuaWindow.cpp:137
Definition: Player.h:27
void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem &a_Item)
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
Definition: Player.h:437
cLuaState::cCallbackPtr m_OnClicked
The Lua callback to call when the player clicked on a slot.
Definition: LuaWindow.h:71
void DistributeStackToAreas(cItem &a_ItemStack, cPlayer &a_Player, cSlotAreas &a_AreasInOrder, bool a_ShouldApply, bool a_BackFill)
Called from DistributeStack() to distribute the stack into a_AreasInOrder; Modifies a_ItemStack as it...
Definition: Window.cpp:401
void UnRef(void)
Removes the bound reference, resets the object to Unbound state.
Definition: LuaState.cpp:2497
virtual void OpenedByPlayer(cPlayer &a_Player) override
Definition: LuaWindow.cpp:121
Encapsulates a Lua state and provides some syntactic sugar for common operations. ...
Definition: LuaState.h:57
Handles the armor area of the player's inventory.
Definition: SlotArea.h:168
void SetOnClosing(cLuaState::cCallbackPtr &&a_OnClosing)
Sets the Lua callback function to call when the window is about to close.
Definition: LuaWindow.cpp:95
bool m_IsDestroyed
Definition: Window.h:191
void AddListener(cListener &a_Listener)
Adds a callback that gets called whenever a slot changes.
Definition: ItemGrid.cpp:785
virtual void OnSlotChanged(cItemGrid *a_ItemGrid, int a_SlotNum) override
Called whenever a slot changes.
Definition: LuaWindow.cpp:197
eClickAction
Individual actions sent in the WindowClick packet.
Definition: Defines.h:73
virtual void DistributeStack(cItem &a_ItemStack, int a_Slot, cPlayer &a_Player, cSlotArea *a_ClickedArea, bool a_ShouldApply) override
Called on shift-clicking to distribute the stack into other areas; Modifies a_ItemStack as it is dist...
Definition: LuaWindow.cpp:179
bool ForEachPlayer(cPlayerListCallback a_Callback)
Calls the callback for each player in all worlds.
Definition: Root.cpp:854
cLuaState::cCallbackPtr m_OnSlotChanged
The Lua callback to call when a slot has changed.
Definition: LuaWindow.h:77
void RemoveListener(cListener &a_Listener)
Removes a slot-change-callback.
Definition: ItemGrid.cpp:796
Handles any slot area that is representing a cItemGrid; same items for all the players.
Definition: SlotArea.h:191
cItemGrid m_Contents
Contents of the non-inventory part.
Definition: LuaWindow.h:65
std::vector< cSlotArea * > cSlotAreas
Definition: Window.h:34
void SetOnClicked(cLuaState::cCallbackPtr &&a_OnClicked)
Sets the Lua callback to call when the player clicks on the window.
Definition: LuaWindow.cpp:82
virtual void OpenedByPlayer(cPlayer &a_Player)
Definition: Window.cpp:286
std::unique_ptr< cCallback > cCallbackPtr
Definition: LuaState.h:328
virtual void Clicked(cPlayer &a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem &a_ClickedItem) override
Handles a click event from a player.
Definition: LuaWindow.cpp:216
cLuaWindow(cLuaState &a_LuaState, cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString &a_Title)
Create a window of the specified type, with a slot grid of a_SlotsX * a_SlotsY size.
Definition: LuaWindow.cpp:20
#define ASSERT(x)
Definition: Globals.h:335
void CloseWindow(bool a_CanRefuse=true)
Closes the current window, resets current window to m_InventoryWindow.
Definition: Player.cpp:1370
cPlayerList m_OpenedBy
Definition: Window.h:189
std::atomic< int > m_PlayerCount
Number of players that are currently using the window.
Definition: LuaWindow.h:81
static const cRet Return
Definition: LuaState.h:446
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
Definition: Window.cpp:308
std::string AString
Definition: StringUtils.h:13
cLuaState * m_LuaState
The canon Lua state that has opened the window and owns the m_LuaRef.
Definition: LuaWindow.h:68
static cRoot * Get()
Definition: Root.h:51
cLuaState::cRef m_LuaRef
Reference to self, to keep Lua from GCing the object while a player is still using it...
Definition: LuaWindow.h:85
Represents a UI window.
Definition: Window.h:53
virtual void Destroy(void) override
Sets the internal flag as "destroyed"; notifies the owner that the window is destroying.
Definition: LuaWindow.cpp:167
cSlotAreas m_SlotAreas
Definition: Window.h:182
virtual void Destroy(void)
Sets the internal flag as "destroyed"; notifies the owner that the window is destroying.
Definition: Window.cpp:470
Handles the hotbar of each player.
Definition: SlotArea.h:134
WindowType
Definition: Window.h:56
Definition: Item.h:36
void SetOnSlotChanged(cLuaState::cCallbackPtr &&a_OnSlotChanged)
Sets the Lua callback function to call when a slot is changed.
Definition: LuaWindow.cpp:108
cLuaState::cCallbackPtr m_OnClosing
The Lua callback to call when the window is closing for any player.
Definition: LuaWindow.h:74
cClientHandle * GetClientHandle(void) const
Returns the raw client handle associated with the player.
Definition: Player.h:254
void BroadcastWholeWindow(void)
Sends the contents of the whole window to all clients of this window.
Definition: Window.cpp:738