diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..048d102 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,24 @@ +Missing Features: +- Supplier implementation +- Item Storage implementation +- On/Off state of demander and supplier +- Storage Access Point +- Crafting recipes + +High Priority: +- Rework demanders to be run from controller and to have priority +- Remote Storage Access Point +- Crafting Supplier +- Ability to name storages +- Machine Upgrades + +Medium Priority +- Wirelss Network Extender +- Ability to add entity display on storages +- Rework all node textures; make new textures 32x32 +- Rework all UI icons to be.. 48x48? 64x64? something else? +- Direct pipeworks compatibility +- Direct tubelib compatibility + +Low Priority: +- Improve node sounds diff --git a/api/controller.lua b/api/controller.lua index 9f0c19d..f5d6a14 100644 --- a/api/controller.lua +++ b/api/controller.lua @@ -1,9 +1,50 @@ +local SET_BUTTON = "logsetbtn" +local NAME_FIELD = "namef" +local FORMSPEC_NAME = "logconren" +local controllerForms = {} + +local function get_controller_formspec(pos) + local name = logistica.get_network_name_or_nil(pos) or "" + return "formspec_version[6]" .. + "size[10.5,2]" .. + logistica.ui.background.. + "field[2.5,0.6;3,0.8;"..NAME_FIELD..";Network Name;"..name.."]" .. + "button[5.6,0.6;3,0.8;"..SET_BUTTON..";Set]" +end + +local function show_controller_formspec(pos, playerName) + local pInfo = {} + pInfo.position = pos + controllerForms[playerName] = pInfo + minetest.show_formspec(playerName, FORMSPEC_NAME, get_controller_formspec(pos)) +end + +local function on_controller_receive_fields(player, formname, fields) + if formname ~= FORMSPEC_NAME then return end + local playerName = player:get_player_name() + minetest.chat_send_all("rec: "..logistica.ttos(fields)) + if fields.quit and not fields.key_enter_field then + controllerForms[playerName] = nil + elseif (fields[SET_BUTTON] or fields.key_enter_field) and fields[NAME_FIELD] then + local pos = controllerForms[playerName].position + local newNetworkName = fields[NAME_FIELD] + logistica.rename_network(minetest.hash_node_position(pos), newNetworkName) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Controller of Network: "..newNetworkName) + meta:set_string("name", newNetworkName) + end + return true +end + +-- registration stuff +minetest.register_on_player_receive_fields(on_controller_receive_fields) --[[ The definition table will get the fololwing fields overriden (and currently originals are not called): - on_construct - after_destruct - on_timer + - on_rightclick The definition must also provide a `logistica_controller` table. This table should contains: { @@ -46,11 +87,15 @@ function logistica.register_controller(simpleName, def, tier) def.after_destruct = after_destruct def.on_timer = on_timer def.drop = controller_name + def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if clicker and clicker:is_player() then + show_controller_formspec(pos, clicker:get_player_name()) + end + end minetest.register_node(controller_name, def) - local def_disabled = {} - for k, v in pairs(def) do def_disabled[k] = v end + 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 @@ -58,6 +103,7 @@ function logistica.register_controller(simpleName, def, tier) def_disabled.on_construct = nil def_disabled.after_desctruct = nil def_disabled.on_timer = nil + def_disabled.on_rightclick = nil minetest.register_node(controller_name.."_disabled", def_disabled) end diff --git a/api/demander.lua b/api/demander.lua index 9121df4..c750677 100644 --- a/api/demander.lua +++ b/api/demander.lua @@ -1,22 +1,33 @@ local NUM_DEMAND_SLOTS = 4 -- maybe at some point make this a param, but why? local PUSH_LIST_PICKER = "push_pick" +local ON_OFF_BUTTON = "on_off_btn" local FORMSPEC_NAME = "logistica_demander" local demanderForms = {} + + local function get_demander_formspec(pos) local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z local pushPos = logistica.get_demander_target(pos) local meta = minetest.get_meta(pos) local selectedList = meta:get_string("demtarlist") + local isOn = logistica.is_machine_on(pos) return "formspec_version[4]" .. "size[10.6,7]" .. logistica.ui.background.. - logistica.get_push_list_dropdown(PUSH_LIST_PICKER, 8.5, 0.7, pushPos, selectedList).. + logistica.ui.push_list_picker(PUSH_LIST_PICKER, 7.5, 0.7, pushPos, selectedList).. + logistica.ui.on_off_btn(isOn, 9.5, 0.5, ON_OFF_BUTTON).. "list["..posForm..";filter;0.5,0.5;"..NUM_DEMAND_SLOTS..",1;0]".. - "list[current_player;main;0.5,2;8,4;0]" - + "list[current_player;main;0.5,2;8,4;0]" +end + +local function show_demander_formspec(playerName, pos) + local pInfo = {} + pInfo.position = pos + demanderForms[playerName] = pInfo + minetest.show_formspec(playerName, FORMSPEC_NAME, get_demander_formspec(pos)) end local function on_player_receive_fields(player, formname, fields) @@ -26,6 +37,13 @@ local function on_player_receive_fields(player, formname, fields) if not demanderForms[playerName] then return false end if fields.quit then demanderForms[playerName] = nil + elseif fields[ON_OFF_BUTTON] then + local pos = demanderForms[playerName].position + if not pos then return false end + if logistica.toggle_machine_on_off(pos) then + logistica.start_demander_timer(pos, 1) + end + show_demander_formspec(player:get_player_name(), pos) elseif fields[PUSH_LIST_PICKER] then local selected = fields[PUSH_LIST_PICKER] if logistica.is_allowed_push_list(selected) then @@ -47,10 +65,7 @@ end local function on_demander_rightclick(pos, node, clicker, itemstack, pointed_thing) if not clicker or not clicker:is_player() then return end - local pInfo = {} - pInfo.position = pos - demanderForms[clicker:get_player_name()] = pInfo - minetest.show_formspec(clicker:get_player_name(), FORMSPEC_NAME, get_demander_formspec(pos)) + show_demander_formspec(clicker:get_player_name(), pos) end local function after_place_demander(pos, placer, itemstack, numDemandSlots) diff --git a/logic/demander.lua b/logic/demander.lua index 8e52ff7..3484f5e 100644 --- a/logic/demander.lua +++ b/logic/demander.lua @@ -127,12 +127,14 @@ end function logistica.start_demander_timer(pos, duration) if duration == nil then duration = TIMER_DURATION_SHORT end logistica.start_node_timer(pos, duration) + logistica.set_logistica_node_infotext(pos, true) end function logistica.on_demander_timer(pos, elapsed) local network = logistica.get_network_or_nil(pos) - if not network then - return false -- this will get restarted once the demander is added to a network + if not network or not logistica.is_machine_on(pos) then + logistica.set_logistica_node_infotext(pos, false) + return false end take_demanded_items_from_network(pos, network) return true diff --git a/logic/inv_list_picker.lua b/logic/inv_list_picker.lua deleted file mode 100644 index 0e982d9..0000000 --- a/logic/inv_list_picker.lua +++ /dev/null @@ -1,49 +0,0 @@ -local ALLOWED_PULL_LISTS = {} -ALLOWED_PULL_LISTS["main"] = true -ALLOWED_PULL_LISTS["src"] = true -ALLOWED_PULL_LISTS["dst"] = true -ALLOWED_PULL_LISTS["output"] = true -ALLOWED_PULL_LISTS["fuel"] = true - -local ALLOWED_PUSH_LISTS = {} -ALLOWED_PUSH_LISTS["main"] = true -ALLOWED_PUSH_LISTS["src"] = true -ALLOWED_PUSH_LISTS["fuel"] = true -ALLOWED_PUSH_LISTS["input"] = true -ALLOWED_PUSH_LISTS["shift"] = true - --- 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) - local defaultIndex = 0 - for i, v in ipairs(itemTable) do if default == v then defaultIndex = i end end - local items = table.concat(itemTable, ",") - return "dropdown["..x..","..y..";2,0.6;"..name..";"..items..";"..defaultIndex..";false]" -end - -function logistica.get_pull_list_dropdown(name, x, y, pullFromPos, default) - return list_dropdown(name, get_lists(pullFromPos, ALLOWED_PULL_LISTS), x, y, default) -end - -function logistica.get_push_list_dropdown(name, x, y, pushToPos, default) - return list_dropdown(name, get_lists(pushToPos, ALLOWED_PUSH_LISTS), x, y, default) -end - -function logistica.is_allowed_pull_list(listName) - return ALLOWED_PULL_LISTS[listName] == true -end - -function logistica.is_allowed_push_list(listName) - return ALLOWED_PUSH_LISTS[listName] == true -end diff --git a/logic/logic.lua b/logic/logic.lua index 892539c..c456337 100644 --- a/logic/logic.lua +++ b/logic/logic.lua @@ -1,6 +1,5 @@ local path = logistica.MODPATH .. "/logic" dofile(path .. "/processing_queue.lua") -dofile(path .. "/inv_list_picker.lua") dofile(path .. "/groups.lua") dofile(path .. "/network_logic.lua") dofile(path .. "/controller.lua") diff --git a/logic/network_logic.lua b/logic/network_logic.lua index d3471e7..e6add3b 100644 --- a/logic/network_logic.lua +++ b/logic/network_logic.lua @@ -4,7 +4,7 @@ local STATUS_OK = 0 local CREATE_NETWORK_STATUS_FAIL_OTHER_NETWORK = -1 local CREATE_NETWORK_STATUS_TOO_MANY_NODES = -2 -logistica.networks = networks +-- logistica.networks = networks local p2h = minetest.hash_node_position local h2p = minetest.get_position_from_hash @@ -44,6 +44,12 @@ function logistica.get_network_name_or_nil(pos) if not network then return nil else return network.name end end +function logistica.rename_network(networkId, newName) + local network = networks[networkId] + if not network then return false end + network.name = newName + return true +end function logistica.get_network_id_or_nil(pos) local network = logistica.get_network_or_nil(pos) @@ -187,13 +193,15 @@ local function recursive_scan_for_nodes_for_controller(network, positionHashes, else return recursive_scan_for_nodes_for_controller(network, connections, numScanned) end end -local function create_network(controllerPosition) +local function create_network(controllerPosition, oldNetworkName) local node = minetest.get_node(controllerPosition) if not node.name:find("_controller") or not node.name:find("logistica:") then return false end local meta = minetest.get_meta(controllerPosition) local controllerHash = p2h(controllerPosition) local network = {} - local networkName = logistica.get_network_name_for(controllerPosition) + local nameFromMeta = meta:get_string("name") + if nameFromMeta == "" then nameFromMeta = nil end + local networkName = oldNetworkName or nameFromMeta or logistica.get_network_name_for(controllerPosition) networks[controllerHash] = network meta:set_string("infotext", "Controller of Network: "..networkName) network.controller = controllerHash @@ -227,14 +235,15 @@ end -- worker functions for cable/machine/controllers ---------------------------------------------------------------- -local function rescan_network(networkName) - local network = networks[networkName] +local function rescan_network(networkId) + local network = networks[networkId] if not network then return false end if not network.controller then return false end local conHash = network.controller local controllerPosition = h2p(conHash) - clear_network(networkName) - create_network(controllerPosition) + local oldNetworkName = network.name + clear_network(networkId) + create_network(controllerPosition, oldNetworkName) end local function find_cable_connections(pos, node) diff --git a/logic/processing_queue.lua b/logic/processing_queue.lua index faba88c..6cde570 100644 --- a/logic/processing_queue.lua +++ b/logic/processing_queue.lua @@ -1,62 +1,20 @@ +local ProQ = {} +ProQ.__index = ProQ -logistica.proq = {} - -local function get_meta(pos) - logistica.load_position(pos) - return minetest.get_meta(pos) +function ProQ.new() + local self = setmetatable({}, ProQ) + self.queue = {} + return self end -local QUEUE_KEY = "log_proq" -local DELIM = "|" - --- listOfPositions must be a list (naturally numbered table) of position vectors -local function save_queue(meta, listOfPositions) - local tableOfStrings = {} - for _,v in ipairs(listOfPositions) do - table.insert(tableOfStrings, vector.to_string(v)) - end - local singleString = table.concat(tableOfStrings, DELIM) - meta:set_string(singleString) +-- the : syntax here causes a "self" arg to be implicitly added before any other args +function ProQ:add_pos(newval) + self.value = newval end --- listOfPositions must be a list (naturally numbered table) of position vectors -function logistica.proq.add(pos, listOfPositions) - local meta = get_meta(pos) - local positions = logistica.proq.get_all(pos) - for _, v in ipairs(listOfPositions) do - table.insert(positions, v) - end - save_queue(meta, positions) +function ProQ:get_value() + return self.value end --- returns a table of up to the next N positions -function logistica.proq.pop_next(pos, count) - local meta = get_meta(pos) - local positions = logistica.proq.get_all(pos) - local ret = {} - local rem = {} - for i, v in ipairs(positions) do - if (i <= count) then - table.insert(ret, v) - else - table.insert(rem, v) - end - end - save_queue(meta, rem) - return ret -end - -function logistica.proq.get_all(pos) - local meta = get_meta(pos) - if not meta:contains(QUEUE_KEY) then return {} end - local compressedString = meta:get_string(QUEUE_KEY) - local positionStrings = string.split(compressedString, DELIM, false) - local positions = {} - for _, v in ipairs(positionStrings) do - local vector = vector.from_string(v) - if vector then - table.insert(positions, vector) - end - end - return positions -end +local instance = ProQ.new() +-- do stuff with instance... \ No newline at end of file diff --git a/textures/logistica_basic_demander_front.png b/textures/logistica_basic_demander_front.png index b94585a..65aa825 100644 Binary files a/textures/logistica_basic_demander_front.png and b/textures/logistica_basic_demander_front.png differ diff --git a/textures/logistica_basic_demander_side.png b/textures/logistica_basic_demander_side.png index 4b168c6..2232faa 100644 Binary files a/textures/logistica_basic_demander_side.png and b/textures/logistica_basic_demander_side.png differ diff --git a/textures/logistica_icon_off.png b/textures/logistica_icon_off.png new file mode 100644 index 0000000..7257033 Binary files /dev/null and b/textures/logistica_icon_off.png differ diff --git a/textures/logistica_icon_on.png b/textures/logistica_icon_on.png new file mode 100644 index 0000000..7507f6e Binary files /dev/null and b/textures/logistica_icon_on.png differ diff --git a/util/common.lua b/util/common.lua index 98fd364..1572341 100644 --- a/util/common.lua +++ b/util/common.lua @@ -1,4 +1,5 @@ +local META_ON_OFF_KEY = "logonoff" local charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" local function rand_str(length, seed) @@ -87,4 +88,28 @@ function logistica.start_node_timer(pos, time) timer:start(time) end return timer -end \ No newline at end of file +end + +function logistica.is_machine_on(pos) + local meta = minetest.get_meta(pos) + return meta:get_int(META_ON_OFF_KEY) > 0 +end + +-- toggles the state and returns the new state (true for on, false for off) +function logistica.toggle_machine_on_off(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) + return newState > 0 +end + +-- isOn is optional +function logistica.set_logistica_node_infotext(pos, isOn) + if isOn == nil then isOn = logistica.is_machine_on(pos) end + logistica.load_position(pos) + local meta = minetest.get_meta(pos) + local node = minetest.get_node(pos) + local text = minetest.registered_nodes[node.name].description.. + "\n"..(isOn and "Running" or "Stopped") + meta:set_string("infotext", text) +end diff --git a/util/ui.lua b/util/ui.lua index 9c763be..8c681ee 100644 --- a/util/ui.lua +++ b/util/ui.lua @@ -1,3 +1,45 @@ logistica.ui = {} -logistica.ui.background = "no_prepend[]bgcolor[#0000]background9[0,0;1,1;logistica_formspec_background.png;true;8]" \ No newline at end of file +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) + local defaultIndex = 0 + for i, v in ipairs(itemTable) do if default == v then defaultIndex = i end end + local items = table.concat(itemTable, ",") + return "dropdown["..x..","..y..";2,0.6;"..name..";"..items..";"..defaultIndex..";false]" +end + +-------------------------------- +-- public functions +-------------------------------- + +function logistica.ui.on_off_btn(isOn, x, y, name, w, h) + if not w or not h then + w = 1; h = 1 + end + local texture = (isOn and "logistica_icon_on.png" or "logistica_icon_off.png") + return "image_button["..x..","..y..";"..w..","..h..";".. + ""..texture..";"..name..";;false;false;"..texture.."]" +end + +function logistica.ui.pull_list_picker(name, x, y, pullFromPos, default) + return list_dropdown(name, get_lists(pullFromPos, logistica.ALLOWED_PULL_LISTS), x, y, default) +end + +function logistica.ui.push_list_picker(name, x, y, pushToPos, default) + return list_dropdown(name, get_lists(pushToPos, logistica.ALLOWED_PUSH_LISTS), x, y, default) +end diff --git a/util/ui_logic.lua b/util/ui_logic.lua new file mode 100644 index 0000000..7cc1d05 --- /dev/null +++ b/util/ui_logic.lua @@ -0,0 +1,23 @@ +logistica.ALLOWED_PULL_LISTS = {} +local allowedPull = logistica.ALLOWED_PULL_LISTS +allowedPull["main"] = true +allowedPull["src"] = true +allowedPull["dst"] = true +allowedPull["output"] = true +allowedPull["fuel"] = true + +logistica.ALLOWED_PUSH_LISTS = {} +local allowedPush = logistica.ALLOWED_PUSH_LISTS +allowedPush["main"] = true +allowedPush["src"] = true +allowedPush["fuel"] = true +allowedPush["input"] = true +allowedPush["shift"] = true + +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 diff --git a/util/util.lua b/util/util.lua index e00756d..2f248c7 100644 --- a/util/util.lua +++ b/util/util.lua @@ -3,4 +3,5 @@ local path = logistica.MODPATH.."/util" dofile(path.."/common.lua") dofile(path.."/rotations.lua") dofile(path.."/hud.lua") +dofile(path.."/ui_logic.lua") dofile(path.."/ui.lua")