added importer and exporter for item transfer along with upgrades

This commit is contained in:
theFox6 2023-10-20 18:31:56 +02:00
parent 0dbe8146e9
commit 0403820d39
No known key found for this signature in database
GPG Key ID: 810803FF29A86CCC
24 changed files with 611 additions and 11 deletions

40
api.lua

@ -133,3 +133,43 @@ function microexpansion.update_node(pos,event)
def.me_update(pos,node,ev)
end
end
-- [function] Move items from inv to inv
function microexpansion.move_inv(inv1, inv2, max, filter)
if max <= 0 then return end
local finv, tinv = inv1.inv, inv2.inv
local fname, tname = inv1.name, inv2.name
local huge = inv2.huge
local inserted = 0
for _,v in ipairs(finv:get_list(fname) or {}) do
local left = max-inserted
if left <= 0 then
break;
end
if not v:is_empty() then
if v:get_count() > left then
v = v:peek_item(left)
end
if tinv and tinv:room_for_item(tname, v) and (not filter or not filter(v)) then
if huge then
microexpansion.insert_item(v, tinv, tname)
finv:remove_item(fname, v)
else
--TODO: continue inserting from the same stack if it is bigger than max
if v:get_count() > v:get_stack_max() then
v = v:peek_item(v:get_stack_max())
end
local leftover = tinv:add_item(tname, v)
finv:remove_item(fname, v)
if leftover and not(leftover:is_empty()) then
microexpansion.log("leftover items when transferring inventory","warning")
finv:add_item(fname, leftover)
end
end
inserted = inserted + v:get_count()
end
end
end
return inserted
end

@ -3,3 +3,4 @@ network = true
power = false
storage = true
ores = true
item_transfer = true

@ -0,0 +1,256 @@
-- 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
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

@ -0,0 +1,84 @@
-- microexpansion/machines.lua
local me = microexpansion
local item_transfer = me.item_transfer
local access_level = microexpansion.constants.security.access_levels
local function exporter_timer(pos, elapsed)
local net, cp = me.get_connected_network(pos)
if not net then
return false
end
local node = minetest.get_node(pos)
local target = vector.add(pos, microexpansion.facedir_to_right_dir(node.param2))
--TODO: allow setting list with control upgrade
--TODO: perhaps allow setting limits with control upgrade
local list, inv = item_transfer.get_input_inventory(target)
if list then
--TODO: move more with upgrades
local own_inv = minetest.get_meta(pos):get_inventory()
local upgrades = me.count_upgrades(own_inv)
local export_filter = upgrades.filter and function(stack)
return not own_inv:contains_item("filter",stack:peek_item())
end
local max_count = math.pow(2, upgrades.bulk or 0)
microexpansion.move_inv({inv=net:get_inventory(),name="main",huge=true}, {inv=inv,name=list}, max_count, export_filter)
end
return true
end
-- [MicroExpansion Exporter] Register node
item_transfer.register_io_device("exporter", {
description = "ME exporter",
usedfor = "Exports items from ME Networks into machines",
tiles = {
"exporter",
"exporter",
"interface",
"cable",
"microexpansion_exporter.png^[transform4",
"exporter",
},
drawtype = "nodebox",
node_box = {
--perhaps convert to connectable
type = "fixed",
fixed = {
{-0.5, -0.25, -0.25, 0.25, 0.25, 0.25},
{0.25, -0.375, -0.375, 0.5, 0.375, 0.375},
},
},
connect_sides = { "left" },
recipe = {
{ 1, {
{"", "microexpansion:logic_chip", "default:steel_ingot" },
{"", "microexpansion:cable", "group:shovel" },
{"", "", "default:steel_ingot" },
},
}
},
groups = { crumbly = 1 },
on_timer = exporter_timer,
on_construct = function(pos)
item_transfer.setup_io_device("ME Exporter",pos)
me.send_event(pos,"connect")
--perhaps write a propper update self function
item_transfer.update_timer_based(pos,nil,{type="construct"})
end,
after_destruct = function(pos)
minetest.get_node_timer(pos):stop()
me.send_event(pos,"disconnect")
end,
on_metadata_inventory_put = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Exporter",pos)
end
end,
on_metadata_inventory_take = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Exporter",pos)
end
end
})

@ -0,0 +1,92 @@
-- microexpansion/machines.lua
local me = microexpansion
local item_transfer = me.item_transfer
local access_level = microexpansion.constants.security.access_levels
function importer_timer(pos, elapsed)
local net, cp = me.get_connected_network(pos)
if not net then
return false
end
local node = minetest.get_node(pos)
local target = vector.add(pos, microexpansion.facedir_to_right_dir(node.param2))
--TODO: allow setting list with upgrade
local list, inv = item_transfer.get_output_inventory(target)
if list then
local own_inv = minetest.get_meta(pos):get_inventory()
local upgrades = me.count_upgrades(own_inv)
local count = math.min(net:get_inventory_space(),math.pow(2, upgrades.bulk or 0))
if count <= 0 then
return true
end
local import_filter = function(stack)
local stack_name = stack:get_name()
if minetest.get_item_group(stack_name, "microexpansion_cell") > 0 then
return true
end
if upgrades.filter then
return not own_inv:contains_item("filter",stack:peek_item())
end
return false
end
microexpansion.move_inv({inv=inv,name=list}, {inv=net:get_inventory(),name="main",huge=true}, count, import_filter)
net:set_storage_space(true)
end
return true
end
-- [MicroExpansion Importer] Register node
item_transfer.register_io_device("importer", {
description = "ME Importer",
usedfor = "Imports items from machines into ME Networks",
tiles = {
"importer",
"importer",
"interface",
"cable",
"microexpansion_importer.png^[transform4",
"importer",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.25, -0.25, 0.25, 0.25, 0.25},
{0.25, -0.375, -0.375, 0.5, 0.375, 0.375},
},
},
connect_sides = { "left" },
recipe = {
{ 1, {
{"", "microexpansion:logic_chip", "default:steel_ingot" },
{"", "microexpansion:cable", "group:hoe" },
{"", "", "default:steel_ingot" },
},
}
},
is_ground_content = false,
groups = { crumbly = 1 },
on_timer = importer_timer,
on_construct = function(pos)
item_transfer.setup_io_device("ME Importer",pos)
me.send_event(pos,"connect")
item_transfer.update_timer_based(pos)
end,
after_destruct = function(pos)
minetest.get_node_timer(pos):stop()
me.send_event(pos,"disconnect")
end,
on_metadata_inventory_put = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Importer",pos)
end
end,
on_metadata_inventory_take = function(pos, listname, _, stack, player)
if listname == "upgrades" then
item_transfer.setup_io_device("ME Importer",pos)
end
end
})

@ -0,0 +1,16 @@
-- storage/init.lua
local module_path = microexpansion.get_module_path("item_transfer")
microexpansion.require_module("network")
-- Load API
dofile(module_path.."/api.lua")
-- Load upgrade cards
dofile(module_path.."/upgrades.lua")
-- Load ports
dofile(module_path.."/importer.lua")
dofile(module_path.."/exporter.lua")
--dofile(module_path.."/interface.lua")

@ -0,0 +1,57 @@
-- shared/init.lua
local me = microexpansion
-- TODO: regulation upgrade (1: disable in formspec, mesecon control; 2: requests from the me network and perhaps digiline)
-- [register item] Upgrade Base
me.register_item("upgrade_base", {
description = "Upgrade Base",
usedfor = "the base for crafting upgrades",
recipe = {
{ 1, {
{ "microexpansion:quartz_crystal" },
{ "default:steel_ingot" },
},
},
},
})
-- [register item] Bulk Upgrade
me.register_item("upgrade_bulk", {
description = "Bulk Upgrade",
usedfor = "upgrades components to process more at the same time",
recipe = {
{ 1, {
{"microexpansion:gold_wire"},
{"microexpansion:upgrade_base"}
},
},
},
})
-- [register item] Filter Upgrade
me.register_item("upgrade_filter", {
description = "Filter Upgrade",
usedfor = "allows setting up filters for components",
recipe = {
{ 1, {
{"microexpansion:quartz_crystal"},
{"microexpansion:upgrade_base"}
},
},
},
})
-- [register item] Control Upgrade
me.register_item("upgrade_control", {
description = "Control Upgrade",
usedfor = "allows more fine tuned control over components",
recipe = {
{ 1, {
{"microexpansion:logic_chip"},
{"microexpansion:upgrade_base"}
},
},
},
})

@ -270,6 +270,26 @@ function network:get_inventory_name()
return "microexpansion_storage_"..cp.x.."_"..cp.y.."_"..cp.z
end
function network:get_inventory_space(inv, list)
local inv = inv or self:get_inventory()
local listname = list or "main"
local max_slots = inv:get_size(listname)
local max_items = self.capacity_cache
local slots, items = 0, 0
-- Get amount of items in drive
for i = 1, max_slots do
local dstack = inv:get_stack(listname, i)
if dstack:get_name() ~= "" then
slots = slots + 1
local num = dstack:get_count()
if num == 0 then num = 1 end
items = items + num
end
end
return math.max(max_items-items,0)
end
local function create_inventory(net)
local invname = net:get_inventory_name()
net.inv = minetest.create_detached_inventory(invname, {

@ -23,23 +23,25 @@ me.register_node("incranium", {
disabled = true,
})
-- "Supernatet", pronounced "Super-nat-et" is Latin for "float", this ore will
-- float up if there are no blocks above it, so be careful!
-- Supernatet ore will be used to craft wings of flight
me.register_node("supernatet", {
description = "Supernatant Ore",
tiles = { "default_stone.png^microexpansion_ore_supernatet.png" },
me.register_item("quartz_crystal", {
description = "Quartz Crystal",
})
me.register_node("quartz", {
description = "Quartz Ore",
tiles = { "default_stone.png^microexpansion_ore_quartz.png" },
is_ground_content = true,
type = "ore",
groups = { cracky=3, stone=1 },
drop = "microexpansion:quartz_crystal",
oredef = {
ore_type = "blob",
wherein = "default:stone",
clust_scarcity = 4*4*4,
clust_num_ores = 4,
clust_size = 3,
y_min = -300,
y_max = -90,
},
status = "unstable",
y_min = -3000,
y_max = -50,
}
})

@ -28,3 +28,28 @@ me.register_item("machine_casing", {
},
},
})
-- [register item] Gold Wire
me.register_item("gold_wire", {
description = "Gold Wire",
recipe = {
{ 2, {
{"default:gold_ingot", "default:stick"},
{"default:stick", ""}
},
},
},
})
-- [register item] Control Unit
me.register_item("logic_chip", {
description = "Control Unit",
recipe = {
{ 2, {
{"microexpansion:gold_wire"},
{"microexpansion:quartz_crystal"},
{"group:wood"}
},
},
},
})

@ -47,7 +47,7 @@ function microexpansion.int_to_pagenum(int)
return math.floor(microexpansion.int_to_stacks(int) / 32)
end
-- [function] Move items from inv to inv
--[[ [function] Move items from inv to inv
function microexpansion.move_inv(inv1, inv2, max)
if max <= 0 then return end
local finv, tinv = inv1.inv, inv2.inv
@ -81,3 +81,4 @@ function microexpansion.move_inv(inv1, inv2, max)
end
end
end
]]

@ -177,6 +177,9 @@ microexpansion.register_node("term", {
tube = {
can_insert = function(pos, _, stack) --pos, node, stack, direction
local net = me.get_connected_network(pos)
if not net then
return false
end
local inv = net:get_inventory()
local max_slots = inv:get_size("main")
local max_items = net.capacity_cache
@ -197,6 +200,9 @@ microexpansion.register_node("term", {
end,
insert_object = function(pos, _, stack)
local net = me.get_connected_network(pos)
if not net then
return stack
end
local inv = net:get_inventory()
me.insert_item(stack, inv, "main")
net:set_storage_space(true)

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 309 B

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB