1
0

Merge pull request #1665 from mc-server/Inventory

Own classes for all windows and implemented vanilla-like shift click.
This commit is contained in:
Mattes D 2015-03-11 14:26:04 +01:00
commit 1b60fe12a8
43 changed files with 1392 additions and 701 deletions

View File

@ -167,6 +167,24 @@ void cLuaWindow::Destroy(void)
void cLuaWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer& a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas Areas;
for (auto Area : m_SlotAreas)
{
if (Area != a_ClickedArea)
{
Areas.push_back(Area);
}
}
super::DistributeStackToAreas(a_ItemStack, a_Player, Areas, a_ShouldApply, false);
}
void cLuaWindow::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
if (a_ItemGrid != &m_Contents)

View File

@ -84,6 +84,7 @@ protected:
// cWindow overrides:
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
virtual void Destroy(void) override;
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;

View File

@ -4,6 +4,7 @@
#include "BeaconEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
#include "../UI/BeaconWindow.h"
@ -289,7 +290,7 @@ void cBeaconEntity::UsedBy(cPlayer * a_Player)
OpenWindow(new cBeaconWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != nullptr)
{
// if (a_Player->GetWindow() != Window)

View File

@ -4,7 +4,7 @@
#include "ChestEntity.h"
#include "../Item.h"
#include "../Entities/Player.h"
#include "../UI/Window.h"
#include "../UI/ChestWindow.h"

View File

@ -8,6 +8,7 @@
#include "DropSpenserEntity.h"
#include "../Entities/Player.h"
#include "../Chunk.h"
#include "../UI/DropSpenserWindow.h"

View File

@ -4,7 +4,7 @@
#include "EnderChestEntity.h"
#include "../Item.h"
#include "../Entities/Player.h"
#include "../UI/Window.h"
#include "../UI/EnderChestWindow.h"

View File

@ -2,7 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "FurnaceEntity.h"
#include "../UI/Window.h"
#include "../UI/FurnaceWindow.h"
#include "../Entities/Player.h"
#include "../Root.h"
#include "../Chunk.h"

View File

@ -9,6 +9,7 @@
#include "../Entities/Player.h"
#include "../Entities/Pickup.h"
#include "../Bindings/PluginManager.h"
#include "../UI/HopperWindow.h"
#include "ChestEntity.h"
#include "FurnaceEntity.h"

View File

@ -4,6 +4,7 @@
#include "BlockHandler.h"
#include "../World.h"
#include "../Entities/Player.h"
#include "../UI/AnvilWindow.h"

View File

@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
#include "../UI/Window.h"
#include "../UI/EnchantingWindow.h"
#include "../Entities/Player.h"

View File

@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
#include "../UI/Window.h"
#include "../UI/CraftingWindow.h"
#include "../Entities/Player.h"

View File

@ -9,7 +9,7 @@ include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include
set(FOLDERS
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs
WorldStorage Mobs Entities Simulator BlockEntities UI Generating/Prefabs
Noise
)
@ -318,7 +318,7 @@ if (NOT MSVC)
target_link_libraries(${EXECUTABLE}
OSSupport HTTPServer Bindings Items Blocks Noise
Protocol Generating Generating_Prefabs WorldStorage
Mobs Entities Simulator UI BlockEntities PolarSSL++
Mobs Entities Simulator BlockEntities UI PolarSSL++
)
endif ()
if (WIN32)

View File

@ -12,6 +12,9 @@
#include "BlockEntities/CommandBlockEntity.h"
#include "BlockEntities/SignEntity.h"
#include "UI/Window.h"
#include "UI/AnvilWindow.h"
#include "UI/BeaconWindow.h"
#include "UI/EnchantingWindow.h"
#include "Item.h"
#include "Mobs/Monster.h"
#include "ChatColor.h"

View File

@ -11,6 +11,7 @@
#include "../Chunk.h"
#include "Player.h"
#include "../BoundingBox.h"
#include "../UI/MinecartWithChestWindow.h"
#define NO_SPEED 0.0
#define MAX_SPEED 8

View File

@ -5,7 +5,7 @@
#include <unordered_map>
#include "../ChatColor.h"
#include "../Server.h"
#include "../UI/Window.h"
#include "../UI/InventoryWindow.h"
#include "../UI/WindowOwner.h"
#include "../World.h"
#include "../Bindings/PluginManager.h"

View File

@ -291,6 +291,22 @@ const cFurnaceRecipe::cRecipe * cFurnaceRecipe::GetRecipeFrom(const cItem & a_In
bool cFurnaceRecipe::IsFuel(const cItem & a_Item) const
{
for (auto & Fuel : m_pState->Fuel)
{
if ((Fuel.In->m_ItemType == a_Item.m_ItemType) && (Fuel.In->m_ItemCount <= a_Item.m_ItemCount))
{
return true;
}
}
return false;
}
int cFurnaceRecipe::GetBurnTime(const cItem & a_Fuel) const
{
int BestFuel = 0;

View File

@ -34,6 +34,9 @@ public:
/** Returns a recipe for the specified input, nullptr if no recipe found */
const cRecipe * GetRecipeFrom(const cItem & a_Ingredient) const;
/** Returns true if the item is a fuel, false if not. */
bool IsFuel(const cItem & a_Item) const;
/** Returns the amount of time that the specified fuel burns, in ticks */
int GetBurnTime(const cItem & a_Fuel) const;

83
src/UI/AnvilWindow.cpp Normal file
View File

@ -0,0 +1,83 @@
// AnvilWindow.cpp
// Representing the UI window for the anvil block
#include "Globals.h"
#include "AnvilWindow.h"
#include "SlotArea.h"
cAnvilWindow::cAnvilWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
cWindow(wtAnvil, "Repair"),
m_RepairedItemName(""),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
m_AnvilSlotArea = new cSlotAreaAnvil(*this);
m_SlotAreas.push_back(m_AnvilSlotArea);
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
AString cAnvilWindow::GetRepairedItemName(void) const
{
return m_RepairedItemName;
}
void cAnvilWindow::SetRepairedItemName(const AString & a_Name, cPlayer * a_Player)
{
m_RepairedItemName = a_Name;
if (a_Player != nullptr)
{
m_AnvilSlotArea->UpdateResult(*a_Player);
}
}
void cAnvilWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
{
a_PosX = m_BlockX;
a_PosY = m_BlockY;
a_PosZ = m_BlockZ;
}
void cAnvilWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Anvil Slot
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
}
else
{
// Inventory or Hotbar
AreasInOrder.push_back(m_SlotAreas[0]); /* Anvil */
}
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}

45
src/UI/AnvilWindow.h Normal file
View File

@ -0,0 +1,45 @@
// AnvilWindow.h
// Representing the UI window for the anvil block
#pragma once
#include "Window.h"
class cAnvilWindow :
public cWindow
{
typedef cWindow super;
public:
cAnvilWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Gets the repaired item name. */
AString GetRepairedItemName(void) const;
/** Set the repaired item name. */
void SetRepairedItemName(const AString & a_Name, cPlayer * a_Player);
/** Gets the Position from the Anvil */
void GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
protected:
cSlotAreaAnvil * m_AnvilSlotArea;
AString m_RepairedItemName;
int m_BlockX, m_BlockY, m_BlockZ;
};

76
src/UI/BeaconWindow.cpp Normal file
View File

@ -0,0 +1,76 @@
// BeaconWindow.cpp
// Representing the UI window for the beacon block
#include "Globals.h"
#include "BeaconWindow.h"
#include "SlotArea.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../Entities/Player.h"
cBeaconWindow::cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon) :
cWindow(wtBeacon, "Beacon"),
m_Beacon(a_Beacon)
{
m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cBeaconWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Beacon Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
if (cSlotAreaBeacon::IsPlaceableItem(a_ItemStack.m_ItemType) && (a_ItemStack.m_ItemCount == 1))
{
AreasInOrder.push_back(m_SlotAreas[0]); /* Beacon */
}
if (a_ClickedArea == m_SlotAreas[1])
{
// Inventory Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
}
else
{
// Hotbar Area
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
}
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}
void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player)
{
super::OpenedByPlayer(a_Player);
a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel());
a_Player.GetClientHandle()->SendWindowProperty(*this, 1, m_Beacon->GetPrimaryEffect());
a_Player.GetClientHandle()->SendWindowProperty(*this, 2, m_Beacon->GetSecondaryEffect());
}

40
src/UI/BeaconWindow.h Normal file
View File

@ -0,0 +1,40 @@
// BeaconWindow.h
// Representing the UI window for the beacon block
#pragma once
#include "Window.h"
#include "../Entities/Player.h"
class cBeaconWindow :
public cWindow
{
typedef cWindow super;
public:
cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon);
cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; }
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
// cWindow Overrides:
virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cBeaconEntity * m_Beacon;
};

View File

@ -6,11 +6,32 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
SET (SRCS
SlotArea.cpp
Window.cpp)
Window.cpp
AnvilWindow.cpp
BeaconWindow.cpp
ChestWindow.cpp
CraftingWindow.cpp
DropSpenserWindow.cpp
EnchantingWindow.cpp
EnderChestWindow.cpp
FurnaceWindow.cpp
HopperWindow.cpp
InventoryWindow.cpp)
SET (HDRS
SlotArea.h
Window.h
AnvilWindow.h
BeaconWindow.h
ChestWindow.h
CraftingWindow.h
DropSpenserWindow.h
EnchantingWindow.h
EnderChestWindow.h
FurnaceWindow.h
HopperWindow.h
InventoryWindow.h
MinecartWithChestWindow.h
WindowOwner.h)
if(NOT MSVC)

141
src/UI/ChestWindow.cpp Normal file
View File

@ -0,0 +1,141 @@
// ChestWindow.cpp
// Representing the UI window for the chest block
#include "Globals.h"
#include "ChestWindow.h"
#include "../BlockEntities/ChestEntity.h"
#include "../Entities/Player.h"
cChestWindow::cChestWindow(cChestEntity * a_Chest) :
cWindow(wtChest, (a_Chest->GetBlockType() == E_BLOCK_CHEST) ? "Chest" : "Trapped Chest"),
m_World(a_Chest->GetWorld()),
m_BlockX(a_Chest->GetPosX()),
m_BlockY(a_Chest->GetPosY()),
m_BlockZ(a_Chest->GetPosZ()),
m_PrimaryChest(a_Chest),
m_SecondaryChest(nullptr)
{
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", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_Chest->GetBlockType());
}
cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) :
cWindow(wtChest, (a_PrimaryChest->GetBlockType() == E_BLOCK_CHEST) ? "Double Chest" : "Double Trapped Chest"),
m_World(a_PrimaryChest->GetWorld()),
m_BlockX(a_PrimaryChest->GetPosX()),
m_BlockY(a_PrimaryChest->GetPosY()),
m_BlockZ(a_PrimaryChest->GetPosZ()),
m_PrimaryChest(a_PrimaryChest),
m_SecondaryChest(a_SecondaryChest)
{
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));
// Play the opening sound:
m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_PrimaryChest->GetBlockType());
}
cChestWindow::~cChestWindow()
{
// Send out the chest-close packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, m_PrimaryChest->GetBlockType());
m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
bool cChestWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
{
int ChunkX, ChunkZ;
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() - 1);
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
if (m_SecondaryChest != nullptr)
{
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() - 1);
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
}
cWindow::ClosedByPlayer(a_Player, a_CanRefuse);
return true;
}
void cChestWindow::OpenedByPlayer(cPlayer & a_Player)
{
int ChunkX, ChunkZ;
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() + 1);
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
if (m_SecondaryChest != nullptr)
{
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() + 1);
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
}
cWindow::OpenedByPlayer(a_Player);
}
void cChestWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Chest Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Hotbar or Inventory
AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

45
src/UI/ChestWindow.h Normal file
View File

@ -0,0 +1,45 @@
// ChestWindow.h
// Representing the UI window for the chest block
#pragma once
#include "Window.h"
class cChestWindow :
public cWindow
{
typedef cWindow super;
public:
cChestWindow(cChestEntity * a_Chest);
cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest);
~cChestWindow();
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
virtual void OpenedByPlayer(cPlayer & a_Player) override;
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
protected:
cWorld * m_World;
int m_BlockX, m_BlockY, m_BlockZ; // Position of the chest, for the window-close packet
cChestEntity * m_PrimaryChest;
cChestEntity * m_SecondaryChest;
};

61
src/UI/CraftingWindow.cpp Normal file
View File

@ -0,0 +1,61 @@
// CraftingWindow.cpp
// Representing the UI window for the crafting block
#include "Globals.h"
#include "CraftingWindow.h"
#include "SlotArea.h"
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));
}
void cCraftingWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Crafting Area
if (a_Slot == 0)
{
// Result Slot
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
}
else
{
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
}
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, (a_Slot == 0));
}
else if (a_ClickedArea == m_SlotAreas[1])
{
// Inventory Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
else
{
// Hotbar
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

31
src/UI/CraftingWindow.h Normal file
View File

@ -0,0 +1,31 @@
// CraftingWindow.h
// Representing the UI window for the crafting block
#pragma once
#include "Window.h"
class cCraftingWindow :
public cWindow
{
typedef cWindow super;
public:
cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
};

View File

@ -0,0 +1,46 @@
// DropSpenserWindow.cpp
// Representing the UI window for the dropper/dispenser block
#include "Globals.h"
#include "DropSpenserWindow.h"
cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser) :
cWindow(wtDropSpenser, (a_DropSpenser->GetBlockType() == E_BLOCK_DISPENSER) ? "Dispenser" : "Dropper")
{
m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cDropSpenserWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// DropSpenser Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Inventory or Hotbar
AreasInOrder.push_back(m_SlotAreas[0]); /* DropSpenser */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

View File

@ -0,0 +1,32 @@
// DropSpenserWindow.h
// Representing the UI window for the dropper/dispenser block
#pragma once
#include "Window.h"
#include "../BlockEntities/DropSpenserEntity.h"
class cDropSpenserWindow :
public cWindow
{
typedef cWindow super;
public:
cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
};

100
src/UI/EnchantingWindow.cpp Normal file
View File

@ -0,0 +1,100 @@
// EnchantingWindow.cpp
// Representing the UI window for the enchanting block
#include "Globals.h"
#include "EnchantingWindow.h"
#include "SlotArea.h"
cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
cWindow(wtEnchantment, "Enchant"),
m_SlotArea(),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
m_SlotArea = new cSlotAreaEnchanting(*this, m_BlockX, m_BlockY, m_BlockZ);
m_SlotAreas.push_back(m_SlotArea);
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cEnchantingWindow::SetProperty(short a_Property, short a_Value, cPlayer & a_Player)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return;
}
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value, a_Player);
}
void cEnchantingWindow::SetProperty(short a_Property, short a_Value)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return;
}
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value);
}
short cEnchantingWindow::GetPropertyValue(short a_Property)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return 0;
}
return m_PropertyValue[a_Property];
}
void cEnchantingWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Enchanting Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Inventory or Hotbar
AreasInOrder.push_back(m_SlotAreas[0]); /* Enchanting */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

44
src/UI/EnchantingWindow.h Normal file
View File

@ -0,0 +1,44 @@
// EnchantingWindow.h
// Representing the UI window for the enchanting block
#pragma once
#include "Window.h"
class cEnchantingWindow :
public cWindow
{
typedef cWindow super;
public:
cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
virtual void SetProperty(short a_Property, short a_Value, cPlayer & a_Player) override;
virtual void SetProperty(short a_Property, short a_Value) override;
/** Return the value of a property */
short GetPropertyValue(short a_Property);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
cSlotArea * m_SlotArea;
protected:
short m_PropertyValue[3];
int m_BlockX, m_BlockY, m_BlockZ;
};

View File

@ -0,0 +1,71 @@
// EnderChestWindow.cpp
// Representing the UI window for the enderchest block
#include "Globals.h"
#include "../World.h"
#include "EnderChestWindow.h"
#include "SlotArea.h"
cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest) :
cWindow(wtChest, "Ender Chest"),
m_World(a_EnderChest->GetWorld()),
m_BlockX(a_EnderChest->GetPosX()),
m_BlockY(a_EnderChest->GetPosY()),
m_BlockZ(a_EnderChest->GetPosZ())
{
m_SlotAreas.push_back(new cSlotAreaEnderChest(a_EnderChest, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
// Play the opening sound:
m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_ENDER_CHEST);
}
cEnderChestWindow::~cEnderChestWindow()
{
// Send out the chest-close packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_ENDER_CHEST);
// Play the closing sound
m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
void cEnderChestWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Chest Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Hotbar or Inventory
AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

38
src/UI/EnderChestWindow.h Normal file
View File

@ -0,0 +1,38 @@
// EnderChestWindow.h
// Representing the UI window for the enderchest block
#pragma once
#include "Window.h"
#include "../BlockEntities/EnderChestEntity.h"
class cEnderChestWindow :
public cWindow
{
typedef cWindow super;
public:
cEnderChestWindow(cEnderChestEntity * a_EnderChest);
~cEnderChestWindow();
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
protected:
cWorld * m_World;
int m_BlockX, m_BlockY, m_BlockZ; // Position of the enderchest, for the window-close packet
};

74
src/UI/FurnaceWindow.cpp Normal file
View File

@ -0,0 +1,74 @@
// FurnaceWindow.cpp
// Representing the UI window for the furnace block
#include "Globals.h"
#include "FurnaceWindow.h"
#include "SlotArea.h"
#include "../FurnaceRecipe.h"
#include "../Root.h"
cFurnaceWindow::cFurnaceWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceEntity * a_Furnace) :
cWindow(wtFurnace, "Furnace")
{
m_SlotAreas.push_back(new cSlotAreaFurnace(a_Furnace, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cFurnaceWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Furnace Area
if (a_Slot == 2)
{
// Result Slot
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Furnace Input/Fuel Slot
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}
else
{
cFurnaceRecipe * FurnaceRecipes = cRoot::Get()->GetFurnaceRecipe();
if ((FurnaceRecipes->GetRecipeFrom(a_ItemStack) != nullptr) || (FurnaceRecipes->IsFuel(a_ItemStack)))
{
// The item is a valid input item or fuel
AreasInOrder.push_back(m_SlotAreas[0]); /* Furnace Area */
}
else if (a_ClickedArea == m_SlotAreas[1])
{
// Inventory Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
}
else
{
// Hotbar Area
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
}
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

32
src/UI/FurnaceWindow.h Normal file
View File

@ -0,0 +1,32 @@
// FurnaceWindow.h
// Representing the UI window for the furnace block
#pragma once
#include "Window.h"
class cFurnaceWindow :
public cWindow
{
typedef cWindow super;
public:
cFurnaceWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceEntity * a_Furnace);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
};

48
src/UI/HopperWindow.cpp Normal file
View File

@ -0,0 +1,48 @@
// HopperWindow.cpp
// Representing the UI window for the hopper block
#include "Globals.h"
#include "../BlockEntities/HopperEntity.h"
#include "HopperWindow.h"
#include "../BlockEntities/DropperEntity.h"
cHopperWindow::cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEntity * a_Hopper) :
super(wtHopper, "Hopper")
{
m_SlotAreas.push_back(new cSlotAreaItemGrid(a_Hopper->GetContents(), *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cHopperWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Hopper Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Inventory or Hotbar
AreasInOrder.push_back(m_SlotAreas[0]); /* Hopper */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

32
src/UI/HopperWindow.h Normal file
View File

@ -0,0 +1,32 @@
// HopperWindow.h
// Representing the UI window for the hopper block
#pragma once
#include "Window.h"
class cHopperWindow :
public cWindow
{
typedef cWindow super;
public:
cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEntity * a_Hopper);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
};

View File

@ -0,0 +1,73 @@
// InventoryWindow.cpp
// Representing the UI window for the player inventory
#include "Globals.h"
#include "InventoryWindow.h"
#include "SlotArea.h"
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));
}
void cInventoryWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Crafting Area
if (a_Slot == 0)
{
// Result Slot
AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */
}
else
{
AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */
AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */
}
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, (a_Slot == 0));
}
else if (a_ClickedArea == m_SlotAreas[1])
{
// Armor Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */
AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
else if (a_ClickedArea == m_SlotAreas[2])
{
// Inventory Area
AreasInOrder.push_back(m_SlotAreas[1]); /* Armor */
AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
else
{
// Hotbar
AreasInOrder.push_back(m_SlotAreas[1]); /* Armor */
AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}

34
src/UI/InventoryWindow.h Normal file
View File

@ -0,0 +1,34 @@
// InventoryWindow.h
// Representing the UI window for the player inventory
#pragma once
#include "Window.h"
class cInventoryWindow :
public cWindow
{
typedef cWindow super;
public:
cInventoryWindow(cPlayer & a_Player);
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
protected:
cPlayer & m_Player;
};

View File

@ -0,0 +1,67 @@
// MinecartWithChestWindow.h
// Representing the UI window for the minecart chest entity
#pragma once
#include "Window.h"
#include "../Entities/Minecart.h"
class cMinecartWithChestWindow :
public cWindow
{
typedef cWindow super;
public:
cMinecartWithChestWindow(cMinecartWithChest * a_ChestCart) :
cWindow(wtChest, "Minecart with Chest"),
m_ChestCart(a_ChestCart)
{
m_SlotAreas.push_back(new cSlotAreaMinecartWithChest(a_ChestCart, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
a_ChestCart->GetWorld()->BroadcastSoundEffect("random.chestopen", a_ChestCart->GetPosX(), a_ChestCart->GetPosY(), a_ChestCart->GetPosZ(), 1, 1);
}
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea* a_ClickedArea, bool a_ShouldApply) override
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Chest Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
// Hotbar or Inventory
AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}
~cMinecartWithChestWindow()
{
m_ChestCart->GetWorld()->BroadcastSoundEffect("random.chestclosed", m_ChestCart->GetPosX(), m_ChestCart->GetPosY(), m_ChestCart->GetPosZ(), 1, 1);
}
private:
cMinecartWithChest * m_ChestCart;
};

View File

@ -1,3 +1,4 @@
// SlotArea.cpp
// Implements the cSlotArea class and its descendants
@ -12,6 +13,7 @@
#include "../BlockEntities/FurnaceEntity.h"
#include "../Entities/Minecart.h"
#include "../Items/ItemHandler.h"
#include "AnvilWindow.h"
#include "Window.h"
#include "../CraftingRecipes.h"
#include "../Root.h"
@ -205,7 +207,7 @@ void cSlotArea::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_
{
// 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);
m_ParentWindow.DistributeStack(Slot, a_SlotNum, a_Player, this, true);
if (Slot.IsEmpty())
{
// Empty the slot completely, the client doesn't like left-over ItemType with zero count
@ -340,31 +342,31 @@ void cSlotArea::OnPlayerRemoved(cPlayer & a_Player)
void cSlotArea::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotArea::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
for (int i = 0; i < m_NumSlots; i++)
{
const cItem * Slot = GetSlot(i, a_Player);
int SlotNum = (a_BackFill) ? (m_NumSlots - 1 - i) : i;
const cItem * Slot = GetSlot(SlotNum, a_Player);
if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots))
{
// Different items
continue;
}
int NumFit = ItemHandler(Slot->m_ItemType)->GetMaxStackSize() - Slot->m_ItemCount;
char 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;
}
NumFit = std::min(NumFit, a_ItemStack.m_ItemCount);
if (a_ShouldApply)
{
cItem NewSlot(a_ItemStack);
NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit;
SetSlot(i, a_Player, NewSlot);
SetSlot(SlotNum, a_Player, NewSlot);
}
a_ItemStack.m_ItemCount -= NumFit;
if (a_ItemStack.IsEmpty())
@ -589,12 +591,13 @@ void cSlotAreaCrafting::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem &
void cSlotAreaCrafting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotAreaCrafting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
UNUSED(a_ItemStack);
UNUSED(a_Player);
UNUSED(a_ShouldApply);
UNUSED(a_KeepEmptySlots);
UNUSED(a_BackFill);
}
@ -656,7 +659,7 @@ void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player)
{
// Try distributing the result. If it fails, bail out:
cItem ResultCopy(Result);
m_ParentWindow.DistributeStack(ResultCopy, a_Player, this, false);
m_ParentWindow.DistributeStack(ResultCopy, 0, a_Player, this, false);
if (!ResultCopy.IsEmpty())
{
// Couldn't distribute all of it. Bail out
@ -665,7 +668,7 @@ void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player)
// Distribute the result, this time for real:
ResultCopy = Result;
m_ParentWindow.DistributeStack(ResultCopy, a_Player, this, true);
m_ParentWindow.DistributeStack(ResultCopy, 0, a_Player, this, true);
// Remove the ingredients from the crafting grid and update the recipe:
cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player);
@ -769,7 +772,7 @@ void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Play
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaAnvil:
cSlotAreaAnvil::cSlotAreaAnvil(cAnvilWindow & a_ParentWindow) :
cSlotAreaAnvil::cSlotAreaAnvil(cWindow & a_ParentWindow) :
cSlotAreaTemporary(3, a_ParentWindow),
m_MaximumCost(0),
m_StackSizeToBeUsedInRepair(0)
@ -894,7 +897,7 @@ void cSlotAreaAnvil::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem
return;
}
m_ParentWindow.DistributeStack(Slot, a_Player, this, true);
m_ParentWindow.DistributeStack(Slot, a_SlotNum, a_Player, this, true);
if (Slot.IsEmpty())
{
Slot.Empty();
@ -910,31 +913,31 @@ void cSlotAreaAnvil::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem
void cSlotAreaAnvil::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotAreaAnvil::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
for (int i = 0; i < 2; i++)
{
const cItem * Slot = GetSlot(i, a_Player);
int SlotNum = (a_BackFill) ? (2 - 1 - i) : i;
const cItem * Slot = GetSlot(SlotNum, a_Player);
if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots))
{
// Different items
continue;
}
int NumFit = ItemHandler(Slot->m_ItemType)->GetMaxStackSize() - Slot->m_ItemCount;
char 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;
}
NumFit = std::min(NumFit, a_ItemStack.m_ItemCount);
if (a_ShouldApply)
{
cItem NewSlot(a_ItemStack);
NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit;
SetSlot(i, a_Player, NewSlot);
SetSlot(SlotNum, a_Player, NewSlot);
}
a_ItemStack.m_ItemCount -= NumFit;
if (a_ItemStack.IsEmpty())
@ -1051,7 +1054,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
cItem SecondInput(*GetSlot(1, a_Player));
cItem Output(*GetSlot(2, a_Player));
if (Input.IsEmpty() && !Output.IsEmpty())
if (Input.IsEmpty())
{
Output.Empty();
SetSlot(2, a_Player, Output);
@ -1335,7 +1338,7 @@ void cSlotAreaBeacon::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_
void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
const cItem * Slot = GetSlot(0, a_Player);
if (!Slot->IsEmpty() || !IsPlaceableItem(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemCount != 1))
@ -1390,13 +1393,12 @@ void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:
cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ) :
cSlotAreaEnchanting::cSlotAreaEnchanting(cWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ) :
cSlotAreaTemporary(1, a_ParentWindow),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
a_ParentWindow.m_SlotArea = this;
}
@ -1503,7 +1505,7 @@ void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickActio
void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots)
void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots, bool a_BackFill)
{
const cItem * Slot = GetSlot(0, a_Player);
if (!Slot->IsEmpty())
@ -1833,38 +1835,50 @@ void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a
void cSlotAreaFurnace::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotAreaFurnace::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
for (int i = 0; i < 2; i++)
int SlotNum;
cFurnaceRecipe * FurnaceRecipes = cRoot::Get()->GetFurnaceRecipe();
if (FurnaceRecipes->GetRecipeFrom(a_ItemStack) != nullptr)
{
const cItem * Slot = GetSlot(i, a_Player);
if (!Slot->IsEqual(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_ShouldApply)
{
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
SlotNum = 0;
}
else if (FurnaceRecipes->IsFuel(a_ItemStack))
{
SlotNum = 1;
}
else
{
return;
}
const cItem * Slot = GetSlot(SlotNum, a_Player);
if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots))
{
// Different items
return;
}
char NumFit = ItemHandler(Slot->m_ItemType)->GetMaxStackSize() - Slot->m_ItemCount;
if (NumFit <= 0)
{
// Full stack already
return;
}
NumFit = std::min(NumFit, a_ItemStack.m_ItemCount);
if (a_ShouldApply)
{
cItem NewSlot(a_ItemStack);
NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit;
SetSlot(SlotNum, a_Player, NewSlot);
}
a_ItemStack.m_ItemCount -= NumFit;
if (a_ItemStack.IsEmpty())
{
return;
}
}
@ -2013,7 +2027,7 @@ void cSlotAreaInventoryBase::SetSlot(int a_SlotNum, cPlayer & a_Player, const cI
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaArmor:
void cSlotAreaArmor::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
void cSlotAreaArmor::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
{
if (ItemCategory::IsHelmet(a_ItemStack.m_ItemType) && GetSlot(0, a_Player)->IsEmpty())
{

View File

@ -17,12 +17,10 @@ class cWindow;
class cPlayer;
class cBeaconEntity;
class cChestEntity;
class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cMinecartWithChest;
class cCraftingRecipe;
class cEnchantingWindow;
class cWorld;
@ -73,7 +71,7 @@ public:
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);
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill);
/// Called on DblClicking to collect all stackable items into hand.
/// The items are accumulated in a_Dragging and removed from the slots immediately.
@ -158,7 +156,7 @@ public:
}
/** 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;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override;
/** 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) override;
@ -246,7 +244,7 @@ public:
virtual void SetSlot (int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) 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;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override;
protected:
@ -285,12 +283,12 @@ class cSlotAreaAnvil :
typedef cSlotAreaTemporary super;
public:
cSlotAreaAnvil(cAnvilWindow & a_ParentWindow);
cSlotAreaAnvil(cWindow & a_ParentWindow);
// cSlotArea overrides:
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override;
// cSlotAreaTemporary overrides:
virtual void OnPlayerRemoved(cPlayer & a_Player) override;
@ -326,10 +324,10 @@ public:
cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow);
virtual ~cSlotAreaBeacon();
bool IsPlaceableItem(short a_ItemType);
static bool IsPlaceableItem(short a_ItemType);
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) 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;
@ -350,11 +348,11 @@ class cSlotAreaEnchanting :
typedef cSlotAreaTemporary super;
public:
cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ);
cSlotAreaEnchanting(cWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ);
// cSlotArea overrides:
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override;
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
// cSlotAreaTemporary overrides:
@ -439,7 +437,7 @@ public:
virtual ~cSlotAreaFurnace();
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) 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;

View File

@ -32,7 +32,6 @@ cWindow::cWindow(WindowType a_WindowType, const AString & a_WindowTitle) :
m_WindowType(a_WindowType),
m_WindowTitle(a_WindowTitle),
m_IsDestroyed(false),
m_ShouldDistributeToHotbarFirst(true),
m_Owner(nullptr)
{
if (a_WindowType == wtInventory)
@ -392,43 +391,23 @@ bool cWindow::ForEachClient(cItemCallback<cClientHandle> & a_Callback)
void cWindow::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, cSlotArea * a_ExcludeArea, bool a_ShouldApply)
void cWindow::DistributeStackToAreas(cItem & a_ItemStack, cPlayer & a_Player, cSlotAreas & a_AreasInOrder, bool a_ShouldApply, bool a_BackFill)
{
// 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)
/* 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 (size_t Pass = 0; Pass < 2; Pass++)
{
if (m_ShouldDistributeToHotbarFirst)
for (auto SlotArea : a_AreasInOrder)
{
// 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));
SlotArea->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0), a_BackFill);
if (a_ItemStack.IsEmpty())
{
// Distributed it all
return;
}
} // for itr - m_SlotAreas[]
} // for Pass - repeat twice
}
}
}
@ -779,401 +758,3 @@ void cWindow::SetProperty(short a_Property, short a_Value, cPlayer & a_Player)
////////////////////////////////////////////////////////////////////////////////
// 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));
}
////////////////////////////////////////////////////////////////////////////////
// cAnvilWindow:
cAnvilWindow::cAnvilWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
cWindow(wtAnvil, "Repair"),
m_RepairedItemName(""),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
m_AnvilSlotArea = new cSlotAreaAnvil(*this);
m_SlotAreas.push_back(m_AnvilSlotArea);
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cAnvilWindow::SetRepairedItemName(const AString & a_Name, cPlayer * a_Player)
{
m_RepairedItemName = a_Name;
if (a_Player != nullptr)
{
m_AnvilSlotArea->UpdateResult(*a_Player);
}
}
void cAnvilWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
{
a_PosX = m_BlockX;
a_PosY = m_BlockY;
a_PosZ = m_BlockZ;
}
////////////////////////////////////////////////////////////////////////////////
// cBeaconWindow:
cBeaconWindow::cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon) :
cWindow(wtBeacon, "Beacon"),
m_Beacon(a_Beacon)
{
m_ShouldDistributeToHotbarFirst = true;
m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player)
{
super::OpenedByPlayer(a_Player);
a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel());
a_Player.GetClientHandle()->SendWindowProperty(*this, 1, m_Beacon->GetPrimaryEffect());
a_Player.GetClientHandle()->SendWindowProperty(*this, 2, m_Beacon->GetSecondaryEffect());
}
////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:
cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
cWindow(wtEnchantment, "Enchant"),
m_SlotArea(),
m_BlockX(a_BlockX),
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
m_SlotAreas.push_back(new cSlotAreaEnchanting(*this, m_BlockX, m_BlockY, m_BlockZ));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cEnchantingWindow::SetProperty(short a_Property, short a_Value)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return;
}
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value);
}
void cEnchantingWindow::SetProperty(short a_Property, short a_Value, cPlayer & a_Player)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return;
}
m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value, a_Player);
}
short cEnchantingWindow::GetPropertyValue(short a_Property)
{
if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
{
ASSERT(!"a_Property is invalid");
return 0;
}
return m_PropertyValue[a_Property];
}
////////////////////////////////////////////////////////////////////////////////
// cChestWindow:
cChestWindow::cChestWindow(cChestEntity * a_Chest) :
cWindow(wtChest, (a_Chest->GetBlockType() == E_BLOCK_CHEST) ? "Chest" : "Trapped Chest"),
m_World(a_Chest->GetWorld()),
m_BlockX(a_Chest->GetPosX()),
m_BlockY(a_Chest->GetPosY()),
m_BlockZ(a_Chest->GetPosZ()),
m_PrimaryChest(a_Chest),
m_SecondaryChest(nullptr)
{
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", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_Chest->GetBlockType());
}
cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) :
cWindow(wtChest, (a_PrimaryChest->GetBlockType() == E_BLOCK_CHEST) ? "Double Chest" : "Double Trapped Chest"),
m_World(a_PrimaryChest->GetWorld()),
m_BlockX(a_PrimaryChest->GetPosX()),
m_BlockY(a_PrimaryChest->GetPosY()),
m_BlockZ(a_PrimaryChest->GetPosZ()),
m_PrimaryChest(a_PrimaryChest),
m_SecondaryChest(a_SecondaryChest)
{
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", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_PrimaryChest->GetBlockType());
}
void cChestWindow::OpenedByPlayer(cPlayer & a_Player)
{
int ChunkX, ChunkZ;
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() + 1);
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
if (m_SecondaryChest != nullptr)
{
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() + 1);
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
}
cWindow::OpenedByPlayer(a_Player);
}
bool cChestWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
{
int ChunkX, ChunkZ;
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() - 1);
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
if (m_SecondaryChest != nullptr)
{
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() - 1);
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
}
cWindow::ClosedByPlayer(a_Player, a_CanRefuse);
return true;
}
cChestWindow::~cChestWindow()
{
// Send out the chest-close packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, m_PrimaryChest->GetBlockType());
m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
////////////////////////////////////////////////////////////////////////////////
// cMinecartWithChestWindow:
cMinecartWithChestWindow::cMinecartWithChestWindow(cMinecartWithChest * a_ChestCart) :
cWindow(wtChest, "Minecart with Chest"),
m_ChestCart(a_ChestCart)
{
m_ShouldDistributeToHotbarFirst = false;
m_SlotAreas.push_back(new cSlotAreaMinecartWithChest(a_ChestCart, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
a_ChestCart->GetWorld()->BroadcastSoundEffect("random.chestopen", a_ChestCart->GetPosX(), a_ChestCart->GetPosY(), a_ChestCart->GetPosZ(), 1, 1);
}
cMinecartWithChestWindow::~cMinecartWithChestWindow()
{
m_ChestCart->GetWorld()->BroadcastSoundEffect("random.chestclosed", m_ChestCart->GetPosX(), m_ChestCart->GetPosY(), m_ChestCart->GetPosZ(), 1, 1);
}
////////////////////////////////////////////////////////////////////////////////
// cDropSpenserWindow:
cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser) :
cWindow(wtDropSpenser, (a_DropSpenser->GetBlockType() == E_BLOCK_DISPENSER) ? "Dispenser" : "Dropper")
{
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));
}
////////////////////////////////////////////////////////////////////////////////
// cEnderChestWindow:
cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest) :
cWindow(wtChest, "Ender Chest"),
m_World(a_EnderChest->GetWorld()),
m_BlockX(a_EnderChest->GetPosX()),
m_BlockY(a_EnderChest->GetPosY()),
m_BlockZ(a_EnderChest->GetPosZ())
{
m_ShouldDistributeToHotbarFirst = false;
m_SlotAreas.push_back(new cSlotAreaEnderChest(a_EnderChest, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
// Play the opening sound:
m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_ENDER_CHEST);
}
cEnderChestWindow::~cEnderChestWindow()
{
// Send out the chest-close packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_ENDER_CHEST);
// Play the closing sound
m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
////////////////////////////////////////////////////////////////////////////////
// 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));
}

View File

@ -19,7 +19,6 @@ class cPlayer;
class cWindowOwner;
class cClientHandle;
class cChestEntity;
class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cHopperEntity;
@ -154,14 +153,19 @@ public:
/** 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) */
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) = 0;
/** Called from DistributeStack() to distribute the stack into a_AreasInOrder; 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);
If a_BackFill is true, the areas will be filled from the back (right side). (Example: Empty Hotbar -> Item get in slot 8, not slot 0) */
void DistributeStackToAreas(cItem & a_ItemStack, cPlayer & a_Player, cSlotAreas & a_AreasInOrder, bool a_ShouldApply, bool a_BackFill);
/// 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.
/** 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
@ -178,7 +182,6 @@ protected:
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;
@ -219,188 +222,3 @@ protected:
class cCraftingWindow :
public cWindow
{
typedef cWindow super;
public:
cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
} ;
class cAnvilWindow :
public cWindow
{
typedef cWindow super;
public:
cAnvilWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Gets the repaired item name. */
AString GetRepairedItemName(void) const { return m_RepairedItemName; }
/** Set the repaired item name. */
void SetRepairedItemName(const AString & a_Name, cPlayer * a_Player);
/** Gets the Position from the Anvil */
void GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ);
protected:
cSlotAreaAnvil * m_AnvilSlotArea;
AString m_RepairedItemName;
int m_BlockX, m_BlockY, m_BlockZ;
} ;
class cBeaconWindow :
public cWindow
{
typedef cWindow super;
public:
cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon);
cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; }
// cWindow Overrides:
virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cBeaconEntity * m_Beacon;
} ;
class cEnchantingWindow :
public cWindow
{
typedef cWindow super;
public:
cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ);
virtual void SetProperty(short a_Property, short a_Value, cPlayer & a_Player) override;
virtual void SetProperty(short a_Property, short a_Value) override;
/** Return the Value of a Property */
short GetPropertyValue(short a_Property);
cSlotArea * m_SlotArea;
protected:
short m_PropertyValue[3];
int m_BlockX, m_BlockY, m_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();
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cWorld * m_World;
int m_BlockX, m_BlockY, m_BlockZ; // Position of the chest, for the window-close packet
cChestEntity * m_PrimaryChest;
cChestEntity * m_SecondaryChest;
} ;
class cMinecartWithChestWindow :
public cWindow
{
public:
cMinecartWithChestWindow(cMinecartWithChest * a_ChestCart);
~cMinecartWithChestWindow();
private:
cMinecartWithChest * m_ChestCart;
};
class cEnderChestWindow :
public cWindow
{
public:
cEnderChestWindow(cEnderChestEntity * a_EnderChest);
~cEnderChestWindow();
protected:
cWorld * m_World;
int m_BlockX, m_BlockY, m_BlockZ; // Position of the enderchest, for the window-close packet
};
class cInventoryWindow :
public cWindow
{
public:
cInventoryWindow(cPlayer & a_Player);
protected:
cPlayer & m_Player;
} ;