diff --git a/api.lua b/api.lua index f3e07fe..728a8b3 100644 --- a/api.lua +++ b/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 diff --git a/modules.conf b/modules.conf index 4f08c81..6c1ae5b 100644 --- a/modules.conf +++ b/modules.conf @@ -3,3 +3,4 @@ network = true power = false storage = true ores = true +item_transfer = true diff --git a/modules/item_transfer/api.lua b/modules/item_transfer/api.lua new file mode 100644 index 0000000..fbcf141 --- /dev/null +++ b/modules/item_transfer/api.lua @@ -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 diff --git a/modules/item_transfer/exporter.lua b/modules/item_transfer/exporter.lua new file mode 100644 index 0000000..5aef6c4 --- /dev/null +++ b/modules/item_transfer/exporter.lua @@ -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 +}) + + diff --git a/modules/item_transfer/importer.lua b/modules/item_transfer/importer.lua new file mode 100644 index 0000000..75b7c30 --- /dev/null +++ b/modules/item_transfer/importer.lua @@ -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 +}) + + diff --git a/modules/item_transfer/init.lua b/modules/item_transfer/init.lua new file mode 100644 index 0000000..6387ba5 --- /dev/null +++ b/modules/item_transfer/init.lua @@ -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") diff --git a/modules/item_transfer/upgrades.lua b/modules/item_transfer/upgrades.lua new file mode 100644 index 0000000..5ebe780 --- /dev/null +++ b/modules/item_transfer/upgrades.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"} + }, + }, + }, +}) diff --git a/modules/network/network.lua b/modules/network/network.lua index fdedd8c..8bdb640 100644 --- a/modules/network/network.lua +++ b/modules/network/network.lua @@ -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, { diff --git a/modules/ores/init.lua b/modules/ores/init.lua index 89296e6..0f32daf 100644 --- a/modules/ores/init.lua +++ b/modules/ores/init.lua @@ -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, + } }) diff --git a/modules/shared/init.lua b/modules/shared/init.lua index befb806..396af72 100644 --- a/modules/shared/init.lua +++ b/modules/shared/init.lua @@ -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"} + }, + }, + }, +}) diff --git a/modules/storage/api.lua b/modules/storage/api.lua index 06ae5f5..ba5b430 100644 --- a/modules/storage/api.lua +++ b/modules/storage/api.lua @@ -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 +]] \ No newline at end of file diff --git a/modules/storage/terminal.lua b/modules/storage/terminal.lua index a678998..53b1146 100644 --- a/modules/storage/terminal.lua +++ b/modules/storage/terminal.lua @@ -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) diff --git a/textures/microexpansion_exporter.png b/textures/microexpansion_exporter.png new file mode 100644 index 0000000..16bfcda Binary files /dev/null and b/textures/microexpansion_exporter.png differ diff --git a/textures/microexpansion_gold_wire.png b/textures/microexpansion_gold_wire.png new file mode 100644 index 0000000..8bb14e6 Binary files /dev/null and b/textures/microexpansion_gold_wire.png differ diff --git a/textures/microexpansion_importer.png b/textures/microexpansion_importer.png new file mode 100644 index 0000000..d6069b9 Binary files /dev/null and b/textures/microexpansion_importer.png differ diff --git a/textures/me_interface.png b/textures/microexpansion_interface.png similarity index 100% rename from textures/me_interface.png rename to textures/microexpansion_interface.png diff --git a/textures/microexpansion_logic_chip.png b/textures/microexpansion_logic_chip.png new file mode 100644 index 0000000..651896a Binary files /dev/null and b/textures/microexpansion_logic_chip.png differ diff --git a/textures/microexpansion_ore_supernatet.png b/textures/microexpansion_ore_quartz.png similarity index 100% rename from textures/microexpansion_ore_supernatet.png rename to textures/microexpansion_ore_quartz.png diff --git a/textures/me_quartz_crystal.png b/textures/microexpansion_quartz_crystal.png similarity index 100% rename from textures/me_quartz_crystal.png rename to textures/microexpansion_quartz_crystal.png diff --git a/textures/microexpansion_upgrade_base.png b/textures/microexpansion_upgrade_base.png new file mode 100644 index 0000000..42f0c12 Binary files /dev/null and b/textures/microexpansion_upgrade_base.png differ diff --git a/textures/microexpansion_upgrade_bulk.png b/textures/microexpansion_upgrade_bulk.png new file mode 100644 index 0000000..92bdf9e Binary files /dev/null and b/textures/microexpansion_upgrade_bulk.png differ diff --git a/textures/microexpansion_upgrade_control.png b/textures/microexpansion_upgrade_control.png new file mode 100644 index 0000000..8f447c3 Binary files /dev/null and b/textures/microexpansion_upgrade_control.png differ diff --git a/textures/microexpansion_upgrade_filter.png b/textures/microexpansion_upgrade_filter.png new file mode 100644 index 0000000..43d200f Binary files /dev/null and b/textures/microexpansion_upgrade_filter.png differ diff --git a/textures/microexpansion_upgrade_regulation.png b/textures/microexpansion_upgrade_regulation.png new file mode 100644 index 0000000..4fdf0f4 Binary files /dev/null and b/textures/microexpansion_upgrade_regulation.png differ