====== cLuaWindow class ======
This class is used by plugins wishing to display a custom window to the player, unrelated to block entities or entities near the player. The window can be of any type and have any contents that the plugin defines. Callbacks for when the player modifies the window contents and when the player closes the window can be set.

This class inherits from the [[API:cWindow|cWindow]] class, so all cWindow's functions and constants can be used, in addition to the cLuaWindow-specific functions listed below.

The contents of this window are represented by a [[API:cItemGrid|cItemGrid]] internally; you can get the cItemGrid object by calling the GetContents() function. Note that the player's inventory is always appended to this window and is not part of the cItemGrid representing the contents. Use either [[API:cWindow|cWindow]]:GetSlot() etc. or [[API:cPlayer|cPlayer]]:GetInventory() to access the player inventory.

When creating a new cLuaWindow object, you need to specify both the window type and the contents' width and height. Note that MCServer accepts any combination of these, but opening a window for a player may crash their client if the contents' dimensions don't match the client's expectations.

To open the window for a player, call [[API:cPlayer|cPlayer]]:OpenWindow(). Multiple players can open window of the same cLuaWindow object. All players see the same items in the window's contents (like chest, unlike crafting table).

===== Functions =====
^ Function name ^ Parameters ^ Return value ^ Note ^
| () | WindowType, ContentsWidth, ContentsHeight, Title | | Creates a new object of this class |
| GetContents | | [[API:cItemGrid|cItemGrid]] | Returns the cItemGrid object representing the internal storage in this window |
| SetOnClosing | OnClosingCallback | | Sets the function that the window will call when it is about to be closed by a player |
| SetOnSlotChanged | OnSlotChangedCallback | | Sets the function that the window will call when a slot is changed by a player |

===== Callbacks ======
The object calls the following functions at the appropriate time:
==== OnClosing Callback ====
This callback, settabel via the SetOnClosing() function, will be called when the player tries to close the window, or the window is closed for any other reason (such as a player disconnecting).
<code lua>
function OnWindowClosing(a_Window, a_Player, a_CanRefuse)
</code>
The a_Window parameter is the cLuaWindow object representing the window, a_Player is the player for whom the window is about to close. a_CanRefuse specifies whether the callback can refuse the closing. If the callback returns true and a_CanRefuse is true, the window is not closed (internally, the server sends a new OpenWindow packet to the client).
==== OnSlotChanged Callback ====
This callback, settable via the SetOnSlotChanged() function, will be called whenever the contents of any slot in the window's contents (i. e. NOT in the player inventory!) changes.
<code lua>
function OnWindowSlotChanged(a_Window, a_SlotNum)
</code>
The a_Window parameter is the cLuaWindow object representing the window, a_SlotNum is the slot number. There is no reference to a [[API:cPlayer|cPlayer]], because the slot change needn't originate from the player action. To get or set the slot, you'll need to retrieve a cPlayer object, for example by calling [[API:cWorld|cWorld]]:DoWithPlayer().

Any returned values are ignored.

===== Example =====
This example is taken from the Debuggers plugin, used to test the API functionality. It opens a window and refuse to close it 3 times. It also logs slot changes to the server console.
<code lua>
-- Callback that refuses to close the window twice, then allows:
local Attempt = 1;
local OnClosing = function(Window, Player, CanRefuse)
	Player:SendMessage("Window closing attempt #" .. Attempt .. "; CanRefuse = " .. tostring(CanRefuse));
	Attempt = Attempt + 1;
	return CanRefuse and (Attempt <= 3);  -- refuse twice, then allow, unless CanRefuse is set to true
end

-- Log the slot changes:
local OnSlotChanged = function(Window, SlotNum)
	LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed.");
end

-- Set window contents:
-- a_Player is a cPlayer object received from the outside of this code fragment
local Window = cLuaWindow(cWindow.Hopper, 3, 3, "TestWnd");
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
Window:SetOnClosing(OnClosing);
Window:SetOnSlotChanged(OnSlotChanged);

-- Open the window:
a_Player:OpenWindow(Window);
</code>