From 50c6a660922410e9c010583f597ee3f011f43226 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Fri, 21 Sep 2012 20:50:34 +0000 Subject: Working shift-click support in crafting areas; window update working in 1.3.2 git-svn-id: http://mc-server.googlecode.com/svn/trunk@869 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Protocol132.cpp | 21 +++++++++++++++++++ source/Protocol132.h | 19 +++++++++-------- source/UI/SlotArea.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++----- source/UI/SlotArea.h | 5 ++++- source/UI/cWindow.cpp | 29 +++++++++++++++++++++++++ source/UI/cWindow.h | 5 ++++- 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; -- cgit v1.2.3