bd35a4df55
Protection mechanics are fully disabled for all actions carried out by world mechanics itself, including machine digging/placing and entity/fluid displacement. This may create new opportunities for players to abuse and bypass protection mechanics. This is an acceptable loss; the integrity of game mechanics is more important, or else players are forced to remove protections anyway in order to get their builds to actually work.
171 lines
5.4 KiB
Lua
171 lines
5.4 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, minetest, nodecore, pairs, setmetatable,
|
|
string, type, unpack, vector
|
|
= ItemStack, ipairs, minetest, nodecore, pairs, setmetatable,
|
|
string, type, unpack, vector
|
|
local string_format, string_gsub
|
|
= string.format, string.gsub
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
local dntname = modname .. ":cookcheck"
|
|
|
|
local stacks_only = nodecore.group_expand("group:is_stack_only", true)
|
|
|
|
local nevermatch = {}
|
|
local function nomatches(k)
|
|
local stack = ItemStack(k)
|
|
for _, rc in ipairs(nodecore.registered_recipes) do
|
|
if rc.action == "cook" then
|
|
if nodecore.match({stack = stack}, rc.root.match) then return end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
minetest.after(0, function()
|
|
for k in pairs(minetest.registered_items) do
|
|
if nomatches(k) then nevermatch[k] = true end
|
|
end
|
|
end)
|
|
|
|
local function flameblock(sum) sum.flame = nil end
|
|
nodecore.register_dnt({
|
|
name = dntname,
|
|
time = 1,
|
|
arealoaded = 1,
|
|
nodenames = {"group:visinv"},
|
|
action = function(pos, node)
|
|
node.stack = nodecore.stack_get(pos)
|
|
local data = nodecore.craft_cooking_data()
|
|
if minetest.get_item_group(node.name, "is_stack_only") == 0 then
|
|
data.touchgroupmodify = flameblock
|
|
end
|
|
nodecore.craft_check(pos, node, data)
|
|
if not data.progressing then
|
|
return minetest.get_meta(pos):set_string(modname, "")
|
|
else
|
|
return nodecore.dnt_set(pos, dntname)
|
|
end
|
|
end
|
|
})
|
|
|
|
minetest.register_abm({
|
|
label = "item stack cook",
|
|
nodenames = {"group:visinv"},
|
|
interval = 2,
|
|
chance = 1,
|
|
action = function(pos)
|
|
if nevermatch[nodecore.stack_get(pos):get_name()] then return end
|
|
return nodecore.dnt_set(pos, dntname)
|
|
end
|
|
})
|
|
|
|
-- this function abstracts the actual placement, choosing between node or stack form
|
|
local item_place_node_or_stack = function(itemstack, placer, pointed_thing, param2)
|
|
local def = itemstack:get_definition()
|
|
if def.type == "node" and not def.place_as_item then
|
|
return minetest.item_place_node(itemstack, placer, pointed_thing, param2)
|
|
end
|
|
if not itemstack:is_empty() then
|
|
local above = minetest.get_pointed_thing_position(pointed_thing, true)
|
|
if above and nodecore.buildable_to(above) then
|
|
if def.type == "node" and def.node_placement_prediction ~= "" then
|
|
nodecore.stack_node_sounds_except[minetest.hash_node_position(above)]
|
|
= placer:get_player_name()
|
|
end
|
|
nodecore.place_stack(above, itemstack:take_item(), placer, pointed_thing)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
nodecore.item_place_node_or_stack = item_place_node_or_stack
|
|
|
|
-- placement on right click: place the item as a node or stack as appropriate,
|
|
-- unless the destination has an on_rightclick override and the player is not sneak-placing,
|
|
-- in which case the on_rightclick override is invoked instead
|
|
function minetest.item_place(itemstack, placer, pointed_thing, param2)
|
|
if not nodecore.interact(placer) then return end
|
|
if pointed_thing.type == "node" and placer and
|
|
not placer:get_player_control().sneak then
|
|
local n = minetest.get_node(pointed_thing.under)
|
|
local nn = n.name
|
|
local nd = minetest.registered_items[nn]
|
|
if nd and nd.on_rightclick then
|
|
return nd.on_rightclick(pointed_thing.under, n,
|
|
placer, itemstack, pointed_thing) or itemstack, false
|
|
end
|
|
end
|
|
return item_place_node_or_stack(itemstack, placer, pointed_thing, param2)
|
|
end
|
|
|
|
local olddrop = minetest.item_drop
|
|
function minetest.item_drop(item, player, ...)
|
|
if not (player and player:is_player()) then
|
|
return olddrop(item, player, ...)
|
|
end
|
|
local oldadd = minetest.add_item
|
|
local function additem(pos, stack, ...)
|
|
nodecore.log("action", string_format("%s throws item %q at %s",
|
|
player:get_player_name(), nodecore.stack_shortdesc(stack),
|
|
minetest.pos_to_string(pos, 0)))
|
|
return oldadd(pos, stack, ...)
|
|
end
|
|
function minetest.add_item(pos, stack, ...)
|
|
local start = player:get_pos()
|
|
local eyeheight = player:get_properties().eye_height or 1.625
|
|
start.y = start.y + eyeheight
|
|
local target = vector.add(start, vector.multiply(player:get_look_dir(), 4))
|
|
local pointed = minetest.raycast(start, target, false)()
|
|
if (not pointed) or pointed.type ~= "node" then
|
|
return additem(pos, stack, ...)
|
|
end
|
|
|
|
local dummyent = {}
|
|
setmetatable(dummyent, {
|
|
__index = function()
|
|
return function() return {} end
|
|
end
|
|
})
|
|
|
|
local function tryplace(p)
|
|
if stacks_only[minetest.get_node(p).name] then
|
|
stack = nodecore.stack_add(p, stack, player)
|
|
if stack:is_empty() then return dummyent end
|
|
end
|
|
if nodecore.buildable_to(p) then
|
|
nodecore.place_stack(p, stack, player)
|
|
return dummyent
|
|
end
|
|
end
|
|
|
|
return tryplace(pointed.under)
|
|
or tryplace(pointed.above)
|
|
or additem(pos, stack, ...)
|
|
end
|
|
local function helper(...)
|
|
minetest.add_item = oldadd
|
|
return ...
|
|
end
|
|
return helper(olddrop(item, player, ...))
|
|
end
|
|
|
|
local oldlog = minetest.log
|
|
function minetest.log(...)
|
|
local args = {...}
|
|
if args[1] == "action" then
|
|
args[2] = args[2] and type(args[2]) == "string"
|
|
and string_gsub(args[2], "(( digs " .. modname .. ":stack)( at (%(.-%))))",
|
|
function(full, pre, post, pos)
|
|
pos = pos and minetest.string_to_pos(pos)
|
|
local stack = pos and nodecore.stack_get(pos)
|
|
if stack then
|
|
return string_format("%s %q%s", pre,
|
|
nodecore.stack_shortdesc(stack), post)
|
|
end
|
|
return full
|
|
end
|
|
) or args[2]
|
|
end
|
|
return oldlog(unpack(args))
|
|
end
|