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 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 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()); }
void cWindow::OnMiddlePaintEnd(cPlayer & a_Player) { if (!a_Player.IsGameModeCreative()) { // Midle click paint is only valid for creative mode return; } // Fill available slots with full stacks of the dragging item const auto & DraggingItem = a_Player.GetDraggingItem(); auto StackSize = ItemHandler(DraggingItem.m_ItemType)->GetMaxStackSize(); if (0 < DistributeItemToSlots(a_Player, DraggingItem, StackSize, a_Player.GetInventoryPaintSlots(), false)) { // If any items were distibuted, set dragging item empty a_Player.GetDraggingItem().Empty(); } SendWholeWindow(*a_Player.GetClientHandle()); }
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 / (int)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 cSlotArea::MiddleClicked(cPlayer & a_Player, int a_SlotNum) { cItem Slot(*GetSlot(a_SlotNum, a_Player)); cItem & DraggingItem = a_Player.GetDraggingItem(); if (!a_Player.IsGameModeCreative() || Slot.IsEmpty() || !DraggingItem.IsEmpty()) { return; } DraggingItem = Slot; DraggingItem.m_ItemCount = DraggingItem.GetMaxStackSize(); }
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()); // To fix #2345 (custom recipes don't work when inventory-painting), we send the result slot explicitly once again // This is a fix for what seems like a client-side bug a_Player.GetClientHandle()->SendInventorySlot(m_WindowID, 0, *GetSlot(a_Player, 0)); }
void cSlotAreaEnchanting::DblClicked(cPlayer & a_Player, int a_SlotNum) { cItem & Dragging = a_Player.GetDraggingItem(); if ((!Dragging.IsEmpty()) || (a_SlotNum != 0)) { return; } cItem Item = *GetSlot(0, a_Player); if (!m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, false)) { m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, true); } }
bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { // Checks whether the player is still holding an item if (!a_Player.GetDraggingItem().IsEmpty()) { LOGD("Player holds item! Dropping it..."); a_Player.TossHeldItem(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::Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ) { cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); 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 caLeftClickOutside: case caRightClickOutside: { if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } if (a_Player.IsGameModeCreative()) { a_Player.TossPickup(a_ClickedItem); } if (a_ClickAction == caLeftClickOutside) { // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } else { // Toss one of the dragged items: a_Player.TossHeldItem(); } 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; default: { break; } } 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 cSlotAreaAnvil::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); if (a_SlotNum != 2) { super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); UpdateResult(a_Player); return; } bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == NULL) { LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum); return; } if (a_ClickAction == caDblClick) { return; } if ((a_ClickAction == caShiftLeftClick) || (a_ClickAction == caShiftRightClick)) { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); 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(); if (Slot.IsEmpty()) { return; } if (!DraggingItem.IsEmpty()) { if (!(DraggingItem.IsEqual(Slot) && ((DraggingItem.m_ItemCount + Slot.m_ItemCount) <= cItemHandler::GetItemHandler(Slot)->GetMaxStackSize()))) { return; } } if (!CanTakeResultItem(a_Player)) { return; } cItem NewItem = cItem(Slot); NewItem.m_ItemCount += DraggingItem.m_ItemCount; Slot.Empty(); DraggingItem.Empty(); SetSlot(a_SlotNum, a_Player, Slot); DraggingItem = NewItem; OnTakeResult(a_Player); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } }
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; } default: { break; } } 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 = Slot.CopyOne(); // Obtain copy of slot to preserve lore, enchantments, etc. DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f); Slot.m_ItemCount -= DraggingItem.m_ItemCount; 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())) { char OldSlotCount = Slot.m_ItemCount; Slot = DraggingItem.CopyOne(); // See above OldSlotCount++; Slot.m_ItemCount = OldSlotCount; 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 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 cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { 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; } default: { break; } } 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: { // Right-clicked if (DraggingItem.IsEmpty()) { DraggingItem = Slot.CopyOne(); Slot.Empty(); break; } if (Slot.IsEmpty()) { Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if ((!DraggingItem.IsEqual(Slot)) && (DraggingItem.m_ItemCount == 1)) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } break; } case caLeftClick: { // Left-clicked if (DraggingItem.IsEmpty()) { DraggingItem = Slot.CopyOne(); Slot.Empty(); break; } if (DraggingItem.IsEqual(Slot)) { // Do nothing break; } if (!Slot.IsEmpty()) { if (DraggingItem.m_ItemCount == 1) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } } else { Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; 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(); } UpdateResult(a_Player); }