Add pack controller

This commit is contained in:
Joachim Stolberg 2022-02-08 21:18:41 +01:00
parent b917f63dc0
commit 8e2b7bbd07
2 changed files with 108 additions and 78 deletions

View File

@ -69,7 +69,7 @@ end
-- on_pack/on_unpack fallback functions
local function on_pack_fallback_(pos, node)
print("on_pack_fallback_",P2S(pos), node.name)
--print("on_pack_fallback_",P2S(pos), node.name)
local smeta = techage.pack_meta(pos)
local snvm = techage.pack_nvm(pos)
minetest.remove_node(pos)
@ -77,7 +77,7 @@ local function on_pack_fallback_(pos, node)
end
local function on_unpack_fallback(pos, name, param2, data)
print("on_unpack_fallback",P2S(pos), name)
--print("on_unpack_fallback",P2S(pos), name)
minetest.add_node(pos, {name = name, param2 = param2})
techage.unpack_meta(pos, data.smeta)
if data.snvm then
@ -85,57 +85,94 @@ local function on_unpack_fallback(pos, name, param2, data)
end
end
-- cpos is the center pos
-- npos the the node pos
-- turn is one of "l", "r", "2l", "2r"
local function get_new_node_pos(cpos, npos, turn, item)
item.param2 = techage.rotate_param2(item, turn)
return techage.rotate_around_axis(npos, cpos, turn)
end
-------------------------------------------------------------------------------
-- pack/unpack API functions
function techage.pack_nodes(pos, pos_list)
print("pack_nodes", P2S(pos), #pos_list)
local tbl = {}
for idx, rpos in ipairs(pos_list or {}) do
local pos2 = vector.add(pos, rpos)
-------------------------------------------------------------------------------
-- pos_list is a list of node positions
function techage.pack_nodes(pos_list)
local pack_tbl = {}
for _, pos2 in ipairs(pos_list or {}) do
local node = minetest.get_node(pos2)
--print("node", node.name, P2S(pos))
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.on_pack then
tbl[rpos] = {name = node.name, param2 = node.param2, data = ndef.on_pack(pos2, node)}
pack_tbl[pos2] = {name = node.name, param2 = node.param2, data = ndef.on_pack(pos2, node)}
else
tbl[rpos] = {name = node.name, param2 = node.param2, data = on_pack_fallback_(pos2, node)}
pack_tbl[pos2] = {name = node.name, param2 = node.param2, data = on_pack_fallback_(pos2, node)}
end
end
return tbl
return pack_tbl
end
function techage.unpack_nodes(pos, tbl, turn)
print("unpack_nodes", P2S(pos), turn)
function techage.unpack_nodes(pack_tbl)
-- Check positions
for rpos, item in pairs(tbl or {}) do
local pos2 = vector.add(pos, rpos)
pos2 = techage.rotate_around_axis(pos2, pos, turn)
for pos2, _ in pairs(pack_tbl or {}) do
local node = minetest.get_node(pos2)
if not techage.is_air_like(node.name) then
return false
end
end
-- Place nodes
local out = {}
for rpos, item in pairs(tbl or {}) do
local pos2 = vector.add(pos, rpos)
item.param2 = techage.rotate_param2(item, turn)
pos2 = techage.rotate_around_axis(pos2, pos, turn)
for pos2, item in pairs(pack_tbl or {}) do
local ndef = minetest.registered_nodes[item.name]
if ndef and ndef.on_unpack then
ndef.on_unpack(pos2, item.name, item.param2, item.data)
else
on_unpack_fallback(pos2, item.name, item.param2, item.data)
end
-- Because of the rotated arrangement, generate a new rel-pos table
table.insert(out, vector.subtract(pos2, pos))
end
return true
end
-------------------------------------------------------------------------------
-- move/turn API functions
-------------------------------------------------------------------------------
function techage.determine_turn_rotation(old_param2, new_param2)
local offs = new_param2 - old_param2
if offs == -1 or offs == 3 then return "l"
elseif offs == 1 or offs == -3 then return "r"
elseif offs == 2 or offs == -2 then return "2r"
else return "" end
end
-- move is the distance between old and new pos as vector
function techage.adjust_pos_list_move(pos_list, move)
local out = {}
for idx, pos in ipairs(pos_list or {}) do
local pos2 = vector.add(pos, move)
out[idx] = pos2
end
return out
end
-- Adjust the data for a turn of all nodes around cpos
-- turn is one of "l", "r", "2l", "2r"
function techage.adjust_pos_list_turn(cpos, pos_list, turn)
local out = {}
for idx, npos in ipairs(pos_list or {}) do
local pos2 = techage.rotate_around_axis(npos, cpos, turn)
out[idx] = pos2
end
return out
end
-- move is the distance between old and new pos as vector
function techage.adjust_pack_tbl_move(pack_tbl, move)
local out = {}
for pos, item in pairs(pack_tbl or {}) do
local pos2 = vector.add(pos, move)
out[pos2] = item
end
return out
end
-- Adjust the data for a turn of all nodes around cpos
-- turn is one of "l", "r", "2l", "2r"
function techage.adjust_pack_tbl_turn(cpos, pack_tbl, turn)
local out = {}
for npos, item in pairs(pack_tbl or {}) do
item.param2 = techage.rotate_param2(item, turn)
local pos2 = techage.rotate_around_axis(npos, cpos, turn)
out[pos2] = item
end
return out
end

View File

@ -43,15 +43,6 @@ local function formspec(nvm, meta)
"label[0.3,3.9;" .. status .. "]"
end
local function get_rposlist(pos, pos_list)
local lst = {}
for _,item_pos in ipairs(pos_list or {}) do
local rpos = vector.subtract(item_pos, pos)
table.insert(lst, rpos)
end
return lst
end
local function set_storage_pos(pos, oldnode, oldmetadata, drops)
if oldmetadata.data_stored == "1" then
local meta = drops[1]:get_meta()
@ -63,48 +54,55 @@ local function set_storage_pos(pos, oldnode, oldmetadata, drops)
end
end
local function get_storage_pos(pos, nvm, itemstack)
local function get_storage_pos(pos, itemstack)
local imeta = itemstack:get_meta()
if imeta then
local meta = M(pos)
meta:set_string("node_name", imeta:get_string("node_name"))
meta:set_string("status", imeta:get_string("status"))
meta:set_int("data_stored", imeta:get_int("data_stored"))
nvm.storage_pos = S2P(imeta:get_string("storage_pos"))
return nvm.storage_pos ~= nil
local pos2 = S2P(imeta:get_string("storage_pos"))
if pos2 then
local node = techage.get_node_lvm(pos2)
if node.name == "techage:ta5_packcontainer_storage" then
return pos2, node.param2
end
end
end
end
local function copy_data_and_remove_node(mypos, rmtpos)
local nvm1 = techage.get_nvm(mypos)
local nvm2 = techage.get_nvm(rmtpos)
nvm1.lrpos = nvm2.lrpos
nvm1.pack_tbl = nvm2.pack_tbl
minetest.remove_node(rmtpos)
techage.del_mem(rmtpos)
local function takeover_data(old_pos, new_pos)
local nvm1 = techage.get_nvm(old_pos)
local nvm2 = techage.get_nvm(new_pos)
nvm2.pos_list = nvm1.pos_list
nvm2.pack_tbl = nvm1.pack_tbl
end
local function determine_rotation(old_param2, new_param2)
local offs = new_param2 - old_param2
print("determine_rotation", offs)
if offs == 0 then return ""
elseif offs == -1 then return "l"
elseif offs == 1 then return "r"
else return "2r" end
local function remove_storage_node(old_pos)
minetest.remove_node(old_pos)
techage.del_mem(old_pos)
end
local function adjust_database(pos, nvm, move, turn)
nvm.pos_list = techage.adjust_pos_list_move(nvm.pos_list, move)
nvm.pos_list = techage.adjust_pos_list_turn(pos, nvm.pos_list, turn)
nvm.pack_tbl = techage.adjust_pack_tbl_move(nvm.pack_tbl, move)
nvm.pack_tbl = techage.adjust_pack_tbl_turn(pos, nvm.pack_tbl, turn)
end
local function after_place_node(pos, placer, itemstack)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local meta = M(pos)
meta:set_string("infotext", DESCRIPTION)
meta:set_string("owner", placer:get_player_name())
if get_storage_pos(pos, nvm, itemstack) then
local node = techage.get_node_lvm(nvm.storage_pos)
if node.name == "techage:ta5_packcontainer_storage" then
nvm.turn = determine_rotation(node.param2, minetest.get_node(pos).param2)
copy_data_and_remove_node(pos, nvm.storage_pos)
nvm.storage_pos = nil
end
local old_pos, old_param2 = get_storage_pos(pos, itemstack)
if old_pos then
local new_param2 = minetest.get_node(pos).param2
local turn = techage.determine_turn_rotation(old_param2, new_param2)
local move = vector.subtract(pos, old_pos)
takeover_data(old_pos, pos)
adjust_database(pos, nvm, move, turn)
remove_storage_node(old_pos)
end
meta:set_string("formspec", formspec(nvm, meta))
end
@ -119,7 +117,7 @@ local function on_receive_fields(pos, formname, fields, player)
local data_stored = meta:get_int("data_stored") == 1
if fields.record and not data_stored then
nvm.lrpos = nil
nvm.pos_list = nil
meta:set_string("status", S("Recording..."))
local name = player:get_player_name()
minetest.chat_send_player(name, S("Click on all blocks that shall be turned"))
@ -130,31 +128,26 @@ local function on_receive_fields(pos, formname, fields, player)
meta:set_string("formspec", formspec(nvm, meta))
elseif fields.done and not data_stored then
local name = player:get_player_name()
local pos_list = mark.get_poslist(name)
local text = #pos_list.." "..S("block positions are stored.")
nvm.pos_list = mark.get_poslist(name) or {}
local text = #(nvm.pos_list).." "..S("block positions are stored.")
meta:set_string("status", text)
meta:set_string("node_name", fields.node_name)
nvm.lrpos = get_rposlist(pos, pos_list)
mark.unmark_all(name)
mark.stop(name)
meta:set_string("formspec", formspec(nvm, meta))
elseif fields.pack and nvm.lrpos and #nvm.lrpos > 0 and not data_stored then
nvm.pack_tbl = techage.pack_nodes(pos, nvm.lrpos or {})
elseif fields.pack and nvm.pos_list and #nvm.pos_list > 0 and not data_stored then
nvm.pack_tbl = techage.pack_nodes(nvm.pos_list)
meta:set_string("status", S("Blocks stored"))
meta:set_string("formspec", formspec(nvm, meta))
meta:set_int("data_stored", 1)
elseif fields.unpack and data_stored then
local tbl = techage.unpack_nodes(pos, nvm.pack_tbl, nvm.turn or "")
if tbl then
nvm.lrpos = tbl
elseif fields.unpack and data_stored and nvm.pack_tbl then
if techage.unpack_nodes(nvm.pack_tbl) then
meta:set_string("status", S("Blocks placed"))
meta:set_string("formspec", formspec(nvm, meta))
meta:set_int("data_stored", 0)
nvm.turn = ""
else
meta:set_string("status", S("Position(s) occupied"))
meta:set_string("formspec", formspec(nvm, meta))
end
meta:set_string("formspec", formspec(nvm, meta))
end
end