microexpansion/modules/item_transfer/api.lua
2023-10-20 18:44:45 +02:00

264 lines
7.2 KiB
Lua

-- item_transfer/api.lua
local me = microexpansion
local item_transfer = {}
me.item_transfer = item_transfer
function item_transfer.get_output_inventory(pos,metadata,inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local lists = inv:get_lists()
if not lists then
return
elseif lists["dst"] then
return "dst", inv
elseif lists["main"] then
return "main", inv
end
end
function item_transfer.get_input_inventory(pos,metadata,inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local lists = inv:get_lists()
if not lists then
return
elseif lists["src"] then
return "src", inv
elseif lists["main"] then
return "main", inv
end
end
function microexpansion.vector_cross(a, b)
return {
x = a.y * b.z - a.z * b.y,
y = a.z * b.x - a.x * b.z,
z = a.x * b.y - a.y * b.x
}
end
function microexpansion.facedir_to_top_dir(facedir)
return ({[0] = {x = 0, y = 1, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1},
{x = 1, y = 0, z = 0},
{x = -1, y = 0, z = 0},
{x = 0, y = -1, z = 0}})
[math.floor(facedir / 4)]
end
function microexpansion.facedir_to_right_dir(facedir)
return microexpansion.vector_cross(
microexpansion.facedir_to_top_dir(facedir),
minetest.facedir_to_dir(facedir)
)
end
function microexpansion.count_upgrades(inv)
local upgrades = {}
for i = 0, inv:get_size("upgrades") do
local stack = inv:get_stack("upgrades", i)
local item = stack:get_name()
if item == "microexpansion:upgrade_filter" then
upgrades.filter = (upgrades.filter or 0) + stack:get_count()
elseif item == "microexpansion:upgrade_bulk" then
upgrades.bulk = (upgrades.bulk or 0) + stack:get_count()
end
end
return upgrades
end
function item_transfer.update_timer_based(pos,_,ev)
if ev then
if ev.type ~= "disconnect"
and ev.type ~= "connect"
and ev.type ~= "construct" then
return
end
end
local meta = minetest.get_meta(pos)
if me.get_connected_network(pos) then
meta:set_string("infotext", "Network connected")
if not minetest.get_node_timer(pos):is_started() then
minetest.get_node_timer(pos):start(2)
end
else
meta:set_string("infotext", "No Network")
minetest.get_node_timer(pos):stop()
end
end
function item_transfer.setup_io_device(title, pos, metadata, inventory)
local meta = metadata or minetest.get_meta(pos)
local inv = inventory or meta:get_inventory()
local formspec = [[
formspec_version[2]
size[11,11]
]] ..
microexpansion.gui_bg ..
microexpansion.gui_slots
if title then
formspec = formspec .. "label[9,0.5;"..title.."]"
end
local upgrades = me.count_upgrades(inv)
if upgrades.filter then
inv:set_size("filter", math.pow(2, upgrades.filter - 1))
formspec = formspec .. [[
label[0.5,0.75;filter]
list[context;filter;0.5,1;5,3]
]]
else
inv:set_size("filter",0)
end
--TODO: target inventory dropdown
inv:set_size("upgrades", 4)
meta:set_string("formspec",
formspec ..
[[
label[8.5,2.5;upgrades]
list[context;upgrades;8,2.75;2,2]
list[current_player;main;0.5,5.5;8,1;]
list[current_player;main;0.5,7;8,3;8]
listring[current_name;upgrades]
listring[current_player;main]
]])
end
local access_level = microexpansion.constants.security.access_levels
local io_device_base = {
is_ground_content = false,
groups = { crumbly = 1, me_connect = 1 },
paramtype = "light",
paramtype2 = "facedir",
me_update = item_transfer.update_timer_based,
after_place_node = function(pos, placer)
if not placer then
return false
end
local name = placer:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
-- prevent placing exporters on a network that a player doesn't have access to
--Do we need to send a disconnect or stop any node timers?
minetest.remove_node(pos)
return true
else
return false
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
--protection probably handles this itself
--minetest.remove_node(pos)
return true
end
end,
can_dig = function(pos, player)
if not player then
return false
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return false
end
elseif minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return false
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("upgrades")
end,
allow_metadata_inventory_put = function(pos, listname, _, stack, player)
local max_allowed = stack:get_count()
if listname == "upgrades" then
local item = stack:get_name()
if item == "microexpansion:upgrade_filter" then
local filter_upgrades = me.count_upgrades(minetest.get_meta(pos):get_inventory()).filter
if filter_upgrades then
max_allowed = math.max(0, math.min(stack:get_count(), 5 - filter_upgrades))
else
max_allowed = math.min(stack:get_count(), 5)
end
elseif item == "microexpansion:upgrade_bulk" then
local bulk_upgrades = me.count_upgrades(minetest.get_meta(pos):get_inventory()).bulk
if bulk_upgrades then
max_allowed = math.max(0, math.min(stack:get_count(), 10 - bulk_upgrades))
else
max_allowed = math.min(stack:get_count(), 10)
end
else
return 0
end
end
if not player then
return max_allowed
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return 0
end
elseif minetest.is_protected(pos, name) then
--minetest.record_protection_violation(pos, name)
return 0
end
if listname == "filter" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local filter = stack:peek_item()
if inv:room_for_item(listname,filter) and not inv:contains_item(listname, filter) then
inv:add_item(listname, filter)
end
return 0
else
return max_allowed
end
end,
allow_metadata_inventory_take = function(pos, listname, _, stack, player)
if not player then
return 0
end
local name = player:get_player_name()
local net,cp = me.get_connected_network(pos)
if net then
if net:get_access_level(name) < access_level.modify then
return 0
end
elseif minetest.is_protected(pos, name) then
--minetest.record_protection_violation(pos, name)
return 0
end
if listname == "filter" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:remove_item(listname, stack)
return 0
else
return stack:get_count()
end
end,
allow_metadata_inventory_move = function(pos, from_list, _, to_list, _, count, player)
--perhaps allow filtering for upgrades and removing filters in this way
if from_list ~= to_list then
return 0
end
return count
end,
}
function item_transfer.register_io_device(itemstring, def)
for k,v in pairs(io_device_base) do
if def[k] == nil then
def[k] = v
end
end
if not def.groups.me_connect then
def.groups.me_connect = 1
end
microexpansion.register_node(itemstring, def)
end