diff options
-rw-r--r-- | MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua | 7 | ||||
-rw-r--r-- | src/ClientHandle.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 107 | ||||
-rw-r--r-- | src/Entities/Player.h | 9 | ||||
-rw-r--r-- | src/UI/Window.cpp | 37 |
5 files changed, 105 insertions, 60 deletions
diff --git a/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua b/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua index 85c943721..2b65294ef 100644 --- a/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua +++ b/MCServer/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua @@ -5,7 +5,7 @@ return CalledWhen = "A player is tossing an item. Plugin may override / refuse.", DefaultFnName = "OnPlayerTossingItem", -- also used as pagename Desc = [[ - This hook is called when a {{cPlayer|player}} has tossed an item (Q keypress). The + This hook is called when a {{cPlayer|player}} has tossed an item. The {{cPickup|pickup}} has not been spawned yet. Plugins may disallow the tossing, but in that case they need to clean up - the player's client already thinks the item has been tossed so the {{cInventory|inventory}} needs to be re-sent to the player.</p> @@ -18,8 +18,9 @@ return }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and finally MCServer - creates the pickup for the item and tosses it, using {{cPlayer}}:TossItem. If the function returns - true, no other callbacks are called for this event and MCServer doesn't toss the item. + creates the pickup for the item and tosses it, using {{cPlayer}}:TossHeldItem, {{cPlayer}}:TossEquippedItem, + or {{cPlayer}}:TossPickup. If the function returns true, no other callbacks are called for this event + and MCServer doesn't toss the item. ]], }, -- HOOK_PLAYER_TOSSING_ITEM } diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 74d192129..ab3c85ba9 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -658,7 +658,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - m_Player->TossItem(false); + + m_Player->TossEquippedItem(); return; } @@ -713,7 +714,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } - m_Player->TossItem(false, 64); // Toss entire slot - if there aren't enough items, the maximum will be ejected + m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected return; } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index c1f2456eb..ca39d4d9d 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1342,59 +1342,68 @@ AString cPlayer::GetColor(void) const -void cPlayer::TossItem( - bool a_bDraggingItem, - char a_Amount /* = 1 */, - short a_CreateType /* = 0 */, - short a_CreateHealth /* = 0 */ -) +void cPlayer::TossEquippedItem(char a_Amount) { cItems Drops; - if (a_CreateType != 0) - { - // Just create item without touching the inventory (used in creative mode) - Drops.push_back(cItem(a_CreateType, a_Amount, a_CreateHealth)); - } - else - { - // Drop an item from the inventory: - if (a_bDraggingItem) - { - cItem & Item = GetDraggingItem(); - if (!Item.IsEmpty()) - { - char OriginalItemAmount = Item.m_ItemCount; - Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); - Drops.push_back(Item); - if (OriginalItemAmount > a_Amount) - { - Item.m_ItemCount = OriginalItemAmount - (char)a_Amount; - } - else - { - Item.Empty(); - } - } - } - else - { - // Else drop equipped item - cItem DroppedItem(GetInventory().GetEquippedItem()); - if (!DroppedItem.IsEmpty()) - { - char NewAmount = a_Amount; - if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) - { - NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there - } + cItem DroppedItem(GetInventory().GetEquippedItem()); + if (!DroppedItem.IsEmpty()) + { + char NewAmount = a_Amount; + if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) + { + NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there + } - GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); + GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); + + DroppedItem.m_ItemCount = NewAmount; + Drops.push_back(DroppedItem); + } + + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + vY = -vY * 2 + 1.f; + m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player +} + + + + + +void cPlayer::TossHeldItem(char a_Amount) +{ + cItems Drops; + cItem & Item = GetDraggingItem(); + if (!Item.IsEmpty()) + { + char OriginalItemAmount = Item.m_ItemCount; + Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); + Drops.push_back(Item); + if (OriginalItemAmount > a_Amount) + { + Item.m_ItemCount = OriginalItemAmount - a_Amount; + } + else + { + Item.Empty(); + } + } + + double vX = 0, vY = 0, vZ = 0; + EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); + vY = -vY * 2 + 1.f; + m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player +} + + + + + +void cPlayer::TossPickup(const cItem & a_Item) +{ + cItems Drops; + Drops.push_back(a_Item); - DroppedItem.m_ItemCount = NewAmount; - Drops.push_back(DroppedItem); - } - } - } double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index bf3ca08e8..71033ab77 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -214,7 +214,14 @@ public: /// Returns the full color code to use for this player, based on their primary group or set in m_Color AString GetColor(void) const; - void TossItem(bool a_bDraggingItem, char a_Amount = 1, short a_CreateType = 0, short a_CreateHealth = 0); + // tosses the item in the selected hotbar slot + void TossEquippedItem(char a_Amount = 1); + + // tosses the item held in hand (when in UI windows) + void TossHeldItem(char a_Amount = 1); + + // tosses a pickup newly created from a_Item + void TossPickup(const cItem & a_Item); /// Heals the player by the specified amount of HPs (positive only); sends health update void Heal(int a_Health); diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 3ffeff7a0..3dd6d2264 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -13,7 +13,8 @@ #include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/HopperEntity.h" - +#include "../Root.h" +#include "../Bindings/PluginManager.h" @@ -169,6 +170,8 @@ void cWindow::Clicked( 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()); @@ -179,14 +182,36 @@ void cWindow::Clicked( { 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); + } + // Toss one of the dragged items: - a_Player.TossItem(true); + a_Player.TossHeldItem(); return; } case caLeftClickOutside: { + 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); + } + // Toss all dragged items: - a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); return; } case caLeftClickOutsideHoldNothing: @@ -259,11 +284,13 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player) bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { + cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); + // Checks whether the player is still holding an item if (a_Player.IsDraggingItem()) { - LOGD("Player holds item! Dropping it..."); - a_Player.TossItem(true, a_Player.GetDraggingItem().m_ItemCount); + LOGD("Player holds item! Dropping it..."); + a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); |