summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-09-21 22:50:34 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-09-21 22:50:34 +0200
commit50c6a660922410e9c010583f597ee3f011f43226 (patch)
treec3a53b70f7ff1d390d7469b739b2f4afaafa9f8f
parentUI: Added shift-click support to most slot areas, except crafting. (diff)
downloadcuberite-50c6a660922410e9c010583f597ee3f011f43226.tar
cuberite-50c6a660922410e9c010583f597ee3f011f43226.tar.gz
cuberite-50c6a660922410e9c010583f597ee3f011f43226.tar.bz2
cuberite-50c6a660922410e9c010583f597ee3f011f43226.tar.lz
cuberite-50c6a660922410e9c010583f597ee3f011f43226.tar.xz
cuberite-50c6a660922410e9c010583f597ee3f011f43226.tar.zst
cuberite-50c6a660922410e9c010583f597ee3f011f43226.zip
-rw-r--r--source/Protocol132.cpp21
-rw-r--r--source/Protocol132.h19
-rw-r--r--source/UI/SlotArea.cpp57
-rw-r--r--source/UI/SlotArea.h5
-rw-r--r--source/UI/cWindow.cpp29
-rw-r--r--source/UI/cWindow.h5
6 files changed, 120 insertions, 16 deletions
diff --git a/source/Protocol132.cpp b/source/Protocol132.cpp
index 207266d99..32fd4b63c 100644
--- a/source/Protocol132.cpp
+++ b/source/Protocol132.cpp
@@ -13,6 +13,7 @@
#include "ChunkDataSerializer.h"
#include "cPlayer.h"
#include "cMonster.h"
+#include "UI/cWindow.h"
@@ -360,6 +361,26 @@ void cProtocol132::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cProtocol132::SendWholeInventory(const cWindow & a_Window)
+{
+ // 1.3.2 requires player inventory slots to be sent as SetSlot packets,
+ // otherwise it sometimes fails to update the window
+ super::SendWholeInventory(a_Window);
+ const cItem * Slots = m_Client->GetPlayer()->GetInventory().GetSlots();
+ int BaseOffset = a_Window.GetNumSlots() - cInventory::c_NumSlots + cInventory::c_MainOffset; // the number of non-inventory slots the window has; inventory follows
+ char WindowID = a_Window.GetWindowID();
+ for (int i = 0; i < cInventory::c_NumSlots - cInventory::c_MainOffset; i++)
+ {
+ SendInventorySlot(WindowID, BaseOffset + i, Slots[i + cInventory::c_MainOffset]);
+ } // for i - Slots[]
+ // Send even the item being dragged:
+ SendInventorySlot(-1, -1, m_Client->GetPlayer()->GetDraggingItem());
+}
+
+
+
+
+
AString cProtocol132::GetAuthServerID(void)
{
// http://wiki.vg/wiki/index.php?title=Session&oldid=2615
diff --git a/source/Protocol132.h b/source/Protocol132.h
index 3f21d4841..5705ba680 100644
--- a/source/Protocol132.h
+++ b/source/Protocol132.h
@@ -32,15 +32,16 @@ public:
virtual void DataReceived(const char * a_Data, int a_Size) override;
// Sending commands:
- virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
- virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
- virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendDestroyEntity(const cEntity & a_Entity) override;
- virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
- virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
- virtual void SendSpawnMob (const cMonster & a_Mob) override;
- virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
+ virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
+ virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
+ virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
+ virtual void SendDestroyEntity (const cEntity & a_Entity) override;
+ virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
+ virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ virtual void SendSpawnMob (const cMonster & a_Mob) override;
+ virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
+ virtual void SendWholeInventory(const cWindow & a_Window) override;
virtual AString GetAuthServerID(void) override;
diff --git a/source/UI/SlotArea.cpp b/source/UI/SlotArea.cpp
index 60929be2f..6bc90b78e 100644
--- a/source/UI/SlotArea.cpp
+++ b/source/UI/SlotArea.cpp
@@ -257,7 +257,14 @@ void cSlotAreaCrafting::Clicked(cPlayer & a_Player, int a_SlotNum, bool a_IsRigh
// Override for craft result slot
if (a_SlotNum == 0)
{
- ClickedResult(a_Player, a_IsShiftPressed);
+ if (a_IsShiftPressed)
+ {
+ ShiftClickedResult(a_Player);
+ }
+ else
+ {
+ ClickedResult(a_Player);
+ }
return;
}
super::Clicked(a_Player, a_SlotNum, a_IsRightClick, a_IsShiftPressed, a_ClickedItem);
@@ -290,12 +297,9 @@ void cSlotAreaCrafting::OnPlayerRemoved(cPlayer & a_Player)
-void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player, bool a_IsShiftPressed)
+void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
{
const cItem * ResultSlot = GetSlot(0, a_Player);
- LOGD("Clicked in craft result slot, item there: %d:%d (%d times)",
- ResultSlot->m_ItemID, ResultSlot->m_ItemHealth, ResultSlot->m_ItemCount
- );
cItem & DraggingItem = a_Player.GetDraggingItem();
// Get the current recipe:
@@ -333,11 +337,54 @@ void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player, bool a_IsShiftPressed)
+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);
}
diff --git a/source/UI/SlotArea.h b/source/UI/SlotArea.h
index 0f3182036..79f95c5d5 100644
--- a/source/UI/SlotArea.h
+++ b/source/UI/SlotArea.h
@@ -197,7 +197,10 @@ protected:
cRecipeMap m_Recipes;
/// Handles a click in the result slot. Crafts using the current recipe, if possible
- void ClickedResult(cPlayer & a_Player, bool a_IsShiftPressed);
+ 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);
diff --git a/source/UI/cWindow.cpp b/source/UI/cWindow.cpp
index 71d2a1200..7efbfaa5e 100644
--- a/source/UI/cWindow.cpp
+++ b/source/UI/cWindow.cpp
@@ -294,6 +294,35 @@ void cWindow::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, cSlotArea
+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)
{
LOGD("Destroying window %p (type %d)", this, m_WindowType);
diff --git a/source/UI/cWindow.h b/source/UI/cWindow.h
index 980a1e711..0fc368c9c 100644
--- a/source/UI/cWindow.h
+++ b/source/UI/cWindow.h
@@ -58,7 +58,7 @@ public:
cWindow(WindowType a_WindowType, const AString & a_WindowTitle);
virtual ~cWindow();
- int GetWindowID(void) const { return m_WindowID; }
+ char GetWindowID(void) const { return m_WindowID; }
int GetWindowType(void) const { return m_WindowType; }
cWindowOwner * GetOwner() { return m_Owner; }
@@ -99,6 +99,9 @@ public:
*/
void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, cSlotArea * a_ExcludeArea, bool a_ShouldApply);
+ /// 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;