diff --git a/api/api.lua b/api/api.lua index f0c8bb1..500d463 100644 --- a/api/api.lua +++ b/api/api.lua @@ -5,3 +5,4 @@ dofile(path.."/controller.lua") dofile(path.."/mass_storage.lua") dofile(path.."/supplier.lua") dofile(path.."/demander.lua") +dofile(path.."/injector.lua") \ No newline at end of file diff --git a/api/controller.lua b/api/controller.lua index 33b6e97..964b65d 100644 --- a/api/controller.lua +++ b/api/controller.lua @@ -102,7 +102,7 @@ function logistica.register_controller(simpleName, def, tier) def_disabled.tiles = tiles_disabled def_disabled.groups = { oddly_breakable_by_hand = 3, cracky = 3, choppy = 3, not_in_creative_inventory = 1 } def_disabled.on_construct = nil - def_disabled.after_desctruct = nil + def_disabled.after_destruct = nil def_disabled.on_timer = nil def_disabled.on_rightclick = nil diff --git a/api/demander.lua b/api/demander.lua index 617eca8..bffe0c0 100644 --- a/api/demander.lua +++ b/api/demander.lua @@ -71,6 +71,7 @@ local function after_place_demander(pos, placer, itemstack, numDemandSlots) local inv = meta:get_inventory() inv:set_size("filter", numDemandSlots) logistica.on_demander_change(pos) + logistica.update_demander_on_item_added(pos) logistica.start_demander_timer(pos) end @@ -80,6 +81,7 @@ local function allow_demander_storage_inv_put(pos, listname, index, stack, playe local slotStack = inv:get_stack(listname, index) slotStack:add_item(stack) inv:set_stack(listname, index, slotStack) + logistica.update_demander_on_item_added(pos) logistica.start_demander_timer(pos, 1) return 0 end @@ -90,6 +92,7 @@ local function allow_demander_inv_take(pos, listname, index, stack, player) local slotStack = inv:get_stack(listname, index) slotStack:take_item(stack:get_count()) inv:set_stack(listname, index, slotStack) + logistica.update_demander_cache_pos(pos) return 0 end @@ -136,6 +139,7 @@ function logistica.register_demander(simpleName, transferRate) after_place_node = function (pos, placer, itemstack) after_place_demander(pos, placer, itemstack, NUM_DEMAND_SLOTS) end, + after_destruct = logistica.on_demander_change, on_punch = on_demander_punch, on_rightclick = on_demander_rightclick, allow_metadata_inventory_put = allow_demander_storage_inv_put, @@ -163,7 +167,7 @@ function logistica.register_demander(simpleName, transferRate) def_disabled.tiles = tiles_disabled def_disabled.groups = { oddly_breakable_by_hand = 3, cracky = 3, choppy = 3, not_in_creative_inventory = 1 } def_disabled.on_construct = nil - def_disabled.after_desctruct = nil + def_disabled.after_destruct = nil def_disabled.on_punch = nil def_disabled.on_rightclick = nil def_disabled.on_timer = nil diff --git a/api/injector.lua b/api/injector.lua new file mode 100644 index 0000000..3a650f5 --- /dev/null +++ b/api/injector.lua @@ -0,0 +1,150 @@ + +local PULL_LIST_PICKER = "pull_pick" +local ON_OFF_BUTTON = "on_off_btn" +local FORMSPEC_NAME = "logistica_storinject" + +local injectorForms = {} + +local function get_injector_formspec(pos) + local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z + local pushPos = logistica.get_injector_target(pos) + local selectedList = logistica.get_injector_target_list(pos) + local isOn = logistica.is_machine_on(pos) + return "formspec_version[4]" .. + "size[7,2.0]" .. + logistica.ui.background.. + "label[0.5,0.3;Active Suppliers try to insert items in the network one at a time]".. + logistica.ui.pull_list_picker(PULL_LIST_PICKER, 0.5, 1.0, pushPos, selectedList, "Take items from:").. + logistica.ui.on_off_btn(isOn, 4.5, 0.8, ON_OFF_BUTTON, "Enable") +end + +local function show_injector_formspec(playerName, pos) + local pInfo = {} + pInfo.position = pos + injectorForms[playerName] = pInfo + minetest.show_formspec(playerName, FORMSPEC_NAME, get_injector_formspec(pos)) +end + +-- callbacks + +local function on_player_receive_fields(player, formname, fields) + if not player or not player:is_player() then return false end + if formname ~= FORMSPEC_NAME then return false end + local playerName = player:get_player_name() + if not injectorForms[playerName] then return false end + if fields.quit then + injectorForms[playerName] = nil + elseif fields[ON_OFF_BUTTON] then + local pos = injectorForms[playerName].position + if not pos then return false end + logistica.toggle_machine_on_off(pos) + show_injector_formspec(player:get_player_name(), pos) + elseif fields[PULL_LIST_PICKER] then + local selected = fields[PULL_LIST_PICKER] + if logistica.is_allowed_pull_list(selected) then + local pos = injectorForms[playerName].position + if not pos then return false end + logistica.set_injector_target_list(pos, selected) + end + end + return true +end + +local function on_injector_punch(pos, node, puncher, pointed_thing) + local targetPos = logistica.get_injector_target(pos) + if targetPos and puncher:is_player() and puncher:get_player_control().sneak then + minetest.add_entity(targetPos, "logistica:input_entity") + end +end + +local function on_injector_rightclick(pos, node, clicker, itemstack, pointed_thing) + if not clicker or not clicker:is_player() then return end + show_injector_formspec(clicker:get_player_name(), pos) +end + +local function after_place_injector(pos, placer, itemstack) + local meta = minetest.get_meta(pos) + if placer and placer:is_player() then + meta:set_string("owner", placer:get_player_name()) + end + logistica.set_injector_target_list(pos, "main") + logistica.on_injector_change(pos) + logistica.start_injector_timer(pos) +end + +---------------------------------------------------------------- +-- Minetest registration +---------------------------------------------------------------- + +minetest.register_on_player_receive_fields(on_player_receive_fields) + +---------------------------------------------------------------- +-- Public Registration API +---------------------------------------------------------------- + +-- `simpleName` is used for the description and for the name (can contain spaces) +-- transferRate is how many items per tick this injector can transfer, -1 for unlimited +function logistica.register_injector(simpleName, transferRate) + local lname = string.lower(simpleName:gsub(" ", "_")) + local injectorName = "logistica:injector_"..lname + logistica.injectors[injectorName] = true + local grps = {oddly_breakable_by_hand = 3, cracky = 3 } + grps[logistica.TIER_ALL] = 1 + local def = { + description = simpleName.." Active Supplier", + drawtype = "normal", + tiles = { + "logistica_"..lname.."_injector_side.png^[transformR270", + "logistica_"..lname.."_injector_side.png^[transformR90", + "logistica_"..lname.."_injector_side.png^[transformR180", + "logistica_"..lname.."_injector_side.png", + "logistica_"..lname.."_injector_back.png", + "logistica_"..lname.."_injector_front.png", + }, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = grps, + drop = injectorName, + sounds = logistica.node_sound_metallic(), + on_timer = logistica.on_injector_timer, + after_place_node = function (pos, placer, itemstack) + after_place_injector(pos, placer, itemstack) + end, + after_destruct = logistica.on_injector_change, + on_punch = on_injector_punch, + on_rightclick = on_injector_rightclick, + logistica = { + injector_transfer_rate = transferRate, + on_connect_to_network = function(pos, networkId) + logistica.start_injector_timer(pos) + end, + on_power = function(pos, isPoweredOn) + if isPoweredOn then + logistica.start_injector_timer(pos) + end + end, + } + } + + minetest.register_node(injectorName, def) + + local def_disabled = table.copy(def) + local tiles_disabled = {} + for k, v in pairs(def.tiles) do tiles_disabled[k] = v.."^logistica_disabled.png" end + + def_disabled.tiles = tiles_disabled + def_disabled.groups = { oddly_breakable_by_hand = 3, cracky = 3, choppy = 3, not_in_creative_inventory = 1 } + def_disabled.on_construct = nil + def_disabled.after_destruct = nil + def_disabled.on_punch = nil + def_disabled.on_rightclick = nil + def_disabled.on_timer = nil + def_disabled.logistica = nil + + minetest.register_node(injectorName.."_disabled", def_disabled) + +end + +logistica.register_injector("Item", 1) +logistica.register_injector("Stack", 99) diff --git a/api/mass_storage.lua b/api/mass_storage.lua index bc5e732..bf3fb12 100644 --- a/api/mass_storage.lua +++ b/api/mass_storage.lua @@ -190,12 +190,12 @@ local function after_place_mass_storage(pos, placer, itemstack, numSlots, numUpg logistica.set_mass_storage_image_slot(meta, selImgIndex) for i, v in ipairs(reserves) do logistica.set_mass_storage_reserve(meta, i, v) end logistica.update_mass_storage_front_image(pos) - logistica.on_storage_change(pos) + logistica.on_mass_storage_change(pos) end local function after_mass_storage_destruct(pos, oldNode) logistica.remove_item_on_block_front(pos) - logistica.on_storage_change(pos, oldNode) + logistica.on_mass_storage_change(pos, oldNode) end local function on_mass_storage_preserve_metadata(pos, oldnode, oldmeta, drops) @@ -366,6 +366,7 @@ function logistica.register_mass_storage(simpleName, numSlots, numItemsPerSlot, for k, v in pairs(def.tiles) do tiles_disabled[k] = v.."^logistica_disabled.png" end def_disabled.tiles = tiles_disabled def_disabled.groups = { cracky = 3, choppy = 3, oddly_breakable_by_hand = 3, not_in_creative_inventory = 1 } + def_disabled.after_destruct = nil minetest.register_node(storageName.."_disabled", def_disabled) diff --git a/api/supplier.lua b/api/supplier.lua index 5a955d8..8e0a4fa 100644 --- a/api/supplier.lua +++ b/api/supplier.lua @@ -14,9 +14,9 @@ local function get_supplier_formspec(pos) return "formspec_version[4]" .. "size[10.6,8]" .. logistica.ui.background.. - logistica.ui.pull_list_picker(PULL_LIST_PICKER, 6.7, 0.7, pushPos, selectedList, "Take from:").. + logistica.ui.pull_list_picker(PULL_LIST_PICKER, 6.7, 0.7, pushPos, selectedList, "Supply from:").. logistica.ui.on_off_btn(isOn, 9.3, 0.5, ON_OFF_BUTTON, "Enable").. - "label[0.6,1.2;Items to Supply (if empty nothing will be taken)]".. + "label[0.6,1.2;Items to make available as Supply. If left empty, nothing is supplied]".. "list["..posForm..";filter;0.5,1.5;"..NUM_SUPPLY_SLOTS..",1;0]".. "list[current_player;main;0.5,3;8,4;0]" end @@ -135,6 +135,7 @@ function logistica.register_supplier(simpleName, maxTransferRate) after_place_node = function (pos, placer, itemstack) after_place_supplier(pos, placer, itemstack, NUM_SUPPLY_SLOTS) end, + after_destruct = logistica.on_supplier_change, on_punch = on_supplier_punch, on_rightclick = on_supplier_rightclick, allow_metadata_inventory_put = allow_supplier_storage_inv_put, @@ -154,7 +155,7 @@ function logistica.register_supplier(simpleName, maxTransferRate) def_disabled.tiles = tiles_disabled def_disabled.groups = { oddly_breakable_by_hand = 3, cracky = 3, choppy = 3, not_in_creative_inventory = 1 } def_disabled.on_construct = nil - def_disabled.after_desctruct = nil + def_disabled.after_destruct = nil def_disabled.on_punch = nil def_disabled.on_rightclick = nil def_disabled.on_timer = nil diff --git a/logic/demander.lua b/logic/demander.lua index 3baf405..987a950 100644 --- a/logic/demander.lua +++ b/logic/demander.lua @@ -3,6 +3,9 @@ local TIMER_DURATION_LONG = 3.0 local META_DEMANDER_LISTNAME = "demtarlist" local TARGET_NODES_REQUIRING_TIMER = {} TARGET_NODES_REQUIRING_TIMER["default:furnace"] = true +TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve0"] = true +TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve1"] = true +TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve2"] = true TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve3"] = true local function get_meta(pos) @@ -45,7 +48,7 @@ local function get_valid_demander_and_target_inventory(demanderPos) } end -local function get_actual_demand_for_item(demandStack, invs) +local function get_target_missing_item_stack(demandStack, invs) local storageList = invs.targetInventory:get_list(invs.targetList) local remaining = demandStack:get_count() for i,_ in ipairs(storageList) do @@ -77,7 +80,7 @@ local function get_next_demanded_stack(pos) repeat if nextSlot <= 0 then return nil end local filterStack = inventories.demanderInventory:get_list("filter")[nextSlot] - demandStack = get_actual_demand_for_item(filterStack, inventories) + demandStack = get_target_missing_item_stack(filterStack, inventories) if demandStack:get_count() > 0 then return demandStack end nextSlot = logistica.get_next_filled_item_slot(get_meta(pos), "filter") until( nextSlot == startingSlot ) -- until we get back to the starting slot @@ -95,6 +98,15 @@ local function take_demanded_items_from_network(pos, network) return true end +local function get_filter_demand_for(inv, itemName) + local filterList = inv:get_list("filter") + local maxDemand = 0 + for _, v in ipairs(filterList) do + if v:get_name() == itemName and v:get_count() > maxDemand then maxDemand = v:get_count() end + end + return maxDemand +end + ---------------------------------------------------------------- -- Storage operation functions ---------------------------------------------------------------- @@ -155,27 +167,38 @@ end function logistica.get_demander_target(pos) local node = minetest.get_node_or_nil(pos) if not node then return nil end - local shift = logistica.get_rot_directions(node.param2).backward - if not shift then return nil end - return {x = (pos.x + shift.x), - y = (pos.y + shift.y), - z = (pos.z + shift.z)} + return vector.add(pos, logistica.get_rot_directions(node.param2).backward) end -- returns how many items remain from the itemstack after we attempt to insert it -- `targetInventory` and `targetList` are optional (tied together), if not passed, it will be looked up -function logistica.insert_itemstack_for_demander(demanderPos, itemstack) +-- `limitByDemand` is optional - if set to true, no more items than needed will be inserted +function logistica.insert_itemstack_for_demander(demanderPos, itemstack, limitByDemand) if not itemstack or itemstack:is_empty() then return 0 end + if not logistica.is_machine_on(demanderPos) then return itemstack:get_count() end + local itemStackCount = itemstack:get_count() + local itemStackName = itemstack:get_name() local inventories = get_valid_demander_and_target_inventory(demanderPos) - if not inventories then return itemstack:get_count() end + if not inventories then return itemStackCount end local targetInventory = inventories.targetInventory local targetList = inventories.targetList - local leftover = targetInventory:add_item(targetList, itemstack) + local toInsertStack = ItemStack(itemstack) + local demand = itemStackCount + if limitByDemand then + demand = get_filter_demand_for(inventories.demanderInventory, itemStackName) + minetest.chat_send_all("-- filterDemand = "..demand) + toInsertStack:set_count(demand) + toInsertStack = get_target_missing_item_stack(toInsertStack, inventories) + minetest.chat_send_all("-- missing item stack = "..toInsertStack:get_count()) + end + if toInsertStack:is_empty() then return itemStackCount end + + local leftover = targetInventory:add_item(targetList, toInsertStack) local targetNode = minetest.get_node(inventories.targetPos) - if leftover:get_count() < itemstack:get_count() and TARGET_NODES_REQUIRING_TIMER[targetNode.name] then + if leftover:get_count() < toInsertStack:get_count() and TARGET_NODES_REQUIRING_TIMER[targetNode.name] then logistica.start_node_timer(inventories.targetPos, 1) end - return leftover:get_count() + return leftover:get_count() + itemStackCount - demand end diff --git a/logic/groups.lua b/logic/groups.lua index 8583943..244f07f 100644 --- a/logic/groups.lua +++ b/logic/groups.lua @@ -1,6 +1,7 @@ logistica.cables = {} logistica.machines = {} logistica.controllers = {} +logistica.injectors = {} logistica.demanders = {} logistica.suppliers = {} logistica.mass_storage = {} @@ -46,6 +47,10 @@ function logistica.is_controller(name) return logistica.controllers[name] ~= nil end +function logistica.is_injector(name) + return logistica.injectors[name] ~= nil +end + function logistica.get_item_tiers(name) local tiers = {} for tier,_ in pairs(logistica.tiers) do diff --git a/logic/injector.lua b/logic/injector.lua new file mode 100644 index 0000000..9b1e8d2 --- /dev/null +++ b/logic/injector.lua @@ -0,0 +1,73 @@ +local META_INJECTOR_LISTNAME = "tarinjlist" +local TIMER_DURATION_SHORT = 1 +local TIMER_DURATION_LONG = 3 + +local function get_meta(pos) + logistica.load_position(pos) + return minetest.get_meta(pos) +end + +local function get_injector_rate(nodeName) + local def = minetest.registered_nodes[nodeName] + if def and def.logistica and def.logistica.injector_transfer_rate then + return def.logistica.injector_transfer_rate + end + return 0 +end + +-- public functions + +function logistica.get_injector_target(pos) + local node = minetest.get_node(pos) + if not node then return pos end + return vector.add(pos, logistica.get_rot_directions(node.param2).backward) +end + +function logistica.get_injector_target_list(pos) + local meta = get_meta(pos) + return meta:get_string(META_INJECTOR_LISTNAME) +end + +function logistica.set_injector_target_list(pos, listName) + local meta = get_meta(pos) + meta:set_string(META_INJECTOR_LISTNAME, listName) +end + +function logistica.start_injector_timer(pos) + logistica.start_node_timer(pos, TIMER_DURATION_SHORT) +end + +function logistica.on_injector_timer(pos, elapsed) + local networkId = logistica.get_network_id_or_nil(pos) + if not networkId then + logistica.set_node_on_off_state(pos, false) + return false + end + + local node = minetest.get_node_or_nil(pos) + local meta = minetest.get_meta(pos) + if not node then + logistica.start_node_timer(pos, TIMER_DURATION_LONG) + return false + end + local targetList = logistica.get_injector_target_list(pos) + local targetPos = logistica.get_injector_target(pos) + local targetMeta = minetest.get_meta(targetPos) + local targetSlot = logistica.get_next_filled_item_slot(targetMeta, targetList) + local maxStack = get_injector_rate(node.name) + if targetSlot <= 0 or maxStack <= 0 then + logistica.start_node_timer(pos, TIMER_DURATION_LONG) + return false + end + + local inv = targetMeta:get_inventory() + local copyStack = inv:get_stack(targetList, targetSlot) + local copyStackSize = copyStack:get_count() + local numRemaining = logistica.insert_item_in_network(copyStack, networkId) + minetest.chat_send_all("attempted to insert: "..copyStackSize..", remain: "..numRemaining) + copyStack:set_count(numRemaining) + inv:set_stack(targetList, targetSlot, copyStack) + + logistica.start_node_timer(pos, TIMER_DURATION_SHORT) + return false +end diff --git a/logic/logic.lua b/logic/logic.lua index 228abd1..5e6e6c3 100644 --- a/logic/logic.lua +++ b/logic/logic.lua @@ -9,3 +9,4 @@ dofile(path .. "/controller.lua") dofile(path .. "/mass_storage.lua") dofile(path .. "/supplier.lua") dofile(path .. "/demander.lua") +dofile(path .. "/injector.lua") diff --git a/logic/mass_storage.lua b/logic/mass_storage.lua index cc00a05..b0b15a2 100644 --- a/logic/mass_storage.lua +++ b/logic/mass_storage.lua @@ -84,7 +84,10 @@ end function logistica.pull_items_from_network_into_mass_storage(pos) local network = logistica.get_network_or_nil(pos) - if not network then return end + if not network then + logistica.set_node_on_off_state(pos, false) + return + end local meta = minetest.get_meta(pos) local stackPos = logistica.get_next_filled_item_slot(meta, "filter") if stackPos <= 0 then return end diff --git a/logic/network_cache.lua b/logic/network_cache.lua index 72ce360..bc3c7da 100644 --- a/logic/network_cache.lua +++ b/logic/network_cache.lua @@ -11,6 +11,12 @@ local CACHE_PICKER_SUPPLIER = { cache = function (network) return network.supplier_cache end, nodes = function (network) return network.suppliers end, } +local CACHE_PICKER_DEMANDER = { + listName = "filter", + clear = function (network) network.demander_cache = {} end, + cache = function (network) return network.demander_cache end, + nodes = function (network) return network.demanders end, +} -- local function notify_demanders_of_new_cache(network) -- for hash, _ in pairs(network.demanders) do @@ -111,3 +117,15 @@ end function logistica.update_supplier_on_item_added(pos) update_cache_on_item_added_at_pos(pos, CACHE_PICKER_SUPPLIER) end + +function logistica.update_demander_cache_pos(pos) + update_network_cache_for_pos(pos, CACHE_PICKER_DEMANDER) +end + +function logistica.update_demander_cache(network) + update_network_cache(network, CACHE_PICKER_DEMANDER) +end + +function logistica.update_demander_on_item_added(pos) + update_cache_on_item_added_at_pos(pos, CACHE_PICKER_DEMANDER) +end \ No newline at end of file diff --git a/logic/network_logic.lua b/logic/network_logic.lua index f23d4e0..8a3dd8f 100644 --- a/logic/network_logic.lua +++ b/logic/network_logic.lua @@ -20,7 +20,11 @@ local adjecent = { local function has_machine(network, id) if not network then return false end - if network.demanders[id] or network.suppliers[id] or network.mass_storage[id] or network.item_storage[id] + if network.demanders[id] + or network.suppliers[id] + or network.mass_storage[id] + or network.item_storage[id] + or network.injectors[id] then return true else @@ -139,6 +143,9 @@ local function recursive_scan_for_nodes_for_controller(network, positionHashes, elseif logistica.is_demander(otherNode.name) then network.demanders[otherHash] = true valid = true + elseif logistica.is_injector(otherNode.name) then + network.injectors[otherHash] = true + valid = true elseif logistica.is_supplier(otherNode.name) then network.suppliers[otherHash] = true valid = true @@ -178,11 +185,13 @@ local function create_network(controllerPosition, oldNetworkName) network.name = networkName network.cables = {} network.demanders = {} + network.injectors = {} network.suppliers = {} network.mass_storage = {} network.item_storage = {} network.storage_cache = {} network.supplier_cache = {} + network.demander_cache = {} local startPos = {} startPos[controllerHash] = true local status = recursive_scan_for_nodes_for_controller(network, startPos) @@ -196,6 +205,7 @@ local function create_network(controllerPosition, oldNetworkName) -- controller scan skips updating storage cache, do so now logistica.update_mass_storage_cache(network) logistica.update_supplier_cache(network) + logistica.update_demander_cache(network) end if errorMsg ~= nil then networks[controllerHash] = nil @@ -269,25 +279,12 @@ local function MASS_STORAGE_OPS(pos) return { update_cache_node_added = function(_) logistica.update_mass_storage_cache_on_item_added(pos) end, update_cache_node_removed = function(network) logistica.update_mass_storage_cache(network) end, } end -local function try_to_add_mass_storage_to_network(pos) - try_to_add_to_network(pos, MASS_STORAGE_OPS(pos)) -end -local function remove_mass_storage_from_network(pos) - remove_from_network(pos, MASS_STORAGE_OPS(pos)) -end - -local DEMANDER_OPS = { +local function DEMANDER_OPS(pos) return { get_list = function(network) return network.demanders end, - update_cache_node_added = function(_) end, - update_cache_node_removed = function(_) end, -} -local function try_to_add_demander_to_network(pos) - try_to_add_to_network(pos,DEMANDER_OPS) -end -local function remove_demander_from_network(pos) - remove_from_network(pos, DEMANDER_OPS) -end + update_cache_node_added = function(_) logistica.update_demander_on_item_added(pos) end, + update_cache_node_removed = function(network) logistica.update_demander_cache(network) end, +} end local function SUPPLIER_OPS(pos) return { get_list = function(network) return network.suppliers end, @@ -295,13 +292,11 @@ local function SUPPLIER_OPS(pos) return { update_cache_node_removed = function(network) logistica.update_supplier_cache(network) end, } end -local function try_to_add_supplier_to_network(pos) - try_to_add_to_network(pos, SUPPLIER_OPS(pos)) -end - -local function remove_supplier_from_network(pos) - remove_from_network(pos, SUPPLIER_OPS(pos)) -end +local INJECTOR_OPS = { + get_list = function(network) return network.injectors end, + update_cache_node_added = function(_) end, + update_cache_node_removed = function(_) end, +} local function cable_can_extend_network_from(pos) local node = minetest.get_node_or_nil(pos) @@ -370,29 +365,38 @@ function logistica.on_controller_change(pos, oldNode) end end -function logistica.on_storage_change(pos, oldNode) +function logistica.on_mass_storage_change(pos, oldNode) local placed = (oldNode == nil) -- if oldNode is nil, we placed a new one if placed == true then - try_to_add_mass_storage_to_network(pos) + try_to_add_to_network(pos, MASS_STORAGE_OPS(pos)) else - remove_mass_storage_from_network(pos) + remove_from_network(pos, MASS_STORAGE_OPS(pos)) end end function logistica.on_demander_change(pos, oldNode) local placed = (oldNode == nil) -- if oldNode is nil, we placed a new one if placed == true then - try_to_add_demander_to_network(pos) + try_to_add_to_network(pos, DEMANDER_OPS(pos)) else - remove_demander_from_network(pos) + remove_from_network(pos, DEMANDER_OPS(pos)) end end function logistica.on_supplier_change(pos, oldNode) local placed = (oldNode == nil) -- if oldNode is nil, we placed a new one if placed == true then - try_to_add_supplier_to_network(pos) + try_to_add_to_network(pos, SUPPLIER_OPS(pos)) else - remove_supplier_from_network(pos) + remove_from_network(pos, SUPPLIER_OPS(pos)) + end +end + +function logistica.on_injector_change(pos, oldNode) + local placed = (oldNode == nil) -- if oldNode is nil, we placed a new one + if placed == true then + try_to_add_to_network(pos, INJECTOR_OPS) + else + remove_from_network(pos, INJECTOR_OPS) end end diff --git a/logic/network_storage.lua b/logic/network_storage.lua index 9848c83..f03d505 100644 --- a/logic/network_storage.lua +++ b/logic/network_storage.lua @@ -79,7 +79,7 @@ function logistica.take_stack_from_mass_storage(stackToTake, network, collectorF return false end --- try to insert the item into the storage, returning how many items were taken +-- try to insert the item into the storage, returning how many items remain function logistica.try_to_add_item_to_storage(pos, inputStack, dryRun) local node = minetest.get_node(pos) if not logistica.is_mass_storage(node.name) and not logistica.is_item_storage(node.name) then return 0 end @@ -88,30 +88,33 @@ function logistica.try_to_add_item_to_storage(pos, inputStack, dryRun) local inv = minetest.get_meta(pos):get_inventory() if isMassStorage then local remainingStack = logistica.insert_item_into_mass_storage(pos, inv, inputStack, dryRun) - return inputStack:get_count() - remainingStack:get_count() + return remainingStack:get_count() else -- it's not mass storage, must be tool storage if inputStack:get_stack_max() == 1 and inv:room_for_item("main", inputStack) then -- tool storage only takes individual items inv:add_item("main", inputStack) - return 1 + return 0 end end - return 0 + return inputStack:get_count() end --- attempts to insert the given itemstack in the network, returns how many items were inserted +-- attempts to insert the given itemstack in the network, returns how many items remain function logistica.insert_item_in_network(itemstack, networkId) - local network = logistica.networks[networkId] - if not itemstack or not network then return 0 end + local network = logistica.get_network_by_id_or_nil(networkId) + if not itemstack or itemstack:is_empty() then return 0 end + if not network then return itemstack:get_count() end local workingStack = ItemStack(itemstack) + -- check demanders first - for hash, _ in pairs(network.demanders) do + local listOfDemandersInNeedOfItem = network.demander_cache[itemstack:get_name()] or {} + for hash, _ in pairs(listOfDemandersInNeedOfItem) do local pos = minetest.get_position_from_hash(hash) logistica.load_position(pos) - local taken = 0 -- logistica.try_to_give_item_to_demander(pos, workingStack) - local leftover = workingStack:get_count() - taken - if leftover <= 0 then return itemstack:get_count() end -- we took all items + local leftover = logistica.insert_itemstack_for_demander(pos, workingStack, true) + minetest.chat_send_all("insert_in_network: from: "..itemstack:get_count().." remain "..leftover) + if leftover <= 0 then return 0 end -- we took all items workingStack:set_count(leftover) end @@ -125,11 +128,10 @@ function logistica.insert_item_in_network(itemstack, networkId) for hash, _ in pairs(storages) do local pos = minetest.get_position_from_hash(hash) logistica.load_position(pos) - local taken = logistica.try_to_add_item_to_storage(pos, workingStack) - local leftover = workingStack:get_count() - taken - if leftover <= 0 then return itemstack:get_count() end -- we took all items - workingStack:set_count(leftover) + local remain = logistica.try_to_add_item_to_storage(pos, workingStack) + if remain <= 0 then return 0 end -- we took all items + workingStack:set_count(remain) end - return itemstack:get_count() - workingStack:get_count() + return workingStack:get_count() end \ No newline at end of file diff --git a/textures/logistica_basic_mass_storage_front.png b/textures/logistica_basic_mass_storage_front.png index 19a0054..7c041d5 100644 Binary files a/textures/logistica_basic_mass_storage_front.png and b/textures/logistica_basic_mass_storage_front.png differ diff --git a/textures/logistica_item_injector_back.png b/textures/logistica_item_injector_back.png new file mode 100644 index 0000000..66525ba Binary files /dev/null and b/textures/logistica_item_injector_back.png differ diff --git a/textures/logistica_item_injector_front.png b/textures/logistica_item_injector_front.png new file mode 100644 index 0000000..25e9fc0 Binary files /dev/null and b/textures/logistica_item_injector_front.png differ diff --git a/textures/logistica_item_injector_side.png b/textures/logistica_item_injector_side.png new file mode 100644 index 0000000..dd1ff06 Binary files /dev/null and b/textures/logistica_item_injector_side.png differ diff --git a/textures/logistica_stack_injector_back.png b/textures/logistica_stack_injector_back.png new file mode 100644 index 0000000..913b333 Binary files /dev/null and b/textures/logistica_stack_injector_back.png differ diff --git a/textures/logistica_stack_injector_front.png b/textures/logistica_stack_injector_front.png new file mode 100644 index 0000000..3f8194b Binary files /dev/null and b/textures/logistica_stack_injector_front.png differ diff --git a/textures/logistica_stack_injector_side.png b/textures/logistica_stack_injector_side.png new file mode 100644 index 0000000..baef3e1 Binary files /dev/null and b/textures/logistica_stack_injector_side.png differ diff --git a/util/common.lua b/util/common.lua index 91f08fe..7eefc55 100644 --- a/util/common.lua +++ b/util/common.lua @@ -87,15 +87,16 @@ end -- toggles the state and returns the new state (true for on, false for off) function logistica.toggle_machine_on_off(pos) logistica.load_position(pos) + local node = minetest.get_node(pos) local meta = minetest.get_meta(pos) local newState = (meta:get_int(META_ON_OFF_KEY) + 1) % 2 - meta:set_int(META_ON_OFF_KEY, newState) - local node = minetest.get_node(pos) local def = minetest.registered_nodes[node.name] if def and def.logistica and def.logistica.on_power then def.logistica.on_power(pos, newState) + meta:set_int(META_ON_OFF_KEY, newState) + return newState > 0 end - return newState > 0 + return nil end -- isOn is optional diff --git a/util/ui.lua b/util/ui.lua index 244113e..b721dfb 100644 --- a/util/ui.lua +++ b/util/ui.lua @@ -2,18 +2,6 @@ logistica.ui = {} logistica.ui.background = "no_prepend[]bgcolor[#0000]background9[0,0;1,1;logistica_formspec_background.png;true;8]" --- returns a string of comma separated lists we're allowed to push to at the given pushToPos -local function get_lists(pushToPos, allowedLists) - logistica.load_position(pushToPos) - local availableLists = minetest.get_meta(pushToPos):get_inventory():get_lists() - local pushLists = {} - for name, _ in pairs(availableLists) do - if allowedLists[name] then - table.insert(pushLists, name) - end - end - return pushLists -end local function list_dropdown(name, itemTable, x, y, default, label) @@ -42,9 +30,9 @@ function logistica.ui.on_off_btn(isOn, x, y, name, label, w, h) end function logistica.ui.pull_list_picker(name, x, y, pullFromPos, default, label) - return list_dropdown(name, get_lists(pullFromPos, logistica.ALLOWED_PULL_LISTS), x, y, default, label) + return list_dropdown(name, logistica.get_pull_lists(pullFromPos), x, y, default, label) end function logistica.ui.push_list_picker(name, x, y, pushToPos, default, label) - return list_dropdown(name, get_lists(pushToPos, logistica.ALLOWED_PUSH_LISTS), x, y, default, label) + return list_dropdown(name, logistica.get_push_lists(pushToPos), x, y, default, label) end diff --git a/util/ui_logic.lua b/util/ui_logic.lua index 7cc1d05..8797e19 100644 --- a/util/ui_logic.lua +++ b/util/ui_logic.lua @@ -1,23 +1,58 @@ -logistica.ALLOWED_PULL_LISTS = {} -local allowedPull = logistica.ALLOWED_PULL_LISTS +local allowedPull = {} allowedPull["main"] = true -allowedPull["src"] = true +--allowedPull["src"] = true allowedPull["dst"] = true allowedPull["output"] = true -allowedPull["fuel"] = true +--allowedPull["fuel"] = true -logistica.ALLOWED_PUSH_LISTS = {} -local allowedPush = logistica.ALLOWED_PUSH_LISTS +local allowedPush = {} allowedPush["main"] = true allowedPush["src"] = true allowedPush["fuel"] = true allowedPush["input"] = true allowedPush["shift"] = true +local function get_lists(targetPosition, allowedLists) + logistica.load_position(targetPosition) + local availableLists = minetest.get_meta(targetPosition):get_inventory():get_lists() + local pushLists = {} + for name, _ in pairs(availableLists) do + if allowedLists[name] then + table.insert(pushLists, name) + end + end + return pushLists +end + +---------------------------------------------------------------- +-- API +---------------------------------------------------------------- + +-- returns a string of comma separated lists allowed to push to at the given position +function logistica.get_push_lists(targetPosition) + return get_lists(targetPosition, allowedPush) +end + +-- returns a string of comma separated lists allowed to pull to at the given position +function logistica.get_pull_lists(targetPosition) + return get_lists(targetPosition, allowedPull) +end + function logistica.is_allowed_pull_list(listName) return allowedPull[listName] == true end function logistica.is_allowed_push_list(listName) return allowedPush[listName] == true -end \ No newline at end of file +end + +function logistica.add_allowed_push_list(listName) + if not listName then return end + allowedPush[listName] = true +end + +function logistica.add_allowed_pull_list(listName) + if not listName then return end + allowedPull[listName] = true +end +