89236813e4
This effectively destroys the dais, converting it back into its source materials in-place, not destroying any contents/customizations, returning craft inputs, and clearing the dais status for that player. This can be used to return materials to the world after a player has been destroyed, similar to how YCTIWY automatically drops inventory.
289 lines
8.5 KiB
Lua
289 lines
8.5 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local io, ipairs, math, minetest, nodecore, pairs, string, tonumber,
|
|
type, vector
|
|
= io, ipairs, math, minetest, nodecore, pairs, string, tonumber,
|
|
type, vector
|
|
local io_open, math_floor, string_format
|
|
= io.open, math.floor, string.format
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
local modstore = minetest.get_mod_storage()
|
|
|
|
local function getsetting(n, v)
|
|
return tonumber(minetest.settings:get(modname .. "_" .. n)) or v
|
|
end
|
|
local exmachina = {
|
|
path = minetest.get_worldpath() .. "/" .. modname,
|
|
extent = math_floor(getsetting("extent", 3)),
|
|
height = math_floor(getsetting("height", 3)),
|
|
}
|
|
nodecore[modname] = exmachina
|
|
|
|
exmachina.txr_puff = modname .. "_pattern.png^[mask:" .. modname .. "_mask.png"
|
|
exmachina.txr_frame = "nc_terrain_stone.png^(" .. modname .. "_pattern.png^[opacity:32)"
|
|
exmachina.txr_core = exmachina.txr_frame .. "^(" .. exmachina.txr_puff .. "^[opacity:128])"
|
|
exmachina.txr_sparkle = modname .. "_sparkle.png"
|
|
|
|
minetest.mkdir(exmachina.path)
|
|
|
|
local function getplayer(pspec)
|
|
if type(pspec) == "userdata" then
|
|
return pspec, pspec:get_player_name()
|
|
end
|
|
return minetest.get_player_by_name(pspec), pspec
|
|
end
|
|
|
|
function exmachina.location_get(pspec)
|
|
local player, pname = getplayer(pspec)
|
|
local pos = modstore:get_string(pname)
|
|
if pos == "X" then return end
|
|
if pos and pos ~= "" then return minetest.string_to_pos(pos) end
|
|
if not player then return end
|
|
pos = player:get_meta():get_string(modname)
|
|
if pos and pos ~= "" then
|
|
modstore:set_string(pname, pos)
|
|
return minetest.string_to_pos(pos)
|
|
end
|
|
end
|
|
|
|
function exmachina.location_set(pspec, pos)
|
|
local _, pname = getplayer(pspec)
|
|
pos = pos and minetest.pos_to_string(pos) or "X"
|
|
modstore:set_string(pname, pos)
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
-- Automatically migrate legacy data.
|
|
return exmachina.location_get(player)
|
|
end)
|
|
|
|
local dxz = exmachina.extent + 1
|
|
local dy = exmachina.height + 1
|
|
function exmachina.getbounds(pos, margin)
|
|
margin = margin or 0
|
|
return {
|
|
x = pos.x - dxz - margin,
|
|
y = pos.y - margin,
|
|
z = pos.z - dxz - margin
|
|
}, {
|
|
x = pos.x + dxz + margin,
|
|
y = pos.y + dy + margin,
|
|
z = pos.z + dxz + margin
|
|
}
|
|
end
|
|
|
|
function exmachina.owner_search(pos)
|
|
for k, v in pairs(modstore:to_table().fields) do
|
|
v = minetest.string_to_pos(v)
|
|
if v then
|
|
local min, max = exmachina.getbounds(v, 0.5)
|
|
if pos.x >= min.x and pos.x <= max.x
|
|
and pos.y >= min.y and pos.y <= max.y
|
|
and pos.z >= min.z and pos.z <= max.z then return k end
|
|
end
|
|
end
|
|
end
|
|
|
|
function exmachina.areapuffs(pos, qty, time)
|
|
local minpos, maxpos = exmachina.getbounds(pos, 0.5)
|
|
return minetest.add_particlespawner({
|
|
amount = qty,
|
|
time = time,
|
|
minpos = minpos,
|
|
maxpos = maxpos,
|
|
minvel = {x = -0.2, y = -0.2, z = -0.2},
|
|
maxvel = {x = 0.2, y = 0.2, z = 0.2},
|
|
minexptime = 1,
|
|
maxexptime = 2,
|
|
texture = exmachina.txr_puff,
|
|
glow = 2
|
|
})
|
|
end
|
|
|
|
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)
|
|
end
|
|
end
|
|
|
|
function exmachina.summon_start(pos, pname)
|
|
local minpos, maxpos = exmachina.getbounds(pos)
|
|
minetest.place_schematic(minpos, exmachina.schematic_trans)
|
|
for z = minpos.z, maxpos.z do
|
|
for y = minpos.y, maxpos.y do
|
|
for x = minpos.x, maxpos.x do
|
|
local p = {x = x, y = y, z = z}
|
|
minetest.get_meta(p):get_inventory():set_size("solo", 0)
|
|
nodecore.visinv_update_ents(p)
|
|
end
|
|
end
|
|
end
|
|
minetest.get_meta(pos):set_string(modname, pname)
|
|
exmachina.location_set(pname, pos)
|
|
return exmachina.areapuffs(pos, 250, 0.01)
|
|
end
|
|
|
|
function exmachina.summon_occupied(pos)
|
|
local minpos, maxpos = exmachina.getbounds(pos, 1)
|
|
for _, player in pairs(minetest.get_connected_players()) do
|
|
if nodecore.interact(player) then
|
|
local pp = player:get_pos()
|
|
if (pp.x > minpos.x)
|
|
and (pp.x < maxpos.x)
|
|
and (pp.z > minpos.z)
|
|
and (pp.z < maxpos.z)
|
|
and (pp.y > minpos.y - 1)
|
|
and (pp.y < maxpos.y) then
|
|
return player
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function exmachina.pathbase(pname)
|
|
return exmachina.path .. "/" .. pname:gsub("%W", "")
|
|
.. "_" .. minetest.sha1(pname)
|
|
end
|
|
|
|
function exmachina.summon_complete(pos, pname)
|
|
local pathbase = exmachina.pathbase(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 = 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
|
|
end
|
|
minetest.get_meta(pos):set_string(modname, pname)
|
|
|
|
local found = minetest.find_nodes_in_area(minpos, maxpos, "group:visinv")
|
|
for _, p in pairs(found) do nodecore.visinv_update_ents(p) end
|
|
|
|
exmachina.location_set(pname, pos)
|
|
exmachina.finalcheck(pos)
|
|
return exmachina.areapuffs(pos, 250, 0.01)
|
|
end
|
|
|
|
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)
|
|
minetest.place_schematic(minpos, exmachina.schematic_banish)
|
|
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.finalcheck(pos)
|
|
nodecore.item_eject({x = pos.x, y = pos.y + 1, z = pos.z}, "nc_tree:eggcorn 5")
|
|
return exmachina.areapuffs(pos, 250, 0.01)
|
|
end
|
|
|
|
function exmachina.degrade(pos, pname)
|
|
local minpos = exmachina.getbounds(pos)
|
|
minetest.place_schematic(minpos, exmachina.schematic_degrade)
|
|
local pathbase = exmachina.pathbase(pname)
|
|
minetest.safe_file_write(pathbase .. ".mts", "")
|
|
minetest.safe_file_write(pathbase .. ".meta", "")
|
|
exmachina.location_set(pname)
|
|
exmachina.finalcheck(pos)
|
|
nodecore.item_eject({x = pos.x, y = pos.y + 1, z = pos.z}, "nc_tree:eggcorn 5")
|
|
return exmachina.areapuffs(pos, 250, 0.01)
|
|
end
|
|
|
|
function exmachina.arealoaded(pos)
|
|
return minetest.get_node_or_nil(vector.add(pos, {x = -dxz, y = 0, z = -dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = dxz, y = 0, z = -dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = -dxz, y = 0, z = dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = dxz, y = 0, z = dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = -dxz, y = dy, z = -dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = dxz, y = dy, z = -dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = -dxz, y = dy, z = dxz}))
|
|
and minetest.get_node_or_nil(vector.add(pos, {x = dxz, y = dy, z = dxz}))
|
|
end
|
|
|
|
function exmachina.validate(pos)
|
|
for _, v in ipairs(exmachina.craftnodes_operating) do
|
|
local np = vector.add(v, pos)
|
|
if not nodecore.match(np, v.match) then
|
|
nodecore.log("warning", string_format("%s: validation failed for dais "
|
|
.. " at %s: found %s (expected %s) at %s",
|
|
modname,
|
|
minetest.pos_to_string(pos),
|
|
minetest.get_node(np).name,
|
|
minetest.serialize(v.match):gsub("^return ", ""),
|
|
minetest.pos_to_string(np)))
|
|
return
|
|
end
|
|
end
|
|
return true
|
|
end
|