node states changed, bugs fixed, command interface to several nodes added

This commit is contained in:
Joachim Stolberg 2019-06-28 23:46:44 +02:00
parent 8df777c43d
commit ac0e8f3978
18 changed files with 250 additions and 87 deletions

View File

@ -26,8 +26,8 @@ local CRD = function(pos) return (minetest.registered_nodes[minetest.get_node(po
local MP = minetest.get_modpath("techage")
local I,_ = dofile(MP.."/intllib.lua")
local STANDBY_TICKS = 10
local COUNTDOWN_TICKS = 10
local STANDBY_TICKS = 6
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 4
local function formspec(self, pos, mem)
@ -72,24 +72,32 @@ local function get_craft(pos, inventory, hash)
local recipe = inventory:get_list("recipe")
local output, decremented_input = minetest.get_craft_result(
{method = "normal", width = 3, items = recipe})
craft = {recipe = recipe, consumption=count_index(recipe),
craft = {recipe = recipe, consumption = count_index(recipe),
output = output, decremented_input = decremented_input}
autocrafterCache[hash] = craft
end
return craft
end
local function autocraft(pos, crd, mem, inventory, craft)
if not craft then return false end
local function autocraft(pos, crd, mem, inv)
local craft = get_craft(pos, inv)
if not craft then
crd.State:idle(pos, mem)
return
end
local output_item = craft.output.item
if output_item:get_name() == "" then
crd.State:idle(pos, mem)
return
end
-- check if we have enough room in dst
if not inventory:room_for_item("dst", output_item) then
if not inv:room_for_item("dst", output_item) then
crd.State:blocked(pos, mem)
return
end
local consumption = craft.consumption
local inv_index = count_index(inventory:get_list("src"))
local inv_index = count_index(inv:get_list("src"))
-- check if we have enough material available
for itemname, number in pairs(consumption) do
if (not inv_index[itemname]) or inv_index[itemname] < number then
@ -100,14 +108,14 @@ local function autocraft(pos, crd, mem, inventory, craft)
-- consume material
for itemname, number in pairs(consumption) do
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
inventory:remove_item("src", ItemStack(itemname))
inv:remove_item("src", ItemStack(itemname))
end
end
-- craft the result into the dst inventory and add any "replacements" as well
inventory:add_item("dst", output_item)
inv:add_item("dst", output_item)
for i = 1, 9 do
inventory:add_item("dst", craft.decremented_input.items[i])
inv:add_item("dst", craft.decremented_input.items[i])
end
crd.State:keep_running(pos, mem, COUNTDOWN_TICKS)
@ -118,10 +126,7 @@ local function keep_running(pos, elapsed)
local mem = tubelib2.get_mem(pos)
local crd = CRD(pos)
local inv = M(pos):get_inventory()
local craft = get_craft(pos, inv)
local output_item = craft.output.item
autocraft(pos, crd, mem, inv, craft)
return crd.State:is_active(mem)
autocraft(pos, crd, mem, inv)
end
-- note, that this function assumes allready being updated to virtual items
@ -353,12 +358,7 @@ local tubing = {
end
end,
on_recv_message = function(pos, topic, payload)
local resp = CRD(pos).State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "unsupported"
end
return CRD(pos).State:on_receive_message(pos, topic, payload)
end,
on_node_load = function(pos)
CRD(pos).State:on_node_load(pos)
@ -408,3 +408,4 @@ minetest.register_craft({
{"", "techage:vacuum_tube", ""},
},
})

View File

@ -250,7 +250,8 @@ techage.register_node({"techage:chest_ta2", "techage:chest_ta3", "techage:chest_
on_recv_message = function(pos, topic, payload)
if topic == "state" then
local meta = minetest.get_meta(pos)
return techage.get_inv_state(meta, "main")
local inv = meta:get_inventory()
return techage.get_inv_state(inv, "main")
elseif topic == "player_action" then
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")

View File

@ -113,7 +113,6 @@ local function keep_running(pos, elapsed)
local crd = CRD(pos)
local inv = M(pos):get_inventory()
grinding(pos, crd, mem, inv)
return crd.State:is_active(mem)
end
local function on_receive_fields(pos, formname, fields, player)
@ -188,12 +187,7 @@ local tubing = {
end
end,
on_recv_message = function(pos, topic, payload)
local resp = CRD(pos).State:on_receive_message(pos, topic, payload)
if resp then
return resp
else
return "unsupported"
end
return CRD(pos).State:on_receive_message(pos, topic, payload)
end,
on_node_load = function(pos)
CRD(pos).State:on_node_load(pos)

View File

@ -0,0 +1,22 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
TA2 help pages for basic machines
]]--
-- Load support for intllib.
local MP = minetest.get_modpath("techage")
local I,_ = dofile(MP.."/intllib.lua")
techage.register_help_page(I("TA2 Autocrafter"),
I([[Supports automated crafting of items.
Crafts 1 item in 2 seconds.
Needs axle power: 4]]), "techage:ta2_autocrafter_pas")

View File

@ -0,0 +1,22 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
TA3 help pages for basic machines
]]--
-- Load support for intllib.
local MP = minetest.get_modpath("techage")
local I,_ = dofile(MP.."/intllib.lua")
techage.register_help_page(I("TA3 Autocrafter"),
I([[Supports automated crafting of items.
Crafts 2 items in 2 seconds.
Needs electrical power: 6]]), "techage:ta3_autocrafter_pas")

View File

@ -28,12 +28,6 @@ local CRDN = function(node) return (minetest.registered_nodes[node.name] or {}).
local CYCLE_TIME = 2 -- required from power
local ValidPowerConsumingStates = {
[techage.RUNNING] = true,
[techage.BLOCKED] = true,
[techage.NOPOWER] = true,
}
local consume_power = techage.power.consume_power
local power_available = techage.power.power_available
@ -50,32 +44,32 @@ local function stop_node(pos, mem, state)
end
local function node_timer(pos, elapsed)
--print("node_timer")
local crd = CRD(pos)
local mem = tubelib2.get_mem(pos)
local state = crd.State:get_state(mem)
if ValidPowerConsumingStates[state] then
local state = mem.techage_state
if techage.needs_power(mem) then
local got = consume_power(pos, crd.power_consumption)
if state == techage.NOPOWER and got == crd.power_consumption then
crd.State:start(pos, mem)
elseif state ~= techage.NOPOWER and got < crd.power_consumption then
if got < crd.power_consumption then
crd.State:nopower(pos, mem)
end
elseif state == techage.STANDBY then
if crd.power_consumption > 0 and not power_available(pos) then
crd.State:nopower(pos, mem)
end
elseif state == techage.NOPOWER and power_available(pos) then
crd.State:start(pos, mem)
end
-- call the secondary timer routine with the requested frequency
local res
mem.conn_next_call = mem.conn_next_call or 0
mem.conn_cycle_timer = (mem.conn_cycle_timer or 0) + CYCLE_TIME
--print(mem.conn_next_call, mem.conn_cycle_timer)
if mem.conn_cycle_timer >= mem.conn_next_call then
crd.node_timer(pos, crd.cycle_time)
mem.conn_next_call = mem.conn_next_call + crd.cycle_time
if techage.is_operational(mem) then
mem.conn_next_call = mem.conn_next_call or 0
mem.conn_cycle_timer = (mem.conn_cycle_timer or 0) + CYCLE_TIME
--print(mem.conn_next_call, mem.conn_cycle_timer)
if mem.conn_cycle_timer >= mem.conn_next_call then
crd.node_timer(pos, crd.cycle_time)
mem.conn_next_call = mem.conn_next_call + crd.cycle_time
end
end
return ValidPowerConsumingStates[state] or state == techage.STANDBY
return crd.State:is_active(mem)
end
local function prepare_tiles(tiles, stage, power_png)

View File

@ -74,6 +74,13 @@ function techage.index(list, x)
return nil
end
function techage.in_list(list, x)
for idx, v in pairs(list) do
if v == x then return true end
end
return false
end
function techage.add_to_set(set, x)
if not techage.index(set, x) then
table.insert(set, x)

View File

@ -36,11 +36,21 @@ Node states:
| | | | | | |
| | V | V V |
| +---------+ +----------+ +---------+ |
| | | | NOPOWER/ | | | |
| | | | | | | |
+---| NOPOWER | | STANDBY/ | | FAULT |----------+
| | | BLOCKED | | |
+---------+ +----------+ +---------+
| cycle time operational needs power
+---------+------------+-------------+-------------
| RUNNING normal yes yes
| BLOCKED long yes yes
| STANDBY long yes no
| NOPOWER long no no
| FAULT none no no
| STOPPED none no no
Node mem data:
"techage_state" - node state, like "RUNNING"
"techage_item_meter" - node item/runtime counter
@ -56,21 +66,20 @@ local M = minetest.get_meta
-- TechAge machine states
--
techage.STOPPED = 1 -- not operational/turned off
techage.RUNNING = 2 -- in normal operation/turned on
techage.STANDBY = 3 -- nothing to do (e.g. no input items), or blocked anyhow (output jammed),
-- or node (world) not loaded
techage.NOPOWER = 4 -- only for power consuming nodes
techage.RUNNING = 1 -- in normal operation/turned on
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory
techage.STANDBY = 3 -- nothing to do (e.g. no input items), or node (world) not loaded
techage.NOPOWER = 4 -- only for power consuming nodes, no operation
techage.FAULT = 5 -- any fault state (e.g. wrong source items), which can be fixed by the player
techage.BLOCKED = 6 -- a pushing node is blocked due to a full destination inventory
techage.STOPPED = 6 -- not operational/turned off
techage.StatesImg = {
"techage_inv_button_off.png",
"techage_inv_button_on.png",
"techage_inv_button_warning.png",
"techage_inv_button_standby.png",
"techage_inv_button_nopower.png",
"techage_inv_button_error.png",
"techage_inv_button_warning.png",
"techage_inv_button_off.png",
}
-- Return state button image for the node inventory
@ -91,17 +100,17 @@ function techage.get_power_image(pos, mem)
end
-- State string based on button states
techage.StateStrings = {"stopped", "running", "standby", "nopower", "fault", "blocked"}
techage.StateStrings = {"running", "blocked", "standby", "nopower", "fault", "stopped"}
--
-- Local States
--
local STOPPED = techage.STOPPED
local RUNNING = techage.RUNNING
local BLOCKED = techage.BLOCKED
local STANDBY = techage.STANDBY
local NOPOWER = techage.NOPOWER
local FAULT = techage.FAULT
local BLOCKED = techage.BLOCKED
local STOPPED = techage.STOPPED
--
@ -123,6 +132,17 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node)
end
-- true if node_timer should be executed
function techage.is_operational(mem)
local state = mem.techage_state or STOPPED
return state < NOPOWER
end
function techage.needs_power(mem)
local state = mem.techage_state or STOPPED
return state < STANDBY
end
function NodeStates:new(attr)
local o = {
-- mandatory
@ -182,7 +202,7 @@ end
function NodeStates:start(pos, mem, called_from_on_timer)
local state = mem.techage_state or STOPPED
if state == STOPPED or state == STANDBY or state == BLOCKED or state == NOPOWER then
if state ~= RUNNING and state ~= FAULT then
if not self.can_start(pos, mem, state) then
self:fault(pos, mem)
return false
@ -279,6 +299,8 @@ function NodeStates:nopower(pos, mem)
local state = mem.techage_state or RUNNING
if state ~= STOPPED then
mem.techage_state = NOPOWER
-- timer has to be stopped once to be able to be restarted
self.stop_timer = true
if self.node_name_passive then
swap_node(pos, self.node_name_passive)
end
@ -292,7 +314,7 @@ function NodeStates:nopower(pos, mem)
if self.on_state_change then
self.on_state_change(pos, state, NOPOWER)
end
minetest.get_node_timer(pos):stop()
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
return true
end
return false
@ -329,13 +351,14 @@ function NodeStates:get_state_string(mem)
return techage.StateStrings[mem.techage_state or STOPPED]
end
-- keep the timer running?
function NodeStates:is_active(mem)
local state = mem.techage_state or STOPPED
if self.stop_timer == true then
self.stop_timer = false
return false
end
return state == RUNNING or state == STANDBY or state == BLOCKED
return state < FAULT
end
function NodeStates:start_if_standby(pos)
@ -404,6 +427,15 @@ function NodeStates:on_receive_message(pos, topic, payload)
elseif topic == "clear_counter" then
mem.techage_item_meter = 0
return true
elseif topic == "fuel" then
local inv = M(pos):get_inventory()
if inv:get_size("fuel") == 1 then
local stack = inv:get_stack("fuel", 1)
return stack:get_count()
end
return
else
return "unsupported"
end
end
@ -415,7 +447,9 @@ function NodeStates:on_node_load(pos, not_start_timer)
local number = M(pos):get_string("node_number")
if number == "" then
minetest.log("warning", "[TA] Node at "..S(pos).." has no node_number")
swap_node(pos, "techage:defect_dummy")
local name = minetest.get_node(pos).name
local number = techage.add_node(pos, name)
self:node_init(pos, mem, number)
return
end

View File

@ -104,6 +104,7 @@ minetest.register_node("techage:coalfirebox", {
on_construct = function(pos)
local mem = tubelib2.init_mem(pos)
techage.add_node(pos, "techage:coalfirebox")
mem.running = false
mem.burn_cycles = 0
mem.power_level = 4
@ -208,9 +209,17 @@ techage.register_node({"techage:coalfirebox"}, {
return techage.put_items(inv, "fuel", stack)
end,
on_recv_message = function(pos, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "state" then
local meta = minetest.get_meta(pos)
return techage.get_inv_state(meta, "fuel")
if mem.running then
return "running"
else
return "stopped"
end
elseif topic == "fuel" then
local inv = M(pos):get_inventory()
local stack = inv:get_stack("fuel", 1)
return stack:get_count()
else
return "unsupported"
end

View File

@ -65,6 +65,7 @@ local State = techage.NodeStates:new({
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = "TA3 Generator",
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
@ -124,7 +125,8 @@ minetest.register_node("techage:generator", {
after_place_node = function(pos, placer)
local mem = tubelib2.get_mem(pos)
State:node_init(pos, mem, "")
local number = techage.add_node(pos, "techage:generator")
State:node_init(pos, mem, number)
on_rightclick(pos)
end,
@ -213,7 +215,18 @@ techage.register_node({"techage:generator", "techage:generator_on"}, {
return 0
end
end
end
end,
on_recv_message = function(pos, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "load" then
return techage.power.percent(PWR_CAPA, mem.provided)
else
return State:on_receive_message(pos, topic, payload)
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
})
techage.register_help_page(I("TA3 Generator"),

View File

@ -29,6 +29,16 @@ local KeyList = {} -- index to Recipes key translation
techage.furnace = {}
local function all_ingredients_available(output, ingr)
for _,item in ipairs(Recipes[output].input) do
if not techage.in_list(ingr, item) then
return false
end
end
return true
end
-- Return a list with all outputs of the given list of ingredients
local function get_recipes(ingr)
if #ingr > 0 then
@ -36,7 +46,9 @@ local function get_recipes(ingr)
for _,item in ipairs(ingr) do
if Ingredients[item] then
for _,output in ipairs(Ingredients[item]) do
tbl[#tbl+1] = output
if all_ingredients_available(output, ingr) then
techage.add_to_set(tbl, output)
end
end
end
end

View File

@ -176,9 +176,17 @@ techage.register_node({"techage:furnace_firebox", "techage:furnace_firebox_on"},
return techage.put_items(inv, "fuel", stack)
end,
on_recv_message = function(pos, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "state" then
local meta = minetest.get_meta(pos)
return techage.get_inv_state(meta, "fuel")
if mem.running then
return "running"
else
return "stopped"
end
elseif topic == "fuel" then
local inv = M(pos):get_inventory()
local stack = inv:get_stack("fuel", 1)
return stack:get_count()
else
return "unsupported"
end

View File

@ -38,7 +38,7 @@ local range = techage.range
local function formspec(self, pos, mem)
local ingr = get_ingredients(pos)
local num = num_recipes(ingr)
mem.recipe_idx = range(mem.recipe_idx or 1, 1, num)
mem.recipe_idx = range(mem.recipe_idx or 1, 0, num)
local idx = mem.recipe_idx
local output = get_output(mem, ingr, idx)
return "size[8,7.2]"..

View File

@ -76,6 +76,8 @@ else
dofile(MP.."/steam_engine/flywheel.lua")
dofile(MP.."/steam_engine/gearbox.lua")
dofile(MP.."/basic_machines/ta2_help.lua")
-- Basic Machines
dofile(MP.."/basis/consumer.lua") -- consumer base model
dofile(MP.."/basic_machines/source.lua")
@ -90,7 +92,6 @@ else
dofile(MP.."/basic_machines/autocrafter.lua")
dofile(MP.."/basic_machines/forceload.lua")
dofile(MP.."/basic_machines/electronic_fab.lua")
dofile(MP.."/basic_machines/generator.lua")
-- Coal power station
dofile(MP.."/coal_power_station/help.lua")
@ -101,6 +102,8 @@ else
dofile(MP.."/coal_power_station/turbine.lua")
dofile(MP.."/coal_power_station/cooler.lua")
dofile(MP.."/coal_power_station/akkubox.lua")
dofile(MP.."/basic_machines/ta3_help.lua")
-- Industrial Furnace
dofile(MP.."/furnace/help.lua")
@ -125,6 +128,7 @@ else
dofile(MP.."/oil/tower.lua")
dofile(MP.."/oil/drillbox.lua")
dofile(MP.."/oil/pumpjack.lua")
dofile(MP.."/oil/generator.lua")
-- Nodes2
if techage.basalt_stone_enabled then

View File

@ -76,6 +76,7 @@ local State = techage.NodeStates:new({
cycle_time = CYCLE_TIME,
standby_ticks = 0,
formspec_func = formspec,
infotext_name = "TA3 Tiny Power Generator",
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
@ -108,6 +109,7 @@ local function node_timer(pos, elapsed)
pos = pos,
gain = 1,
max_hear_distance = 10})
State:keep_running(pos, mem, CYCLE_TIME)
return true
else
mem.provided = 0
@ -143,7 +145,7 @@ local function on_rightclick(pos)
end
minetest.register_node("techage:tiny_generator", {
description = "Tiny Power Generator",
description = "TA3 Tiny Power Generator",
tiles = {
-- up, down, right, left, back, front
"techage_appl_electric_gen_top.png^techage_frame_ta3_top.png",
@ -160,8 +162,10 @@ minetest.register_node("techage:tiny_generator", {
on_construct = function(pos)
local mem = tubelib2.init_mem(pos)
local number = techage.add_node(pos, "techage:tiny_generator")
mem.generating = false
mem.burn_cycles = 0
State:node_init(pos, mem, number)
local meta = M(pos)
meta:set_string("formspec", formspec(State, pos, mem))
local inv = meta:get_inventory()
@ -177,7 +181,7 @@ minetest.register_node("techage:tiny_generator", {
})
minetest.register_node("techage:tiny_generator_on", {
description = "Tiny Power Generator",
description = "TA3 Tiny Power Generator",
tiles = {
-- up, down, right, left, back, front
"techage_appl_electric_gen_top.png^techage_frame_ta3_top.png",
@ -226,6 +230,20 @@ techage.power.register_node({"techage:tiny_generator", "techage:tiny_generator_o
power_network = Power,
})
techage.register_node({"techage:tiny_generator", "techage:tiny_generator_on"}, {
on_recv_message = function(pos, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "load" then
return techage.power.percent(PWR_CAPA, mem.provided)
else
return State:on_receive_message(pos, topic, payload)
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
})
minetest.register_craft({
output = "techage:tiny_generator",
recipe = {
@ -234,3 +252,9 @@ minetest.register_craft({
{'default:steel_ingot', 'techage:vacuum_tube', 'default:steel_ingot'},
},
})
techage.register_help_page(I("TA3 Tiny Power Generator"),
I([[Small electrical power generator. Need oil as fuel.
Provides power: 12
Oil burn time: 100s]]), "techage:tiny_generator")

View File

@ -29,4 +29,3 @@ But oil is difficult and expensive to recover:
techage.register_chap_page(S("TA3 Oil Age"), HelpText, "techage:oil_source")

View File

@ -66,10 +66,12 @@ end
local function start_node(pos, mem, state)
mem.running = true
mem.power_ratio = 0
end
local function stop_node(pos, mem, state)
mem.running = false
mem.power_ratio = 0
end
local State = techage.NodeStates:new({

View File

@ -40,14 +40,29 @@ local M = minetest.get_meta
local function read_state(itemstack, user, pointed_thing)
local pos = pointed_thing.under
if pos then
if pos and user then
local number = techage.get_node_number(pos)
if number then
local state = techage.send_single(number, "state", nil)
local counter = techage.send_single(number, "counter", nil)
if state and counter then
if type(counter) ~= "number" then counter = "unknown" end
minetest.chat_send_player(user:get_player_name(), "[TechAge] state ="..state..", counter = "..counter)
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
if ndef and ndef.description then
local state = techage.send_single(number, "state", nil)
if state and state ~= "" and state ~= "unsupported" then
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": state = "..state.." ")
end
local fuel = techage.send_single(number, "fuel", nil)
if fuel and fuel ~= "" and fuel ~= "unsupported" then
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": fuel = "..fuel.." ")
end
local counter = techage.send_single(number, "counter", nil)
if counter and counter ~= "" and counter ~= "unsupported" then
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": counter = "..counter.." ")
end
local load = techage.send_single(number, "load", nil)
if load and load ~= "" and load ~= "unsupported" then
minetest.chat_send_player(user:get_player_name(), ndef.description.." "..number..": load = "..load.." % ")
end
itemstack:add_wear(65636/200)
return itemstack
end
end
end
@ -60,17 +75,19 @@ minetest.register_tool("techage:repairkit", {
groups = {cracky=1, book=1},
on_use = read_state,
node_placement_prediction = "",
stack_max = 1,
})
minetest.register_node("techage:end_wrench", {
description = "TechAge End Wrench (use = read status, place = destroy)",
minetest.register_tool("techage:end_wrench", {
description = "TechAge End Wrench (use = read status, place = cmd: on/off)",
inventory_image = "techage_end_wrench.png",
wield_image = "techage_end_wrench.png",
groups = {cracky=1, book=1},
on_use = read_state,
on_place = read_state,
node_placement_prediction = "",
stack_max = 1,
})
minetest.register_craft({
@ -83,10 +100,10 @@ minetest.register_craft({
})
minetest.register_craft({
output = "techage:end_wrench 4",
output = "techage:end_wrench",
recipe = {
{"", "", "default:steel_ingot"},
{"", "default:tin_ingot", ""},
{"", "techage:iron_ingot", ""},
{"default:steel_ingot", "", ""},
},
})