315 lines
9.7 KiB
Lua
315 lines
9.7 KiB
Lua
--[[
|
|
|
|
TechAge
|
|
=======
|
|
|
|
Copyright (C) 2019-2022 Joachim Stolberg
|
|
|
|
AGPL v3
|
|
See LICENSE.txt for more information
|
|
|
|
Consumer node basis functionality.
|
|
It handles:
|
|
- up to 4 stages of nodes (TA2/TA3/TA4/TA5)
|
|
- power consumption
|
|
- node state handling
|
|
- registration of passive and active nodes
|
|
- Tube connections are on left and right side (from left to right)
|
|
- Power connection are on front and back side (front or back)
|
|
]]--
|
|
|
|
-- for lazy programmers
|
|
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
|
local P = minetest.string_to_pos
|
|
local M = minetest.get_meta
|
|
|
|
-- Consumer Related Data
|
|
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
|
local CRDN = function(node) return (minetest.registered_nodes[node.name] or {}).consumer end
|
|
|
|
local Tube = techage.Tube
|
|
local power = networks.power
|
|
local liquid = networks.liquid
|
|
local CYCLE_TIME = 2
|
|
|
|
local function get_keys(tbl)
|
|
local keys = {}
|
|
for k,v in pairs(tbl) do
|
|
keys[#keys + 1] = k
|
|
end
|
|
return keys
|
|
end
|
|
|
|
local function has_power(pos, nvm, state)
|
|
local crd = CRD(pos)
|
|
return power.power_available(pos, crd.power_netw)
|
|
end
|
|
|
|
local function start_node(pos, nvm, state)
|
|
end
|
|
|
|
local function stop_node(pos, nvm, state)
|
|
end
|
|
|
|
local function node_timer_pas(pos, elapsed)
|
|
local crd = CRD(pos)
|
|
local nvm = techage.get_nvm(pos)
|
|
|
|
-- handle power consumption
|
|
if crd.power_netw and techage.needs_power(nvm) then
|
|
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
|
if consumed == crd.power_consumption then
|
|
crd.State:start(pos, nvm)
|
|
end
|
|
end
|
|
|
|
-- call the node timer routine
|
|
if techage.is_operational(nvm) then
|
|
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
|
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
|
crd.node_timer(pos, crd.cycle_time)
|
|
nvm.node_timer_call_cyle = 0
|
|
end
|
|
end
|
|
return crd.State:is_active(nvm)
|
|
end
|
|
|
|
local function node_timer_act(pos, elapsed)
|
|
local crd = CRD(pos)
|
|
local nvm = techage.get_nvm(pos)
|
|
|
|
-- handle power consumption
|
|
if crd.power_netw and techage.needs_power(nvm) then
|
|
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
|
if consumed < crd.power_consumption then
|
|
crd.State:nopower(pos, nvm)
|
|
end
|
|
end
|
|
|
|
-- call the node timer routine
|
|
if techage.is_operational(nvm) then
|
|
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
|
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
|
crd.node_timer(pos, crd.cycle_time)
|
|
nvm.node_timer_call_cyle = 0
|
|
end
|
|
end
|
|
return crd.State:is_active(nvm)
|
|
end
|
|
|
|
local function prepare_tiles(tiles, stage, power_png)
|
|
local tbl = {}
|
|
for _,item in ipairs(tiles) do
|
|
if type(item) == "string" then
|
|
tbl[#tbl+1] = item:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
|
else
|
|
local temp = table.copy(item)
|
|
temp.name = temp.name:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
|
tbl[#tbl+1] = temp
|
|
end
|
|
end
|
|
return tbl
|
|
end
|
|
|
|
-- 'validStates' is optional and can be used to e.g. enable
|
|
-- only one TA2 node {false, true, false, false}
|
|
function techage.register_consumer(base_name, inv_name, tiles, tNode, validStates, node_name_prefix, inv_name_prefix)
|
|
local names = {}
|
|
validStates = validStates or {true, true, true, true}
|
|
|
|
node_name_prefix = node_name_prefix or "techage:ta"
|
|
if inv_name_prefix then
|
|
inv_name_prefix = inv_name_prefix.." "
|
|
else
|
|
inv_name_prefix = ""
|
|
end
|
|
|
|
for stage = 2,5 do
|
|
local name_pas = node_name_prefix..stage.."_"..base_name.."_pas"
|
|
local name_act = node_name_prefix..stage.."_"..base_name.."_act"
|
|
local name_inv = inv_name_prefix.."TA"..stage.." "..inv_name
|
|
names[#names+1] = name_pas
|
|
|
|
if validStates[stage] then
|
|
local power_network
|
|
local power_png = 'techage_axle_clutch.png'
|
|
local power_used = tNode.power_consumption ~= nil
|
|
local sides
|
|
-- power needed?
|
|
if power_used then
|
|
if stage > 2 then
|
|
power_network = techage.ElectricCable
|
|
power_png = 'techage_appl_hole_electric.png'
|
|
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
|
else
|
|
power_network = techage.Axle
|
|
power_png = 'techage_axle_clutch.png'
|
|
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
|
end
|
|
end
|
|
|
|
local tState = techage.NodeStates:new({
|
|
node_name_passive = name_pas,
|
|
node_name_active = name_act,
|
|
infotext_name = name_inv,
|
|
cycle_time = CYCLE_TIME,
|
|
standby_ticks = tNode.standby_ticks,
|
|
formspec_func = tNode.formspec,
|
|
on_state_change = tNode.on_state_change,
|
|
can_start = tNode.can_start,
|
|
quick_start = tNode.quick_start,
|
|
has_power = tNode.has_power or power_used and has_power or nil,
|
|
start_node = power_used and start_node or nil,
|
|
stop_node = power_used and stop_node or nil,
|
|
})
|
|
|
|
local tConsumer = {
|
|
stage = stage,
|
|
State = tState,
|
|
-- number of items to be processed per cycle
|
|
num_items = tNode.num_items and tNode.num_items[stage],
|
|
power_consumption = power_used and
|
|
tNode.power_consumption[stage] or 0,
|
|
node_timer = tNode.node_timer,
|
|
cycle_time = tNode.cycle_time,
|
|
call_cycle = tNode.cycle_time / 2,
|
|
power_netw = power_network,
|
|
}
|
|
|
|
local after_place_node = function(pos, placer, itemstack, pointed_thing)
|
|
local crd = CRD(pos)
|
|
local meta = M(pos)
|
|
local nvm = techage.get_nvm(pos)
|
|
local node = minetest.get_node(pos)
|
|
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
|
|
meta:set_int("pull_dir", techage.side_to_indir("R", node.param2))
|
|
meta:set_string("owner", placer:get_player_name())
|
|
-- Delete existing node number. Needed for Digtron compatibility.
|
|
if (meta:contains("node_number")) then
|
|
meta:set_string("node_number", "")
|
|
end
|
|
local number = techage.add_node(pos, name_pas, stage == 2)
|
|
if crd.power_netw then
|
|
crd.power_netw:after_place_node(pos)
|
|
end
|
|
if tNode.after_place_node then
|
|
tNode.after_place_node(pos, placer, itemstack, pointed_thing)
|
|
end
|
|
crd.State:node_init(pos, nvm, number)
|
|
end
|
|
|
|
local after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
if tNode.after_dig_node then
|
|
tNode.after_dig_node(pos, oldnode, oldmetadata, digger)
|
|
end
|
|
local crd = CRDN(oldnode)
|
|
if crd.power_netw then
|
|
crd.power_netw:after_dig_node(pos)
|
|
end
|
|
techage.remove_node(pos, oldnode, oldmetadata)
|
|
techage.del_mem(pos)
|
|
end
|
|
|
|
tNode.groups.not_in_creative_inventory = 0
|
|
|
|
local def_pas = {
|
|
description = name_inv,
|
|
tiles = prepare_tiles(tiles.pas, stage, power_png),
|
|
consumer = tConsumer,
|
|
drawtype = tNode.drawtype,
|
|
node_box = tNode.node_box,
|
|
selection_box = tNode.selection_box,
|
|
|
|
can_dig = tNode.can_dig,
|
|
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
|
on_timer = node_timer_pas,
|
|
on_receive_fields = tNode.on_receive_fields,
|
|
on_rightclick = tNode.on_rightclick,
|
|
after_place_node = after_place_node,
|
|
after_dig_node = after_dig_node,
|
|
preserve_metadata = tNode.preserve_metadata,
|
|
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
|
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
|
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
|
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
|
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
|
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
|
ta_rotate_node = tNode.ta_rotate_node,
|
|
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
|
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
|
|
|
paramtype = tNode.paramtype,
|
|
paramtype2 = "facedir",
|
|
drop = tNode.drop,
|
|
groups = table.copy(tNode.groups),
|
|
is_ground_content = false,
|
|
sounds = tNode.sounds,
|
|
}
|
|
|
|
-- Copy custom properties (starting with an underscore)
|
|
for k,v in pairs(tNode) do
|
|
if string.sub(k, 1, 1) == "_" then
|
|
def_pas[k] = v
|
|
end
|
|
end
|
|
|
|
minetest.register_node(name_pas, def_pas)
|
|
|
|
tNode.groups.not_in_creative_inventory = 1
|
|
|
|
local def_act = {
|
|
description = name_inv,
|
|
tiles = prepare_tiles(tiles.act, stage, power_png),
|
|
consumer = tConsumer,
|
|
drawtype = tNode.drawtype,
|
|
node_box = tNode.node_box,
|
|
selection_box = tNode.selection_box,
|
|
|
|
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
|
on_timer = node_timer_act,
|
|
on_receive_fields = tNode.on_receive_fields,
|
|
on_rightclick = tNode.on_rightclick,
|
|
after_place_node = after_place_node,
|
|
after_dig_node = after_dig_node,
|
|
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
|
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
|
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
|
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
|
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
|
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
|
ta_rotate_node = tNode.ta_rotate_node,
|
|
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
|
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
|
|
|
paramtype = tNode.paramtype,
|
|
paramtype2 = "facedir",
|
|
drop = "",
|
|
diggable = false,
|
|
groups = table.copy(tNode.groups),
|
|
is_ground_content = false,
|
|
sounds = tNode.sounds,
|
|
}
|
|
|
|
-- Copy custom properties (starting with an underscore)
|
|
for k,v in pairs(tNode) do
|
|
if string.sub(k, 1, 1) == "_" then
|
|
def_act[k] = v
|
|
end
|
|
end
|
|
|
|
minetest.register_node(name_act, def_act)
|
|
|
|
if power_used then
|
|
power.register_nodes({name_pas, name_act}, power_network, "con", sides)
|
|
end
|
|
techage.register_node({name_pas, name_act}, tNode.tubing)
|
|
|
|
if tNode.tube_sides then
|
|
Tube:set_valid_sides(name_pas, get_keys(tNode.tube_sides))
|
|
Tube:set_valid_sides(name_act, get_keys(tNode.tube_sides))
|
|
end
|
|
end
|
|
end
|
|
return names[1], names[2], names[3], names[4]
|
|
end
|