1
0

Merge pull request #1858 from mc-server/BucketPluginCalls

Bucket plugin calls
This commit is contained in:
Mattes D 2015-04-15 11:07:03 +02:00
commit 1d8a22cb7b
24 changed files with 270 additions and 504 deletions

View File

@ -2031,8 +2031,6 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
HOOK_HOPPER_PUSHING_ITEM = { Notes = "Called when a hopper is pushing an item into the container it is aimed at." },
HOOK_KILLING = { Notes = "Called when an entity has just been killed. A plugin may resurrect the entity by setting its health to above zero." },
HOOK_LOGIN = { Notes = "Called when a Login packet is sent to the client, before the client is queued for authentication." },
HOOK_MAX = { Notes = "The maximum TypeID of a hook. Used internally by MCS to check hook type for validity." },
HOOK_NUM_HOOKS = { Notes = "Total number of hook types MCS supports. Used internally by MCS to check hook type for validity." },
HOOK_PLAYER_ANIMATION = { Notes = "Called when a client send the Animation packet." },
HOOK_PLAYER_BREAKING_BLOCK = { Notes = "Called when a player is about to break a block. A plugin may cancel the event." },
HOOK_PLAYER_BROKEN_BLOCK = { Notes = "Called after a player has broken a block." },

View File

@ -1,457 +1,65 @@
-- Global variables
PLUGIN = {} -- Reference to own plugin object
-- HookNotify.lua
--[[
Implements the entire plugin
NOTE: This plugin is not meant for production servers. It is used mainly by developers to verify that things
are working properly when implementing MCServer features. Do not enable this plugin on production servers!
This plugin logs a notification for each hook that is being called by the server.
The TICK and WORLD_TICK hooks are disabled because they produce too much output.
--]]
function Initialize(Plugin)
PLUGIN = Plugin
Plugin:SetName("HookNotify");
Plugin:SetVersion(1);
PluginManager = cPluginManager:Get();
cPluginManager.AddHook(cPluginManager.HOOK_BLOCK_TO_PICKUPS, OnBlockToPickups);
cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChat);
cPluginManager.AddHook(cPluginManager.HOOK_CHUNK_AVAILABLE, OnChunkAvailable);
cPluginManager.AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
cPluginManager.AddHook(cPluginManager.HOOK_CHUNK_GENERATING, OnChunkGenerating);
cPluginManager.AddHook(cPluginManager.HOOK_CHUNK_UNLOADED, OnChunkUnloaded);
cPluginManager.AddHook(cPluginManager.HOOK_CHUNK_UNLOADING, OnChunkUnloading);
cPluginManager.AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup);
cPluginManager.AddHook(cPluginManager.HOOK_CRAFTING_NO_RECIPE, OnCraftingNoRecipe);
cPluginManager.AddHook(cPluginManager.HOOK_DISCONNECT, OnDisconnect);
cPluginManager.AddHook(cPluginManager.HOOK_ENTITY_TELEPORT, OnEntityTeleport);
cPluginManager.AddHook(cPluginManager.HOOK_EXECUTE_COMMAND, OnExecuteCommand);
cPluginManager.AddHook(cPluginManager.HOOK_HANDSHAKE, OnHandshake);
cPluginManager.AddHook(cPluginManager.HOOK_KILLING, OnKilling);
cPluginManager.AddHook(cPluginManager.HOOK_LOGIN, OnLogin);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_BREAKING_BLOCK, OnPlayerBreakingBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_BROKEN_BLOCK, OnPlayerBrokenBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_EATING, OnPlayerEating);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_LEFT_CLICK, OnPlayerLeftClick);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_PLACED_BLOCK, OnPlayerPlacedBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_PLACING_BLOCK, OnPlayerPlacingBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICK, OnPlayerRightClick);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_SHOOTING, OnPlayerShooting);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_SPAWNED, OnPlayerSpawned);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_TOSSING_ITEM, OnPlayerTossingItem);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USED_BLOCK, OnPlayerUsedBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USED_ITEM, OnPlayerUsedItem);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USING_BLOCK, OnPlayerUsingBlock);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USING_ITEM, OnPlayerUsingItem);
cPluginManager.AddHook(cPluginManager.HOOK_POST_CRAFTING, OnPostCrafting);
cPluginManager.AddHook(cPluginManager.HOOK_PRE_CRAFTING, OnPreCrafting);
cPluginManager.AddHook(cPluginManager.HOOK_SPAWNED_ENTITY, OnSpawnedEntity);
cPluginManager.AddHook(cPluginManager.HOOK_SPAWNED_MONSTER, OnSpawnedMonster);
cPluginManager.AddHook(cPluginManager.HOOK_SPAWNING_ENTITY, OnSpawningEntity);
cPluginManager.AddHook(cPluginManager.HOOK_SPAWNING_MONSTER, OnSpawningMonster);
cPluginManager.AddHook(cPluginManager.HOOK_TAKE_DAMAGE, OnTakeDamage);
cPluginManager.AddHook(cPluginManager.HOOK_UPDATED_SIGN, OnUpdatedSign);
cPluginManager.AddHook(cPluginManager.HOOK_UPDATING_SIGN, OnUpdatingSign);
cPluginManager.AddHook(cPluginManager.HOOK_WEATHER_CHANGED, OnWeatherChanged);
cPluginManager.AddHook(cPluginManager.HOOK_WEATHER_CHANGING, OnWeatherChanging);
function Initialize(a_Plugin)
-- Notify the admin that HookNotify is installed, this is not meant for production servers
LOGINFO("HookNotify plugin is installed, beware, the log output may be quite large!");
LOGINFO("You want this plugin enabled only when developing another plugin, not for regular gameplay.");
-- These hooks will not be notified:
local hooksToIgnore =
{
["HOOK_TICK"] = true, -- Too much spam
["HOOK_WORLD_TICK"] = true, -- Too much spam
["HOOK_TAKE_DAMAGE"] = true, -- Has a separate handler with more info logged
["HOOK_MAX"] = true, -- No such hook, placeholder only
["HOOK_NUM_HOOKS"] = true, -- No such hook, placeholder only
}
-- Add all hooks:
for n, v in pairs(cPluginManager) do
if (n:match("HOOK_.*")) then
if not(hooksToIgnore[n]) then
LOG("Adding notification for hook " .. n .. " (" .. v .. ").")
cPluginManager.AddHook(v,
function (...)
LOG(n .. "(")
for i, param in ipairs(arg) do
LOG(" " .. i .. ": " .. tolua.type(param) .. ": " .. tostring(param))
end
LOG(")");
end -- hook handler
) -- AddHook
end -- not (ignore)
end -- n matches "HOOK"
end -- for cPluginManager{}
-- OnTakeDamage has a special handler listing the details of the damage dealt:
cPluginManager.AddHook(cPluginManager.HOOK_TAKE_DAMAGE,
function (a_Receiver, a_TDI)
-- a_Receiver is cPawn
-- a_TDI is TakeDamageInfo
LOG("OnTakeDamage(): " .. a_Receiver:GetClass() .. " was dealt RawDamage " .. a_TDI.RawDamage .. ", FinalDamage " .. a_TDI.FinalDamage .. " (that is, " .. (a_TDI.RawDamage - a_TDI.FinalDamage) .. " HPs covered by armor)");
end
)
return true
end
function LogHook(FnName, ...)
LOG(FnName .. "(");
for i, v in ipairs(arg) do
local vt = tostring(v);
local TypeString = type(v);
if (type(v) == "userdata") then
TypeString = tolua.type(v);
end;
LOG(" " .. tostring(i) .. ": " .. TypeString .. ": " .. tostring(v));
end
LOG(")");
end
function OnBlockToPickups(...)
LogHook("OnBlockToPickups", unpack(arg));
local World, Digger, BlockX, BlockY, BlockZ, BlockType, BlockMeta, Pickups = unpack(arg);
if (Pickups ~= nil) then
local Name = "NULL";
if (Digger ~= nil) then
Name = Digger:GetName()
end
LOG("Got cItems from " .. Name .. ", trying to manipulate them.");
Pickups:Add(cItem:new(E_ITEM_DIAMOND_SHOVEL, 1));
LOG("Current size: " .. Pickups:Size());
end;
end;
function OnChat(...)
LogHook("OnChat", unpack(arg));
end
function OnChunkAvailable(...)
LogHook("OnChunkAvailable", unpack(arg));
end
function OnChunkGenerated(...)
LogHook("OnChunkGenerated", unpack(arg));
end
function OnChunkGenerating(...)
LogHook("OnChunkGenerating", unpack(arg));
end
function OnChunkUnloaded(...)
LogHook("OnChunkUnloaded", unpack(arg));
end
function OnChunkUnloading(...)
LogHook("OnChunkUnloading", unpack(arg));
end
function OnPlayerUsingItem(...)
LogHook("OnPlayerUsingItem", unpack(arg));
end
function OnCollectingPickup(...)
LogHook("OnCollectingPickup", unpack(arg));
end
function OnCraftingNoRecipe(...)
LogHook("OnCraftingNoRecipe", unpack(arg));
end
function OnDisconnect(...)
LogHook("OnDisconnect", unpack(arg));
end
function OnEntityTeleport(arg1,arg2,arg3)
if arg1.IsPlayer() then
-- if it's a player, get his name
LOG("OnEntityTeleport: Player: " .. arg1.GetName());
else
-- if it's a entity, get its type
LOG("OnEntityTeleport: EntityType: " .. arg1.GetEntityType());
end
LOG("OldPos: " .. arg2.x .. " / " .. arg2.y .. " / " .. arg2.z);
LOG("NewPos: " .. arg3.x .. " / " .. arg3.y .. " / " .. arg3.z);
end
function OnExecuteCommand(...)
LogHook("OnExecuteCommand", unpack(arg));
-- For some reason logging doesn't work for this callback, so list some stuff manually to verify:
LOG("arg1 type: " .. type(arg[1]));
if (arg[1] ~= nil) then
LOG("Player name: " .. arg[1]:GetName());
end
LOG("Command: " .. arg[2][1]);
end
function OnHandshake(...)
LogHook("OnHandshake", unpack(arg));
end
function OnKilling(...)
LogHook("OnKilling", unpack(arg));
end
function OnLogin(...)
LogHook("OnLogin", unpack(arg));
end
function OnPlayerBreakingBlock(...)
LogHook("OnPlayerBreakingBlock", unpack(arg));
end
function OnPlayerBrokenBlock(...)
LogHook("OnPlayerBrokenBlock", unpack(arg));
end
function OnPlayerEating(...)
LogHook("OnPlayerEating", unpack(arg));
end
function OnPlayerJoined(...)
LogHook("OnPlayerJoined", unpack(arg));
end
function OnPlayerLeftClick(...)
LogHook("OnPlayerLeftClick", unpack(arg));
end
function OnPlayerMoving(...)
LogHook("OnPlayerMoving", unpack(arg));
end
function OnPlayerPlacedBlock(...)
LogHook("OnPlayerPlacedBlock", unpack(arg));
end
function OnPlayerPlacingBlock(...)
LogHook("OnPlayerPlacingBlock", unpack(arg));
end
function OnPlayerRightClick(...)
LogHook("OnPlayerRightClick", unpack(arg));
end
function OnPlayerShooting(...)
LogHook("OnPlayerShooting", unpack(arg));
end
function OnPlayerSpawned(...)
LogHook("OnPlayerSpawned", unpack(arg));
end
function OnPlayerTossingItem(...)
LogHook("OnPlayerTossingItem", unpack(arg));
end
function OnPlayerUsedBlock(...)
LogHook("OnPlayerUsedBlock", unpack(arg));
end
function OnPlayerUsedItem(...)
LogHook("OnPlayerUsedItem", unpack(arg));
end
function OnPlayerUsingBlock(...)
LogHook("OnPlayerUsingBlock", unpack(arg));
end
function OnPlayerUsingItem(...)
LogHook("OnPlayerUsingItem", unpack(arg));
end
function OnPostCrafting(...)
LogHook("OnPostCrafting", unpack(arg));
end
function OnPreCrafting(...)
LogHook("OnPreCrafting", unpack(arg));
end
function OnSpawnedEntity(...)
LogHook("OnSpawnedEntity", unpack(arg));
end
function OnSpawnedMonster(...)
LogHook("OnSpawnedMonster", unpack(arg));
end
function OnSpawningEntity(...)
LogHook("OnSpawningEntity", unpack(arg));
end
function OnSpawningMonster(...)
LogHook("OnSpawningMonster", unpack(arg));
end
function OnUpdatedSign(...)
LogHook("OnUpdatedSign", unpack(arg));
end
function OnUpdatingSign(...)
LogHook("OnUpdatingSign", unpack(arg));
end
function OnWeatherChanged(...)
LogHook("OnWeatherChanged", unpack(arg));
end
function OnWeatherChanging(...)
LogHook("OnWeatherChanging", unpack(arg));
end
------------------------------------------------------------------
-- Special handling for OnTakeDamage to print the contents of TDI:
function OnTakeDamage(Receiver, TDI)
-- Receiver is cPawn
-- TDI is TakeDamageInfo
LOG("OnTakeDamage(): " .. Receiver:GetClass() .. " was dealt RawDamage " .. TDI.RawDamage .. ", FinalDamage " .. TDI.FinalDamage .. " (that is, " .. (TDI.RawDamage - TDI.FinalDamage) .. " HPs covered by armor)");
end

View File

@ -134,6 +134,8 @@ public:
HOOK_WEATHER_CHANGING,
HOOK_WORLD_STARTED,
HOOK_WORLD_TICK,
// tolua_end
// Note that if a hook type is added, it may need processing in cPlugin::CanAddHook() descendants,
// and it definitely needs adding in cPluginLua::GetHookFnName() !
@ -141,8 +143,7 @@ public:
// Keep these two as the last items, they are used for validity checking and get their values automagically
HOOK_NUM_HOOKS,
HOOK_MAX = HOOK_NUM_HOOKS - 1,
} ;
// tolua_end
} ; // tolua_export
/** Used as a callback for enumerating bound commands */
class cCommandEnumCallback

View File

@ -1,4 +1,12 @@
// BlockInServerPluginInterface.h
// Defines the cBlockInServerPluginInterface class that implements the cBlockPluginInterface for blocks, using the plugin manager
#pragma once
#include "Blocks/BlockPluginInterface.h"
@ -16,7 +24,7 @@ class cBlockInServerPluginInterface :
public:
cBlockInServerPluginInterface(cWorld & a_World) : m_World(a_World) {}
virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source)
virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) override
{
return cPluginManager::Get()->CallHookBlockSpread(m_World, a_BlockX, a_BlockY, a_BlockZ, a_Source);
}
@ -26,6 +34,16 @@ public:
return cPluginManager::Get()->CallHookBlockToPickups(m_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_Pickups);
}
virtual bool CallHookPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
return cPluginManager::Get()->CallHookPlayerBreakingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta);
}
virtual bool CallHookPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
return cPluginManager::Get()->CallHookPlayerBrokenBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta);
}
private:
cWorld & m_World;
};

View File

@ -1,10 +1,25 @@
// BlockPluginInterface.h
// Declares the cBlockPluginInterface class representing an interface that the blockhandlers and itemhandlers use for calling plugins
#pragma once
// fwd:
class cPlayer;
/** This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
The block handlers call this interface, which is then implemented by the specific classes that
the caller provides.
@ -16,6 +31,8 @@ public:
virtual bool CallHookBlockSpread(int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
virtual bool CallHookBlockToPickups(cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
virtual bool CallHookPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool CallHookPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
};

View File

@ -23,6 +23,7 @@
#include "Blocks/BlockSlab.h"
#include "Blocks/BlockBed.h"
#include "Blocks/ChunkInterface.h"
#include "BlockInServerPluginInterface.h"
#include "Root.h"
@ -1432,7 +1433,8 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
// A plugin doesn't agree with using the item, abort
return;
}
ItemHandler->OnItemUse(World, m_Player, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
cBlockInServerPluginInterface PluginInterface(*World);
ItemHandler->OnItemUse(World, m_Player, PluginInterface, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
}
}

View File

@ -17,8 +17,13 @@ public:
{
}
/** Move the armor to the armor slot of the player's inventory */
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
int SlotNum;
if (ItemCategory::IsHelmet(a_Item.m_ItemType))
@ -60,6 +65,8 @@ public:
return true;
}
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
{
switch (m_ItemType)

View File

@ -28,9 +28,12 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if ((a_Dir != BLOCK_FACE_YM) && (a_Dir != BLOCK_FACE_NONE))
if ((a_BlockFace != BLOCK_FACE_YM) && (a_BlockFace != BLOCK_FACE_NONE))
{
return false;
}

View File

@ -26,8 +26,12 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
ASSERT(a_Player != nullptr);
@ -40,6 +44,7 @@ public:
a_Player->StartChargingBow();
return true;
}
virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override

View File

@ -23,13 +23,18 @@ public:
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
switch (m_ItemType)
{
case E_ITEM_BUCKET: return ScoopUpFluid(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
case E_ITEM_LAVA_BUCKET: return PlaceFluid (a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir, E_BLOCK_LAVA);
case E_ITEM_WATER_BUCKET: return PlaceFluid (a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir, E_BLOCK_WATER);
case E_ITEM_BUCKET: return ScoopUpFluid(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
case E_ITEM_LAVA_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, E_BLOCK_LAVA);
case E_ITEM_WATER_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, E_BLOCK_WATER);
default:
{
ASSERT(!"Unhandled ItemType");
@ -40,7 +45,7 @@ public:
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
{
if (a_BlockFace != BLOCK_FACE_NONE)
{
@ -75,6 +80,12 @@ public:
return false;
}
// Remove water / lava block (unless plugins disagree)
if (!a_Player->PlaceBlock(BlockPos.x, BlockPos.y, BlockPos.z, E_BLOCK_AIR, 0))
{
return false;
}
// Give new bucket, filled with fluid when the gamemode is not creative:
if (!a_Player->IsGameModeCreative())
{
@ -85,25 +96,33 @@ public:
ASSERT(!"Inventory bucket mismatch");
return true;
}
a_Player->GetInventory().AddItem(cItem(NewItem), true, true);
if (a_Player->GetInventory().AddItem(cItem(NewItem), true, true) != 1)
{
// The bucket didn't fit, toss it as a pickup:
a_Player->TossPickup(cItem(NewItem));
}
}
// Remove water / lava block
a_Player->GetWorld()->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, E_BLOCK_AIR, 0);
return true;
}
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock)
bool PlaceFluid(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock
)
{
if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}
BLOCKTYPE CurrentBlock;
BLOCKTYPE CurrentBlockType;
NIBBLETYPE CurrentBlockMeta;
eBlockFace EntryFace;
Vector3i BlockPos;
if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlock))
if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlockType, CurrentBlockMeta, EntryFace))
{
return false;
}
@ -125,23 +144,29 @@ public:
}
// Wash away anything that was there prior to placing:
if (cFluidSimulator::CanWashAway(CurrentBlock))
if (cFluidSimulator::CanWashAway(CurrentBlockType))
{
cBlockHandler * Handler = BlockHandler(CurrentBlock);
if (a_PluginInterface.CallHookPlayerBreakingBlock(*a_Player, BlockPos.x, BlockPos.y, BlockPos.z, EntryFace, CurrentBlockType, CurrentBlockMeta))
{
// Plugin disagrees with the washing-away
return false;
}
cBlockHandler * Handler = BlockHandler(CurrentBlockType);
if (Handler->DoesDropOnUnsuitable())
{
cChunkInterface ChunkInterface(a_World->GetChunkMap());
cBlockInServerPluginInterface PluginInterface(*a_World);
Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
Handler->DropBlock(ChunkInterface, *a_World, a_PluginInterface, a_Player, BlockPos.x, BlockPos.y, BlockPos.z);
}
a_PluginInterface.CallHookPlayerBrokenBlock(*a_Player, BlockPos.x, BlockPos.y, BlockPos.z, EntryFace, CurrentBlockType, CurrentBlockMeta);
}
a_World->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, a_FluidBlock, 0);
return true;
// Place the actual fluid block:
return a_Player->PlaceBlock(BlockPos.x, BlockPos.y, BlockPos.z, a_FluidBlock, 0);
}
bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos)
{
class cCallbacks :
@ -190,20 +215,25 @@ public:
}
bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType)
bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta, eBlockFace & a_BlockFace)
{
class cCallbacks :
public cBlockTracer::cCallbacks
{
public:
Vector3i m_Pos;
BLOCKTYPE m_ReplacedBlock;
BLOCKTYPE m_ReplacedBlockType;
NIBBLETYPE m_ReplacedBlockMeta;
eBlockFace m_EntryFace;
virtual bool OnNextBlock(int a_CBBlockX, int a_CBBlockY, int a_CBBlockZ, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, char a_CBEntryFace) override
{
if (a_CBBlockType != E_BLOCK_AIR)
{
m_ReplacedBlock = a_CBBlockType;
m_ReplacedBlockType = a_CBBlockType;
m_ReplacedBlockMeta = a_CBBlockMeta;
m_EntryFace = static_cast<eBlockFace>(a_CBEntryFace);
if (!cFluidSimulator::CanWashAway(a_CBBlockType) && !IsBlockLiquid(a_CBBlockType))
{
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, (eBlockFace)a_CBEntryFace); // Was an unwashawayable block, can't overwrite it!
@ -219,12 +249,14 @@ public:
Vector3d Start(a_Player->GetEyePosition());
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
// cTracer::Trace returns true when whole line was traversed. By returning true when we hit something, we ensure that this never happens if liquid could be placed
// cTracer::Trace returns true when whole line was traversed. By returning true from the callback when we hit something, we ensure that this never happens if liquid could be placed
// Use this to judge whether the position is valid
if (!Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z))
{
a_BlockPos = Callbacks.m_Pos;
a_BlockType = Callbacks.m_ReplacedBlock;
a_BlockType = Callbacks.m_ReplacedBlockType;
a_BlockMeta = Callbacks.m_ReplacedBlockMeta;
a_BlockFace = Callbacks.m_EntryFace;
return true;
}

View File

@ -19,7 +19,12 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
// Handle growing the plants:
if (a_Item.m_ItemDamage == E_META_DYE_WHITE)

View File

@ -27,12 +27,17 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
UNUSED(a_Item);
UNUSED(a_BlockX);
UNUSED(a_BlockZ);
UNUSED(a_Dir);
UNUSED(a_BlockFace);
// The map center is fixed at the central point of the 8x8 block of chunks you are standing in when you right-click it.
@ -60,3 +65,7 @@ public:
return true;
}
} ;

View File

@ -93,9 +93,14 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_Dir != BLOCK_FACE_NONE)
if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}

View File

@ -411,15 +411,19 @@ bool cItemHandler::OnPlayerPlace(
bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir)
bool cItemHandler::OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
)
{
UNUSED(a_World);
UNUSED(a_Player);
UNUSED(a_PluginInterface);
UNUSED(a_Item);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_Dir);
UNUSED(a_BlockFace);
return false;
}

View File

@ -4,6 +4,7 @@
#include "../Defines.h"
#include "../Item.h"
#include "../Entities/EntityEffect.h"
#include "../Blocks/BlockPluginInterface.h"
@ -56,8 +57,12 @@ public:
);
/** Called when the player tries to use the item (right mouse button). Return false to make the item unusable. DEFAULT: False */
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir);
/** Called when the player tries to use the item (right mouse button).
Return false to abort the usage. DEFAULT: False */
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
);
/** Called when the client sends the SHOOT status in the lclk packet */

View File

@ -18,9 +18,14 @@ public:
{
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if ((a_Dir == BLOCK_FACE_NONE) || (a_BlockY >= cChunkDef::Height))
if ((a_BlockFace == BLOCK_FACE_NONE) || (a_BlockY >= cChunkDef::Height))
{
return false;
}

View File

@ -19,21 +19,26 @@ public:
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if ((a_Dir == BLOCK_FACE_NONE) || (a_Dir == BLOCK_FACE_YP) || (a_Dir == BLOCK_FACE_YM))
if ((a_BlockFace == BLOCK_FACE_NONE) || (a_BlockFace == BLOCK_FACE_YP) || (a_BlockFace == BLOCK_FACE_YM))
{
// Client sends this if clicked on top or bottom face
return false;
}
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // We want the clicked block, so go back again
if (Block == E_BLOCK_AIR)
{
cItemFrame * ItemFrame = new cItemFrame(a_Dir, a_BlockX, a_BlockY, a_BlockZ);
cItemFrame * ItemFrame = new cItemFrame(a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
if (!ItemFrame->Initialize(*a_World))
{
delete ItemFrame;

View File

@ -19,7 +19,12 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_BlockFace < 0)
{

View File

@ -29,7 +29,11 @@ public:
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_BlockFace > BLOCK_FACE_NONE)
{

View File

@ -27,9 +27,12 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_Dir < 0)
if (a_BlockFace < 0)
{
return false;
}

View File

@ -19,15 +19,20 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if ((a_Dir == BLOCK_FACE_NONE) || (a_Dir == BLOCK_FACE_YM) || (a_Dir == BLOCK_FACE_YP))
if ((a_BlockFace == BLOCK_FACE_NONE) || (a_BlockFace == BLOCK_FACE_YM) || (a_BlockFace == BLOCK_FACE_YP))
{
// Paintings can't be flatly placed
return false;
}
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (Block == E_BLOCK_AIR)
@ -65,7 +70,7 @@ public:
{ "BurningSkull" }
};
cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, a_Dir, a_BlockX, a_BlockY, a_BlockZ);
cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, a_BlockFace, a_BlockX, a_BlockY, a_BlockZ);
Painting->Initialize(*a_World);
if (!a_Player->IsGameModeCreative())

View File

@ -26,7 +26,10 @@ public:
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
short PotionDamage = a_Item.m_ItemDamage;

View File

@ -19,7 +19,11 @@ public:
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_BlockFace < 0)
{

View File

@ -26,7 +26,11 @@ public:
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
Vector3d Pos = a_Player->GetThrowStartPos();
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
@ -128,7 +132,12 @@ public:
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
virtual bool OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
) override
{
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
{
@ -149,3 +158,7 @@ public:
}
};