Currently I'm trying to block item use, and even though it seems to work fine for preventing flint and steel use, any bucket just refuses.
No matter if I return true (preventing use) or false (allowing use) using HOOK_PLAYER_USING_ITEM, the bucket is used.
If it's a waterbucket the water is placed, if it's a lavabucket the lava is placed, if it's an empty bucket then whatever fluid was there before is now in the bucket.
Again, I can prevent flint and steel fine with this method, and Player:GetEquippedItem() does show the proper bucket when logged.
I'm not sure what's happening here, is it a bug in Cuberite?
Try the OnPlayerRightClick hook instead. I do believe we should call the OnPlayerUsingItem hook when the bucket is used though.
Well it is called, that's the thing. The action is just not prevented. I'll try OnPlayerRightClick though.
EDIT: Bucket use can't be prevented using that hook either.
Could you upload the code?
local sql = "SELECT towns.town_id, towns.nation_id, towns.town_permissions FROM townChunks INNER JOIN towns ON townChunks.town_id = towns.town_id WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if not (town) then --The item is used on a block that is not part of a town, so it's allowed
return false;
else
if (town[1] == GetPlayerTown(Player:GetUUID())) then
allowed = CheckPermission(town[3], RESIDENTITEMUSE);
else
if (town[2] == GetPlayerNation(Player:GetUUID())) then
allowed = CheckPermission(town[3], ALLYITEMUSE);
else
allowed = CheckPermission(town[3], OUTSIDERITEMUSE);
end
end
if (allowed == true) then
if (ItemToString(Player:GetEquippedItem()) == "lighter") then
local sql = "SELECT towns.town_id, towns.town_fire_enabled FROM towns INNER JOIN townChunks ON towns.town_id = townChunks.town_id WHERE townChunks.chunkX = ? AND townChunks.chunkZ = ? AND townChunks.world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if (town and town[2] == 0) then --If fire is disabled in this town, prevent the player from starting a fire
return true; --Prevent item use
else
return false; --Allow item use
end
else
return false; --Allow item use
end
else
return true; --Prevent item use
end
end
The CheckPermission function returns either true or false depending on if it's allowed or not.
I've tried a simple
cPluginManager:AddHook(cPluginManager.HOOK_PLAYER_RIGHT_CLICK, function() return true end)
and it prevented the placements of buckets. On occasion the water/lava was there, but it was only client-side as it wasn't there anymore when re-logging. Are you sure your code is correct everywhere and returns true when it needs to?
Just returning true does indeed block the use somehow... However, I'm 100% sure it doesn't with more code, no idea why. I literally have LOG('test') 1 row before returning true, and even though it does log the 'test', it allows bucket use.
Ooh and the water showing up while it's not actually placed, is related to
this issue.
OnPlayerRightClick (Maybe OnPlayerUsingItem as well) gets called twice. Once with a BLOCK_FACE_NONE parameter. Perhaps the LOG('test') is called from that?
Yeah I just found that out, OnPlayerUsingItem gets called twice as well. If I LOG(town) then the first time it returns fine, the second time time will be a nil value. It seems the second time BlockX and BlockY both return -1 instead of the actual block that is being changed, meaning the query won't find anything, meaning it will return false at the first conditional statement.
Why exactly is it called twice? And how would I now prevent buckets from being placed like this?
It's called twice because the client sends it twice. This allows things like fishing since you don't have a block selected in the world as well. It also makes the compass tool in WorldEdit possible.