diff --git a/Server/Plugins/APIDump/Classes/Plugins.lua b/Server/Plugins/APIDump/Classes/Plugins.lua index bb9848667..63f4172e6 100644 --- a/Server/Plugins/APIDump/Classes/Plugins.lua +++ b/Server/Plugins/APIDump/Classes/Plugins.lua @@ -790,6 +790,10 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage); { Notes = "Called when a hopper is pushing an item into the container it is aimed at.", }, + HOOK_DROPSPENSE = + { + Notes = "Called when a {{cDropSpenserEntity|DropSpenser}} is dropspensing an {{cItem|item}}.", + }, HOOK_KILLED = { Notes = "Called when an entity has been killed.", diff --git a/Server/Plugins/APIDump/Hooks/OnDropSpense.lua b/Server/Plugins/APIDump/Hooks/OnDropSpense.lua new file mode 100644 index 000000000..8a7e93abb --- /dev/null +++ b/Server/Plugins/APIDump/Hooks/OnDropSpense.lua @@ -0,0 +1,26 @@ +return +{ + HOOK_DROPSPENSE = + { + CalledWhen = "A dispenser or dropper is about to dispense/drop an item.", + DefaultFnName = "OnDropSpense", -- also used as pagename + Desc = [[ + This callback is called whenever a {{cDropSpenserEntity|dropspenser}} dropspenses an {{cItem|item}}. A plugin may decide to disallow + the move by returning true. + ]], + Params = + { + { Name = "World", Type = "{{cWorld}}", Notes = "World where the dropspenser resides" }, + { Name = "DropSpenser", Type = "{{cDropSpenserEntity}}", Notes = "The dropspenser that is pulling the item" }, + { Name = "SlotNum", Type = "number", Notes = "The slot of the dropspensed item in the dropspenser's {{cItemGrid|internal storage}}" }, + }, + Returns = [[ + If the function returns false or no value, the next plugin's callback is called. If the function + returns true, no other callback is called for this event and the dropspenser will not dropspense the item. + ]], + }, -- HOOK_DROPSPENSE +} + + + + diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h index afc575b13..19947ff2e 100644 --- a/src/Bindings/Plugin.h +++ b/src/Bindings/Plugin.h @@ -66,6 +66,7 @@ public: virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0; + virtual bool OnDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) = 0; virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) = 0; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0; virtual bool OnLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) = 0; diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index abac8b9a8..f4cfd4a86 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -523,6 +523,15 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper, +bool cPluginLua::OnDropSpense(cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) +{ + return CallSimpleHooks(cPluginManager::HOOK_DROPSPENSE, &a_World, &a_DropSpenser, a_SlotNum); +} + + + + + bool cPluginLua::OnKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) { cOperation op(*this); diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h index a9e488074..352c444dc 100644 --- a/src/Bindings/PluginLua.h +++ b/src/Bindings/PluginLua.h @@ -87,6 +87,7 @@ public: virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override; + virtual bool OnDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) override; virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) override; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override; virtual bool OnLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) override; diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 88bc82172..6593097dd 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -613,6 +613,19 @@ bool cPluginManager::CallHookHopperPushingItem(cWorld & a_World, cHopperEntity & +bool cPluginManager::CallHookDropSpense(cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) +{ + return GenericCallHook(HOOK_DROPSPENSE, [&](cPlugin * a_Plugin) + { + return a_Plugin->OnDropSpense(a_World, a_DropSpenser, a_SlotNum); + } + ); +} + + + + + bool cPluginManager::CallHookKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) { return GenericCallHook(HOOK_KILLED, [&](cPlugin * a_Plugin) diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index 3b35a826a..353950f18 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -18,6 +18,7 @@ class cClientHandle; class cCommandOutputCallback; class cCraftingGrid; class cCraftingRecipe; +class cDropSpenserEntity; class cEntity; class cHopperEntity; class cItems; @@ -101,6 +102,7 @@ public: HOOK_HANDSHAKE, HOOK_HOPPER_PULLING_ITEM, HOOK_HOPPER_PUSHING_ITEM, + HOOK_DROPSPENSE, HOOK_KILLED, HOOK_KILLING, HOOK_LOGIN, @@ -249,7 +251,8 @@ public: bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username); bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum); bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum); - bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage); + bool CallHookDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum); + bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage); bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI); bool CallHookLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username); bool CallHookLoginForge (cClientHandle & a_Client, AStringMap & a_Mods); @@ -457,4 +460,3 @@ private: - diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp index 97a67ff60..243ec8594 100644 --- a/src/BlockEntities/DropSpenserEntity.cpp +++ b/src/BlockEntities/DropSpenserEntity.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "DropSpenserEntity.h" +#include "../Bindings/PluginManager.h" #include "../EffectID.h" #include "../Entities/Player.h" #include "../Chunk.h" @@ -80,8 +81,16 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) int RandomSlot = m_World->GetTickRandomNumber(SlotsCnt - 1); + int SpenseSlot = OccupiedSlots[RandomSlot]; + + if (cPluginManager::Get()->CallHookDropSpense(*m_World, *this, SpenseSlot)) + { + // Plugin disagrees with the move + return; + } + // DropSpense the item, using the specialized behavior in the subclasses: - DropSpenseFromSlot(a_Chunk, OccupiedSlots[RandomSlot]); + DropSpenseFromSlot(a_Chunk, SpenseSlot); // Broadcast a smoke and click effects: NIBBLETYPE Meta = a_Chunk.GetMeta(GetRelPos()); diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 9665b9f25..2e4264204 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -95,7 +95,7 @@ bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cHopperEntity::SendTo(cClientHandle & a_Client) { // The hopper entity doesn't need anything sent to the client when it's created / gets in the viewdistance - // All the actual handling is in the cWindow UI code that gets called when the hopper is rclked + // All the actual handling is in the cWindow UI code that gets called when the hopper is right-clicked UNUSED(a_Client); }