summaryrefslogtreecommitdiffstats
path: root/source/UI
diff options
context:
space:
mode:
authorAlexander Harkness <bearbin@gmail.com>2013-11-24 15:19:41 +0100
committerAlexander Harkness <bearbin@gmail.com>2013-11-24 15:19:41 +0100
commit675b4aa878f16291ce33fced48a2bc7425f635ae (patch)
tree409914df27a98f65adf866da669429c4de141b6f /source/UI
parentLineBlockTracer: Using the coord-based block faces. (diff)
downloadcuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.gz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.bz2
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.lz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.xz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.zst
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.zip
Diffstat (limited to 'source/UI')
-rw-r--r--source/UI/SlotArea.cpp897
-rw-r--r--source/UI/SlotArea.h313
-rw-r--r--source/UI/Window.cpp886
-rw-r--r--source/UI/Window.h300
-rw-r--r--source/UI/WindowOwner.h125
5 files changed, 0 insertions, 2521 deletions
diff --git a/source/UI/SlotArea.cpp b/source/UI/SlotArea.cpp
deleted file mode 100644
index 7fd7cd996..000000000
--- a/source/UI/SlotArea.cpp
+++ /dev/null
@@ -1,897 +0,0 @@
-
-// SlotArea.cpp
-
-// Implements the cSlotArea class and its descendants
-
-#include "Globals.h"
-#include "SlotArea.h"
-#include "../Entities/Player.h"
-#include "../BlockEntities/ChestEntity.h"
-#include "../BlockEntities/DropSpenserEntity.h"
-#include "../BlockEntities/FurnaceEntity.h"
-#include "../Items/ItemHandler.h"
-#include "Window.h"
-#include "../CraftingRecipes.h"
-#include "../Root.h"
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotArea:
-
-cSlotArea::cSlotArea(int a_NumSlots, cWindow & a_ParentWindow) :
- m_NumSlots(a_NumSlots),
- m_ParentWindow(a_ParentWindow)
-{
-}
-
-
-
-
-
-void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
-{
- /*
- LOGD("Slot area with %d slots clicked at slot number %d, clicked item %s, slot item %s",
- GetNumSlots(), a_SlotNum,
- ItemToFullString(a_ClickedItem).c_str(),
- ItemToFullString(*GetSlot(a_SlotNum, a_Player)).c_str()
- );
- */
-
- 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;
- }
- }
-
- 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:
- {
- if (DraggingItem.m_ItemType <= 0) // Empty-handed?
- {
- DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f);
- Slot.m_ItemCount -= DraggingItem.m_ItemCount;
- DraggingItem.m_ItemType = Slot.m_ItemType;
- DraggingItem.m_ItemDamage = Slot.m_ItemDamage;
-
- if (Slot.m_ItemCount <= 0)
- {
- Slot.Empty();
- }
- }
- else if ((Slot.m_ItemType <= 0) || DraggingItem.IsEqual(Slot))
- {
- // Drop one item in slot
- cItemHandler * Handler = ItemHandler(Slot.m_ItemType);
- if ((DraggingItem.m_ItemCount > 0) && (Slot.m_ItemCount < Handler->GetMaxStackSize()))
- {
- Slot.m_ItemType = DraggingItem.m_ItemType;
- Slot.m_ItemCount++;
- Slot.m_ItemDamage = DraggingItem.m_ItemDamage;
- DraggingItem.m_ItemCount--;
- }
- if (DraggingItem.m_ItemCount <= 0)
- {
- DraggingItem.Empty();
- }
- }
- else if (!DraggingItem.IsEqual(Slot))
- {
- // Swap contents
- cItem tmp(DraggingItem);
- DraggingItem = Slot;
- Slot = tmp;
- }
- break;
- }
-
- case caLeftClick:
- {
- // Left-clicked
- if (!DraggingItem.IsEqual(Slot))
- {
- // Switch contents
- cItem tmp(DraggingItem);
- DraggingItem = Slot;
- Slot = tmp;
- }
- else
- {
- // Same type, add items:
- cItemHandler * Handler = ItemHandler(DraggingItem.m_ItemType);
- int FreeSlots = Handler->GetMaxStackSize() - Slot.m_ItemCount;
- if (FreeSlots < 0)
- {
- ASSERT(!"Bad item stack size - where did we get more items in a slot than allowed?");
- 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)
- {
- 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();
- }
-
-}
-
-
-
-
-
-void cSlotArea::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem)
-{
- // Make a copy of the slot, distribute it among the other areas, then update the slot to contain the leftover:
- cItem Slot(*GetSlot(a_SlotNum, a_Player));
- m_ParentWindow.DistributeStack(Slot, a_Player, this, true);
- if (Slot.IsEmpty())
- {
- // Empty the slot completely, the cilent doesn't like left-over ItemType with zero count
- Slot.Empty();
- }
- SetSlot(a_SlotNum, a_Player, Slot);
-
- // Some clients try to guess our actions and not always right (armor slots in 1.2.5), so we fix them:
- m_ParentWindow.BroadcastWholeWindow();
-}
-
-
-
-
-
-void cSlotArea::DblClicked(cPlayer & a_Player, int a_SlotNum)
-{
- cItem & Dragging = a_Player.GetDraggingItem();
- if (Dragging.IsEmpty())
- {
- // Move the item in the dblclicked slot into hand:
- Dragging = *GetSlot(a_SlotNum, a_Player);
- cItem EmptyItem;
- SetSlot(a_SlotNum, a_Player, EmptyItem);
- }
- if (Dragging.IsEmpty())
- {
- LOGD("%s DblClicked with an empty hand over empty slot, ignoring", a_Player.GetName().c_str());
- return;
- }
-
- // Add as many items from the surrounding area into hand as possible:
- // First skip full stacks, then if there's still space, process full stacks as well:
- if (!m_ParentWindow.CollectItemsToHand(Dragging, *this, a_Player, false))
- {
- m_ParentWindow.CollectItemsToHand(Dragging, *this, a_Player, true);
- }
-
- m_ParentWindow.BroadcastWholeWindow(); // We need to broadcast, in case the window was a chest opened by multiple players
-}
-
-
-
-
-
-void cSlotArea::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots)
-{
- for (int i = 0; i < m_NumSlots; i++)
- {
- const cItem * Slot = GetSlot(i, a_Player);
- if (!Slot->IsStackableWith(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots))
- {
- // Different items
- continue;
- }
- int NumFit = ItemHandler(Slot->m_ItemType)->GetMaxStackSize() - Slot->m_ItemCount;
- if (NumFit <= 0)
- {
- // Full stack already
- continue;
- }
- if (NumFit > a_ItemStack.m_ItemCount)
- {
- NumFit = a_ItemStack.m_ItemCount;
- }
- if (a_Apply)
- {
- cItem NewSlot(a_ItemStack);
- NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit;
- SetSlot(i, a_Player, NewSlot);
- }
- a_ItemStack.m_ItemCount -= NumFit;
- if (a_ItemStack.IsEmpty())
- {
- return;
- }
- } // for i - Slots
-}
-
-
-
-
-
-bool cSlotArea::CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks)
-{
- int NumSlots = GetNumSlots();
- for (int i = 0; i < NumSlots; i++)
- {
- const cItem & SlotItem = *GetSlot(i, a_Player);
- if (!SlotItem.IsStackableWith(a_Dragging))
- {
- continue;
- }
- int ToMove = a_Dragging.GetMaxStackSize() - a_Dragging.m_ItemCount;
- if (ToMove > SlotItem.m_ItemCount)
- {
- ToMove = SlotItem.m_ItemCount;
- }
- a_Dragging.m_ItemCount += ToMove;
- cItem NewSlot(SlotItem);
- NewSlot.m_ItemCount -= ToMove;
- SetSlot(i, a_Player, NewSlot);
- if (!NewSlot.IsEmpty())
- {
- // There are leftovers in the slot, so a_Dragging must be full
- return true;
- }
- } // for i - Slots[]
- // a_Dragging may be full if there were exactly the number of items needed to fill it
- return a_Dragging.IsFullStack();
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaChest:
-
-cSlotAreaChest::cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow) :
- cSlotArea(27, a_ParentWindow),
- m_Chest(a_Chest)
-{
-}
-
-
-
-
-
-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));
-}
-
-
-
-
-
-void cSlotAreaChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- m_Chest->SetSlot(a_SlotNum, a_Item);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaDoubleChest:
-
-cSlotAreaDoubleChest::cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow) :
- cSlotArea(54, a_ParentWindow),
- m_TopChest(a_TopChest),
- m_BottomChest(a_BottomChest)
-{
-}
-
-
-
-
-
-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)
- {
- return &(m_TopChest->GetSlot(a_SlotNum));
- }
- else
- {
- return &(m_BottomChest->GetSlot(a_SlotNum - 27));
- }
-}
-
-
-
-
-
-void cSlotAreaDoubleChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- if (a_SlotNum < 27)
- {
- m_TopChest->SetSlot(a_SlotNum, a_Item);
- }
- else
- {
- m_BottomChest->SetSlot(a_SlotNum - 27, a_Item);
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaCrafting:
-
-cSlotAreaCrafting::cSlotAreaCrafting(int a_GridSize, cWindow & a_ParentWindow) :
- cSlotAreaTemporary(1 + a_GridSize * a_GridSize, a_ParentWindow),
- m_GridSize(a_GridSize)
-{
- ASSERT((a_GridSize == 2) || (a_GridSize == 3));
-}
-
-
-
-
-
-void cSlotAreaCrafting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
-{
- // Override for craft result slot
- if (a_SlotNum == 0)
- {
- if ((a_ClickAction == caShiftLeftClick) || (a_ClickAction == caShiftRightClick))
- {
- ShiftClickedResult(a_Player);
- }
- else
- {
- ClickedResult(a_Player);
- }
- return;
- }
- super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
- UpdateRecipe(a_Player);
-}
-
-
-
-
-
-void cSlotAreaCrafting::DblClicked(cPlayer & a_Player, int a_SlotNum)
-{
- if (a_SlotNum == 0)
- {
- // Dbl-clicking the crafting result slot shouldn't collect items to hand
- return;
- }
- super::DblClicked(a_Player, a_SlotNum);
-}
-
-
-
-
-
-void cSlotAreaCrafting::OnPlayerRemoved(cPlayer & a_Player)
-{
- // Toss all items on the crafting grid:
- TossItems(a_Player, 1, m_NumSlots);
-
- // Remove the current recipe from the player -> recipe map:
- for (cRecipeMap::iterator itr = m_Recipes.begin(), end = m_Recipes.end(); itr != end; ++itr)
- {
- if (itr->first == a_Player.GetUniqueID())
- {
- // Remove the player from the recipe map:
- m_Recipes.erase(itr);
- return;
- }
- } // for itr - m_Recipes[]
- // Player not found - that is acceptable
-}
-
-
-
-
-
-void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
-{
- const cItem * ResultSlot = GetSlot(0, a_Player);
- cItem & DraggingItem = a_Player.GetDraggingItem();
-
- // Get the current recipe:
- cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);
-
- cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1;
- cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize);
-
- // If possible, craft:
- if (DraggingItem.IsEmpty())
- {
- DraggingItem = Recipe.GetResult();
- Recipe.ConsumeIngredients(Grid);
- Grid.CopyToItems(PlayerSlots);
- }
- else if (DraggingItem.IsEqual(Recipe.GetResult()))
- {
- cItemHandler * Handler = ItemHandler(Recipe.GetResult().m_ItemType);
- if (DraggingItem.m_ItemCount + Recipe.GetResult().m_ItemCount <= Handler->GetMaxStackSize())
- {
- DraggingItem.m_ItemCount += Recipe.GetResult().m_ItemCount;
- Recipe.ConsumeIngredients(Grid);
- Grid.CopyToItems(PlayerSlots);
- }
- }
-
- // Get the new recipe and update the result slot:
- UpdateRecipe(a_Player);
-
- // We're done. Send all changes to the client and bail out:
- m_ParentWindow.BroadcastWholeWindow();
-}
-
-
-
-
-
-void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player)
-{
- cItem Result(*GetSlot(0, a_Player));
- if (Result.IsEmpty())
- {
- return;
- }
- cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1;
- do
- {
- // Try distributing the result. If it fails, bail out:
- cItem ResultCopy(Result);
- m_ParentWindow.DistributeStack(ResultCopy, a_Player, this, false);
- if (!ResultCopy.IsEmpty())
- {
- // Couldn't distribute all of it. Bail out
- return;
- }
-
- // Distribute the result, this time for real:
- ResultCopy = Result;
- m_ParentWindow.DistributeStack(ResultCopy, a_Player, this, true);
-
- // Remove the ingredients from the crafting grid and update the recipe:
- cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);
- cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize);
- Recipe.ConsumeIngredients(Grid);
- Grid.CopyToItems(PlayerSlots);
- UpdateRecipe(a_Player);
- if (!Recipe.GetResult().IsEqual(Result))
- {
- // The recipe has changed, bail out
- return;
- }
- } while (true);
-}
-
-
-
-
-
-void cSlotAreaCrafting::UpdateRecipe(cPlayer & a_Player)
-{
- cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize);
- cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);
- cRoot::Get()->GetCraftingRecipes()->GetRecipe(&a_Player, Grid, Recipe);
- SetSlot(0, a_Player, Recipe.GetResult());
- m_ParentWindow.SendSlot(a_Player, this, 0);
-}
-
-
-
-
-
-cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
-{
- for (cRecipeMap::iterator itr = m_Recipes.begin(), end = m_Recipes.end(); itr != end; ++itr)
- {
- if (itr->first == a_Player.GetUniqueID())
- {
- return itr->second;
- }
- } // for itr - m_Recipes[]
-
- // Not found. Add a new one:
- cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize);
- cCraftingRecipe Recipe(Grid);
- cRoot::Get()->GetCraftingRecipes()->GetRecipe(&a_Player, Grid, Recipe);
- m_Recipes.push_back(std::make_pair(a_Player.GetUniqueID(), Recipe));
- return m_Recipes.back().second;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaFurnace:
-
-cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow) :
- cSlotArea(3, a_ParentWindow),
- m_Furnace(a_Furnace)
-{
- m_Furnace->GetContents().AddListener(*this);
-}
-
-
-
-
-
-cSlotAreaFurnace::~cSlotAreaFurnace()
-{
- m_Furnace->GetContents().RemoveListener(*this);
-}
-
-
-
-
-
-void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
-{
- super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
-
- if (m_Furnace == NULL)
- {
- LOGERROR("cSlotAreaFurnace::Clicked(): m_Furnace == NULL");
- ASSERT(!"cSlotAreaFurnace::Clicked(): m_Furnace == NULL");
- return;
- }
-}
-
-
-
-
-
-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));
-}
-
-
-
-
-
-void cSlotAreaFurnace::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- m_Furnace->SetSlot(a_SlotNum, a_Item);
-}
-
-
-
-
-
-void cSlotAreaFurnace::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
-{
- // Something has changed in the window, broadcast the entire window to all clients
- ASSERT(a_ItemGrid == &(m_Furnace->GetContents()));
-
- m_ParentWindow.BroadcastWholeWindow();
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaInventoryBase:
-
-cSlotAreaInventoryBase::cSlotAreaInventoryBase(int a_NumSlots, int a_SlotOffset, cWindow & a_ParentWindow) :
- cSlotArea(a_NumSlots, a_ParentWindow),
- m_SlotOffset(a_SlotOffset)
-{
-}
-
-
-
-
-
-void cSlotAreaInventoryBase::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
-{
- if (a_Player.IsGameModeCreative() && (m_ParentWindow.GetWindowType() == cWindow::wtInventory))
- {
- // Creative inventory must treat a_ClickedItem as a DraggedItem instead, replacing the inventory slot with it
- SetSlot(a_SlotNum, a_Player, a_ClickedItem);
- return;
- }
-
- // Survival inventory and all other windows' inventory has the same handling as normal slot areas
- super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
- return;
-}
-
-
-
-
-
-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);
-}
-
-
-
-
-
-void cSlotAreaInventoryBase::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- a_Player.GetInventory().SetSlot(a_SlotNum + m_SlotOffset, a_Item);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaArmor:
-
-void cSlotAreaArmor::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
-{
- if (ItemCategory::IsHelmet(a_ItemStack.m_ItemType) && GetSlot(0, a_Player)->IsEmpty())
- {
- if (a_ShouldApply)
- {
- SetSlot(0, a_Player, a_ItemStack.CopyOne());
- }
- a_ItemStack.m_ItemCount -= 1;
- }
- else if (ItemCategory::IsChestPlate(a_ItemStack.m_ItemType) && GetSlot(1, a_Player)->IsEmpty())
- {
- if (a_ShouldApply)
- {
- SetSlot(1, a_Player, a_ItemStack.CopyOne());
- }
- a_ItemStack.m_ItemCount -= 1;
- }
- else if (ItemCategory::IsLeggings(a_ItemStack.m_ItemType) && GetSlot(2, a_Player)->IsEmpty())
- {
- if (a_ShouldApply)
- {
- SetSlot(2, a_Player, a_ItemStack.CopyOne());
- }
- a_ItemStack.m_ItemCount -= 1;
- }
- else if (ItemCategory::IsBoots(a_ItemStack.m_ItemType) && GetSlot(3, a_Player)->IsEmpty())
- {
- if (a_ShouldApply)
- {
- SetSlot(3, a_Player, a_ItemStack.CopyOne());
- }
- a_ItemStack.m_ItemCount -= 1;
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaItemGrid:
-
-cSlotAreaItemGrid::cSlotAreaItemGrid(cItemGrid & a_ItemGrid, cWindow & a_ParentWindow) :
- super(a_ItemGrid.GetNumSlots(), a_ParentWindow),
- m_ItemGrid(a_ItemGrid)
-{
- m_ItemGrid.AddListener(*this);
-}
-
-
-
-
-
-cSlotAreaItemGrid::~cSlotAreaItemGrid()
-{
- m_ItemGrid.RemoveListener(*this);
-}
-
-
-
-
-
-const cItem * cSlotAreaItemGrid::GetSlot(int a_SlotNum, cPlayer & a_Player) const
-{
- return &m_ItemGrid.GetSlot(a_SlotNum);
-}
-
-
-
-
-
-void cSlotAreaItemGrid::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- m_ItemGrid.SetSlot(a_SlotNum, a_Item);
-}
-
-
-
-
-
-void cSlotAreaItemGrid::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
-{
- ASSERT(a_ItemGrid == &m_ItemGrid);
- m_ParentWindow.BroadcastSlot(this, a_SlotNum);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cSlotAreaTemporary:
-
-cSlotAreaTemporary::cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow) :
- cSlotArea(a_NumSlots, a_ParentWindow)
-{
-}
-
-
-
-
-
-const cItem * cSlotAreaTemporary::GetSlot(int a_SlotNum, cPlayer & a_Player) const
-{
- 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);
- ASSERT(!"cSlotAreaTemporary: player not found!");
-
- // Player not found, this should not happen, ever! Return NULL, but things may break by this.
- return NULL;
- }
-
- if (a_SlotNum >= (int)(itr->second.size()))
- {
- LOGERROR("cSlotAreaTemporary: asking for more slots than actually stored!");
- ASSERT(!"cSlotAreaTemporary: asking for more slots than actually stored!");
- return NULL;
- }
-
- return &(itr->second[a_SlotNum]);
-}
-
-
-
-
-
-void cSlotAreaTemporary::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
-{
- cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID());
- if (itr == m_Items.end())
- {
- // Player not found
- LOGWARNING("cSlotAreaTemporary: player not found!");
- return;
- }
-
- if (a_SlotNum >= (int)(itr->second.size()))
- {
- LOGERROR("cSlotAreaTemporary: asking for more slots than actually stored!");
- return;
- }
-
- itr->second[a_SlotNum] = a_Item;
-}
-
-
-
-
-
-void cSlotAreaTemporary::OnPlayerAdded(cPlayer & a_Player)
-{
- ASSERT(m_Items.find(a_Player.GetUniqueID()) == m_Items.end()); // The player shouldn't be in the itemmap, otherwise we probably have a leak
- m_Items[a_Player.GetUniqueID()].resize(m_NumSlots); // Make the vector the specified size of empty items
-}
-
-
-
-
-
-void cSlotAreaTemporary::OnPlayerRemoved(cPlayer & a_Player)
-{
- cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID());
- ASSERT(itr != m_Items.end()); // The player should be in the list, otherwise a call to OnPlayerAdded() was mismatched
- m_Items.erase(itr);
-}
-
-
-
-
-
-void cSlotAreaTemporary::TossItems(cPlayer & a_Player, int a_Begin, int a_End)
-{
- cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID());
- if (itr == m_Items.end())
- {
- LOGWARNING("Player tossing items (%s) not found in the item map", a_Player.GetName().c_str());
- return;
- }
-
- cItems Drops;
- for (int i = a_Begin; i < a_End; i++)
- {
- cItem & Item = itr->second[i];
- if (!Item.IsEmpty())
- {
- Drops.push_back(Item);
- }
- Item.Empty();
- } // for i - itr->second[]
-
- double vX = 0, vY = 0, vZ = 0;
- EulerToVector(-a_Player.GetRotation(), a_Player.GetPitch(), vZ, vX, vY);
- vY = -vY * 2 + 1.f;
- a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because player created
-}
-
-
-
-
-
-cItem * cSlotAreaTemporary::GetPlayerSlots(cPlayer & a_Player)
-{
- cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID());
- if (itr == m_Items.end())
- {
- return NULL;
- }
- return &(itr->second[0]);
-}
-
-
-
-
diff --git a/source/UI/SlotArea.h b/source/UI/SlotArea.h
deleted file mode 100644
index b1944d901..000000000
--- a/source/UI/SlotArea.h
+++ /dev/null
@@ -1,313 +0,0 @@
-
-// SlotArea.h
-
-// Interfaces to the cSlotArea class representing a contiguous area of slots in a UI window
-
-
-
-
-#pragma once
-
-#include "../Inventory.h"
-
-
-
-class cWindow;
-class cPlayer;
-class cChestEntity;
-class cDropSpenserEntity;
-class cFurnaceEntity;
-class cCraftingRecipe;
-
-
-
-
-
-class cSlotArea
-{
-public:
- cSlotArea(int a_NumSlots, cWindow & a_ParentWindow);
- virtual ~cSlotArea() {} // force a virtual destructor in all subclasses
-
- 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) 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;
-
- /// Called when a player clicks in the window. Parameters taken from the click packet.
- virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem);
-
- /// Called from Clicked when the action is a shiftclick (left or right)
- virtual void ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem);
-
- /// Called from Clicked when the action is a caDblClick
- virtual void DblClicked(cPlayer & a_Player, int a_SlotNum);
-
- /// Called when a new player opens the same parent window. The window already tracks the player. CS-locked.
- virtual void OnPlayerAdded(cPlayer & a_Player) {} ;
-
- /// Called when one of the players closes the parent window. The window already doesn't track the player. CS-locked.
- virtual void OnPlayerRemoved(cPlayer & a_Player) {} ;
-
- /** Called to store as much of a_ItemStack in the area as possible. a_ItemStack is modified to reflect the change.
- The default implementation searches each slot for available space and distributes the stack there.
- if a_ShouldApply is true, the changes are written into the slots;
- if a_ShouldApply is false, only a_ItemStack is modified to reflect the number of fits (for fit-testing purposes)
- If a_KeepEmptySlots is true, empty slots will be skipped and won't be filled
- */
- virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots);
-
- /// Called on DblClicking to collect all stackable items into hand.
- /// The items are accumulated in a_Dragging and removed from the slots immediately.
- /// 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;
-} ;
-
-
-
-
-
-/// Handles any part of the inventory, using parameters in constructor to distinguish between the parts
-class cSlotAreaInventoryBase :
- public cSlotArea
-{
- typedef cSlotArea super;
-
-public:
- cSlotAreaInventoryBase(int a_NumSlots, int a_SlotOffset, cWindow & a_ParentWindow);
-
- // 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) const override;
- virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
-
-protected:
- int m_SlotOffset; // Index that this area's slot 0 has in the underlying cInventory
-} ;
-
-
-
-
-
-/// Handles the main inventory of each player, excluding the armor and hotbar
-class cSlotAreaInventory :
- public cSlotAreaInventoryBase
-{
- typedef cSlotAreaInventoryBase super;
-
-public:
- cSlotAreaInventory(cWindow & a_ParentWindow) :
- cSlotAreaInventoryBase(cInventory::invInventoryCount, cInventory::invInventoryOffset, a_ParentWindow)
- {
- }
-} ;
-
-
-
-
-
-/// Handles the hotbar of each player
-class cSlotAreaHotBar :
- public cSlotAreaInventoryBase
-{
- typedef cSlotAreaInventoryBase super;
-
-public:
- cSlotAreaHotBar(cWindow & a_ParentWindow) :
- cSlotAreaInventoryBase(cInventory::invHotbarCount, cInventory::invHotbarOffset, a_ParentWindow)
- {
- }
-} ;
-
-
-
-
-
-/// Handles the armor area of the player's inventory
-class cSlotAreaArmor :
- public cSlotAreaInventoryBase
-{
-public:
- cSlotAreaArmor(cWindow & a_ParentWindow) :
- cSlotAreaInventoryBase(cInventory::invArmorCount, cInventory::invArmorOffset, a_ParentWindow)
- {
- }
-
- // Distributing the stack is allowed only for compatible items (helmets into helmet slot etc.)
- virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
-} ;
-
-
-
-
-
-/// Handles any slot area that is representing a cItemGrid; same items for all the players
-class cSlotAreaItemGrid :
- public cSlotArea,
- public cItemGrid::cListener
-{
- typedef cSlotArea super;
-
-public:
- cSlotAreaItemGrid(cItemGrid & a_ItemGrid, cWindow & a_ParentWindow);
-
- virtual ~cSlotAreaItemGrid();
-
- 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:
- cItemGrid & m_ItemGrid;
-
- // cItemGrid::cListener overrides:
- virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
-} ;
-
-
-
-
-
-/** A cSlotArea with items layout that is private to each player and is temporary, such as
-a crafting grid or an enchantment table.
-This common ancestor stores the items in a per-player map. It also implements tossing items from the map.
-*/
-class cSlotAreaTemporary :
- public cSlotArea
-{
- typedef cSlotArea super;
-
-public:
- cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow);
-
- // cSlotArea overrides:
- 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;
-
- /// Tosses the player's items in slots [a_Begin, a_End) (ie. incl. a_Begin, but excl. a_End)
- void TossItems(cPlayer & a_Player, int a_Begin, int a_End);
-
-protected:
- typedef std::map<int, std::vector<cItem> > cItemMap; // Maps EntityID -> items
-
- cItemMap m_Items;
-
- /// Returns the pointer to the slot array for the player specified.
- cItem * GetPlayerSlots(cPlayer & a_Player);
-} ;
-
-
-
-
-
-class cSlotAreaCrafting :
- public cSlotAreaTemporary
-{
- typedef cSlotAreaTemporary super;
-
-public:
- /// a_GridSize is allowed to be only 2 or 3
- cSlotAreaCrafting(int a_GridSize, cWindow & a_ParentWindow);
-
- // cSlotAreaTemporary 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);
- virtual void OnPlayerRemoved(cPlayer & a_Player) override;
-
- // Distributing items into this area is completely disabled
- virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override {}
-
-protected:
- /// Maps player's EntityID -> current recipe; not a std::map because cCraftingGrid needs proper constructor params
- typedef std::list<std::pair<int, cCraftingRecipe> > cRecipeMap;
-
- int m_GridSize;
- cRecipeMap m_Recipes;
-
- /// Handles a click in the result slot. Crafts using the current recipe, if possible
- void ClickedResult(cPlayer & a_Player);
-
- /// Handles a shift-click in the result slot. Crafts using the current recipe until it changes or no more space for result.
- void ShiftClickedResult(cPlayer & a_Player);
-
- /// Updates the current recipe and result slot based on the ingredients currently in the crafting grid of the specified player
- void UpdateRecipe(cPlayer & a_Player);
-
- /// Retrieves the recipe for the specified player from the map, or creates one if not found
- cCraftingRecipe & GetRecipeForPlayer(cPlayer & a_Player);
-} ;
-
-
-
-
-
-class cSlotAreaChest :
- public cSlotArea
-{
-public:
- cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow);
-
- 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:
- cChestEntity * m_Chest;
-} ;
-
-
-
-
-
-class cSlotAreaDoubleChest :
- public cSlotArea
-{
-public:
- cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow);
-
- 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:
- cChestEntity * m_TopChest;
- cChestEntity * m_BottomChest;
-} ;
-
-
-
-
-
-class cSlotAreaFurnace :
- public cSlotArea,
- public cItemGrid::cListener
-{
- typedef cSlotArea super;
-
-public:
- cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow);
-
- virtual ~cSlotAreaFurnace();
-
- 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) const override;
- virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
-
-protected:
- cFurnaceEntity * m_Furnace;
-
- // cItemGrid::cListener overrides:
- virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
-} ;
-
-
-
-
diff --git a/source/UI/Window.cpp b/source/UI/Window.cpp
deleted file mode 100644
index f5c62692f..000000000
--- a/source/UI/Window.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "Window.h"
-#include "WindowOwner.h"
-#include "SlotArea.h"
-#include "../Item.h"
-#include "../ClientHandle.h"
-#include "../Entities/Player.h"
-#include "../Entities/Pickup.h"
-#include "../Inventory.h"
-#include "../Items/ItemHandler.h"
-#include "../BlockEntities/ChestEntity.h"
-#include "../BlockEntities/DropSpenserEntity.h"
-#include "../BlockEntities/HopperEntity.h"
-
-
-
-
-
-char cWindow::m_WindowIDCounter = 1;
-
-
-
-
-
-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 == wtInventory)
- {
- m_WindowID = 0;
- }
-}
-
-
-
-
-
-cWindow::~cWindow()
-{
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- delete *itr;
- }
- m_SlotAreas.clear();
-}
-
-
-
-
-
-int cWindow::GetNumSlots(void) const
-{
- int res = 0;
- for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- res += (*itr)->GetNumSlots();
- } // for itr - m_SlotAreas[]
- return res;
-}
-
-
-
-
-
-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);
-}
-
-
-
-
-
-bool cWindow::IsSlotInPlayerMainInventory(int a_SlotNum) const
-{
- // Returns true if the specified slot is in the Player Main Inventory slotarea
- // The player main inventory is always 27 slots, 9 slots from the end of the inventory
- return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots() - 9));
-}
-
-
-
-
-
-bool cWindow::IsSlotInPlayerHotbar(int a_SlotNum) const
-{
- // Returns true if the specified slot is in the Player Hotbar slotarea
- // The hotbar is always the last 9 slots
- return ((a_SlotNum >= GetNumSlots() - 9) && (a_SlotNum < GetNumSlots()));
-}
-
-
-
-
-
-bool cWindow::IsSlotInPlayerInventory(int a_SlotNum) const
-{
- // Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor.
- // The player combined inventory is always the last 36 slots
- return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots()));
-}
-
-
-
-
-
-void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const
-{
- a_Slots.clear();
- a_Slots.reserve(GetNumSlots());
- for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- int NumSlots = (*itr)->GetNumSlots();
- for (int i = 0; i < NumSlots; i++)
- {
-
- const cItem * Item = (*itr)->GetSlot(i, a_Player);
- if (Item == NULL)
- {
- a_Slots.push_back(cItem());
- }
- else
- {
- a_Slots.push_back(*Item);
- }
- }
- } // for itr - m_SlotAreas[]
-}
-
-
-
-
-
-void cWindow::Clicked(
- cPlayer & a_Player,
- int a_WindowID, short a_SlotNum, eClickAction a_ClickAction,
- const cItem & a_ClickedItem
-)
-{
- if (a_WindowID != m_WindowID)
- {
- 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;
- }
-
- switch (a_ClickAction)
- {
- case caRightClickOutside:
- {
- // Toss one of the dragged items:
- a_Player.TossItem(true);
- return;
- }
- case caLeftClickOutside:
- {
- // Toss all dragged items:
- a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount);
- return;
- }
- case caLeftClickOutsideHoldNothing:
- case caRightClickOutsideHoldNothing:
- {
- // 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)
- {
- // TODO: Other click actions with irrelevant slot number (FS #371)
- return;
- }
-
- int LocalSlotNum = a_SlotNum;
- int idx = 0;
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- if (LocalSlotNum < (*itr)->GetNumSlots())
- {
- (*itr)->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem);
- return;
- }
- LocalSlotNum -= (*itr)->GetNumSlots();
- idx++;
- }
-
- LOGWARNING("Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.",
- a_SlotNum, GetNumSlots(), a_Player.GetName().c_str()
- );
-}
-
-
-
-
-
-void cWindow::OpenedByPlayer(cPlayer & a_Player)
-{
- {
- cCSLock Lock(m_CS);
- // If player is already in OpenedBy remove player first
- m_OpenedBy.remove(&a_Player);
- // Then add player
- m_OpenedBy.push_back(&a_Player);
-
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- (*itr)->OnPlayerAdded(a_Player);
- } // for itr - m_SlotAreas[]
- }
-
- a_Player.GetClientHandle()->SendWindowOpen(*this);
-}
-
-
-
-
-
-bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
-{
- // Checks whether the player is still holding an item
- if (a_Player.IsDraggingItem())
- {
- LOGD("Player holds item! Dropping it...");
- a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount);
- }
-
- cClientHandle * ClientHandle = a_Player.GetClientHandle();
- if (ClientHandle != NULL)
- {
- ClientHandle->SendWindowClose(*this);
- }
-
- {
- cCSLock Lock(m_CS);
-
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- (*itr)->OnPlayerRemoved(a_Player);
- } // for itr - m_SlotAreas[]
-
- m_OpenedBy.remove(&a_Player);
-
- if ((m_WindowType != wtInventory) && m_OpenedBy.empty())
- {
- Destroy();
- }
- }
- if (m_IsDestroyed)
- {
- delete this;
- }
-
- return true;
-}
-
-
-
-
-
-void cWindow::OwnerDestroyed()
-{
- m_Owner = NULL;
- // Close window for each player. Note that the last one needs special handling
- while (m_OpenedBy.size() > 1)
- {
- (*m_OpenedBy.begin() )->CloseWindow();
- }
- (*m_OpenedBy.begin() )->CloseWindow();
-}
-
-
-
-
-
-bool cWindow::ForEachPlayer(cItemCallback<cPlayer> & a_Callback)
-{
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(), end = m_OpenedBy.end(); itr != end; ++itr)
- {
- if (a_Callback.Item(*itr))
- {
- return false;
- }
- } // for itr - m_OpenedBy[]
- return true;
-}
-
-
-
-
-
-bool cWindow::ForEachClient(cItemCallback<cClientHandle> & a_Callback)
-{
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(), end = m_OpenedBy.end(); itr != end; ++itr)
- {
- if (a_Callback.Item((*itr)->GetClientHandle()))
- {
- return false;
- }
- } // for itr - m_OpenedBy[]
- return true;
-}
-
-
-
-
-
-void cWindow::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, cSlotArea * a_ExcludeArea, bool a_ShouldApply)
-{
- // Ask each slot area to take as much of the stack as it can.
- // First ask only slots that already have the same kind of item
- // Then ask any remaining slots
- for (int Pass = 0; Pass < 2; ++Pass)
- {
- if (m_ShouldDistributeToHotbarFirst)
- {
- // First distribute into the hotbar:
- if (a_ExcludeArea != m_SlotAreas.back())
- {
- m_SlotAreas.back()->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0));
- if (a_ItemStack.IsEmpty())
- {
- // Distributed it all
- return;
- }
- }
- }
-
- // The distribute to all other areas:
- cSlotAreas::iterator end = m_ShouldDistributeToHotbarFirst ? (m_SlotAreas.end() - 1) : m_SlotAreas.end();
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(); itr != end; ++itr)
- {
- if (*itr == a_ExcludeArea)
- {
- continue;
- }
- (*itr)->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0));
- if (a_ItemStack.IsEmpty())
- {
- // Distributed it all
- return;
- }
- } // for itr - m_SlotAreas[]
- } // for Pass - repeat twice
-}
-
-
-
-
-
-bool cWindow::CollectItemsToHand(cItem & a_Dragging, cSlotArea & a_Area, cPlayer & a_Player, bool a_CollectFullStacks)
-{
- // First ask the slot areas from a_Area till the end of list:
- bool ShouldCollect = false;
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- if (&a_Area == *itr)
- {
- ShouldCollect = true;
- }
- if (!ShouldCollect)
- {
- continue;
- }
- if ((*itr)->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks))
- {
- // a_Dragging is full
- return true;
- }
- }
-
- // a_Dragging still not full, ask slot areas before a_Area in the list:
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- if (*itr == &a_Area)
- {
- // All areas processed
- return false;
- }
- if ((*itr)->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks))
- {
- // a_Dragging is full
- return true;
- }
- }
- // Shouldn't reach here
- // a_Area is expected to be part of m_SlotAreas[], so the "return false" in the loop above should have returned already
- ASSERT(!"This branch should not be reached");
- return false;
-}
-
-
-
-
-
-void cWindow::SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum)
-{
- int SlotBase = 0;
- bool Found = false;
- for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- if (*itr == a_SlotArea)
- {
- Found = true;
- break;
- }
- SlotBase += (*itr)->GetNumSlots();
- } // for itr - m_SlotAreas[]
- if (!Found)
- {
- LOGERROR("cWindow::SendSlot(): unknown a_SlotArea");
- ASSERT(!"cWindow::SendSlot(): unknown a_SlotArea");
- return;
- }
-
- a_Player.GetClientHandle()->SendInventorySlot(
- m_WindowID, a_RelativeSlotNum + SlotBase, *(a_SlotArea->GetSlot(a_RelativeSlotNum, a_Player))
- );
-}
-
-
-
-
-
-void cWindow::Destroy(void)
-{
- if (m_Owner != NULL)
- {
- m_Owner->CloseWindow();
- m_Owner = NULL;
- }
- m_IsDestroyed = true;
-}
-
-
-
-
-
-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());
- int ToEachSlot = (int)ToDistribute.m_ItemCount / SlotNums.size();
-
- int NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, ToEachSlot, 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
-
- const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots();
- cItem ToDistribute(a_Player.GetDraggingItem());
-
- int NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, 1, 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());
-}
-
-
-
-
-
-int cWindow::DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, int a_NumToEachSlot, const cSlotNums & a_SlotNums)
-{
- if ((size_t)(a_Item.m_ItemCount) < a_SlotNums.size())
- {
- LOGWARNING("%s: Distributing less items (%d) than slots (%u)", __FUNCTION__, (int)a_Item.m_ItemCount, a_SlotNums.size());
- // This doesn't seem to happen with the 1.5.1 client, so we don't worry about it for now
- return 0;
- }
-
- // Distribute to individual slots, keep track of how many items were actually distributed (full stacks etc.)
- int NumDistributed = 0;
- for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_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 = AtSlot.GetMaxStackSize();
- if (AtSlot.IsEmpty())
- {
- // Empty, just move all of it there:
- cItem ToStore(a_Item);
- ToStore.m_ItemCount = std::min(a_NumToEachSlot, (int)MaxStack);
- Area->SetSlot(LocalSlotNum, a_Player, ToStore);
- NumDistributed += ToStore.m_ItemCount;
- }
- else if (AtSlot.IsStackableWith(a_Item))
- {
- // Occupied, add and cap at MaxStack:
- int CanStore = std::min(a_NumToEachSlot, (int)MaxStack - AtSlot.m_ItemCount);
- AtSlot.m_ItemCount += CanStore;
- Area->SetSlot(LocalSlotNum, a_Player, AtSlot);
- NumDistributed += CanStore;
- }
- } // for itr - SlotNums[]
- return NumDistributed;
-}
-
-
-
-
-
-void cWindow::BroadcastSlot(cSlotArea * a_Area, int a_LocalSlotNum)
-{
- // Translate local slot num into global slot num:
- int SlotNum = 0;
- bool HasFound = false;
- for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
- {
- if (a_Area == *itr)
- {
- SlotNum += a_LocalSlotNum;
- HasFound = true;
- break;
- }
- SlotNum += (*itr)->GetNumSlots();
- } // for itr - m_SlotAreas[]
- if (!HasFound)
- {
- LOGWARNING("%s: Invalid slot area parameter", __FUNCTION__);
- ASSERT(!"Invalid slot area");
- return;
- }
-
- // Broadcast the update packet:
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(); itr != m_OpenedBy.end(); ++itr)
- {
- (*itr)->GetClientHandle()->SendInventorySlot(m_WindowID, SlotNum, *a_Area->GetSlot(a_LocalSlotNum, **itr));
- } // for itr - m_OpenedBy[]
-}
-
-
-
-
-
-void cWindow::SendWholeWindow(cClientHandle & a_Client)
-{
- a_Client.SendWholeInventory(*this);
-}
-
-
-
-
-
-void cWindow::BroadcastWholeWindow(void)
-{
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(); itr != m_OpenedBy.end(); ++itr)
- {
- SendWholeWindow(*(*itr)->GetClientHandle());
- } // for itr - m_OpenedBy[]
-}
-
-
-
-
-
-void cWindow::BroadcastProgress(int a_Progressbar, int a_Value)
-{
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(); itr != m_OpenedBy.end(); ++itr)
- {
- (*itr)->GetClientHandle()->SendWindowProperty(*this, a_Progressbar, a_Value);
- } // for itr - m_OpenedBy[]
-}
-
-
-
-
-
-void cWindow::SetProperty(int a_Property, int a_Value)
-{
- cCSLock Lock(m_CS);
- for (cPlayerList::iterator itr = m_OpenedBy.begin(), end = m_OpenedBy.end(); itr != end; ++itr)
- {
- (*itr)->GetClientHandle()->SendWindowProperty(*this, a_Property, a_Value);
- } // for itr - m_OpenedBy[]
-}
-
-
-
-
-
-void cWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Player)
-{
- a_Player.GetClientHandle()->SendWindowProperty(*this, a_Property, a_Value);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cInventoryWindow:
-
-cInventoryWindow::cInventoryWindow(cPlayer & a_Player) :
- cWindow(wtInventory, "Inventory"),
- m_Player(a_Player)
-{
- m_SlotAreas.push_back(new cSlotAreaCrafting(2, *this)); // The creative inventory doesn't display it, but it's still counted into slot numbers
- m_SlotAreas.push_back(new cSlotAreaArmor(*this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cCraftingWindow:
-
-cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
- cWindow(wtWorkbench, "Crafting Table")
-{
- m_SlotAreas.push_back(new cSlotAreaCrafting(3, *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cChestWindow:
-
-cChestWindow::cChestWindow(cChestEntity * a_Chest) :
- cWindow(wtChest, "Chest"),
- m_World(a_Chest->GetWorld()),
- m_BlockX(a_Chest->GetPosX()),
- m_BlockY(a_Chest->GetPosY()),
- m_BlockZ(a_Chest->GetPosZ())
-{
- m_SlotAreas.push_back(new cSlotAreaChest(a_Chest, *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-
- // Play the opening sound:
- m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
-
- // Send out the chest-open packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
-}
-
-
-
-
-
-cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) :
- cWindow(wtChest, "Double Chest"),
- m_World(a_PrimaryChest->GetWorld()),
- m_BlockX(a_PrimaryChest->GetPosX()),
- m_BlockY(a_PrimaryChest->GetPosY()),
- m_BlockZ(a_PrimaryChest->GetPosZ())
-{
- m_SlotAreas.push_back(new cSlotAreaDoubleChest(a_PrimaryChest, a_SecondaryChest, *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-
- m_ShouldDistributeToHotbarFirst = false;
-
- // Play the opening sound:
- m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
-
- // Send out the chest-open packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
-}
-
-
-
-
-
-cChestWindow::~cChestWindow()
-{
- // Send out the chest-close packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_CHEST);
-
- m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cDropSpenserWindow:
-
-cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser) :
- cWindow(wtDropSpenser, "Dropspenser")
-{
- m_ShouldDistributeToHotbarFirst = false;
- m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cHopperWindow:
-
-cHopperWindow::cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEntity * a_Hopper) :
- super(wtHopper, "Hopper")
-{
- m_ShouldDistributeToHotbarFirst = false;
- m_SlotAreas.push_back(new cSlotAreaItemGrid(a_Hopper->GetContents(), *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cFurnaceWindow:
-
-cFurnaceWindow::cFurnaceWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceEntity * a_Furnace) :
- cWindow(wtFurnace, "Furnace")
-{
- m_ShouldDistributeToHotbarFirst = false;
- m_SlotAreas.push_back(new cSlotAreaFurnace(a_Furnace, *this));
- m_SlotAreas.push_back(new cSlotAreaInventory(*this));
- m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
-}
-
-
-
-
diff --git a/source/UI/Window.h b/source/UI/Window.h
deleted file mode 100644
index c44b900d7..000000000
--- a/source/UI/Window.h
+++ /dev/null
@@ -1,300 +0,0 @@
-
-// Window.h
-
-// Interfaces to the cWindow class representing a UI window for a specific block
-
-
-
-
-
-#pragma once
-
-#include "../ItemGrid.h"
-
-
-
-
-
-class cPlayer;
-class cWindowOwner;
-class cClientHandle;
-class cChestEntity;
-class cDropSpenserEntity;
-class cFurnaceEntity;
-class cHopperEntity;
-class cSlotArea;
-class cWorld;
-
-typedef std::list<cPlayer *> cPlayerList;
-typedef std::vector<cSlotArea *> cSlotAreas;
-
-
-
-
-
-// tolua_begin
-
-/**
-Represents a UI window.
-
-Each window has a list of players that are currently using it
-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
-{
-public:
- enum WindowType
- {
- wtInventory = -1, // This value is never actually sent to a client
- wtChest = 0,
- wtWorkbench = 1,
- wtFurnace = 2,
- wtDropSpenser = 3, // Dropper or Dispenser
- wtEnchantment = 4,
- wtBrewery = 5,
- wtNPCTrade = 6,
- wtBeacon = 7,
- wtAnvil = 8,
- wtHopper = 9,
- // Unknown: 10
- wtAnimalChest = 11,
- };
-
- // 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; } // tolua_export
- int GetWindowType(void) const { return m_WindowType; } // tolua_export
-
- cWindowOwner * GetOwner(void) { return m_Owner; }
- void SetOwner( cWindowOwner * a_Owner ) { m_Owner = a_Owner; }
-
- /// Returns the total number of slots
- int GetNumSlots(void) const;
-
- /// Returns the number of slots, excluding the player's inventory (used for network protocols)
- int GetNumNonInventorySlots(void) const { return GetNumSlots() - c_NumInventorySlots; }
-
- // 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);
-
- /// Returns true if the specified slot is in the Player Main Inventory slotarea
- bool IsSlotInPlayerMainInventory(int a_SlotNum) const;
-
- /// Returns true if the specified slot is in the Player Hotbar slotarea
- bool IsSlotInPlayerHotbar(int a_SlotNum) const;
-
- /// Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor.
- bool IsSlotInPlayerInventory(int a_SlotNum) const;
-
- // 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,
- const cItem & a_ClickedItem
- );
-
- void OpenedByPlayer(cPlayer & a_Player);
-
- /// Called when a player closes this window; notifies all slot areas. Returns true if close accepted
- virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse);
-
- /// Sends the specified slot's contents to all clients of this window; the slot is specified as local in an area
- void BroadcastSlot(cSlotArea * a_Area, int a_LocalSlotNum);
-
- /// Sends the contents of the whole window to the specified client
- void SendWholeWindow(cClientHandle & a_Client);
-
- /// Sends the contents of the whole window to all clients of this window.
- void BroadcastWholeWindow(void);
-
- /// Sends the progressbar to all clients of this window (same as SetProperty)
- void BroadcastProgress(int a_Progressbar, int a_Value);
-
- // tolua_begin
-
- const AString & GetWindowTitle() const { return m_WindowTitle; }
- 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);
-
- /// Sends the UpdateWindowPropert(0x69) packet to the specified player
- void SetProperty(int a_Property, int a_Value, cPlayer & a_Player);
-
- // tolua_end
-
- void OwnerDestroyed(void);
-
- /// Calls the callback safely for each player that has this window open; returns true if all players have been enumerated
- bool ForEachPlayer(cItemCallback<cPlayer> & a_Callback);
-
- /// Calls the callback safely for each client that has this window open; returns true if all clients have been enumerated
- bool ForEachClient(cItemCallback<cClientHandle> & a_Callback);
-
- /** Called on shift-clicking to distribute the stack into other areas; Modifies a_ItemStack as it is distributed!
- if a_ShouldApply is true, the changes are written into the slots;
- if a_ShouldApply is false, only a_ItemStack is modified to reflect the number of fits (for fit-testing purposes)
- */
- void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, cSlotArea * a_ExcludeArea, bool a_ShouldApply);
-
- /// Called on DblClicking to collect all stackable items from all areas into hand, starting with the specified area.
- /// The items are accumulated in a_Dragging and removed from the SlotAreas immediately.
- /// If a_CollectFullStacks is false, slots with full stacks in the area are skipped while collecting.
- /// Returns true if full stack has been collected, false if there's space remaining to fill.
- bool CollectItemsToHand(cItem & a_Dragging, cSlotArea & a_Area, cPlayer & a_Player, bool a_CollectFullStacks);
-
- /// 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;
-
- char m_WindowID;
- int m_WindowType;
- AString m_WindowTitle;
-
- cCriticalSection m_CS;
- cPlayerList m_OpenedBy;
-
- bool m_IsDestroyed;
- bool m_ShouldDistributeToHotbarFirst; ///< If set (default), shift+click tries to distribute to hotbar first, then other areas. False for doublechests
-
- cWindowOwner * m_Owner;
-
- static char m_WindowIDCounter;
-
- /// Sets the internal flag as "destroyed"; notifies the owner that the window is destroying
- virtual 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);
-
- /// Distributes a_NumToEachSlot items into the slots specified in a_SlotNums; returns the total number of items distributed
- int DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, int a_NumToEachSlot, const cSlotNums & a_SlotNums);
-} ; // tolua_export
-
-
-
-
-
-class cCraftingWindow :
- public cWindow
-{
- typedef cWindow super;
-public:
- cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
-} ;
-
-
-
-
-
-class cFurnaceWindow :
- public cWindow
-{
- typedef cWindow super;
-public:
- cFurnaceWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceEntity * a_Furnace);
-} ;
-
-
-
-
-
-class cDropSpenserWindow :
- public cWindow
-{
- typedef cWindow super;
-public:
- cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_Dispenser);
-} ;
-
-
-
-
-
-class cHopperWindow :
- public cWindow
-{
- typedef cWindow super;
-public:
- cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEntity * a_Hopper);
-} ;
-
-
-
-
-
-class cChestWindow :
- public cWindow
-{
-public:
- cChestWindow(cChestEntity * a_Chest);
- cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest);
- ~cChestWindow();
-
-protected:
- cWorld * m_World;
- int m_BlockX, m_BlockY, m_BlockZ; // Position of the chest, for the window-close packet
-} ;
-
-
-
-
-
-class cInventoryWindow :
- public cWindow
-{
-public:
- cInventoryWindow(cPlayer & a_Player);
-
-protected:
- cPlayer & m_Player;
-
-} ;
-
-
-
-
-
diff --git a/source/UI/WindowOwner.h b/source/UI/WindowOwner.h
deleted file mode 100644
index d41abf66d..000000000
--- a/source/UI/WindowOwner.h
+++ /dev/null
@@ -1,125 +0,0 @@
-
-#pragma once
-
-#include "../BlockEntities/BlockEntity.h"
-#include "../Entities/Entity.h"
-#include "Window.h"
-
-/*
-Being a descendant of cWindowOwner means that the class can own one window. That window can be
-queried, opened by other players, closed by players and finally destroyed.
-Also, a cWindowOwner can be queried for the block coords where the window is displayed. That will be used
-for entities / players in motion to close their windows when they get too far away from the window "source".
-*/
-
-
-
-
-
-// class cWindow;
-
-
-
-
-
-/**
-Base class for the window owning
-*/
-class cWindowOwner
-{
-public:
- cWindowOwner() :
- m_Window(NULL)
- {
- }
-
- void CloseWindow(void)
- {
- m_Window = NULL;
- }
-
- void OpenWindow(cWindow * a_Window)
- {
- m_Window = a_Window;
- m_Window->SetOwner(this);
- }
-
- cWindow * GetWindow(void) const
- {
- return m_Window;
- }
-
- /// Returns the block position at which the element owning the window is
- virtual void GetBlockPos(int & a_BlockX, int & a_BlockY, int & a_BlockZ) = 0;
-
-private:
- cWindow * m_Window;
-} ;
-
-
-
-
-
-/**
-Window owner that is associated with a block entity (chest, furnace, ...)
-*/
-class cBlockEntityWindowOwner :
- public cWindowOwner
-{
-public:
- cBlockEntityWindowOwner(void) :
- m_BlockEntity(NULL)
- {
- }
-
- void SetBlockEntity(cBlockEntity * a_BlockEntity)
- {
- m_BlockEntity = a_BlockEntity;
- }
-
- virtual void GetBlockPos(int & a_BlockX, int & a_BlockY, int & a_BlockZ) override
- {
- a_BlockX = m_BlockEntity->GetPosX();
- a_BlockY = m_BlockEntity->GetPosY();
- a_BlockZ = m_BlockEntity->GetPosZ();
- }
-
-private:
- cBlockEntity * m_BlockEntity;
-} ;
-
-
-
-
-
-/**
-Window owner that is associated with an entity (chest minecart)
-*/
-class cEntityWindowOwner :
- public cWindowOwner
-{
-public:
- cEntityWindowOwner(void) :
- m_Entity(NULL)
- {
- }
-
- void SetEntity(cEntity * a_Entity)
- {
- m_Entity = a_Entity;
- }
-
- virtual void GetBlockPos(int & a_BlockX, int & a_BlockY, int & a_BlockZ) override
- {
- a_BlockX = (int)floor(m_Entity->GetPosX() + 0.5);
- a_BlockY = (int)floor(m_Entity->GetPosY() + 0.5);
- a_BlockZ = (int)floor(m_Entity->GetPosZ() + 0.5);
- }
-
-private:
- cEntity * m_Entity;
-} ;
-
-
-
-