logistica-cd2025/api/requester.lua

220 lines
8.7 KiB
Lua

local S = logistica.TRANSLATOR
local NUM_REQUEST_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 INF_CHECKBOX_PREFIX = "infchk"
local FORMSPEC_NAME = "logistica_requester"
local requesterForms = {}
local function get_checkbox_name_from_index(index)
return INF_CHECKBOX_PREFIX..tostring(index)
end
local function get_filter_list_inf_checkboxes(checkboxStates, x, y)
local checkboxes = {}
for i = 1, NUM_REQUEST_SLOTS do
local checkboxName = get_checkbox_name_from_index(i)
local ticked = "false" ; if checkboxStates[i] then ticked = "true" end
checkboxes[i] =
"checkbox["..(x + 0.1 + (i - 1) * 1.25)..","..y..";"..checkboxName..";Inf;"..ticked.."]"..
"tooltip["..checkboxName..";"..S("Tick this to always try to insert the item above into the target inventory,\nregardless of how many of that item the target inventory contains.\nThe number of items put above is then requested every second.").."]"
end
return table.concat(checkboxes)
end
local function get_requester_formspec(pos)
local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z
local pushPos = logistica.get_requester_target(pos)
local selectedList = logistica.get_requester_target_list(pos)
local isOn = logistica.is_machine_on(pos)
local checkboxStates = logistica.get_requester_inf_state(pos)
return "formspec_version[4]" ..
"size["..logistica.inv_size(10.6, 8.45).."]" ..
logistica.ui.background..
logistica.ui.push_list_picker(PUSH_LIST_PICKER, 6.7, 1.5, pushPos, selectedList, S("Put items in:"))..
logistica.ui.on_off_btn(isOn, 9.3, 1.3, ON_OFF_BUTTON, S("Enable"))..
"label[0.5,0.4;"..S("Configure items and count to put, and keep a minimium of, in target's inventory").."]"..
"label[0.5,0.7;"..S("Or tick the \"Inf\" (infinite) checkbox below a slot to always keep inserting the item.").."]"..
"list["..posForm..";filter;0.5,1.2;"..NUM_REQUEST_SLOTS..",1;0]"..
get_filter_list_inf_checkboxes(checkboxStates, 0.5, 2.5)..
logistica.player_inv_formspec(0.5, 3.0)..
"listring[current_player;main]"..
"listring["..posForm..";filter]"
end
local function show_requester_formspec(playerName, pos)
requesterForms[playerName] = {position = pos}
minetest.show_formspec(playerName, FORMSPEC_NAME, get_requester_formspec(pos))
end
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 requesterForms[playerName] then return false end
local pos = requesterForms[playerName].position
if minetest.is_protected(pos, playerName) then return true end
local reshow = false
-- infinite checkboxes check
for i = 1, NUM_REQUEST_SLOTS do
local checkboxName = get_checkbox_name_from_index(i)
if fields[checkboxName] ~= nil then
logistica.requester_on_infinite_request_toggle(pos, i, fields[checkboxName] == "true")
reshow = true
end
end
if fields.quit then
requesterForms[playerName] = nil
elseif fields[ON_OFF_BUTTON] then
if not pos then return false end
logistica.toggle_machine_on_off(pos)
show_requester_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
local pos = requesterForms[playerName].position
if not pos then return false end
logistica.set_requester_target_list(pos, selected)
end
end
if reshow then show_requester_formspec(player:get_player_name(), pos) end
return true
end
local function on_requester_punch(pos, node, puncher, pointed_thing)
local targetPos = logistica.get_requester_target(pos)
if targetPos and puncher:is_player() and puncher:get_player_control().sneak then
logistica.show_output_at(targetPos)
end
end
local function on_requester_rightclick(pos, node, clicker, itemstack, pointed_thing)
if not clicker or not clicker:is_player() then return end
if minetest.is_protected(pos, clicker:get_player_name()) then return end
show_requester_formspec(clicker:get_player_name(), pos)
end
local function after_place_requester(pos, placer, itemstack, numRequestSlots)
local meta = minetest.get_meta(pos)
if placer and placer:is_player() then
meta:set_string("owner", placer:get_player_name())
end
logistica.set_requester_target_list(pos, "main")
local inv = meta:get_inventory()
inv:set_size("filter", numRequestSlots)
inv:set_size("actual", numRequestSlots)
logistica.on_requester_change(pos)
logistica.show_output_at(logistica.get_requester_target(pos))
logistica.set_node_tooltip_from_state(pos, nil, false)
end
local function allow_requester_storage_inv_put(pos, listname, index, stack, player)
if listname ~= "filter" then return 0 end
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
local inv = minetest.get_meta(pos):get_inventory()
local slotStack = inv:get_stack(listname, index)
slotStack:add_item(stack)
inv:set_stack(listname, index, slotStack)
logistica.update_cache_at_pos(pos, LOG_CACHE_REQUESTER)
logistica.start_requester_timer(pos, 1)
return 0
end
local function allow_requester_inv_take(pos, listname, index, stack, player)
if listname ~= "filter" then return 0 end
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
local inv = minetest.get_meta(pos):get_inventory()
local slotStack = inv:get_stack(listname, index)
slotStack:take_item(stack:get_count())
inv:set_stack(listname, index, slotStack)
logistica.update_cache_at_pos(pos, LOG_CACHE_REQUESTER)
return 0
end
local function allow_requester_inv_move(_, _, _, _, _, _, _)
return 0
end
----------------------------------------------------------------
-- Minetest registration
----------------------------------------------------------------
minetest.register_on_player_receive_fields(on_player_receive_fields)
minetest.register_on_leaveplayer(function(objRef, timed_out)
if objRef:is_player() then
requesterForms[objRef:get_player_name()] = nil
end
end)
----------------------------------------------------------------
-- Public Registration API
----------------------------------------------------------------
-- `simpleName` is used for the description and for the name (can contain spaces)
-- transferRate is how many items per tick this requester can transfer, -1 for unlimited
function logistica.register_requester(description, name, transferRate, tiles)
local lname = string.lower(name:gsub(" ", "_"))
local requester_name = "logistica:"..lname
logistica.GROUPS.requesters.register(requester_name)
local grps = {oddly_breakable_by_hand = 3, cracky = 3, handy = 1, pickaxey = 1, }
grps[logistica.TIER_ALL] = 1
local def = {
description = description,
drawtype = "normal",
tiles = tiles,
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
groups = grps,
drop = requester_name,
sounds = logistica.node_sound_metallic(),
on_timer = logistica.on_timer_powered(logistica.on_requester_timer),
after_place_node = function (pos, placer, itemstack)
after_place_requester(pos, placer, itemstack, NUM_REQUEST_SLOTS)
end,
after_dig_node = logistica.on_requester_change,
on_punch = on_requester_punch,
on_rightclick = on_requester_rightclick,
allow_metadata_inventory_put = allow_requester_storage_inv_put,
allow_metadata_inventory_take = allow_requester_inv_take,
allow_metadata_inventory_move = allow_requester_inv_move,
logistica = {
requester_transfer_rate = transferRate,
on_connect_to_network = function(pos, networkId)
logistica.start_requester_timer(pos)
end,
on_power = function(pos, isPoweredOn)
logistica.set_node_tooltip_from_state(pos, nil, isPoweredOn)
if isPoweredOn then
logistica.start_requester_timer(pos)
end
end,
},
_mcl_hardness = 1.5,
_mcl_blast_resistance = 10
}
minetest.register_node(requester_name, def)
logistica.register_non_pushable(requester_name)
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, handy = 1, pickaxey = 1, axey = 1, not_in_creative_inventory = 1 }
def_disabled.on_construct = nil
def_disabled.after_dig_node = nil
def_disabled.on_punch = nil
def_disabled.on_rightclick = nil
def_disabled.on_timer = nil
def_disabled.logistica = nil
minetest.register_node(requester_name.."_disabled", def_disabled)
end