Fix multiple issues

- Clean up stale visinv ents from summoning/banishing.
- When banishing via recipe, ensure on-disk data is purged to
  signal summoning recipe to use factory-reset schematic, to avoid
  exploits where a user summons a dais, empties it, and then
  banishes and re-summons it to duplicate items.
- Give player back initial eggcorn investment from banishing.
master
Aaron Suen 2021-03-01 08:47:30 -05:00
parent d9644c80e3
commit 972630bef8
2 changed files with 64 additions and 8 deletions

70
api.lua
View File

@ -99,8 +99,15 @@ function exmachina.areapuffs(pos, qty, time)
})
end
function exmachina.fallcheck(pos)
function exmachina.finalcheck(pos)
local minpos, maxpos = exmachina.getbounds(pos)
for z = minpos.z, maxpos.z do
for y = minpos.y, maxpos.y do
for x = minpos.x, maxpos.x do
nodecore.visinv_update_ents({x = x, y = y, z = z})
end
end
end
for _, p in pairs(minetest.find_nodes_in_area(minpos,
maxpos, "group:falling_node")) do
nodecore.fallcheck(p)
@ -142,20 +149,38 @@ function exmachina.summon_complete(pos, pname)
local minpos, maxpos = exmachina.getbounds(pos)
local path = pathbase .. ".mts"
local anymts
local f = io_open(path, "rb")
if f then
anymts = f:read(1)
f:close()
end
if anymts then
minetest.place_schematic(minpos, path)
else
minetest.place_schematic(minpos, exmachina.schematic_final)
end
for _, mp in pairs(minetest.find_nodes_with_meta(minpos, maxpos)) do
minetest.get_meta(mp):from_table()
end
for z = minpos.z, maxpos.z do
for y = minpos.y, maxpos.y do
for x = minpos.x, maxpos.x do
minetest.get_meta({
x = pos.x + x,
y = pos.y + y,
z = pos.z + z
}):from_table()
end
end
end
path = pathbase .. ".meta"
f = io_open(path, "rb")
if f then
local s = f:read("*all")
f:close()
s = minetest.deserialize(s)
s = s and s ~= "" and minetest.deserialize(s) or {}
for k, v in pairs(s) do
minetest.get_meta(vector.add(pos, k)):from_table(v)
end
@ -166,17 +191,48 @@ function exmachina.summon_complete(pos, pname)
for _, p in pairs(found) do nodecore.visinv_update_ents(p) end
exmachina.location_set(pname, pos)
exmachina.fallcheck(pos)
exmachina.finalcheck(pos)
return exmachina.areapuffs(pos, 250, 0.01)
end
function exmachina.banish(pos, pname)
function exmachina.commit(pos, pname)
local pathbase = exmachina.pathbase(pname)
local minpos, maxpos = exmachina.getbounds(pos)
minetest.create_schematic(minpos, maxpos, nil, pathbase .. ".mts")
local allmeta = {}
for _, p in pairs(minetest.find_nodes_with_meta(minpos, maxpos)) do
local meta = minetest.get_meta(p):to_table()
for _, v1 in pairs(meta.inventory or {}) do
for k2, v2 in pairs(v1) do
if type(v2) == "userdata" then
v1[k2] = v2:to_string()
end
end
end
allmeta[vector.subtract(p, pos)] = meta
end
minetest.safe_file_write(
pathbase .. ".meta",
minetest.serialize(allmeta)
)
end
function exmachina.banish(pos, pname, nuke)
local minpos, maxpos = exmachina.getbounds(pos)
local found = minetest.find_nodes_in_area(minpos, maxpos, "group:visinv")
minetest.place_schematic(minpos, exmachina.schematic_banish)
for _, p in pairs(found) do nodecore.visinv_update_ents(p) end
for _, mp in pairs(minetest.find_nodes_with_meta(minpos, maxpos)) do
minetest.get_meta(mp):from_table()
end
if nuke then
local pathbase = exmachina.pathbase(pname)
minetest.safe_file_write(pathbase .. ".mts", "")
minetest.safe_file_write(pathbase .. ".meta", "")
end
exmachina.location_set(pname)
exmachina.fallcheck(pos)
exmachina.finalcheck(pos)
nodecore.item_eject(pos, "nc_tree:eggcorn " .. exmachina.extent * 4 + 5)
return exmachina.areapuffs(pos, 250, 0.01)
end

View File

@ -54,6 +54,6 @@ nodecore.register_craft({
nodes = exmachina.craftnodes_banish,
after = function(pos, data)
local pname = data.pname or data.crafter:get_player_name()
exmachina.banish(pos, pname)
exmachina.banish(pos, pname, true)
end
})