Skip to content

Commit

Permalink
Fix default item callbacks to work with nil users
Browse files Browse the repository at this point in the history
  • Loading branch information
raymoo committed May 26, 2017
1 parent 4d5ce84 commit 788670d
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 48 deletions.
2 changes: 1 addition & 1 deletion builtin/game/chatcommands.lua
Expand Up @@ -653,7 +653,7 @@ core.register_chatcommand("pulverize", {
core.rollback_punch_callbacks = {}

core.register_on_punchnode(function(pos, node, puncher)
local name = puncher:get_player_name()
local name = puncher and puncher:get_player_name() or "!nonplayer"
if core.rollback_punch_callbacks[name] then
core.rollback_punch_callbacks[name](pos, node, puncher)
core.rollback_punch_callbacks[name] = nil
Expand Down
120 changes: 73 additions & 47 deletions builtin/game/item.lua
Expand Up @@ -181,14 +181,16 @@ function core.get_node_drops(nodename, toolname)
end
if item.tools ~= nil then
good_tool = false
for _, tool in ipairs(item.tools) do
if tool:sub(1, 1) == '~' then
good_tool = toolname:find(tool:sub(2)) ~= nil
else
good_tool = toolname == tool
end
if good_tool then
break
if toolname then
for _, tool in ipairs(item.tools) do
if tool:sub(1, 1) == '~' then
good_tool = toolname:find(tool:sub(2)) ~= nil
else
good_tool = toolname == tool
end
if good_tool then
break
end
end
end
end
Expand All @@ -205,6 +207,16 @@ function core.get_node_drops(nodename, toolname)
return got_items
end

local non_player_name = "!nonplayer"
local function user_name(user)
return user and user:get_player_name() or non_player_name
end

local function is_protected(pos, name, user)
return core.is_protected(pos, name) and
not (name ~= non_player_name and minetest.check_player_privs(user, "protection_bypass"))
end

function core.item_place_node(itemstack, placer, pointed_thing, param2)
local def = itemstack:get_definition()
if def.type ~= "node" or pointed_thing.type ~= "node" then
Expand All @@ -215,7 +227,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
local oldnode_under = core.get_node_or_nil(under)
local above = pointed_thing.above
local oldnode_above = core.get_node_or_nil(above)
local playername = placer:get_player_name()
local playername = user_name(placer)

if not oldnode_under or not oldnode_above then
core.log("info", playername .. " tried to place"
Expand Down Expand Up @@ -244,8 +256,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
place_to = {x = under.x, y = under.y, z = under.z}
end

if core.is_protected(place_to, playername) and
not minetest.check_player_privs(placer, "protection_bypass") then
if is_protected(place_to, playername, placer) then
core.log("action", playername
.. " tried to place " .. def.name
.. " at protected position "
Expand Down Expand Up @@ -274,7 +285,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
-- Calculate the direction for furnaces and chests and stuff
elseif (def.paramtype2 == "facedir" or
def.paramtype2 == "colorfacedir") and not param2 then
local placer_pos = placer:getpos()
local placer_pos = placer and placer:getpos()
if placer_pos then
local dir = {
x = above.x - placer_pos.x,
Expand Down Expand Up @@ -360,28 +371,27 @@ function core.item_secondary_use(itemstack, placer)
end

function core.item_drop(itemstack, dropper, pos)
if dropper and dropper:is_player() then
local v = dropper:get_look_dir()
local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
local cs = itemstack:get_count()
local dropper_is_player = dropper and dropper:is_player()
local p = pos
local cs = itemstack:get_count()
if dropper_is_player then
p = {x=pos.x, y=pos.y+1.2, z=pos.z}
if dropper:get_player_control().sneak then
cs = 1
end
local item = itemstack:take_item(cs)
local obj = core.add_item(p, item)
if obj then
end
local item = itemstack:take_item(cs)
local obj = core.add_item(p, item)
if obj then
if dropper_is_player then
local v = dropper:get_look_dir()
v.x = v.x*2
v.y = v.y*2 + 2
v.z = v.z*2
obj:setvelocity(v)
obj:get_luaentity().dropped_by = dropper:get_player_name()
return itemstack
end

else
if core.add_item(pos, itemstack) then
return itemstack
end
return itemstack
end
-- If we reach this, adding the object to the
-- environment failed
Expand All @@ -402,7 +412,8 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", {name=replace_with_item}) then
-- Check if inv is null, since non-players don't have one
if inv and inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:getpos()
Expand All @@ -417,7 +428,9 @@ end

function core.item_eat(hp_change, replace_with_item)
return function(itemstack, user, pointed_thing) -- closure
return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
if user then
return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
end
end
end

Expand All @@ -434,7 +447,7 @@ end

function core.handle_node_drops(pos, drops, digger)
-- Add dropped items to object's inventory
if digger:get_inventory() then
if digger and digger:get_inventory() then
local _, dropped_item
for _, dropped_item in ipairs(drops) do
local left = digger:get_inventory():add_item("main", dropped_item)
Expand All @@ -447,6 +460,16 @@ function core.handle_node_drops(pos, drops, digger)
core.add_item(p, left)
end
end
else
for _, dropped_item in ipairs(drops) do
local p = {
x = pos.x + math.random()/2-0.25,
y = pos.y + math.random()/2-0.25,
z = pos.z + math.random()/2-0.25,
}
core.add_item(p, dropped_item)
end

end
end

Expand All @@ -460,37 +483,40 @@ function core.node_dig(pos, node, digger)
return
end

if core.is_protected(pos, digger:get_player_name()) and
not minetest.check_player_privs(digger, "protection_bypass") then
core.log("action", digger:get_player_name()
local diggername = user_name(digger)

if is_protected(pos, diggername, digger) then
core.log("action", diggername
.. " tried to dig " .. node.name
.. " at protected position "
.. core.pos_to_string(pos))
core.record_protection_violation(pos, digger:get_player_name())
core.record_protection_violation(pos, diggername)
return
end

core.log('action', digger:get_player_name() .. " digs "
core.log('action', diggername .. " digs "
.. node.name .. " at " .. core.pos_to_string(pos))

local wielded = digger:get_wielded_item()
local drops = core.get_node_drops(node.name, wielded:get_name())
local wielded = digger and digger:get_wielded_item()
local drops = core.get_node_drops(node.name, wielded and wielded:get_name())

local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities()
local dp = core.get_dig_params(def and def.groups, tp)
if wdef and wdef.after_use then
wielded = wdef.after_use(wielded, digger, node, dp) or wielded
else
-- Wear out tool
if not core.settings:get_bool("creative_mode") then
wielded:add_wear(dp.wear)
if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
core.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5})
if wielded then
local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities()
local dp = core.get_dig_params(def and def.groups, tp)
if wdef and wdef.after_use then
wielded = wdef.after_use(wielded, digger, node, dp) or wielded
else
-- Wear out tool
if not core.settings:get_bool("creative_mode") then
wielded:add_wear(dp.wear)
if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
core.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5})
end
end
end
digger:set_wielded_item(wielded)
end
digger:set_wielded_item(wielded)

-- Handle drops
core.handle_node_drops(pos, drops, digger)
Expand Down

0 comments on commit 788670d

Please sign in to comment.