built on 11/07/2022 20:24:44

This commit is contained in:
Joachim Stolberg 2022-07-11 20:24:44 +02:00
parent a9cc1d4579
commit 10dabd04ff
156 changed files with 3229 additions and 748 deletions

View File

@ -3,7 +3,7 @@
This modpack covers all necessary and useful mods to be able to use techage. This modpack covers all necessary and useful mods to be able to use techage.
All mods have the own README.txt. For further information please consult these files. All mods have the own README.txt. For further information please consult these files.
This modpack includes: This modpack contains:
- techage: The main mod - techage: The main mod
- ta4_jetpack: A Jetpack for techage with hydrogen as fuel and TA4 recipe - ta4_jetpack: A Jetpack for techage with hydrogen as fuel and TA4 recipe
- ta4_paraglider: A Paraglider for techage with TA4 recipe - ta4_paraglider: A Paraglider for techage with TA4 recipe
@ -47,6 +47,12 @@ ta4_jetpack requires the modpack 3d_armor. 3d_armor is itself a modpack and can'
### History ### History
#### 2022-07-11
Updated Mods:
- techage (fusion reactor added)
#### 2022-01-28 #### 2022-01-28
Updated Mods: Updated Mods:

View File

@ -109,7 +109,7 @@ minetest.register_node("hyperloop:tube_crowbar", {
description = S("Hyperloop Tube Crowbar"), description = S("Hyperloop Tube Crowbar"),
inventory_image = "hyperloop_tubecrowbar.png", inventory_image = "hyperloop_tubecrowbar.png",
wield_image = "hyperloop_tubecrowbar.png", wield_image = "hyperloop_tubecrowbar.png",
use_texture_alpha = true, use_texture_alpha = hyperloop.CLIP,
groups = {cracky=1, book=1}, groups = {cracky=1, book=1},
on_use = remove_tube, on_use = remove_tube,
on_place = repair_tubes, on_place = repair_tubes,

View File

@ -2,7 +2,7 @@
This LCD Lib is based on Display Lib and Font Lib from Pierre-Yves Rollo This LCD Lib is based on Display Lib and Font Lib from Pierre-Yves Rollo
**Dependancies**: default **Dependancies**: none
**License**: LGPL **License**: LGPL

View File

1
lcdlib/mod.conf Normal file
View File

@ -0,0 +1 @@
name = lcdlib

View File

@ -144,7 +144,7 @@ minetest.register_entity("minecart:marker", {
initial_properties = { initial_properties = {
visual = "upright_sprite", visual = "upright_sprite",
textures = {"minecart_marker_cube.png"}, textures = {"minecart_marker_cube.png"},
use_texture_alpha = true, use_texture_alpha = minecart.CLIP,
physical = false, physical = false,
glow = 12, glow = 12,
static_save = false, static_save = false,
@ -196,23 +196,27 @@ function minecart.is_owner(player, owner)
end end
function minecart.get_buffer_pos(pos, player_name) function minecart.get_buffer_pos(pos, player_name)
local pos1 = minecart.find_node_near_lvm(pos, 1, {"minecart:buffer"}) if pos then
if pos1 then local pos1 = minecart.find_node_near_lvm(pos, 1, {"minecart:buffer"})
local meta = minetest.get_meta(pos1) if pos1 then
if player_name == nil or player_name == meta:get_string("owner") then local meta = minetest.get_meta(pos1)
return pos1 if player_name == nil or player_name == meta:get_string("owner") then
return pos1
end
end end
end end
end end
function minecart.get_buffer_name(pos) function minecart.get_buffer_name(pos)
local pos1 = minecart.find_node_near_lvm(pos, 1, {"minecart:buffer"}) if pos then
if pos1 then local pos1 = minecart.find_node_near_lvm(pos, 1, {"minecart:buffer"})
local name = M(pos1):get_string("name") if pos1 then
if name ~= "" then local name = M(pos1):get_string("name")
return name if name ~= "" then
return name
end
return P2S(pos1)
end end
return P2S(pos1)
end end
end end

View File

@ -102,7 +102,7 @@ minetest.register_node("minecart:tool", {
inventory_image = "minecart_tool.png", inventory_image = "minecart_tool.png",
wield_image = "minecart_tool.png", wield_image = "minecart_tool.png",
liquids_pointable = true, liquids_pointable = true,
use_texture_alpha = true, use_texture_alpha = minecart.CLIP,
groups = {cracky=1, book=1}, groups = {cracky=1, book=1},
on_use = click_left, on_use = click_left,
on_place = click_right, on_place = click_right,

View File

@ -181,16 +181,16 @@ end
function networks.liquid.srv_peek(nvm) function networks.liquid.srv_peek(nvm)
nvm.liquid = nvm.liquid or {} nvm.liquid = nvm.liquid or {}
return nvm.liquid.name nvm.liquid.amount = math.floor((nvm.liquid.amount or 0) + 0.5)
return nvm.liquid.amount > 0 and nvm.liquid.name
end end
function networks.liquid.srv_put(nvm, name, amount, capa) function networks.liquid.srv_put(nvm, name, amount, capa)
assert(name) assert(name)
assert(amount and amount >= 0)
assert(capa and capa > 0) assert(capa and capa > 0)
amount = math.floor((amount or 0) + 0.5)
nvm.liquid = nvm.liquid or {} nvm.liquid = nvm.liquid or {}
amount = amount or 0
if not nvm.liquid.name then if not nvm.liquid.name then
nvm.liquid.name = name nvm.liquid.name = name
nvm.liquid.amount = amount nvm.liquid.amount = amount
@ -210,10 +210,9 @@ function networks.liquid.srv_put(nvm, name, amount, capa)
end end
function networks.liquid.srv_take(nvm, name, amount) function networks.liquid.srv_take(nvm, name, amount)
assert(amount and amount >= 0) amount = math.floor((amount or 0) + 0.5)
nvm.liquid = nvm.liquid or {} nvm.liquid = nvm.liquid or {}
amount = amount or 0
if not name or nvm.liquid.name == name then if not name or nvm.liquid.name == name then
name = nvm.liquid.name name = nvm.liquid.name
nvm.liquid.amount = nvm.liquid.amount or 0 nvm.liquid.amount = nvm.liquid.amount or 0

View File

@ -184,4 +184,6 @@ optional: farming redo, node_io, doc, techage, minecart, xdecor, compost
- 2021-05-04 v1.08 * Add print command, improve error msg - 2021-05-04 v1.08 * Add print command, improve error msg
- 2021-08-22 v1.09 * Add soup commands and signs, add aspen sign - 2021-08-22 v1.09 * Add soup commands and signs, add aspen sign
- 2021-09-18 v1.10 * Add techage command 'set <num>' to the Bot Control Unit - 2021-09-18 v1.10 * Add techage command 'set <num>' to the Bot Control Unit
- 2022-03-19 V1.11 * Extend farming (and add ethereal) support (Thanks to nixnoxus)

View File

@ -417,6 +417,10 @@ minetest.register_node("signs_bot:box", {
end, end,
after_place_node = function(pos, placer, itemstack) after_place_node = function(pos, placer, itemstack)
if not placer or not placer:is_player() then
minetest.remove_node(pos)
minetest.add_item(pos, itemstack)
end
local mem = tubelib2.init_mem(pos) local mem = tubelib2.init_mem(pos)
mem.running = false mem.running = false
mem.error = false mem.error = false

View File

@ -19,9 +19,9 @@ local lib = signs_bot.lib
local bot_inv_put_item = signs_bot.bot_inv_put_item local bot_inv_put_item = signs_bot.bot_inv_put_item
local bot_inv_take_item = signs_bot.bot_inv_take_item local bot_inv_take_item = signs_bot.bot_inv_take_item
local function soil_availabe(pos) local function soil_availabe(pos, trellis)
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
if node.name == "air" then if node.name == (trellis or "air") then
node = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z}) node = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z})
if node and minetest.get_item_group(node.name, "soil") >= 1 then if node and minetest.get_item_group(node.name, "soil") >= 1 then
return true return true
@ -33,13 +33,13 @@ end
local function planting(base_pos, mem, slot) local function planting(base_pos, mem, slot)
local pos = mem.pos_tbl and mem.pos_tbl[mem.steps] local pos = mem.pos_tbl and mem.pos_tbl[mem.steps]
mem.steps = (mem.steps or 1) + 1 mem.steps = (mem.steps or 1) + 1
if pos and lib.not_protected(base_pos, pos) and soil_availabe(pos) then if pos and lib.not_protected(base_pos, pos) then
local stack = bot_inv_take_item(base_pos, slot, 1) local stack = bot_inv_take_item(base_pos, slot, 1)
if stack and stack ~= "" then if stack and stack ~= "" then
local plant = stack:get_name() local plant = stack:get_name()
if plant then if plant then
local item = signs_bot.FarmingSeed[plant] local item = signs_bot.FarmingSeed[plant]
if item then if item and soil_availabe(pos, signs_bot.FarmingNeedTrellis[item]) then
if minetest.registered_nodes[item] then if minetest.registered_nodes[item] then
local p2 = minetest.registered_nodes[item].place_param2 or 1 local p2 = minetest.registered_nodes[item].place_param2 or 1
minetest.set_node(pos, {name = item, param2 = p2}) minetest.set_node(pos, {name = item, param2 = p2})
@ -87,13 +87,20 @@ local function harvesting(base_pos, mem)
if pos and lib.not_protected(base_pos, pos) then if pos and lib.not_protected(base_pos, pos) then
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
if signs_bot.FarmingCrop[node.name] then if signs_bot.FarmingCrop[node.name] then
minetest.remove_node(pos) local trellis = signs_bot.FarmingKeepTrellis[node.name]
if trellis then
minetest.set_node(pos, {name = trellis})
elseif not trellis then
minetest.remove_node(pos)
end
-- Do not cache the result of get_node_drops; it is a probabilistic function! -- Do not cache the result of get_node_drops; it is a probabilistic function!
local drops = minetest.get_node_drops(node.name) local drops = minetest.get_node_drops(node.name)
for _,itemstring in ipairs(drops) do for _,itemstring in ipairs(drops) do
local leftover = bot_inv_put_item(base_pos, 0, ItemStack(itemstring)) if not trellis or trellis ~= itemstring then
if leftover and leftover:get_count() > 0 then local leftover = bot_inv_put_item(base_pos, 0, ItemStack(itemstring))
signs_bot.lib.drop_items(mem.robot_pos, leftover) if leftover and leftover:get_count() > 0 then
signs_bot.lib.drop_items(mem.robot_pos, leftover)
end
end end
end end
end end

View File

@ -1,4 +1,4 @@
name=signs_bot name=signs_bot
depends = default,farming,basic_materials,tubelib2 depends = default,farming,basic_materials,tubelib2
optional_depends = node_io,techage,doc,minecart,bucket,fire,xdecor optional_depends = node_io,techage,doc,minecart,bucket,fire,xdecor,ethereal
description = A robot controlled by signs description = A robot controlled by signs

View File

@ -14,14 +14,20 @@
signs_bot.FarmingSeed = {} signs_bot.FarmingSeed = {}
signs_bot.FarmingCrop = {} signs_bot.FarmingCrop = {}
signs_bot.FarmingNeedTrellis = {}
signs_bot.FarmingKeepTrellis = {}
signs_bot.TreeSaplings = {} signs_bot.TreeSaplings = {}
-- inv_seed is the seed inventory name -- inv_seed is the seed inventory name
-- plantlet is what has to be placed on the ground (stage 1) -- plantlet is what has to be placed on the ground (stage 1)
-- crop is the farming crop in the final stage -- crop is the farming crop in the final stage
function signs_bot.register_farming_plant(inv_seed, plantlet, crop) function signs_bot.register_farming_plant(inv_seed, plantlet, crop, trellis)
signs_bot.FarmingCrop[crop] = true signs_bot.FarmingCrop[crop] = true
signs_bot.FarmingSeed[inv_seed] = plantlet signs_bot.FarmingSeed[inv_seed] = plantlet
if trellis then
signs_bot.FarmingNeedTrellis[plantlet] = trellis
signs_bot.FarmingKeepTrellis[crop] = trellis
end
end end
-- inv_sapling is the sapling inventory name -- inv_sapling is the sapling inventory name
@ -44,42 +50,27 @@ end
-- Farming Redo -- Farming Redo
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
if farming.mod == "redo" then if farming.mod == "redo" then
fp("farming:seed_wheat", "farming:wheat_1", "farming:wheat_8") local fp_grows = function(def, step)
fp("farming:seed_cotton", "farming:cotton_1", "farming:cotton_8") local crop = def.crop .. "_" .. step
fp("farming:carrot", "farming:carrot_1", "farming:carrot_8") local node = minetest.registered_nodes[crop]
fp("farming:potato", "farming:potato_1", "farming:potato_4") if node then
fp("farming:tomato", "farming:tomato_1", "farming:tomato_8") fp(def.seed, def.crop .. "_1", crop, def.trellis)
fp("farming:cucumber", "farming:cucumber_1", "farming:cucumber_4") return node.groups and node.groups.growing
fp("farming:corn", "farming:corn_1", "farming:corn_8") end
fp("farming:coffee_beans", "farming:coffee_1", "farming:coffee_5") end
fp("farming:melon_slice", "farming:melon_1", "farming:melon_8")
fp("farming:pumpkin_slice", "farming:pumpkin_1", "farming:pumpkin_8") for name, def in pairs(farming.registered_plants) do
fp("farming:raspberries", "farming:raspberry_1", "farming:raspberry_4") -- everything except cocoa (these can only be placed on jungletree)
fp("farming:blueberries", "farming:blueberry_1", "farming:blueberry_4") if name ~= "farming:cocoa_beans" then
fp("farming:rhubarb", "farming:rhubarb_1", "farming:rhubarb_3") local step = def.steps
fp("farming:beans", "farming:beanpole_1", "farming:beanpole_5") while fp_grows(def, step) do step = step + 1 end
fp("farming:grapes", "farming:grapes_1", "farming:grapes_8") end
fp("farming:seed_barley", "farming:barley_1", "farming:barley_7") end
fp("farming:chili_pepper", "farming:chili_1", "farming:chili_8")
fp("farming:seed_hemp", "farming:hemp_1", "farming:hemp_8")
fp("farming:seed_oat", "farming:oat_1", "farming:oat_8")
fp("farming:seed_rye", "farming:rye_1", "farming:rye_8")
fp("farming:seed_rice", "farming:rice_1", "farming:rice_8")
fp("farming:beetroot", "farming:beetroot_1", "farming:beetroot_5")
fp("farming:cocoa_beans", "farming:cocoa_1", "farming:cocoa_4")
fp("farming:garlic_clove", "farming:garlic_1", "farming:garlic_5")
fp("farming:onion", "farming:onion_1", "farming:onion_5")
fp("farming:pea_pod", "farming:pea_1", "farming:pea_5")
fp("farming:peppercorn", "farming:pepper_1", "farming:pepper_5")
fp("farming:pineapple_top", "farming:pineapple_1", "farming:pineapple_8")
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Ethereal Farming -- Ethereal Farming
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
--fn("ethereal:strawberry_8", "ethereal:strawberry 2", "ethereal:strawberry 1")
--fn("ethereal:onion_5", "ethereal:wild_onion_plant 2", "ethereal:onion_1")
--fn("ethereal:willow_trunk", "ethereal:willow_trunk", "ethereal:willow_sapling") --fn("ethereal:willow_trunk", "ethereal:willow_trunk", "ethereal:willow_sapling")
--fn("ethereal:redwood_trunk", "ethereal:redwood_trunk", "ethereal:redwood_sapling") --fn("ethereal:redwood_trunk", "ethereal:redwood_trunk", "ethereal:redwood_sapling")

View File

@ -121,3 +121,22 @@ minetest.register_node("signs_bot:robot_foot", {
}, },
sounds = default.node_sound_metal_defaults(), sounds = default.node_sound_metal_defaults(),
}) })
minetest.register_lbm({
label = "[signs_bot] Remove lost robots",
name = "signs_bot:lost_robot_remove",
nodenames = {"signs_bot:robot"},
run_at_every_load = true,
action = function(pos, node)
local found = false
tubelib2.walk_over_all(function(npos, node, mem)
if node.name == "signs_bot:box" and mem.robot_pos and
vector.equals(pos, mem.robot_pos) then
found = true
end
end, "robot_pos")
if not found then
signs_bot.remove_robot({robot_pos = pos})
end
end
})

View File

@ -14,6 +14,7 @@
local S = minetest.get_translator("ta4_jetpack") local S = minetest.get_translator("ta4_jetpack")
local liquid = networks.liquid local liquid = networks.liquid
local LQD = function(pos) return (minetest.registered_nodes[tubelib2.get_node_lvm(pos).name] or {}).liquid end
local ta4_jetpack = {} local ta4_jetpack = {}
@ -333,12 +334,12 @@ local function load_fuel(itemstack, user, pointed_thing)
local value = get_fuel_value(name) local value = get_fuel_value(name)
local newvalue local newvalue
if user:get_player_control().sneak then -- back to tank? if user:get_player_control().sneak then -- back to tank?
local amount = math.min(value, FUEL_UNIT) local amount = math.max(math.min(value, FUEL_UNIT), 0)
local rest = liquid.srv_put(nvm, "techage:hydrogen", amount, MAX_FUEL) local rest = liquid.srv_put(nvm, "techage:hydrogen", amount, LQD(pos).capa)
newvalue = value - amount + rest newvalue = value - (amount - rest)
else else
local amount = math.min(FUEL_UNIT, MAX_FUEL - value) local amount = math.max(math.min(FUEL_UNIT, MAX_FUEL - value), 0)
local taken = liquid.srv_take(nvm, "techage:hydrogen", amount) local taken = liquid.srv_take(nvm, "techage:hydrogen", amount)
newvalue = value + taken newvalue = value + taken
end end

View File

@ -2,12 +2,9 @@
Tech Age, a mod to go through 5 tech ages in search of wealth and power. Tech Age, a mod to go through 5 tech ages in search of wealth and power.
**Tech Age (techage) is the successor to TechPack V2, at first glance similar and yet completely different!**
![screenshot](https://github.com/joe7575/techage/blob/master/screenshot.png) ![screenshot](https://github.com/joe7575/techage/blob/master/screenshot.png)
Important facts: Important facts:
- techage is not backwards compatible and cannot be installed on a server together with TechPack - techage is not backwards compatible and cannot be installed on a server together with TechPack
- techage is significantly more extensive, since additional mods are integrated - techage is significantly more extensive, since additional mods are integrated
@ -22,6 +19,10 @@ Important facts:
In contrast to TechPack, the resources are more limited and it is much more difficult to pass all levels. In contrast to TechPack, the resources are more limited and it is much more difficult to pass all levels.
(no endless ore generation by means of cobble generators) (no endless ore generation by means of cobble generators)
**Techage blocks store information outside of the block. This is for performance reasons.
If you move, place, or remove blocks with any tool, at best, only the information is lost.
In the worst case, the server crashes.**
[Manuals](https://github.com/joe7575/techage/wiki) [Manuals](https://github.com/joe7575/techage/wiki)
@ -75,11 +76,14 @@ For the installation of 'luarocks' (if not already available), see [luarocks](ht
Available worlds will be converted to 'lsqlite3', but there is no way back, so: Available worlds will be converted to 'lsqlite3', but there is no way back, so:
** Never disable 'lsqlite3' for a world that has already been used!** **Never disable 'lsqlite3' for a world that has already been used!**
### History ### History
**2022-06-06 V1.08**
- Native support for the mod Beduino added
**2022-01-22 V1.07** **2022-01-22 V1.07**
- TA5 fusion reactor added - TA5 fusion reactor added

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -180,6 +180,15 @@ techage.register_node({"techage:chest_ta2", "techage:chest_ta3"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
else
return 2, ""
end
end,
}) })
@ -412,6 +421,15 @@ techage.register_node({"techage:chest_ta4"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
else
return 2, ""
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -65,6 +65,10 @@ local names = networks.register_junction("techage:concentrator", 2/8, Boxes, Tub
end, end,
}, 27) }, 27)
for _, name in ipairs(names) do
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
end
techage.register_node(names, { techage.register_node(names, {
on_push_item = function(pos, in_dir, stack) on_push_item = function(pos, in_dir, stack)
local push_dir = M(pos):get_int("push_dir") local push_dir = M(pos):get_int("push_dir")
@ -110,6 +114,10 @@ names = networks.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube,
end, end,
}, 27) }, 27)
for _, name in ipairs(names) do
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
end
techage.register_node(names, { techage.register_node(names, {
on_push_item = function(pos, in_dir, stack) on_push_item = function(pos, in_dir, stack)
local push_dir = M(pos):get_int("push_dir") local push_dir = M(pos):get_int("push_dir")

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -34,6 +34,7 @@ local INFO = [[Turn port on/off or read its state: command = 'port', payload = r
--local Side2Color = {B="red", L="green", F="blue", R="yellow"} --local Side2Color = {B="red", L="green", F="blue", R="yellow"}
local SlotColors = {"red", "green", "blue", "yellow"} local SlotColors = {"red", "green", "blue", "yellow"}
local SlotNumbers = {red = 1, green = 2, blue = 3, yellow = 4}
local Num2Ascii = {"B", "L", "F", "R"} local Num2Ascii = {"B", "L", "F", "R"}
local FilterCache = {} -- local cache for filter settings local FilterCache = {} -- local cache for filter settings
@ -383,16 +384,16 @@ end
-- techage command to turn on/off filter channels -- techage command to turn on/off filter channels
local function change_filter_settings(pos, slot, val) local function change_filter_settings(pos, slot, val)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local meta = M(pos) local meta = M(pos)
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false} local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
local num = slots[slot] or 1 local num = SlotNumbers[slot] or 1
if num >= 1 and num <= 4 then if num >= 1 and num <= 4 then
filter[num] = val == "on" filter[num] = val == "on"
end end
meta:set_string("filter", minetest.serialize(filter)) meta:set_string("filter", minetest.serialize(filter))
filter_settings(pos) local hash = minetest.hash_node_position(pos)
FilterCache[hash] = nil
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
meta:set_string("formspec", formspec(CRD(pos).State, pos, nvm)) meta:set_string("formspec", formspec(CRD(pos).State, pos, nvm))
@ -401,9 +402,45 @@ end
-- techage command to read filter channel status (on/off) -- techage command to read filter channel status (on/off)
local function read_filter_settings(pos, slot) local function read_filter_settings(pos, slot)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false} local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
return filter[slots[slot]] and "on" or "off" return filter[SlotNumbers[slot]] and "on" or "off"
end
local function get_payload_values(payload)
local color
local idx = 0
local items = {ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack("")}
for s in payload:gmatch("[^%s]+") do --- white spaces
if not color then
if SlotNumbers[s] then
color = s
else
return "red", {}
end
else
idx = idx + 1
if idx <= 6 then
items[idx] = ItemStack(s)
end
end
end
return color, items
end
local function str_of_inv_items(pos, color)
color = SlotColors[color] or color
if SlotNumbers[color] then
local inv = M(pos):get_inventory()
local t = {}
for idx = 1, 6 do
local item = inv:get_stack(color, idx)
if item:get_count() > 0 then
t[#t + 1] = item:get_name()
end
end
return table.concat(t, " ")
end
return ""
end end
local function can_dig(pos, player) local function can_dig(pos, player)
@ -474,10 +511,47 @@ local tubing = {
else else
return change_filter_settings(pos, slot, val) return change_filter_settings(pos, slot, val)
end end
elseif topic == "config" then
local color, items = get_payload_values(payload)
local inv = M(pos):get_inventory()
for idx,item in ipairs(items) do
inv:set_stack(color, idx, item)
end
local hash = minetest.hash_node_position(pos)
FilterCache[hash] = nil
return true
elseif topic == "get" then
return str_of_inv_items(pos, payload)
else else
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 4 then
local slot = SlotColors[payload[1]]
local state = payload[2] == 1 and "on" or "off"
change_filter_settings(pos, slot, state)
return 0
elseif topic == 67 then
local color, items = get_payload_values(payload)
local inv = M(pos):get_inventory()
for idx,item in ipairs(items) do
inv:set_stack(color, idx, item)
end
local hash = minetest.hash_node_position(pos)
FilterCache[hash] = nil
return 0
else
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 148 then
return 0, str_of_inv_items(pos, payload[1])
else
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -74,8 +74,9 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
end end
local function making(pos, crd, nvm, inv) local function making(pos, crd, nvm, inv)
local owner = M(pos):get_string("owner")
local rtype = RecipeType[crd.stage] local rtype = RecipeType[crd.stage]
local recipe = recipes.get(nvm, rtype) local recipe = recipes.get(nvm, rtype, owner)
local output = ItemStack(recipe.output.name.." "..recipe.output.num) local output = ItemStack(recipe.output.name.." "..recipe.output.num)
if inv:room_for_item("dst", output) then if inv:room_for_item("dst", output) then
for _,item in ipairs(recipe.input) do for _,item in ipairs(recipe.input) do
@ -202,6 +203,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -91,13 +91,13 @@ local function set_pos_list(player, lPos)
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos)) meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
end end
local function shoe_flbs(pos, name, range) local function show_flbs(pos, name, range)
local pos1 = {x=pos.x-range, y=pos.y-range, z=pos.z-range} local pos1 = {x=pos.x-range, y=pos.y-range, z=pos.z-range}
local pos2 = {x=pos.x+range, y=pos.y+range, z=pos.z+range} local pos2 = {x=pos.x+range, y=pos.y+range, z=pos.z+range}
for _,npos in ipairs(minetest.find_nodes_in_area(pos1, pos2, {"techage:forceload", "techage:forceloadtile"})) do for _,npos in ipairs(minetest.find_nodes_in_area(pos1, pos2, {"techage:forceload", "techage:forceloadtile"})) do
local _pos1, _pos2 = calc_area(npos) local _pos1, _pos2 = calc_area(npos)
local owner = M(npos):get_string("owner") local owner = M(npos):get_string("owner")
techage.mark_region(name, _pos1, _pos2, owner) techage.mark_region(name, _pos1, _pos2, owner .. " " .. P2S(npos))
end end
end end
@ -204,6 +204,7 @@ minetest.register_node("techage:forceload", {
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
use_texture_alpha = techage.CLIP,
groups = {choppy=2, cracky=2, crumbly=2, groups = {choppy=2, cracky=2, crumbly=2,
digtron_protected = 1, digtron_protected = 1,
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0}, not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
@ -292,15 +293,11 @@ minetest.register_chatcommand("forceload", {
params = "", params = "",
description = S("Show all forceload blocks in a 64x64x64 range"), description = S("Show all forceload blocks in a 64x64x64 range"),
func = function(name, param) func = function(name, param)
if minetest.check_player_privs(name, "superminer") then local player = minetest.get_player_by_name(name)
local player = minetest.get_player_by_name(name) if player then
if player then local pos = player:get_pos()
local pos = player:get_pos() pos = vector.round(pos)
pos = vector.round(pos) show_flbs(pos, name, 64)
shoe_flbs(pos, name, 64)
end
else
return false, S("Priv missing")
end end
end, end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -249,6 +249,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
remove_objects({x=pos.x, y=pos.y+1, z=pos.z}) remove_objects({x=pos.x, y=pos.y+1, z=pos.z})
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -174,6 +174,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -56,7 +56,10 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
return 0 return 0
end end
if listname == "src" then if listname == "src" then
CRD(pos).State:start_if_standby(pos) local state = CRD(pos).State
if state then
state:start_if_standby(pos)
end
end end
return stack:get_count() return stack:get_count()
end end
@ -206,6 +209,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -173,6 +173,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
} }
local node_name_ta2, node_name_ta3, _ = local node_name_ta2, node_name_ta3, _ =

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -181,13 +181,21 @@ local function can_start(pos, nvm, state)
end end
local function config_item(pos, payload) local function config_item(pos, payload)
local name, count = unpack(payload:split(" ")) if type(payload) == "string" then
if name and (minetest.registered_nodes[name] or minetest.registered_items[name] if payload == "" then
or minetest.registered_craftitems[name]) then local inv = M(pos):get_inventory()
count = tonumber(count) or 1 inv:set_stack("main", 1, nil)
local inv = M(pos):get_inventory() return 0
inv:set_stack("main", 1, {name = name, count = 1}) else
return count local name, count = unpack(payload:split(" "))
if name and (minetest.registered_nodes[name] or minetest.registered_items[name]
or minetest.registered_craftitems[name]) then
count = tonumber(count) or 1
local inv = M(pos):get_inventory()
inv:set_stack("main", 1, {name = name, count = 1})
return count
end
end
end end
return 0 return 0
end end
@ -256,6 +264,24 @@ local tubing = {
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 64 then -- Start pusher
local nvm = techage.get_nvm(pos)
CRD(pos).State:stop(pos, nvm)
nvm.item_count = math.min(config_item(pos, payload), 12)
nvm.rmt_num = src
CRD(pos).State:start(pos, nvm)
return 0
elseif topic == 65 then -- Config Pusher
local nvm = techage.get_nvm(pos)
CRD(pos).State:stop(pos, nvm)
config_item(pos, payload)
CRD(pos).State:start(pos, nvm)
return 0
else
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end
end,
} }
local node_name_ta2, node_name_ta3, node_name_ta4 = local node_name_ta2, node_name_ta3, node_name_ta4 =

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -368,6 +368,17 @@ local tubing = {
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 133 then -- Quarry Depth
local nvm = techage.get_nvm(pos)
return 0, {nvm.level or 0}
else
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -45,7 +45,7 @@ local SpecialItems = {
["dye:black"] = "", ["dye:black"] = "",
["techage:basalt_glass_thin"] = "", ["techage:basalt_glass_thin"] = "",
["group:stone"] = "techage:sieved_gravel", ["group:stone"] = "techage:sieved_gravel",
["basic_materials:plastic_sheet"] = "", --["basic_materials:plastic_sheet"] = "",
["group:wood"] = "default:stick 5", ["group:wood"] = "default:stick 5",
["techage:basalt_glass"] = "", ["techage:basalt_glass"] = "",
["default:junglewood"] = "default:stick 5", ["default:junglewood"] = "default:stick 5",
@ -235,6 +235,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -92,6 +92,18 @@ local function inv_state(nvm)
return "loaded" return "loaded"
end end
local function inv_state_num(nvm)
local num = 0
for _,item in ipairs(nvm.inventory or {}) do
if item.count and item.count > 0 then
num = num + 1
end
end
if num == 0 then return 0 end
if num == 8 then return 2 end
return 1
end
local function max_stacksize(item_name) local function max_stacksize(item_name)
-- It is sufficient to use minetest.registered_items as all registration -- It is sufficient to use minetest.registered_items as all registration
-- functions (node, craftitems, tools) add the definitions there. -- functions (node, craftitems, tools) add the definitions there.
@ -324,12 +336,17 @@ local function count_number_of_chests(pos)
local node = techage.get_node_lvm(pos) local node = techage.get_node_lvm(pos)
local dir = techage.side_to_outdir("B", node.param2) local dir = techage.side_to_outdir("B", node.param2)
local pos1 = tubelib2.get_pos(pos, dir) local pos1 = tubelib2.get_pos(pos, dir)
local param2 = node.param2
local cnt = 1 local cnt = 1
while cnt < 50 do while cnt < 50 do
node = techage.get_node_lvm(pos1) node = techage.get_node_lvm(pos1)
if node.name ~= "techage:ta4_chest_dummy" then if node.name ~= "techage:ta4_chest_dummy" then
break break
end end
local meta = M(pos1)
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
break
end
pos1 = tubelib2.get_pos(pos1, dir) pos1 = tubelib2.get_pos(pos1, dir)
cnt = cnt + 1 cnt = cnt + 1
end end
@ -339,12 +356,17 @@ end
local function search_chest_in_front(pos, node) local function search_chest_in_front(pos, node)
local dir = techage.side_to_outdir("F", node.param2) local dir = techage.side_to_outdir("F", node.param2)
local pos1 = tubelib2.get_pos(pos, dir) local pos1 = tubelib2.get_pos(pos, dir)
local param2 = node.param2
local cnt = 1 local cnt = 1
while cnt < 50 do while cnt < 50 do
node = techage.get_node_lvm(pos1) node = techage.get_node_lvm(pos1)
if node.name ~= "techage:ta4_chest_dummy" then if node.name ~= "techage:ta4_chest_dummy" then
break break
end end
local meta = M(pos1)
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
break
end
pos1 = tubelib2.get_pos(pos1, dir) pos1 = tubelib2.get_pos(pos1, dir)
cnt = cnt + 1 cnt = cnt + 1
end end
@ -517,6 +539,7 @@ minetest.register_node("techage:ta4_chest", {
if search_chest_in_front(pos, node) then if search_chest_in_front(pos, node) then
node.name = "techage:ta4_chest_dummy" node.name = "techage:ta4_chest_dummy"
minetest.swap_node(pos, node) minetest.swap_node(pos, node)
M(pos):set_int("param2", node.param2)
else else
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
gen_inv(nvm) gen_inv(nvm)
@ -597,10 +620,10 @@ techage.register_node({"techage:ta4_chest"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
if topic == "count" then if topic == "count" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return get_count(nvm, tonumber(payload) or 0) return get_count(nvm, tonumber(payload or 1) or 1)
elseif topic == "itemstring" then elseif topic == "itemstring" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return get_itemstring(nvm, tonumber(payload) or 0) return get_itemstring(nvm, tonumber(payload or 1) or 1)
elseif topic == "state" then elseif topic == "state" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return inv_state(nvm) return inv_state(nvm)
@ -608,6 +631,20 @@ techage.register_node({"techage:ta4_chest"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 140 and payload[1] == 1 then -- Inventory Item Count
local nvm = techage.get_nvm(pos)
return 0, {get_count(nvm, tonumber(payload[2] or 1) or 1)}
elseif topic == 140 and payload[1] == 2 then -- Inventory Item Name
local nvm = techage.get_nvm(pos)
return 0, get_itemstring(nvm, tonumber(payload[2] or 1) or 1)
elseif topic == 131 then -- Chest State
local nvm = techage.get_nvm(pos)
return 0, {inv_state_num(nvm)}
else
return 2, ""
end
end,
}) })
techage.register_node({"techage:ta4_chest_dummy"}, { techage.register_node({"techage:ta4_chest_dummy"}, {

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -242,6 +242,12 @@ local tubing = {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end,
on_node_load = function(pos) on_node_load = function(pos)
CRD(pos).State:on_node_load(pos) CRD(pos).State:on_node_load(pos)
end, end,

View File

@ -175,6 +175,15 @@ techage.register_node({"techage:ta5_hl_chest"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
else
return 2, ""
end
end,
}) })

View File

@ -173,13 +173,14 @@ local function remove_inv(pos, inv, param2, AssemblyPlan, player_name, idx)
if inv:room_for_item("src", stack) then if inv:room_for_item("src", stack) then
local node = minetest.get_node(pos1) local node = minetest.get_node(pos1)
if node.name == node_name then if node.name == node_name then
local meta = M(pos1):to_table()
minetest.remove_node(pos1) minetest.remove_node(pos1)
inv:add_item("src", stack) inv:add_item("src", stack)
play_sound(pos, "default_dig_cracky") play_sound(pos, "default_dig_cracky")
local ndef = minetest.registered_nodes[node_name] local ndef = minetest.registered_nodes[node_name]
if ndef and ndef.after_dig_node then if ndef and ndef.after_dig_node then
local digger = minetest.get_player_by_name(player_name) local digger = minetest.get_player_by_name(player_name)
ndef.after_dig_node(pos1, pos, ItemStack(node_name), {}, digger) ndef.after_dig_node(pos1, node, meta, digger)
end end
end end
end end

View File

@ -406,6 +406,33 @@ function techage.transfer(pos, outdir, topic, payload, network, nodenames)
return false return false
end end
-------------------------------------------------------------------
-- Beduino functions (see "bep-005_ta_cmnd.md")
-------------------------------------------------------------------
function techage.beduino_send_cmnd(src, number, topic, payload)
--print("beduino_send_cmnd", src, number, topic)
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
if ninfo and ninfo.name and ninfo.pos then
local ndef = NodeDef[ninfo.name]
if ndef and ndef.on_beduino_receive_cmnd then
return ndef.on_beduino_receive_cmnd(ninfo.pos, src, topic, payload or {})
end
end
return 1, ""
end
function techage.beduino_request_data(src, number, topic, payload)
--print("beduino_request_data", src, number, topic)
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
if ninfo and ninfo.name and ninfo.pos then
local ndef = NodeDef[ninfo.name]
if ndef and ndef.on_beduino_request_data then
return ndef.on_beduino_request_data(ninfo.pos, src, topic, payload or {})
end
end
return 1, ""
end
------------------------------------------------------------------- -------------------------------------------------------------------
-- Client side Push/Pull item functions -- Client side Push/Pull item functions
------------------------------------------------------------------- -------------------------------------------------------------------
@ -564,6 +591,23 @@ function techage.get_inv_state(inv, listname)
return state return state
end end
-- Beduino variant
function techage.get_inv_state_num(inv, listname)
local state
if inv:is_empty(listname) then
state = 0
else
local list = inv:get_list(listname)
state = 2
for _, item in ipairs(list) do
if item:is_empty() then
return 1
end
end
end
return state
end
minetest.register_chatcommand("ta_send", { minetest.register_chatcommand("ta_send", {
description = minetest.formspec_escape( description = minetest.formspec_escape(
"Send a techage command to the block with the number given: /ta_send <number> <command> [<data>]"), "Send a techage command to the block with the number given: /ta_send <number> <command> [<data>]"),

View File

@ -134,13 +134,39 @@ local function dest_offset(lpath)
return offs return offs
end end
-------------------------------------------------------------------------------
-- Protect the doors from being opened by hand
-------------------------------------------------------------------------------
local function new_on_rightclick(old_on_rightclick)
return function(pos, node, clicker, itemstack, pointed_thing)
if M(pos):contains("ta_door_locked") then
return itemstack
end
if old_on_rightclick then
return old_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
else
return itemstack
end
end
end
function flylib.protect_door_from_being_opened(name)
-- Change on_rightclick function.
local ndef = minetest.registered_nodes[name]
if ndef then
local old_on_rightclick = ndef.on_rightclick
minetest.override_item(ndef.name, {
on_rightclick = new_on_rightclick(old_on_rightclick)
})
end
end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Entity / Move / Attach / Detach -- Entity / Move / Attach / Detach
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local MIN_SPEED = 0.4 local MIN_SPEED = 0.4
local MAX_SPEED = 8 local MAX_SPEED = 8
local CORNER_SPEED = 4 local CORNER_SPEED = 4
local SimpleNodes = techage.logic.SimpleNodes
local function calc_speed(v) local function calc_speed(v)
return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) return math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
@ -292,8 +318,7 @@ local function entity_to_node(pos, obj)
local nvm = techage.get_nvm(self.base_pos) local nvm = techage.get_nvm(self.base_pos)
nvm.running = nil nvm.running = nil
end end
obj:remove() minetest.after(0.1, obj.remove, obj)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local ndef1 = minetest.registered_nodes[name] local ndef1 = minetest.registered_nodes[name]
local ndef2 = minetest.registered_nodes[node.name] local ndef2 = minetest.registered_nodes[node.name]
@ -303,6 +328,7 @@ local function entity_to_node(pos, obj)
minetest.set_node(pos, {name=name, param2=param2}) minetest.set_node(pos, {name=name, param2=param2})
meta:from_table(metadata) meta:from_table(metadata)
meta:set_string("ta_move_block", "") meta:set_string("ta_move_block", "")
meta:set_int("ta_door_locked", 1)
return return
end end
local meta = M(pos) local meta = M(pos)
@ -326,11 +352,14 @@ local function node_to_entity(start_pos)
node = minetest.deserialize(meta:get_string("ta_move_block")) node = minetest.deserialize(meta:get_string("ta_move_block"))
metadata = {} metadata = {}
meta:set_string("ta_move_block", "") meta:set_string("ta_move_block", "")
else meta:set_string("ta_block_locked", "true")
elseif not meta:contains("ta_block_locked") then
-- Block with other metadata -- Block with other metadata
node = minetest.get_node(start_pos) node = minetest.get_node(start_pos)
metadata = meta:to_table() metadata = meta:to_table()
minetest.remove_node(start_pos) minetest.after(0.1, minetest.remove_node, start_pos)
else
return
end end
local obj = minetest.add_entity(start_pos, "techage:move_item") local obj = minetest.add_entity(start_pos, "techage:move_item")
if obj then if obj then
@ -388,36 +417,38 @@ end
-- Handover the entity to the next movecontroller -- Handover the entity to the next movecontroller
local function handover_to(obj, self, pos1) local function handover_to(obj, self, pos1)
local info = techage.get_node_info(self.handover) if self.handover then
if info and info.name == "techage:ta4_movecontroller" then local info = techage.get_node_info(self.handover)
local meta = M(info.pos) if info and info.name == "techage:ta4_movecontroller" then
if self.move2to1 then local meta = M(info.pos)
self.handover = meta:contains("handoverA") and meta:get_string("handoverA")
else
self.handover = meta:contains("handoverB") and meta:get_string("handoverB")
end
self.lpath = flylib.to_path(meta:get_string("path"))
if pos1 and self.lpath then
self.path_idx = 2
if self.move2to1 then if self.move2to1 then
self.lpath[1] = vector.multiply(self.lpath[1], - 1) self.handover = meta:contains("handoverA") and meta:get_string("handoverA") or nil
else
self.handover = meta:contains("handoverB") and meta:get_string("handoverB") or nil
end end
local pos2 = next_path_pos(pos1, self.lpath, 1)
local dir = determine_dir(pos1, pos2)
--print("handover_to", P2S(pos1), P2S(pos2), P2S(dir), P2S(info.pos), meta:get_string("path"))
if not self.handover then
local nvm = techage.get_nvm(info.pos)
nvm.lpos1 = nvm.lpos1 or {}
if self.move2to1 then
nvm.lpos1[self.pos1_idx] = pos2
else self.lpath = flylib.to_path(meta:get_string("path"))
nvm.lpos1[self.pos1_idx] = pos1 if pos1 and self.lpath then
self.path_idx = 2
if self.move2to1 then
self.lpath[1] = vector.multiply(self.lpath[1], - 1)
end end
local pos2 = next_path_pos(pos1, self.lpath, 1)
local dir = determine_dir(pos1, pos2)
--print("handover_to", P2S(pos1), P2S(pos2), P2S(dir), P2S(info.pos), meta:get_string("path"))
if not self.handover then
local nvm = techage.get_nvm(info.pos)
nvm.lpos1 = nvm.lpos1 or {}
if self.move2to1 then
nvm.lpos1[self.pos1_idx] = pos2
else
nvm.lpos1[self.pos1_idx] = pos1
end
end
move_entity(obj, pos2, dir)
return true
end end
move_entity(obj, pos2, dir)
return true
end end
end end
end end
@ -473,7 +504,7 @@ minetest.register_entity("techage:move_item", {
self.object:set_properties({wield_item = self.item}) self.object:set_properties({wield_item = self.item})
--print("tbl.respawn", tbl.respawn) --print("tbl.respawn", tbl.respawn)
if tbl.respawn then if tbl.respawn then
entity_to_node(self.start_pos, self.object) entity_to_node(self.dest_pos, self.object)
end end
end end
end, end,
@ -552,8 +583,7 @@ minetest.register_entity("techage:move_item", {
local function is_valid_dest(pos) local function is_valid_dest(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name] if techage.is_air_like(node.name) then
if ndef and ndef.buildable_to then
return true return true
end end
if not M(pos):contains("ta_move_block") then if not M(pos):contains("ta_move_block") then
@ -563,20 +593,9 @@ local function is_valid_dest(pos)
end end
local function is_simple_node(pos) local function is_simple_node(pos)
-- special handling local node = minetest.get_node(pos)
local name = minetest.get_node(pos).name local ndef = minetest.registered_nodes[node.name]
if SimpleNodes[name] ~= nil then return not techage.is_air_like(node.name) and techage.can_dig_node(node.name, ndef)
return SimpleNodes[name]
end
local ndef = minetest.registered_nodes[name]
if not ndef or name == "air" or name == "ignore" then return false end
-- don't remove nodes with some intelligence or undiggable nodes
if ndef.drop == "" then return false end
if ndef.diggable == false then return false end
if ndef.after_dig_node then return false end
return true
end end
local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover, cpos) local function move_node(pos, pos1_idx, start_pos, lpath, max_speed, height, move2to1, handover, cpos)
@ -649,6 +668,43 @@ local function move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, ha
return true return true
end end
-- Move nodes from lpos1 by the given x/y/z 'line'
local function move_nodes2(pos, meta, lpos1, line, max_speed, height)
--print("move_nodes2", dump(lpos1), dump(line), max_speed, height)
local owner = meta:get_string("owner")
techage.counting_add(owner, #lpos1)
local lpos2 = {}
for idx = 1, #lpos1 do
local pos1 = lpos1[idx]
local pos2 = vector.add(lpos1[idx], line)
lpos2[idx] = pos2
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
if is_simple_node(pos1) and is_valid_dest(pos2) then
move_node(pos, idx, pos1, {line}, max_speed, height, false, false)
else
if not is_simple_node(pos1) then
meta:set_string("status", S("No valid node at the start position"))
else
meta:set_string("status", S("No valid destination position"))
end
end
else
if minetest.is_protected(pos1, owner) then
meta:set_string("status", S("Start position is protected"))
else
meta:set_string("status", S("Destination position is protected"))
end
return false, lpos1
end
end
meta:set_string("status", "")
return true, lpos2
end
function flylib.move_to_other_pos(pos, move2to1) function flylib.move_to_other_pos(pos, move2to1)
local meta = M(pos) local meta = M(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
@ -671,13 +727,36 @@ function flylib.move_to_other_pos(pos, move2to1)
nvm.lpos2 = lvect_add_vec(nvm.lpos1, offs) nvm.lpos2 = lvect_add_vec(nvm.lpos1, offs)
if move2to1 then if move2to1 then
handover = meta:contains("handoverA") and meta:get_string("handoverA") handover = meta:contains("handoverA") and meta:get_string("handoverA") or nil
else else
handover = meta:contains("handoverB") and meta:get_string("handoverB") handover = meta:contains("handoverB") and meta:get_string("handoverB") or nil
end end
return move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover) return move_nodes(pos, meta, nvm, lpath, max_speed, height, move2to1, handover)
end end
function flylib.move_to(pos, line)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local height = techage.in_range(meta:contains("height") and meta:get_float("height") or 1, 0, 1)
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
local resp
resp, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, line, max_speed, height)
return resp
end
function flylib.reset_move(pos)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local height = techage.in_range(meta:contains("height") and meta:get_float("height") or 1, 0, 1)
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
local move = vector.subtract(nvm.lpos1[1], (nvm.lastpos or nvm.lpos1)[1])
local resp
resp, nvm.lastpos = move_nodes2(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed, height)
return resp
end
-- rot is one of "l", "r", "2l", "2r" -- rot is one of "l", "r", "2l", "2r"
-- cpos is the center pos (optional) -- cpos is the center pos (optional)
function flylib.rotate_nodes(pos, posses1, rot) function flylib.rotate_nodes(pos, posses1, rot)
@ -712,6 +791,39 @@ function flylib.rotate_nodes(pos, posses1, rot)
return posses2 return posses2
end end
function flylib.exchange_node(pos, name, param2)
local meta = M(pos)
local move_block
-- consider stored "objects"
if meta:contains("ta_move_block") then
move_block = meta:get_string("ta_move_block")
end
minetest.swap_node(pos, {name = name, param2 = param2})
if move_block then
meta:set_string("ta_move_block", move_block)
end
end
function flylib.remove_node(pos)
local meta = M(pos)
local move_block
-- consider stored "objects"
if meta:contains("ta_move_block") then
move_block = meta:get_string("ta_move_block")
end
minetest.remove_node(pos)
if move_block then
local node = minetest.deserialize(move_block)
minetest.add_node(pos, node)
meta:set_string("ta_move_block", "")
end
end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
unlock_player(player) unlock_player(player)

View File

@ -57,16 +57,19 @@ local function get_remote_pos(pos, rmt_name)
end end
local function get_free_server_list(pos, owner) local function get_free_server_list(pos, owner)
local tbl = {M(pos):get_string("remote_name")} if Stations and Stations.get_node_table then
for key,item in pairs(Stations:get_node_table(pos)) do local tbl = {M(pos):get_string("remote_name")}
if item.single and item.owner == owner then for key,item in pairs(Stations:get_node_table(pos) or {}) do
if M(pos):get_string("node_type") == M(S2P(key)):get_string("node_type") then if item.single and item.owner == owner then
tbl[#tbl+1] = item.conn_name if M(pos):get_string("node_type") == M(S2P(key)):get_string("node_type") then
tbl[#tbl+1] = item.conn_name
end
end end
end end
tbl[#tbl+1] = ""
return tbl
end end
tbl[#tbl+1] = "" return {}
return tbl
end end
local function on_lose_connection(pos, node_type) local function on_lose_connection(pos, node_type)
@ -78,8 +81,11 @@ local function on_lose_connection(pos, node_type)
end end
local function on_dropdown(pos) local function on_dropdown(pos)
local owner = M(pos):get_string("owner") if pos then
return table.concat(get_free_server_list(pos, owner), ",") local owner = M(pos):get_string("owner")
return table.concat(get_free_server_list(pos, owner), ",") or ""
end
return ""
end end
local function update_node_data(pos, state, conn_name, remote_name, rmt_pos) local function update_node_data(pos, state, conn_name, remote_name, rmt_pos)

View File

@ -76,7 +76,7 @@ for _,row in ipairs(ROTATION) do
end end
function techage.facedir_to_rotation(facedir) function techage.facedir_to_rotation(facedir)
return FACEDIR_TO_ROT[facedir] return FACEDIR_TO_ROT[facedir] or FACEDIR_TO_ROT[0]
end end
function techage.param2_turn_left(param2) function techage.param2_turn_left(param2)
@ -129,7 +129,6 @@ function techage.param2_turn_up(facedir, param2)
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Rotate nodes around the center -- Rotate nodes around the center
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -181,12 +180,12 @@ function techage.rotate_around_center(nodes1, turn, cpos)
return nodes2 return nodes2
end end
-- allowed for digging
local RegisteredNodesToBeDug = {}
function techage.register_node_to_be_dug(name) -------------------------------------------------------------------------------
RegisteredNodesToBeDug[name] = true -- Helper functions
end -------------------------------------------------------------------------------
-- allowed for digging
local SimpleNodes = {}
-- translation from param2 to dir (out of the node upwards) -- translation from param2 to dir (out of the node upwards)
local Param2Dir = {} local Param2Dir = {}
@ -244,6 +243,17 @@ function techage.add_to_set(set, x)
end end
end end
-- techage.tbl_filter({"a", "b", "c", "d"}, function(v, k, t) return v >= "c" end) --> {"c","d"}
techage.tbl_filter = function(t, filterIter)
local out = {}
for k, v in pairs(t) do
if filterIter(v, k, t) then out[k] = v end
end
return out
end
function techage.get_node_lvm(pos) function techage.get_node_lvm(pos)
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
if node then if node then
@ -273,21 +283,54 @@ function techage.is_air_like(name)
end end
-- returns true, if node can be dug, otherwise false -- returns true, if node can be dug, otherwise false
function techage.can_node_dig(node, ndef) function techage.can_dig_node(name, ndef)
if RegisteredNodesToBeDug[node.name] then if not ndef then return false end
if SimpleNodes[name] ~= nil then
return SimpleNodes[name]
end
if ndef.groups and ndef.groups.techage_door == 1 then
SimpleNodes[name] = true
return true return true
end end
if not ndef then return false end if name == "ignore" then
if node.name == "ignore" then return false end SimpleNodes[name] = false
if node.name == "air" then return true end return false
if ndef.buildable_to == true then return true end end
if ndef.diggable == false then return false end if name == "air" then
if ndef.after_dig_node then return false end SimpleNodes[name] = true
return true
end
if ndef.buildable_to == true then
SimpleNodes[name] = true
return true
end
-- don't remove nodes with some intelligence or undiggable nodes
if ndef.drop == "" then
SimpleNodes[name] = false
return false
end
if ndef.diggable == false then
SimpleNodes[name] = false
return false
end
if ndef.after_dig_node then
SimpleNodes[name] = false
return false
end
-- add it to the white list -- add it to the white list
RegisteredNodesToBeDug[node.name] = true SimpleNodes[name] = true
return true return true
end end
-- Simple nodes
function techage.register_simple_nodes(node_names, is_valid)
if is_valid == nil then is_valid = true end
for _,name in ipairs(node_names or {}) do
SimpleNodes[name] = is_valid
end
end
techage.dig_states = { techage.dig_states = {
NOT_DIGGABLE = 1, NOT_DIGGABLE = 1,
INV_FULL = 2, INV_FULL = 2,
@ -421,50 +464,6 @@ function techage.item_image_small(x, y, itemname, tooltip_prefix)
tooltip tooltip
end end
function techage.mydump(o, indent, nested, level)
local t = type(o)
if not level and t == "userdata" then
-- when userdata (e.g. player) is passed directly, print its metatable:
return "userdata metatable: " .. techage.mydump(getmetatable(o))
end
if t ~= "table" then
return basic_dump(o)
end
-- Contains table -> true/nil of currently nested tables
nested = nested or {}
if nested[o] then
return "<circular reference>"
end
nested[o] = true
indent = " "
level = level or 1
local t = {}
local dumped_indexes = {}
for i, v in ipairs(o) do
t[#t + 1] = techage.mydump(v, indent, nested, level + 1)
dumped_indexes[i] = true
end
for k, v in pairs(o) do
if not dumped_indexes[k] then
if type(k) ~= "string" or not is_valid_identifier(k) then
k = "["..techage.mydump(k, indent, nested, level + 1).."]"
end
v = techage.mydump(v, indent, nested, level + 1)
t[#t + 1] = k.." = "..v
end
end
nested[o] = nil
if indent ~= "" then
local indent_str = string.rep(indent, level)
local end_indent_str = string.rep(indent, level - 1)
return string.format("{%s%s%s}",
indent_str,
table.concat(t, ","..indent_str),
end_indent_str)
end
return "{"..table.concat(t, ", ").."}"
end
function techage.vector_dump(posses) function techage.vector_dump(posses)
local t = {} local t = {}
for _,pos in ipairs(posses) do for _,pos in ipairs(posses) do
@ -493,6 +492,10 @@ function techage.register_mobs_mods(mod)
techage.RegisteredMobsMods[mod] = true techage.RegisteredMobsMods[mod] = true
end end
function techage.beduino_signed_var(val)
val = val or 0
return val >= 32768 and val - 0x10000 or val
end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Terminal history buffer -- Terminal history buffer
@ -561,6 +564,8 @@ function techage.add_expoint(player, number)
end end
end end
-- Delete number with: `//lua minetest.get_player_by_name("<name>"):get_meta():set_string("techage_collider_number", "")`
function techage.on_remove_collider(player) function techage.on_remove_collider(player)
if player and player.get_meta then if player and player.get_meta then
local meta = player:get_meta() local meta = player:get_meta()

View File

@ -82,7 +82,7 @@ minetest.register_entity(":techage:region_cube", {
initial_properties = { initial_properties = {
visual = "upright_sprite", visual = "upright_sprite",
textures = {"techage_cube_mark.png"}, textures = {"techage_cube_mark.png"},
use_texture_alpha = true, use_texture_alpha = techage.BLEND,
physical = false, physical = false,
glow = 12, glow = 12,
}, },

View File

@ -70,7 +70,7 @@ minetest.register_entity(":techage:position_cube", {
"techage_cube_mark.png", "techage_cube_mark.png",
"techage_cube_mark.png", "techage_cube_mark.png",
}, },
use_texture_alpha = true, use_texture_alpha = techage.BLEND,
physical = false, physical = false,
visual_size = {x = 1.1, y = 1.1}, visual_size = {x = 1.1, y = 1.1},
collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55}, collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},

View File

@ -97,7 +97,6 @@ minetest.register_entity(":techage:block_marker", {
"techage_cube_mark.png", "techage_cube_mark.png",
"techage_cube_mark.png", "techage_cube_mark.png",
}, },
--use_texture_alpha = true,
physical = false, physical = false,
visual_size = {x=1.1, y=1.1}, visual_size = {x=1.1, y=1.1},
collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55}, collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -66,12 +66,14 @@ local N = techage.get_node_lvm
-- TechAge machine states -- TechAge machine states
-- --
techage.RUNNING = 1 -- in normal operation/turned on techage.RUNNING = 1 -- in normal operation/turned on
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory 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.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.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.FAULT = 5 -- any fault state (e.g. wrong source items), which can be fixed by the player
techage.STOPPED = 6 -- not operational/turned off techage.STOPPED = 6 -- not operational/turned off
techage.UNLOADED = 7 -- Map block unloaded
techage.INACTIVE = 8 -- Map block loaded but node is not actively working
techage.StatesImg = { techage.StatesImg = {
"techage_inv_button_on.png", "techage_inv_button_on.png",
@ -133,13 +135,15 @@ local function has_power(pos, nvm)
return true return true
end end
local function swap_node(pos, name) local function swap_node(pos, new_name, old_name)
local node = techage.get_node_lvm(pos) local node = techage.get_node_lvm(pos)
if node.name == name then if node.name == new_name then
return return
end end
node.name = name if node.name == old_name then
minetest.swap_node(pos, node) node.name = new_name
minetest.swap_node(pos, node)
end
end end
-- true if node_timer should be executed -- true if node_timer should be executed
@ -174,7 +178,7 @@ function NodeStates:new(attr)
cycle_time = attr.cycle_time, -- for running state cycle_time = attr.cycle_time, -- for running state
standby_ticks = attr.standby_ticks, -- for standby state standby_ticks = attr.standby_ticks, -- for standby state
-- optional -- optional
countdown_ticks = attr.countdown_ticks or 1, countdown_ticks = attr.countdown_ticks or 1,
node_name_passive = attr.node_name_passive, node_name_passive = attr.node_name_passive,
node_name_active = attr.node_name_active, node_name_active = attr.node_name_active,
infotext_name = attr.infotext_name, infotext_name = attr.infotext_name,
@ -220,7 +224,7 @@ function NodeStates:stop(pos, nvm)
self.stop_node(pos, nvm, state) self.stop_node(pos, nvm, state)
end end
if self.node_name_passive then if self.node_name_passive then
swap_node(pos, self.node_name_passive) swap_node(pos, self.node_name_passive, self.node_name_active)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -257,7 +261,7 @@ function NodeStates:start(pos, nvm)
end end
nvm.techage_countdown = self.countdown_ticks nvm.techage_countdown = self.countdown_ticks
if self.node_name_active then if self.node_name_active then
swap_node(pos, self.node_name_active) swap_node(pos, self.node_name_active, self.node_name_passive)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -288,7 +292,7 @@ function NodeStates:standby(pos, nvm, err_string)
if state == RUNNING or state == BLOCKED then if state == RUNNING or state == BLOCKED then
nvm.techage_state = STANDBY nvm.techage_state = STANDBY
if self.node_name_passive then if self.node_name_passive then
swap_node(pos, self.node_name_passive) swap_node(pos, self.node_name_passive, self.node_name_active)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -313,7 +317,7 @@ function NodeStates:blocked(pos, nvm, err_string)
if state == RUNNING then if state == RUNNING then
nvm.techage_state = BLOCKED nvm.techage_state = BLOCKED
if self.node_name_passive then if self.node_name_passive then
swap_node(pos, self.node_name_passive) swap_node(pos, self.node_name_passive, self.node_name_active)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -337,7 +341,7 @@ function NodeStates:nopower(pos, nvm, err_string)
if state ~= NOPOWER then if state ~= NOPOWER then
nvm.techage_state = NOPOWER nvm.techage_state = NOPOWER
if self.node_name_passive then if self.node_name_passive then
swap_node(pos, self.node_name_passive) swap_node(pos, self.node_name_passive, self.node_name_active)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -362,7 +366,7 @@ function NodeStates:fault(pos, nvm, err_string)
if state == RUNNING or state == STOPPED then if state == RUNNING or state == STOPPED then
nvm.techage_state = FAULT nvm.techage_state = FAULT
if self.node_name_passive then if self.node_name_passive then
swap_node(pos, self.node_name_passive) swap_node(pos, self.node_name_passive, self.node_name_active)
end end
if self.infotext_name then if self.infotext_name then
local number = M(pos):get_string("node_number") local number = M(pos):get_string("node_number")
@ -479,6 +483,40 @@ function NodeStates:on_receive_message(pos, topic, payload)
end end
end end
function NodeStates:on_beduino_receive_cmnd(pos, topic, payload)
if topic == 1 then
if payload[1] == 0 then
self:stop(pos, techage.get_nvm(pos))
return 0
else
self:start(pos, techage.get_nvm(pos))
return 0
end
else
return 2 -- unknown or invalid topic
end
end
function NodeStates:on_beduino_request_data(pos, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then
local node = minetest.get_node(pos)
if node.name == "ignore" then -- unloaded node?
return 0, {techage.UNLOADED}
elseif nvm.techage_state == RUNNING then
local ttl = (nvm.last_active or 0) + 2 * (self.cycle_time or 0)
if ttl < minetest.get_gametime() then
return 0, {techage.INACTIVE}
end
end
return 0, {nvm.techage_state or STOPPED}
else
return 2, "" -- topic is unknown or invalid
end
end
-- restart timer -- restart timer
function NodeStates:on_node_load(pos) function NodeStates:on_node_load(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)

View File

@ -71,7 +71,7 @@ end
------------------------------------------------------------------- -------------------------------------------------------------------
-- Storage scheduler -- Storage scheduler
------------------------------------------------------------------- -------------------------------------------------------------------
local CYCLE_TIME = 900 -- store data every 15 min local CYCLE_TIME = 600 -- store data every 10 min
local JobQueue = {} local JobQueue = {}
local first = 0 local first = 0
local last = -1 local last = -1

View File

@ -74,9 +74,12 @@ local function input_string(recipe)
return table.concat(tbl, "") return table.concat(tbl, "")
end end
function techage.recipes.get(nvm, rtype) function techage.recipes.get(nvm, rtype, owner)
local recipes = Recipes[rtype] or {} local recipes = Recipes[rtype] or {}
return recipes[nvm.recipe_idx or 1] if owner then
recipes = filter_recipes_based_on_points(recipes, owner)
end
return recipes[nvm.recipe_idx or 1] or recipes[1]
end end
-- Add 4 input/output/waste recipe -- Add 4 input/output/waste recipe

View File

@ -101,7 +101,7 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
elseif elem.type == "dropdown" then elseif elem.type == "dropdown" then
local l = elem.choices:split(",") local l = elem.choices:split(",")
if nvm.running or techage.is_running(nvm) then if nvm.running or techage.is_running(nvm) then
local val = elem.default local val = elem.default or ""
if meta:contains(elem.name) then if meta:contains(elem.name) then
val = meta:get_string(elem.name) or "" val = meta:get_string(elem.name) or ""
end end

View File

@ -0,0 +1,60 @@
--[[
TechAge
=======
Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
K/V Store for the Beduino controller
]]--
local COSTS = 400
local function ta_kv_init(cpu_pos, address, regA, regB, regC)
local nvm = techage.get_nvm(cpu_pos)
nvm.kv_store = {}
return 1, COSTS
end
local function ta_kv_add(cpu_pos, address, regA, regB, regC)
local nvm = techage.get_nvm(cpu_pos)
local text = vm16.read_ascii(cpu_pos, regA, 32)
nvm.kv_store[text] = regB
return 1, COSTS
end
local function ta_kv_get(cpu_pos, address, regA, regB, regC)
local nvm = techage.get_nvm(cpu_pos)
local text = vm16.read_ascii(cpu_pos, regA, 32)
return nvm.kv_store[text] or 0, COSTS
end
local kvstore_c = [[
// Initialize the key/value store
func ta_kv_init() {
return system(0x140, 0);
}
// Add a key/value pair to the store
func ta_kv_add(key_str, value) {
return system(0x141, key_str, value);
}
// Returns the value for the given key string
func ta_kv_get(key_str) {
return system(0x142, key_str);
}
]]
minetest.register_on_mods_loaded(function()
if minetest.global_exists("beduino") and minetest.global_exists("vm16") then
beduino.lib.register_SystemHandler(0x140, ta_kv_init)
beduino.lib.register_SystemHandler(0x141, ta_kv_add)
beduino.lib.register_SystemHandler(0x142, ta_kv_get)
vm16.register_ro_file("beduino", "ta_kvstore.c", kvstore_c)
end
end)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -159,6 +159,15 @@ techage.register_node({"techage:chest_cart"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
else
return 2, ""
end
end,
}) })
Tube:set_valid_sides("techage:chest_cart", {"L", "R", "F", "B"}) Tube:set_valid_sides("techage:chest_cart", {"L", "R", "F", "B"})

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -360,6 +360,12 @@ techage.register_node({"techage:ta4_doser", "techage:ta4_doser_on"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return State:on_beduino_request_data(pos, topic, payload)
end,
}) })
techage.recipes.register_craft_type("ta4_doser", { techage.recipes.register_craft_type("ta4_doser", {

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -207,6 +207,18 @@ techage.register_node({"techage:coalfirebox"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then
return 0, {nvm.running and techage.RUNNING or techage.STOPPED}
elseif topic == 132 then
return 0, {techage.fuel.get_fuel_amount(nvm)}
else
return 2, ""
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -231,6 +231,17 @@ techage.register_node({"techage:generator", "techage:generator_on"}, {
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 135 then -- Delivered Power
return 0, {math.floor((nvm.provided or 0) + 0.5)}
else
return State:on_beduino_request_data(pos, topic, payload)
end
end,
}) })
-- used by power terminal -- used by power terminal

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -132,6 +132,18 @@ techage.register_node({"techage:oilfirebox"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then
return 0, {nvm.running and techage.RUNNING or techage.STOPPED}
elseif topic == 132 then
return 0, {fuel.get_fuel_amount(nvm)}
else
return 2, ""
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -21,7 +21,9 @@ local getpos = techage.assemble.get_pos
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local TNO_MAGNETS = 22 local TNO_MAGNETS = 22
local PROBABILITY = 180 -- check every 20 s => 20 * 180 * 50% = 30 min local IMPROBABILITY = 60 -- every 60 min
-- one point per 60 min: check every 20 s => factor = 60 * 3 = 180
IMPROBABILITY = (minetest.settings:get("techage_expoint_rate_in_min") or 60) * 3
local TIME_SLOTS = 10 local TIME_SLOTS = 10
local Schedule = {[0] = local Schedule = {[0] =
@ -59,7 +61,7 @@ local function terminal_message(pos, msg)
end end
local function experience_points(pos) local function experience_points(pos)
if math.random(PROBABILITY) == 1 then if math.random(IMPROBABILITY) == 1 then
local owner = M(pos):get_string("owner") local owner = M(pos):get_string("owner")
local own_num = M(pos):get_string("node_number") local own_num = M(pos):get_string("node_number")
local player = minetest.get_player_by_name(owner) local player = minetest.get_player_by_name(owner)

View File

@ -110,6 +110,7 @@ techage.Items = {
ta3_logic = "techage:ta3_logic", ta3_logic = "techage:ta3_logic",
ta3_nodedetector = "techage:ta3_nodedetector_off", ta3_nodedetector = "techage:ta3_nodedetector_off",
ta3_playerdetector = "techage:ta3_playerdetector_off", ta3_playerdetector = "techage:ta3_playerdetector_off",
ta3_lightdetector = "techage:ta3_lightdetector_off",
ta3_repeater = "techage:ta3_repeater", ta3_repeater = "techage:ta3_repeater",
ta3_sequencer = "techage:ta3_sequencer", ta3_sequencer = "techage:ta3_sequencer",
ta3_timer = "techage:ta3_timer", ta3_timer = "techage:ta3_timer",

View File

@ -124,6 +124,7 @@ techage.manual_DE.aTitel = {
"3,TA3 Wagen Detektor / Cart Detector", "3,TA3 Wagen Detektor / Cart Detector",
"3,TA3 Block Detektor / Node Detector", "3,TA3 Block Detektor / Node Detector",
"3,TA3 Spieler Detektor / Player Detector", "3,TA3 Spieler Detektor / Player Detector",
"3,TA3 Lichtdetektor",
"2,TA3 Maschinen", "2,TA3 Maschinen",
"3,TA3 Schieber / Pusher", "3,TA3 Schieber / Pusher",
"3,TA3 Verteiler / Distributor", "3,TA3 Verteiler / Distributor",
@ -1145,9 +1146,15 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"Wird ein 'on' / 'off' Kommando an den Tür Controller II gesendet\\, entfernt bzw. setzt er die Blöcke ebenfalls.\n".. "Wird ein 'on' / 'off' Kommando an den Tür Controller II gesendet\\, entfernt bzw. setzt er die Blöcke ebenfalls.\n"..
"\n".. "\n"..
"Über ein 'exchange' Kommando können einzelne Böcke gesetzt\\, entfernt\\, bzw. durch andere Blöcke ersetzt werden. Die Slot-Nummer des Inventars (1 .. 16) muss als payload übergeben werden\\, also:\n".. "Mit '$send_cmnd(node_number\\, \"exchange\"\\, 2)' können einzelne Böcke gesetzt\\, entfernt\\, bzw. durch andere Blöcke aus dem Inventar ersetzt werden. \n"..
"\n".. "\n"..
" $send_cmnd(node_number\\, \"exchange\"\\, 2)\n".. "Mit '$send_cmnd(node_number\\, \"set\"\\, 2)' kann ein Block aus dem Inventory explizit gesetzt werden\\, sofern der Inventory Slot nicht leer ist.\n"..
"\n"..
"Mit '$send_cmnd(node_number\\, \"dig\"\\, 2)' kann ein Block wieder entfernt werden\\, sofern der Inventory Slot leer ist. \n"..
"\n"..
"Mit '$send_cmnd(node_number\\, \"get\"\\, 2)' wird der Name des gesetzten Blocks zurückgeliefert. \n"..
"\n"..
"Die Slot-Nummer des Inventars (1 .. 16) muss in allen drei Fällen als payload übergeben werden.\n"..
"\n".. "\n"..
"Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren.\n".. "Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren.\n"..
"\n".. "\n"..
@ -1159,7 +1166,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
" - Kommando 'on' zum Abspielen eines Sounds\n".. " - Kommando 'on' zum Abspielen eines Sounds\n"..
" - Kommando 'sound <idx>' zur Auswahl eines Sounds über den Index\n".. " - Kommando 'sound <idx>' zur Auswahl eines Sounds über den Index\n"..
" - Kommando 'gain <volume>' zum Einstellen der Lautstärke über den '<volume>' Wert (0 bis 1.0).\n".. " - Kommando 'gain <volume>' zum Einstellen der Lautstärke über den '<volume>' Wert (1 bis 5).\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -1198,6 +1205,11 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"Der Lichtdetektor sendet einen 'on'-Kommando\\, wenn der Lichtpegel des darüber liegenden Blocks einen bestimmten Pegel überschreitet\\, der über das Rechtsklickmenü eingestellt werden kann.\n"..
"Mit einen TA4 Lua Controller kann die genaue Lichtstärke mit $get_cmd(num\\, 'light_level') ermitteln werden.\n"..
"\n"..
"\n"..
"\n",
"Bei TA3 existieren die gleichen Maschinen wie bei TA2\\, nur sind diese hier leistungsfähiger und benötigen Strom statt Achsenantrieb.\n".. "Bei TA3 existieren die gleichen Maschinen wie bei TA2\\, nur sind diese hier leistungsfähiger und benötigen Strom statt Achsenantrieb.\n"..
"Im folgenden sind daher nur die unterschiedlichen\\, technischen Daten angegeben.\n".. "Im folgenden sind daher nur die unterschiedlichen\\, technischen Daten angegeben.\n"..
"\n".. "\n"..
@ -1680,6 +1692,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
" - 'goto <num>' Zu einer Kommandozeile springen und damit den Sequenzer starten\n".. " - 'goto <num>' Zu einer Kommandozeile springen und damit den Sequenzer starten\n"..
" - 'stop' Den Sequenzer anhalten\n".. " - 'stop' Den Sequenzer anhalten\n"..
" - 'on' und 'off' als Alias für 'goto 1' bzw. 'stop'\n"..
"\n".. "\n"..
"Das 'goto' Kommando wird nur angenommen\\, wenn der Sequenzer gestoppt ist.\n".. "Das 'goto' Kommando wird nur angenommen\\, wenn der Sequenzer gestoppt ist.\n"..
"\n".. "\n"..
@ -1907,7 +1920,7 @@ techage.manual_DE.aText = {
"\n".. "\n"..
"Der TA4 Schieber besitzt zwei zusätzliche Kommandos für den Lua Controller:\n".. "Der TA4 Schieber besitzt zwei zusätzliche Kommandos für den Lua Controller:\n"..
"\n".. "\n"..
" - 'config' dient zur Konfiguration des Schiebers\\, analog zum manuellen Konfiguration über das Menü.\nBeispiel: '$send_cmnd(1234\\, \"config\"\\, \"default:dirt\")'\n".. " - 'config' dient zur Konfiguration des Schiebers\\, analog zum manuellen Konfiguration über das Menü.\nBeispiel: '$send_cmnd(1234\\, \"config\"\\, \"default:dirt\")'\nMit '$send_cmnd(1234\\, \"config\"\\, \"\")' wird die Konfiguration gelöscht\n"..
" - 'pull' dient zum Absetzen eines Auftrags an den Schieber:\nBeispiel: '$send_cmnd(1234\\, \"pull\"\\, \"default:dirt 8\")'\nAls Nummer sind Werte von 1 bis 12 zulässig. Danach geht der Schieber wieder in den 'stopped' Mode und sendet ein \"off\" Kommando zurück an den Sender des \"pull\" Kommandos.\n".. " - 'pull' dient zum Absetzen eines Auftrags an den Schieber:\nBeispiel: '$send_cmnd(1234\\, \"pull\"\\, \"default:dirt 8\")'\nAls Nummer sind Werte von 1 bis 12 zulässig. Danach geht der Schieber wieder in den 'stopped' Mode und sendet ein \"off\" Kommando zurück an den Sender des \"pull\" Kommandos.\n"..
"\n".. "\n"..
"\n".. "\n"..
@ -2240,6 +2253,7 @@ techage.manual_DE.aItemName = {
"ta3_cartdetector", "ta3_cartdetector",
"ta3_nodedetector", "ta3_nodedetector",
"ta3_playerdetector", "ta3_playerdetector",
"ta3_lightdetector",
"ta3_grinder", "ta3_grinder",
"ta3_pusher", "ta3_pusher",
"ta3_distributor", "ta3_distributor",
@ -2511,6 +2525,7 @@ techage.manual_DE.aPlanTable = {
"", "",
"", "",
"", "",
"",
"ta4_windturbine", "ta4_windturbine",
"", "",
"", "",

View File

@ -124,6 +124,7 @@ techage.manual_EN.aTitel = {
"3,TA3 Cart Detector", "3,TA3 Cart Detector",
"3,TA3 Block Detector", "3,TA3 Block Detector",
"3,TA3 Player Detector", "3,TA3 Player Detector",
"3,TA3 Light Detector",
"2,TA3 Machines", "2,TA3 Machines",
"3,TA3 Pusher", "3,TA3 Pusher",
"3,TA3 Distributor", "3,TA3 Distributor",
@ -1143,9 +1144,15 @@ techage.manual_EN.aText = {
"\n", "\n",
"The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II\\, the \"Record\" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the \"Done\" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the \"Remove\" or \"Set\" buttons. If an 'on' /'off' command is sent to the Door Controller II\\, it removes or sets the blocks as well.\n".. "The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II\\, the \"Record\" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the \"Done\" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the \"Remove\" or \"Set\" buttons. If an 'on' /'off' command is sent to the Door Controller II\\, it removes or sets the blocks as well.\n"..
"\n".. "\n"..
"Individual blocks can be set\\, removed or replaced by other blocks via an 'exchange' command. The slot number of the inventory (1 .. 16) must be transferred as payload\\, i.e.:\n".. "With '$send_cmnd(node_number\\, \"exchange\"\\, 2)' individual blocks can be set\\, removed or replaced by other blocks from the inventory. \n"..
"\n".. "\n"..
" $send_cmnd(node_number\\, \"exchange\"\\, 2)\n".. "With '$send_cmnd(node_number\\, \"set\"\\, 2)' a block from the inventory can be set explicitly\\, as long as the inventory slot is not empty.\n"..
"\n"..
"A block can be removed again with '$send_cmnd(node_number\\, \"dig\"\\, 2)' if the inventory slot is empty. \n"..
"\n"..
"The name of the set block is returned with '$send_cmnd(node_number\\, \"get\"\\, 2)'.\n"..
"\n"..
"The slot number of the inventory (1 .. 16) must be passed as payload in all three cases.\n"..
"\n".. "\n"..
"This can also be used to simulate extendable stairs and the like. \n".. "This can also be used to simulate extendable stairs and the like. \n"..
"\n".. "\n"..
@ -1157,7 +1164,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
" - Command 'on' to play a sound\n".. " - Command 'on' to play a sound\n"..
" - Command 'sound <idx>' to select a sound via the index\n".. " - Command 'sound <idx>' to select a sound via the index\n"..
" - Command 'gain <volume>' to adjust the volume via the '<volume>' value (0 to 1.0).\n".. " - Command 'gain <volume>' to adjust the volume via the '<volume>' value (1 to 5).\n"..
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
@ -1196,6 +1203,11 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"\n".. "\n"..
"\n", "\n",
"The light detector sends an 'on' command if the light level of the block above exceeds a certain level\\, which can be set through the right-click menu.\n"..
"If you have a TA4 Lua Controller\\, you can get the exact light level with $get_cmd(num\\, 'light_level')\n"..
"\n"..
"\n"..
"\n",
"TA3 has the same machines as TA2\\, only these are more powerful and require electricity instead of axis drive.\n".. "TA3 has the same machines as TA2\\, only these are more powerful and require electricity instead of axis drive.\n"..
"Therefore\\, only the different technical data are given below.\n".. "Therefore\\, only the different technical data are given below.\n"..
"\n".. "\n"..
@ -1676,6 +1688,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
" - 'goto <num>' Jump to a command line and start the sequencer\n".. " - 'goto <num>' Jump to a command line and start the sequencer\n"..
" - 'stop' Stop the sequencer\n".. " - 'stop' Stop the sequencer\n"..
" - 'on' and 'off' as aliases for 'goto 1' resp. 'stop'\n"..
"\n".. "\n"..
"The 'goto' command is only accepted when the sequencer is stopped.\n".. "The 'goto' command is only accepted when the sequencer is stopped.\n"..
"\n".. "\n"..
@ -1903,7 +1916,7 @@ techage.manual_EN.aText = {
"\n".. "\n"..
"The TA4 pusher has two additional commands for the Lua controller:\n".. "The TA4 pusher has two additional commands for the Lua controller:\n"..
"\n".. "\n"..
" - 'config' is used to configure the pusher\\, analogous to manual configuration via the menu.\nExample: '$send_cmnd(1234\\, \"config\"\\, \"default: dirt\")'\n".. " - 'config' is used to configure the pusher\\, analogous to manual configuration via the menu.\nExample: '$send_cmnd(1234\\, \"config\"\\, \"default: dirt\")'\nWith '$send_cmnd(1234\\, \"config\"\\, \"\")' the configuration is deleted\n"..
" - 'pull' is used to send an order to the pusher:\nExample: '$send_cmnd(1234\\, \"pull\"\\, \"default: dirt 8\")'\nValues from 1 to 12 are permitted as numbers. Then the pusher goes back to 'stopped' mode and sends an\" off \"command back to the transmitter of the\" pull \"command.\n".. " - 'pull' is used to send an order to the pusher:\nExample: '$send_cmnd(1234\\, \"pull\"\\, \"default: dirt 8\")'\nValues from 1 to 12 are permitted as numbers. Then the pusher goes back to 'stopped' mode and sends an\" off \"command back to the transmitter of the\" pull \"command.\n"..
"\n".. "\n"..
"\n".. "\n"..
@ -2235,6 +2248,7 @@ techage.manual_EN.aItemName = {
"ta3_cartdetector", "ta3_cartdetector",
"ta3_nodedetector", "ta3_nodedetector",
"ta3_playerdetector", "ta3_playerdetector",
"ta3_lightdetector",
"ta3_grinder", "ta3_grinder",
"ta3_pusher", "ta3_pusher",
"ta3_distributor", "ta3_distributor",
@ -2505,6 +2519,7 @@ techage.manual_EN.aPlanTable = {
"", "",
"", "",
"", "",
"",
"ta4_windturbine", "ta4_windturbine",
"", "",
"", "",

View File

@ -511,8 +511,6 @@ techage.ConstructionPlans["ta5_teleport"] = {
{false, false, false, false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false, false, false, false},
{false, TANK4, PUMP4, TELEP, false, ARROW, false, TELEP, PIPEH, TANK4, false}, {false, TANK4, PUMP4, TELEP, false, ARROW, false, TELEP, PIPEH, TANK4, false},
{false, false, false, false, false, false, false, false, false, false, false},
{false, TANK4, PIPEH, TELEP, false, ARROW, false, TELEP, PUMP4, TANK4, false},
} }
-- --

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -356,6 +356,37 @@ techage.register_node({"techage:heatexchanger2"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 1 and payload[1] == 1 then
start_node(pos, techage.get_nvm(pos))
return 0
elseif topic == 1 and payload[1] == 0 then
stop_node(pos, techage.get_nvm(pos))
return 0
else
return 2, ""
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then -- State
if techage.is_running(nvm) then
return 0, {techage.RUNNING}
else
return 0, {techage.STOPPED}
end
elseif topic == 135 then -- Delivered Power
local data = power.get_network_data(pos, Cable, DOWN)
return 0, {data.consumed - data.provided}
elseif topic == 134 then -- Tank Load Percent
return 0, {techage.power.percent(nvm.capa_max, nvm.capa)}
else
return 2, ""
end
end,
on_node_load = function(pos, node) on_node_load = function(pos, node)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then if techage.is_running(nvm) then

View File

@ -74,7 +74,7 @@ for idx,ratio in ipairs(lRatio) do
end end
end, end,
use_texture_alpha = true, use_texture_alpha = techage.BLEND,
inventory_image = "techage_flame.png", inventory_image = "techage_flame.png",
paramtype = "light", paramtype = "light",
light_source = 13, light_source = 13,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -173,6 +173,18 @@ techage.register_node({"techage:furnace_firebox", "techage:furnace_firebox_on"},
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then -- State
return 0, {nvm.running and techage.RUNNING or techage.STOPPED}
elseif topic == 132 then -- Fuel Level
return 0, {fuel.get_fuel_amount(nvm)}
else
return 2, ""
end
end,
-- called from furnace_top -- called from furnace_top
on_transfer = function(pos, in_dir, topic, payload) on_transfer = function(pos, in_dir, topic, payload)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -257,6 +257,17 @@ local tubing = {
return CRD(pos).State:on_receive_message(pos, topic, payload) return CRD(pos).State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 141 then -- Furnace Output
local nvm = techage.get_nvm(pos)
return 0, string.split(nvm.output or "unknown", " ")[1]
else
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
end
end,
} }
local _, node_name_ta3, _ = local _, node_name_ta3, _ =

View File

@ -46,6 +46,7 @@ local function count_trues(t)
end end
local function nucleus(t) local function nucleus(t)
t = techage.tbl_filter(t, function(v, k, t) return type(v) == "table" end)
if #t == 4 then if #t == 4 then
if vector.equals(t[1], t[2]) and vector.equals(t[3], t[4]) then if vector.equals(t[1], t[2]) and vector.equals(t[3], t[4]) then
return true return true
@ -268,6 +269,12 @@ techage.register_node({"techage:ta5_fr_controller_pas", "techage:ta5_fr_controll
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return State:on_beduino_request_data(pos, topic, payload)
end,
}) })
power.register_nodes({"techage:ta5_fr_controller_pas", "techage:ta5_fr_controller_act"}, Cable, "con", {"L", "R"}) power.register_nodes({"techage:ta5_fr_controller_pas", "techage:ta5_fr_controller_act"}, Cable, "con", {"L", "R"})

View File

@ -183,7 +183,7 @@ local function steam_management(pos, nvm)
nvm.temperature = math.min(nvm.temperature + 10, 100) nvm.temperature = math.min(nvm.temperature + 10, 100)
elseif resp ~= true then elseif resp ~= true then
State:fault(pos, nvm, resp) State:fault(pos, nvm, resp)
stop_node(pos, nvm) State:stop(pos, nvm)
return false return false
end end
@ -325,15 +325,44 @@ techage.register_node({"techage:ta5_heatexchanger2"}, {
local data = power.get_network_data(pos, Cable, DOWN) local data = power.get_network_data(pos, Cable, DOWN)
return data.consumed - data.provided return data.consumed - data.provided
elseif topic == "on" then elseif topic == "on" then
start_node(pos, techage.get_nvm(pos)) State:start(pos, nvm)
return true return true
elseif topic == "off" then elseif topic == "off" then
stop_node(pos, techage.get_nvm(pos)) State:stop(pos, nvm)
return true return true
else else
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 1 and payload[1] == 1 then
start_node(pos, techage.get_nvm(pos))
return 0
elseif topic == 1 and payload[1] == 0 then
stop_node(pos, techage.get_nvm(pos))
return 0
else
return 2, ""
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 128 then
return 0, techage.get_node_lvm(pos).name
elseif topic == 129 then -- State
if techage.is_running(nvm) then
return 0, {techage.RUNNING}
else
return 0, {techage.STOPPED}
end
elseif topic == 135 then -- Delivered Power
local data = power.get_network_data(pos, Cable, DOWN)
return 0, {data.consumed - data.provided}
else
return 2, ""
end
end,
on_node_load = function(pos, node) on_node_load = function(pos, node)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then if techage.is_running(nvm) then
@ -344,7 +373,7 @@ techage.register_node({"techage:ta5_heatexchanger2"}, {
-- Attempt to restart the system as the heat exchanger goes into error state -- Attempt to restart the system as the heat exchanger goes into error state
-- when parts of the storage block are unloaded. -- when parts of the storage block are unloaded.
if nvm.techage_state == techage.FAULT then if nvm.techage_state == techage.FAULT then
start_node(pos, nvm) State:start(pos, nvm)
end end
end, end,
}) })

View File

@ -170,6 +170,12 @@ techage.register_node({"techage:ta5_pump", "techage:ta5_pump_on"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return State:on_beduino_request_data(pos, topic, payload)
end,
}) })
-- Pumps have to provide one output and one input side -- Pumps have to provide one output and one input side

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -197,11 +197,11 @@ local tool_config = {
}, },
{ {
type = "dropdown", type = "dropdown",
choices = "0%,20%,40%,60%,80%", choices = "0%,20%,40%,60%,80%,98%",
name = "turnoff", name = "turnoff",
label = S("Turnoff point"), label = S("Turnoff point"),
tooltip = S("If the charge of the storage\nsystem exceeds the configured value,\nthe block switches off"), tooltip = S("If the charge of the storage\nsystem exceeds the configured value,\nthe block switches off"),
default = "0%", default = "98%",
}, },
} }
@ -332,11 +332,24 @@ techage.register_node({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 134 and payload[1] == 1 then
return 0, {techage.power.percent(CAPACITY, (nvm.liquid and nvm.liquid.amount) or 0)}
elseif topic == 135 then
return 0, {math.floor((nvm.provided or 0) + 0.5)}
else
return State:on_beduino_request_data(pos, topic, payload)
end
end,
on_node_load = function(pos, node) on_node_load = function(pos, node)
local meta = M(pos) local meta = M(pos)
if not meta:contains("reduction") then if not meta:contains("reduction") then
meta:set_string("reduction", "100%") meta:set_string("reduction", "100%")
meta:set_string("turnoff", "0%") meta:set_string("turnoff", "100%")
end end
end, end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -304,6 +304,19 @@ techage.register_node({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, {
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 134 and payload[1] == 1 then
return 0, {techage.power.percent(CAPACITY, (nvm.liquid and nvm.liquid.amount) or 0)}
elseif topic == 135 then
return 0, {math.floor((nvm.provided or 0) + 0.5)}
else
return State:on_beduino_request_data(pos, topic, payload)
end
end,
}) })
control.register_nodes({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, { control.register_nodes({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, {

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -176,4 +176,12 @@ techage.register_node({"techage:ta4_battery"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 134 then
local meta = minetest.get_meta(pos)
return 0, {calc_percent(meta:get_int("content"))}
else
return 2, ""
end
end,
}) })

View File

@ -153,7 +153,7 @@ techage.icta_register_condition("input", {
return env.input[data.number] return env.input[data.number]
end end
local result = function(val) local result = function(val)
return techage.compare(val, data.value, data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -196,7 +196,7 @@ techage.icta_register_condition("state", {
return techage.send_single(environ.number, data.number, "state") return techage.send_single(environ.number, data.number, "state")
end end
local result = function(val) local result = function(val)
return techage.compare(val, data.value, data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -238,7 +238,7 @@ techage.icta_register_condition("fuel", {
return techage.send_single(environ.number, data.number, "fuel") return techage.send_single(environ.number, data.number, "fuel")
end end
local result = function(val) local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -280,7 +280,7 @@ techage.icta_register_condition("load", {
return techage.send_single(environ.number, data.number, "load") return techage.send_single(environ.number, data.number, "load")
end end
local result = function(val) local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -322,7 +322,7 @@ techage.icta_register_condition("depth", {
return techage.send_single(environ.number, data.number, "depth") return techage.send_single(environ.number, data.number, "depth")
end end
local result = function(val) local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -364,7 +364,7 @@ techage.icta_register_condition("delivered", {
return techage.send_single(environ.number, data.number, "delivered") return techage.send_single(environ.number, data.number, "delivered")
end end
local result = function(val) local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -408,7 +408,7 @@ techage.icta_register_condition("chest", {
return techage.send_single(environ.number, data.number, "state") return techage.send_single(environ.number, data.number, "state")
end end
local result = function(val) local result = function(val)
return techage.compare(val, data.value, data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -449,7 +449,7 @@ techage.icta_register_condition("signaltower", {
return techage.send_single(environ.number, data.number, "state") return techage.send_single(environ.number, data.number, "state")
end end
local result = function(val) local result = function(val)
return techage.compare(val, data.value, data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,
@ -919,7 +919,7 @@ techage.icta_register_condition("get_filter", {
return techage.send_single(environ.number, data.number, "port", data.color) return techage.send_single(environ.number, data.number, "port", data.color)
end end
local result = function(val) local result = function(val)
return techage.compare(val, data.value, data.operand) return techage.compare(val, tonumber(data.value) or 0, data.operand)
end end
return condition, result return condition, result
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -444,4 +444,30 @@ techage.register_node({"techage:ta4_icta_controller"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local state = meta:get_int("state")
if state == techage.RUNNING and topic == 1 and payload[1] == 1 then
set_input(pos, number, src, topic)
elseif state == techage.RUNNING and topic == 1 and payload[1] == 0 then
set_input(pos, number, src, topic)
else
return 2
end
return 0
end,
on_beduino_request_data = function(pos, src, topic, payload)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local state = meta:get_int("state")
if topic == 129 then
local state = meta:get_int("state") or 0
return 0, {state or techage.STOPPED}
else
return 2, ""
end
end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -211,13 +211,21 @@ function techage.display.add_line(pos, payload, cycle_time)
table.insert(nvm.text, str) table.insert(nvm.text, str)
end end
function techage.display.write_row(pos, payload, cycle_time) function techage.display.write_row(pos, payload, cycle_time, beduino)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
local mem = techage.get_mem(pos) local mem = techage.get_mem(pos)
local str, row
nvm.text = nvm.text or {} nvm.text = nvm.text or {}
mem.ticks = mem.ticks or 0 mem.ticks = mem.ticks or 0
local str = tostring(payload.get("str")) or "oops"
local row = tonumber(payload.get("row")) or 1 if beduino then
row = tonumber(payload:sub(1,1) or "1") or 1
str = payload:sub(2) or "oops"
else
str = tostring(payload.get("str")) or "oops"
row = tonumber(payload.get("row")) or 1
end
if mem.ticks == 0 then if mem.ticks == 0 then
mem.ticks = cycle_time mem.ticks = cycle_time
@ -254,6 +262,18 @@ techage.register_node({"techage:ta4_display"}, {
techage.display.clear_screen(pos, 1) techage.display.clear_screen(pos, 1)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 67 then -- add one line and scroll if necessary
techage.display.add_line(pos, payload, 1)
elseif topic == 68 then -- overwrite the given row
techage.display.write_row(pos, payload, 1, true)
elseif topic == 17 then -- clear the screen
techage.display.clear_screen(pos, 1)
else
return 2
end
return 0
end,
}) })
techage.register_node({"techage:ta4_displayXL"}, { techage.register_node({"techage:ta4_displayXL"}, {
@ -266,6 +286,18 @@ techage.register_node({"techage:ta4_displayXL"}, {
techage.display.clear_screen(pos, 2) techage.display.clear_screen(pos, 2)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 67 then -- add one line and scroll if necessary
techage.display.add_line(pos, payload, 2)
elseif topic == 68 then -- overwrite the given row
techage.display.write_row(pos, payload, 2, true)
elseif topic == 17 then -- clear the screen
techage.display.clear_screen(pos, 2)
else
return 2
end
return 0
end,
}) })
lcdlib.register_display_entity("techage:display_entity") lcdlib.register_display_entity("techage:display_entity")

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -132,4 +132,27 @@ techage.register_node({"techage:ta4_signaltower",
return meta:get_string("state") return meta:get_string("state")
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 2 then
local color = ({"green", "amber", "red"})[payload[1]]
local node = minetest.get_node(pos)
if color then
switch_on(pos, node, color)
else
switch_off(pos, node)
end
return 0
else
return 2 -- unknown or invalid topic
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 130 then
local meta = minetest.get_meta(pos)
local color = ({off = 0, green = 1, amber = 2, red = 3})[meta:get_string("state")] or 1
return 0, {color}
else
return 2, "" -- unknown or invalid topic
end
end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -13,7 +13,7 @@
techage = {} techage = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
techage.version = 1.07 techage.version = 1.08
if minetest.global_exists("tubelib") then if minetest.global_exists("tubelib") then
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!") minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
@ -285,6 +285,7 @@ dofile(MP.."/logic/timer.lua")
dofile(MP.."/logic/lua_logic.lua") -- old dofile(MP.."/logic/lua_logic.lua") -- old
dofile(MP.."/logic/logic_block.lua") -- new dofile(MP.."/logic/logic_block.lua") -- new
dofile(MP.."/logic/node_detector.lua") dofile(MP.."/logic/node_detector.lua")
dofile(MP.."/logic/light_detector.lua")
dofile(MP.."/logic/player_detector.lua") dofile(MP.."/logic/player_detector.lua")
dofile(MP.."/logic/mba_detector.lua") dofile(MP.."/logic/mba_detector.lua")
dofile(MP.."/logic/cart_detector.lua") dofile(MP.."/logic/cart_detector.lua")
@ -412,8 +413,8 @@ dofile(MP.."/fusion_reactor/generator.lua")
dofile(MP.."/fusion_reactor/turbine.lua") dofile(MP.."/fusion_reactor/turbine.lua")
dofile(MP.."/fusion_reactor/ta5_pump.lua") dofile(MP.."/fusion_reactor/ta5_pump.lua")
-- Beduino extensions
dofile(MP.."/beduino/kv_store.lua")
-- Prevent other mods from using IE -- Prevent other mods from using IE
techage.IE = nil techage.IE = nil
function techage.icta_register_condition(key, tData) end

View File

@ -13,7 +13,7 @@
]]-- ]]--
local function register_alias(name) local function register_alias(name)
minetest.register_alias("stairs:slab_" ..name, "techage:slab_" ..name) --minetest.register_alias("stairs:slab_" ..name, "techage:slab_" ..name)
minetest.register_alias("stairs:slab_" ..name.. "_inverted", "techage:slab_" ..name.. "_inverted") minetest.register_alias("stairs:slab_" ..name.. "_inverted", "techage:slab_" ..name.. "_inverted")
minetest.register_alias("stairs:slab_" ..name.. "_wall", "techage:slab_" ..name.. "_wall") minetest.register_alias("stairs:slab_" ..name.. "_wall", "techage:slab_" ..name.. "_wall")
minetest.register_alias("stairs:slab_" ..name.. "_quarter", "techage:slab_" ..name.. "_quarter") minetest.register_alias("stairs:slab_" ..name.. "_quarter", "techage:slab_" ..name.. "_quarter")
@ -22,7 +22,7 @@ local function register_alias(name)
minetest.register_alias("stairs:slab_" ..name.. "_three_quarter", "techage:slab_" ..name.. "_three_quarter") minetest.register_alias("stairs:slab_" ..name.. "_three_quarter", "techage:slab_" ..name.. "_three_quarter")
minetest.register_alias("stairs:slab_" ..name.. "_three_quarter_inverted", "techage:slab_" ..name.. "_three_quarter_inverted") minetest.register_alias("stairs:slab_" ..name.. "_three_quarter_inverted", "techage:slab_" ..name.. "_three_quarter_inverted")
minetest.register_alias("stairs:slab_" ..name.. "_three_quarter_wall", "techage:slab_" ..name.. "_three_quarter_wall") minetest.register_alias("stairs:slab_" ..name.. "_three_quarter_wall", "techage:slab_" ..name.. "_three_quarter_wall")
minetest.register_alias("stairs:stair_" ..name, "techage:stair_" ..name) --minetest.register_alias("stairs:stair_" ..name, "techage:stair_" ..name)
minetest.register_alias("stairs:stair_" ..name.. "_inverted", "techage:stair_" ..name.. "_inverted") minetest.register_alias("stairs:stair_" ..name.. "_inverted", "techage:stair_" ..name.. "_inverted")
minetest.register_alias("stairs:stair_" ..name.. "_wall", "techage:stair_" ..name.. "_wall") minetest.register_alias("stairs:stair_" ..name.. "_wall", "techage:stair_" ..name.. "_wall")
minetest.register_alias("stairs:stair_" ..name.. "_wall_half", "techage:stair_" ..name.. "_wall_half") minetest.register_alias("stairs:stair_" ..name.. "_wall_half", "techage:stair_" ..name.. "_wall_half")

View File

@ -64,4 +64,7 @@ techage.register_mobs_mods("wildlife")
techage.register_mobs_mods("mobs_skeletons") techage.register_mobs_mods("mobs_skeletons")
techage.register_mobs_mods("mobs_dwarves") techage.register_mobs_mods("mobs_dwarves")
techage.register_mobs_mods("mobf_trader") techage.register_mobs_mods("mobf_trader")
techage.register_mobs_mods("ts_vehicles") techage.register_mobs_mods("ts_vehicles_cars")
-- Used as e.g. crane cable
techage.register_simple_nodes({"techage:power_lineS"}, true)

View File

@ -284,6 +284,17 @@ techage.register_node({"techage:t4_pump", "techage:t4_pump_on"}, {
return State4:on_receive_message(pos, topic, payload) return State4:on_receive_message(pos, topic, payload)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State4:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 137 then -- Total Flow Rate
local nvm = techage.get_nvm(pos)
return 0, {nvm.flowrate or 0}
else
return State4:on_beduino_request_data(pos, topic, payload)
end
end,
}) })
-- Pumps have to provide one output and one input side -- Pumps have to provide one output and one input side

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -312,6 +312,25 @@ techage.register_node({"techage:ta3_silo", "techage:ta4_silo"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State
local meta = M(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
elseif topic == 134 then
local inv = M(pos):get_inventory()
local nvm = techage.get_nvm(pos)
nvm.item_count = nvm.item_count or get_item_count(pos)
nvm.capa = nvm.capa or get_silo_capa(pos)
if payload[1] == 1 then
return 0, {techage.power.percent(nvm.capa, nvm.item_count)}
else
return 0, {nvm.item_count}
end
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
nvm.item_count = nil nvm.item_count = nil

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2021 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -139,6 +139,29 @@ techage.register_node({"techage:ta3_valve_closed", "techage:ta3_valve_open"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local node = techage.get_node_lvm(pos)
if topic == 1 and payload[1] == 1 and node.name == "techage:ta3_valve_closed" then
liquid.turn_valve_on(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open")
return 0
elseif topic == 1 and payload[1] == 0 and node.name == "techage:ta3_valve_open" then
liquid.turn_valve_off(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open")
return 0
else
return 2, ""
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
local node = techage.get_node_lvm(pos)
if topic == 142 then -- State
if node.name == "techage:ta3_valve_open" then
return 0, {1}
end
return 0, {0}
else
return 2, ""
end
end,
}) })
liquid.register_nodes({"techage:ta3_valve_closed"}, Pipe, "special", {}, {}) liquid.register_nodes({"techage:ta3_valve_closed"}, Pipe, "special", {}, {})

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -158,4 +158,10 @@ techage.register_node({"techage:t4_waterpump"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload) return State:on_receive_message(pos, topic, payload)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
return State:on_beduino_receive_cmnd(pos, topic, payload)
end,
on_beduino_request_data = function(pos, src, topic, payload)
return State:on_beduino_request_data(pos, topic, payload)
end,
}) })

View File

@ -127,6 +127,7 @@ Command=Kommando
### button.lua ### ### button.lua ###
### cart_detector.lua ### ### cart_detector.lua ###
### detector.lua ### ### detector.lua ###
### light_detector.lua ###
### lua_logic.lua ### ### lua_logic.lua ###
### mesecons_converter.lua ### ### mesecons_converter.lua ###
### node_detector.lua ### ### node_detector.lua ###
@ -178,6 +179,7 @@ TA4 4x Button=TA4 4x Taster
TA3 Cart Detector=TA3 Wagen Detektor TA3 Cart Detector=TA3 Wagen Detektor
### cart_detector.lua ### ### cart_detector.lua ###
### light_detector.lua ###
### node_detector.lua ### ### node_detector.lua ###
accept=akzeptieren accept=akzeptieren
@ -732,6 +734,11 @@ Block has an@nadditional wrench menu=Block besitzt ein@nzusätzliches@nSchrauben
connected with=verbunden mit connected with=verbunden mit
### light_detector.lua ###
Send signal if light level is above:=Sende ein Signal wenn der Lichtwert größer ist als:
TA3 Light Detector=TA3 Lichtdetektor
### lighter.lua ### ### lighter.lua ###
TA1 Lighter=TA1 Anzünder TA1 Lighter=TA1 Anzünder

View File

@ -127,6 +127,7 @@ Command=
### button.lua ### ### button.lua ###
### cart_detector.lua ### ### cart_detector.lua ###
### detector.lua ### ### detector.lua ###
### light_detector.lua ###
### lua_logic.lua ### ### lua_logic.lua ###
### mesecons_converter.lua ### ### mesecons_converter.lua ###
### node_detector.lua ### ### node_detector.lua ###
@ -178,6 +179,7 @@ TA4 4x Button=
TA3 Cart Detector= TA3 Cart Detector=
### cart_detector.lua ### ### cart_detector.lua ###
### light_detector.lua ###
### node_detector.lua ### ### node_detector.lua ###
accept= accept=
@ -732,6 +734,11 @@ Block has an@nadditional wrench menu=
connected with= connected with=
### light_detector.lua ###
Send signal if light level is above:=
TA3 Light Detector=
### lighter.lua ### ### lighter.lua ###
TA1 Lighter= TA1 Lighter=

View File

@ -55,7 +55,10 @@ local function switch_off(pos, is_button)
elseif name == "techage:ta4_button_on" then elseif name == "techage:ta4_button_on" then
logic.swap_node(pos, "techage:ta4_button_off") logic.swap_node(pos, "techage:ta4_button_off")
end end
logic.send_off(pos, M(pos)) local meta = M(pos)
if not meta:contains("command") or meta:get_string("command") == "on" then
logic.send_off(pos, M(pos))
end
if not is_button then if not is_button then
minetest.sound_play("techage_button", { minetest.sound_play("techage_button", {
pos = pos, pos = pos,
@ -149,6 +152,9 @@ local function on_rightclick_on(pos, node, clicker)
if fixed == "true" then if fixed == "true" then
if can_access(pos, clicker) then if can_access(pos, clicker) then
switch_on(pos) switch_on(pos)
local mem = techage.get_mem(pos)
mem.clicker = clicker and clicker:get_player_name()
mem.time = math.floor(minetest.get_us_time() / 100000)
end end
end end
end end
@ -331,3 +337,31 @@ minetest.register_craft({
{"", "", ""}, {"", "", ""},
}, },
}) })
techage.register_node({
"techage:ta4_button_off", "techage:ta4_button_on",
}, {
on_recv_message = function(pos, src, topic, payload)
if topic == "name" then
local mem = techage.get_mem(pos)
return mem.clicker or ""
elseif topic == "time" then
local mem = techage.get_mem(pos)
return mem.time or 0
else
return "unsupported"
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 144 then -- Player Name
local mem = techage.get_mem(pos)
return 0, mem.clicker
elseif topic == 149 then --time
local mem = techage.get_mem(pos)
return 0, {mem.time or 0}
else
return 2, ""
end
end,
}
)

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -151,6 +151,28 @@ techage.register_node({"techage:ta3_cartdetector_off", "techage:ta3_cartdetector
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 1 then
local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2)
minecart.punch_cart(pos, nil, 1.6, dir)
return 0
else
return 2
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 142 then -- Binary State
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_cartdetector_on" then
return 0, {1}
else
return 0, {0}
end
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME) minetest.get_node_timer(pos):start(CYCLE_TIME)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -24,6 +24,7 @@ local CYCLE_TIME = 1
local tStates = {stopped = 0, running = 0, standby = 1, blocked = 2, nopower = 3, fault = 4} local tStates = {stopped = 0, running = 0, standby = 1, blocked = 2, nopower = 3, fault = 4}
local tDropdownPos = {["1 standby"] = 1, ["2 blocked"] = 2, ["3 nopower"] = 3, ["4 fault"] = 4} local tDropdownPos = {["1 standby"] = 1, ["2 blocked"] = 2, ["3 nopower"] = 3, ["4 fault"] = 4}
local lStates = {[0] = "stopped", "standby", "blocked", "nopower", "fault"} local lStates = {[0] = "stopped", "standby", "blocked", "nopower", "fault"}
local TaStates = {running = 1, blocked = 2, standby = 3, nopower = 4, fault = 5, stopped = 6}
local function formspec(nvm, meta) local function formspec(nvm, meta)
nvm.poll_numbers = nvm.poll_numbers or {} nvm.poll_numbers = nvm.poll_numbers or {}
@ -200,13 +201,21 @@ minetest.register_craft({
techage.register_node({"techage:ta4_collector"}, { techage.register_node({"techage:ta4_collector"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
if topic == "state" then if topic == "state" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return lStates[nvm.stored_state or 0] return lStates[nvm.stored_state or 0]
else else
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 129 then
local nvm = techage.get_nvm(pos)
return 0, {TaStates[lStates[nvm.stored_state or 0]]}
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME) minetest.get_node_timer(pos):start(CYCLE_TIME)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -83,12 +83,21 @@ local function formspec(meta)
"button_exit[2,2;3,1;exit;"..S("Save").."]" "button_exit[2,2;3,1;exit;"..S("Save").."]"
end end
local function after_place_node(pos, placer) local function after_place_node3(pos, placer)
local meta = M(pos) local meta = M(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size('cfg', 4) inv:set_size('cfg', 4)
logic.after_place_node(pos, placer, "techage:ta3_detector_off", NDEF(pos).description) logic.after_place_node(pos, placer, "techage:ta3_detector_off", S("TA3 Detector"))
logic.infotext(meta, NDEF(pos).description) logic.infotext(meta, S("TA3 Detector"))
meta:set_string("formspec", formspec(meta))
end
local function after_place_node4(pos, placer)
local meta = M(pos)
local inv = meta:get_inventory()
inv:set_size('cfg', 4)
logic.after_place_node(pos, placer, "techage:ta4_detector_off", S("TA4 Detector"))
logic.infotext(meta, S("TA4 Detector"))
meta:set_string("formspec", formspec(meta)) meta:set_string("formspec", formspec(meta))
end end
@ -126,7 +135,7 @@ minetest.register_node("techage:ta3_detector_off", {
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_detector.png", "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_detector.png",
}, },
after_place_node = after_place_node, after_place_node = after_place_node3,
on_receive_fields = on_receive_fields, on_receive_fields = on_receive_fields,
techage_set_numbers = techage_set_numbers, techage_set_numbers = techage_set_numbers,
after_dig_node = after_dig_node, after_dig_node = after_dig_node,
@ -179,7 +188,7 @@ minetest.register_node("techage:ta4_detector_off", {
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_detector.png", "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_detector.png",
}, },
after_place_node = after_place_node, after_place_node = after_place_node4,
on_receive_fields = on_receive_fields, on_receive_fields = on_receive_fields,
techage_set_numbers = techage_set_numbers, techage_set_numbers = techage_set_numbers,
after_dig_node = after_dig_node, after_dig_node = after_dig_node,
@ -276,4 +285,21 @@ techage.register_node({"techage:ta4_detector_off", "techage:ta4_detector_on"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 6 then -- Detector Block Reset
local nvm = techage.get_nvm(pos)
nvm.counter = 0
return 0
else
return 2
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 139 then
local nvm = techage.get_nvm(pos)
return 0, {nvm.counter or 0}
else
return 2, ""
end
end,
}) })

189
techage/logic/light_detector.lua Executable file
View File

@ -0,0 +1,189 @@
--[[
TechAge
=======
Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Light Detector
]]--
-- for lazy programmers
local M = minetest.get_meta
local S = techage.S
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local logic = techage.logic
local CYCLE_TIME = 2
local function switch_off(pos)
local node = minetest.get_node(pos)
if node.name == "techage:ta3_lightdetector_on" then
logic.swap_node(pos, "techage:ta3_lightdetector_off")
logic.send_off(pos, M(pos))
end
end
local function switch_on(pos)
logic.swap_node(pos, "techage:ta3_lightdetector_on")
if logic.send_on(pos, M(pos)) then
minetest.after(1, switch_off, pos)
end
end
local function node_timer(pos)
local nvm = techage.get_nvm(pos)
local trigger = nvm.mode or 7
local pos_above = {x = pos.x, y = pos.y + 1, z = pos.z}
if minetest.get_node_light(pos_above, nil) == nil then
switch_off(pos)
return true
end
if minetest.get_node_light(pos_above, nil) > trigger then
switch_on(pos)
else
switch_off(pos)
end
return true
end
local function formspec(meta, nvm)
local numbers = meta:get_string("numbers") or ""
local dropdown_label = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15" -- Has to be a cleaner way of doing this, but it's just easier this way
return "size[7.5,4]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"field[0.5,1;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" ..
"label[0.2,1.6;"..S("Send signal if light level is above:").."]"..
"dropdown[0.2,2.1;7.3,1;mode;"..dropdown_label.."; "..(nvm.mode or 7).."]"..
"button_exit[2,3.2;3,1;accept;"..S("accept").."]"
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
local nvm = techage.get_nvm(pos)
if fields.accept then
nvm.mode = tonumber(fields.mode) or 7
if techage.check_numbers(fields.numbers, player:get_player_name()) then
meta:set_string("numbers", fields.numbers)
logic.infotext(M(pos), S("TA3 Light Detector"))
end
meta:set_string("formspec", formspec(meta, nvm))
end
end
local function techage_set_numbers(pos, numbers, player_name)
local meta = M(pos)
local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Light Detector"))
meta:set_string("formspec", formspec(meta))
return res
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
end
minetest.register_node("techage:ta3_lightdetector_off", {
description = S("TA3 Light Detector"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_lightdetector.png",
"techage_filling_ta3.png^techage_frame_ta3_top.png",
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png^[transformR90",
},
after_place_node = function(pos, placer)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
logic.after_place_node(pos, placer, "techage:ta3_lightdetector_off", S("TA3 Light Detector"))
logic.infotext(meta, S("TA3 Light Detector"))
meta:set_string("formspec", formspec(meta, nvm))
minetest.get_node_timer(pos):start(CYCLE_TIME)
end,
on_receive_fields = on_receive_fields,
on_timer = node_timer,
techage_set_numbers = techage_set_numbers,
after_dig_node = after_dig_node,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
})
minetest.register_node("techage:ta3_lightdetector_on", {
description = "TA3 Light Detector (On)",
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_lightdetector_on.png",
"techage_filling_ta3.png^techage_frame_ta3_top.png",
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png^[transformR90",
},
on_receive_fields = on_receive_fields,
on_timer = node_timer,
techage_set_numbers = techage_set_numbers,
after_dig_node = after_dig_node,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
drop = "techage:ta3_lightdetector_off"
})
minetest.register_craft({
output = "techage:ta3_lightdetector_off",
recipe = {
{"", "group:wood", "default:glass"},
{"", "default:copper_ingot", "techage:vacuum_tube"},
{"", "group:wood", "default:mese_crystal"},
},
})
techage.register_node({"techage:ta3_lightdetector_off", "techage:ta3_lightdetector_on"}, {
on_recv_message = function(pos, src, topic, payload)
if topic == "state" then
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_lightdetector_on" then
return "on"
else
return "off"
end
elseif topic == "light_level" then -- Allow finding the specific light level
local pos_above = {x = pos.x, y = pos.y + 1, z = pos.z}
return minetest.get_node_light(pos_above, nil)
else
return "unsupported"
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 142 then -- Binary State
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_lightdetector_on" then
return 0, {1}
else
return 0, {0}
end
elseif topic == 143 then -- Allow finding the specific light level
local pos_above = {x = pos.x, y = pos.y + 1, z = pos.z}
return 0, {minetest.get_node_light(pos_above, nil)}
else
return 2, ""
end
end,
on_node_load = function(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end,
})

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2021 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -407,4 +407,29 @@ techage.register_node({"techage:ta3_logic2"}, {
mem.ttl = techage.SystemTime + (nvm.blocking_time or 0) mem.ttl = techage.SystemTime + (nvm.blocking_time or 0)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
local mem = techage.get_mem(pos)
nvm.own_num = nvm.own_num or M(pos):get_string("node_number")
nvm.blocking_time = nvm.blocking_time or M(pos):get_float("blocking_time")
nvm.inp_tbl = nvm.inp_tbl or {}
if src ~= nvm.own_num then
if topic == 1 and payload[1] == 1 then
debug(mem, "(inp) " .. src .. " = on")
nvm.inp_tbl[src] = "on"
return 0
elseif topic == 1 and payload[1] == 0 then
debug(mem, "(inp) " .. src .. " = off")
nvm.inp_tbl[src] = "off"
return 0
else
debug(mem, "(inp) invalid command")
return 2
end
local t = math.max((mem.ttl or 0) - techage.SystemTime, 0.1)
minetest.get_node_timer(pos):start(t)
mem.ttl = techage.SystemTime + (nvm.blocking_time or 0)
end
end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -246,7 +246,19 @@ techage.register_node({"techage:ta3_logic"}, {
end end
minetest.get_node_timer(pos):start(0.1) minetest.get_node_timer(pos):start(0.1)
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 1 and payload[1] == 1 then
nvm.inp_tbl.inp = true
nvm.inp_tbl["n"..src] = true
return 0
elseif topic == 1 and payload[1] == 0 then
nvm.inp_tbl.inp = false
nvm.inp_tbl["n"..src] = false
return 0
else
return 2
end
end,
on_node_load = function(pos) on_node_load = function(pos)
end, end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -92,6 +92,23 @@ techage.register_node({"techage:ta4_mbadetector"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 142 then -- Binary State
if minetest.compare_block_status then
if minetest.compare_block_status(pos, "active") then
return 0, {1}
else
return 0, {0}
end
else
local mem = techage.get_mem(pos)
local res = mem.gametime and mem.gametime > (minetest.get_gametime() - 2)
return 0, {res and 1 or 0}
end
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
minetest.get_node_timer(pos):start(1) minetest.get_node_timer(pos):start(1)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -189,20 +189,29 @@ minetest.register_craft({
techage.register_node({"techage:ta3_nodedetector_off", "techage:ta3_nodedetector_on"}, { techage.register_node({"techage:ta3_nodedetector_off", "techage:ta3_nodedetector_on"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
if topic == "name" then if topic == "state" then
local nvm = techage.get_nvm(pos)
return nvm.player_name or ""
elseif topic == "state" then
local node = techage.get_node_lvm(pos) local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_nodedetector_off" then if node.name == "techage:ta3_nodedetector_off" then
return "on"
else
return "off" return "off"
else
return "on"
end end
else else
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 142 then
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_nodedetector_off" then
return 0, {0}
else
return 0, {1}
end
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME) minetest.get_node_timer(pos):start(CYCLE_TIME)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -323,6 +323,22 @@ techage.register_node({
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 144 then -- Player Name
local nvm = techage.get_nvm(pos)
return 0, nvm.player_name or ""
elseif topic == 142 then -- Binary State
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_playerdetector_on" or
node.name == "techage:ta4_playerdetector_on" then
return 0, {1}
else
return 0, {0}
end
else
return 2, ""
end
end,
on_node_load = function(pos) on_node_load = function(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME) minetest.get_node_timer(pos):start(CYCLE_TIME)
end, end,

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -278,6 +278,28 @@ techage.register_node({"techage:ta3_sequencer"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 7 then -- TA3 Sequenzer
if payload[1] == 1 then
start_the_sequencer(pos)
return 0
elseif payload[1] == 0 then
-- do not stop immediately
local nvm = techage.get_nvm(pos)
if not nvm.running then
nvm.endless = not (nvm.endless or false)
else
nvm.endless = false
end
return 0
elseif payload[1] == 2 then
stop_the_sequencer(pos)
return 0
end
end
return 2
end,
on_node_load = function(pos) on_node_load = function(pos)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if nvm.running then if nvm.running then

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2021 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -30,6 +30,7 @@ local HELP = S("Syntax:\n") ..
S(" - 'send <node num> <cmnd>' (techage command)\n") .. S(" - 'send <node num> <cmnd>' (techage command)\n") ..
S(" - 'goto <num>' (jump to another line)\n") .. S(" - 'goto <num>' (jump to another line)\n") ..
S(" - 'stop' (stop the execution)\n") .. S(" - 'stop' (stop the execution)\n") ..
S(" - 'nop' (do nothing)\n") ..
S("\n") .. S("\n") ..
S("Example:\n") .. S("Example:\n") ..
" -- move controller commands\n" .. " -- move controller commands\n" ..
@ -108,7 +109,7 @@ local function compile(s, tRes)
tCode[idx] = {next_idx = tonumber(cmnd2) or 1} tCode[idx] = {next_idx = tonumber(cmnd2) or 1}
elseif cmnd1 == "stop" then elseif cmnd1 == "stop" then
tCode[idx] = false tCode[idx] = false
elseif cmnd1 == nil then elseif cmnd1 == nil or cmnd1 == "nop" then
tCode[idx] = {} tCode[idx] = {}
end end
old_idx = idx old_idx = idx
@ -290,18 +291,18 @@ minetest.register_craft({
}, },
}) })
local INFO = [[Commands: 'goto <num>', 'stop']] local INFO = [[Commands: 'goto <num>', 'stop', 'on', 'off']]
techage.register_node({"techage:ta4_sequencer"}, { techage.register_node({"techage:ta4_sequencer"}, {
on_recv_message = function(pos, src, topic, payload) on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
if topic == "goto" and not nvm.running then if (topic == "goto" or topic == "on") and not nvm.running then
local mem = techage.get_mem(pos) local mem = techage.get_mem(pos)
nvm.running = true nvm.running = true
mem.idx = tonumber(payload or 1) or 1 mem.idx = tonumber(payload or 1) or 1
restart_timer(pos, 0.1) restart_timer(pos, 0.1)
logic.infotext(M(pos), S("TA4 Sequencer"), S("running")) logic.infotext(M(pos), S("TA4 Sequencer"), S("running"))
elseif topic == "stop" then elseif topic == "stop" or topic == "off" then
nvm.running = false nvm.running = false
minetest.get_node_timer(pos):stop() minetest.get_node_timer(pos):stop()
logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped")) logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped"))
@ -311,4 +312,23 @@ techage.register_node({"techage:ta4_sequencer"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == 13 then
if payload[1] ~= 0 and not nvm.running then
local mem = techage.get_mem(pos)
nvm.running = true
mem.idx = tonumber(payload or 1) or 1
restart_timer(pos, 0.1)
logic.infotext(M(pos), S("TA4 Sequencer"), S("running"))
return 0
elseif payload[1] == 0 then
nvm.running = false
minetest.get_node_timer(pos):stop()
logic.infotext(M(pos), S("TA4 Sequencer"), S("stopped"))
return 0
end
end
return 2
end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2020 Joachim Stolberg Copyright (C) 2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -121,6 +121,19 @@ techage.register_node({"techage:signal_lamp_off", "techage:signal_lamp_on"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 1 and payload[1] == 1 then
local node = techage.get_node_lvm(pos)
switch_on(pos, node)
return 0
elseif topic == 1 and payload[1] == 0 then
local node = techage.get_node_lvm(pos)
switch_off(pos, node)
return 0
else
return 2
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2021 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -17,9 +17,9 @@ local M = minetest.get_meta
local S = techage.S local S = techage.S
local OFF = 0 local OFF = 0
local RED = 1 local GREEN = 1
local GREEN = 2 local AMBER = 2
local AMBER = 3 local RED = 3
local WRENCH_MENU = { local WRENCH_MENU = {
{ {
@ -139,6 +139,19 @@ techage.register_node({"techage:ta4_signallamp_2x"}, {
lcdlib.update_entities(pos) lcdlib.update_entities(pos)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
nvm.lamp = nvm.lamp or {}
if topic == 3 then -- Signal Lamp
local num = math.min(payload[1] or 1, 2)
local color = math.min(payload[2] or 0, 3)
nvm.lamp[num] = color
lcdlib.update_entities(pos)
return 0
else
return 2
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2017-2021 Joachim Stolberg Copyright (C) 2017-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -17,9 +17,9 @@ local M = minetest.get_meta
local S = techage.S local S = techage.S
local OFF = 0 local OFF = 0
local RED = 1 local GREEN = 1
local GREEN = 2 local AMBER = 2
local AMBER = 3 local RED = 3
local WRENCH_MENU = { local WRENCH_MENU = {
{ {
@ -170,6 +170,19 @@ techage.register_node({"techage:ta4_signallamp_4x"}, {
lcdlib.update_entities(pos) lcdlib.update_entities(pos)
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
nvm.lamp = nvm.lamp or {}
if topic == 3 then -- Signal Lamp
local num = math.min(payload[1] or 1, 4)
local color = math.min(payload[2] or 0, 3)
nvm.lamp[num] = color
lcdlib.update_entities(pos)
return 0
else
return 2
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -654,4 +654,27 @@ techage.register_node({"techage:ta4_lua_controller"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
if topic == 1 and payload[1] == 1 then
set_input(pos, number, src, "on")
elseif topic == 1 and payload[1] == 0 then
set_input(pos, number, src, "off")
else
return 2
end
return 0
end,
on_beduino_request_data = function(pos, src, topic, payload)
local meta = minetest.get_meta(pos)
if topic == 142 then
local running = meta:get_int("running") or STATE_STOPPED
return 0, {running}
else
return 2, ""
end
end,
}) })

View File

@ -3,7 +3,7 @@
TechAge TechAge
======= =======
Copyright (C) 2019-2020 Joachim Stolberg Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3 AGPL v3
See LICENSE.txt for more information See LICENSE.txt for more information
@ -46,6 +46,13 @@ local function send_command(pos)
end end
end end
local function get_stack(pos, idx)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack("main", idx)
return stack:get_name(), stack:get_count()
end
local function get_stacks(pos) local function get_stacks(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -215,7 +222,7 @@ techage.register_node({"techage:ta4_sensor_chest"}, {
elseif topic == "action" then elseif topic == "action" then
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local number = meta:get_string("node_number") local number = meta:get_string("node_number")
return PlayerActions[number][1], PlayerActions[number][2] return (PlayerActions[number] or {})[1], (PlayerActions[number] or {})[2]
elseif topic == "stacks" then elseif topic == "stacks" then
return get_stacks(pos) return get_stacks(pos)
elseif topic == "text" then elseif topic == "text" then
@ -226,6 +233,40 @@ techage.register_node({"techage:ta4_sensor_chest"}, {
return "unsupported" return "unsupported"
end end
end, end,
on_beduino_receive_cmnd = function(pos, src, topic, payload)
if topic == 66 then
local meta = minetest.get_meta(pos)
meta:set_string("text", tostring(payload))
meta:set_string("formspec", formspec2(pos))
return 0
else
return 2
end
end,
on_beduino_request_data = function(pos, src, topic, payload)
if topic == 131 then -- Chest State
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return 0, {techage.get_inv_state_num(inv, "main")}
elseif topic == 138 and payload[1] == 1 then -- Sensor Chests State (action)
local meta = minetest.get_meta(pos)
local number = meta:get_string("node_number")
local action = (PlayerActions[number] or {})[2] or "None"
return 0, {({put = 1, get = 2})[action] or 0}
elseif topic == 138 and payload[1] == 2 then -- Sensor Chests State (player name)
local meta = minetest.get_meta(pos)
local number = meta:get_string("node_number")
return 0, (PlayerActions[number] or {})[1]
elseif topic == 138 and payload[1] == 3 then -- Sensor Chests State (stack item name)
local name, _ = get_stack(pos, payload[2] or 1)
return 0, name
elseif topic == 138 and payload[1] == 4 then -- Sensor Chests State (stack item count)
local _, count = get_stack(pos, payload[2] or 1)
return 0, {count}
else
return 2, ""
end
end,
}) })
minetest.register_craft({ minetest.register_craft({

View File

@ -661,11 +661,15 @@ Der Tür Controller II kann alle Arten von Blöcken entfernen und wieder setzen.
Wird ein `on` / `off` Kommando an den Tür Controller II gesendet, entfernt bzw. setzt er die Blöcke ebenfalls. Wird ein `on` / `off` Kommando an den Tür Controller II gesendet, entfernt bzw. setzt er die Blöcke ebenfalls.
Über ein `exchange` Kommando können einzelne Böcke gesetzt, entfernt, bzw. durch andere Blöcke ersetzt werden. Die Slot-Nummer des Inventars (1 .. 16) muss als payload übergeben werden, also: Mit `$send_cmnd(node_number, "exchange", 2)` können einzelne Böcke gesetzt, entfernt, bzw. durch andere Blöcke aus dem Inventar ersetzt werden.
``` Mit `$send_cmnd(node_number, "set", 2)` kann ein Block aus dem Inventory explizit gesetzt werden, sofern der Inventory Slot nicht leer ist.
$send_cmnd(node_number, "exchange", 2)
``` Mit `$send_cmnd(node_number, "dig", 2)` kann ein Block wieder entfernt werden, sofern der Inventory Slot leer ist.
Mit `$send_cmnd(node_number, "get", 2)` wird der Name des gesetzten Blocks zurückgeliefert.
Die Slot-Nummer des Inventars (1 .. 16) muss in allen drei Fällen als payload übergeben werden.
Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren. Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren.
@ -679,7 +683,7 @@ Die Sounds können über das Menü und über ein Kommando ausgewählt und abgesp
- Kommando `on` zum Abspielen eines Sounds - Kommando `on` zum Abspielen eines Sounds
- Kommando `sound <idx>` zur Auswahl eines Sounds über den Index - Kommando `sound <idx>` zur Auswahl eines Sounds über den Index
- Kommando `gain <volume>` zum Einstellen der Lautstärke über den `<volume>` Wert (0 bis 1.0). - Kommando `gain <volume>` zum Einstellen der Lautstärke über den `<volume>` Wert (1 bis 5).
[ta3_soundblock|image] [ta3_soundblock|image]
@ -737,6 +741,14 @@ Soll die Suche auf bestimmte Spieler eingegrenzt werden, so können diese Spiele
[ta3_playerdetector|image] [ta3_playerdetector|image]
### TA3 Lichtdetektor
Der Lichtdetektor sendet einen `on`-Kommando, wenn der Lichtpegel des darüber liegenden Blocks einen bestimmten Pegel überschreitet, der über das Rechtsklickmenü eingestellt werden kann.
Mit einen TA4 Lua Controller kann die genaue Lichtstärke mit $get_cmd(num, 'light_level') ermitteln werden.
[ta3_lightdetector|image]
## TA3 Maschinen ## TA3 Maschinen
Bei TA3 existieren die gleichen Maschinen wie bei TA2, nur sind diese hier leistungsfähiger und benötigen Strom statt Achsenantrieb. Bei TA3 existieren die gleichen Maschinen wie bei TA2, nur sind diese hier leistungsfähiger und benötigen Strom statt Achsenantrieb.

View File

@ -654,11 +654,15 @@ The door controller is used to control the TA3 door/gate blocks. With the door c
The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II, the "Record" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the "Done" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the "Remove" or "Set" buttons. If an `on` /`off` command is sent to the Door Controller II, it removes or sets the blocks as well. The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II, the "Record" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the "Done" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the "Remove" or "Set" buttons. If an `on` /`off` command is sent to the Door Controller II, it removes or sets the blocks as well.
Individual blocks can be set, removed or replaced by other blocks via an `exchange` command. The slot number of the inventory (1 .. 16) must be transferred as payload, i.e.: With `$send_cmnd(node_number, "exchange", 2)` individual blocks can be set, removed or replaced by other blocks from the inventory.
``` With `$send_cmnd(node_number, "set", 2)` a block from the inventory can be set explicitly, as long as the inventory slot is not empty.
$send_cmnd(node_number, "exchange", 2)
``` A block can be removed again with `$send_cmnd(node_number, "dig", 2)` if the inventory slot is empty.
The name of the set block is returned with `$send_cmnd(node_number, "get", 2)`.
The slot number of the inventory (1 .. 16) must be passed as payload in all three cases.
This can also be used to simulate extendable stairs and the like. This can also be used to simulate extendable stairs and the like.
@ -672,7 +676,7 @@ The sounds can be selected and played via the menu and via command.
- Command `on` to play a sound - Command `on` to play a sound
- Command `sound <idx>` to select a sound via the index - Command `sound <idx>` to select a sound via the index
- Command `gain <volume>` to adjust the volume via the `<volume>` value (0 to 1.0). - Command `gain <volume>` to adjust the volume via the `<volume>` value (1 to 5).
[ta3_soundblock|image] [ta3_soundblock|image]
@ -730,6 +734,12 @@ If the search should be limited to specific players, these player names can also
[ta3_playerdetector|image] [ta3_playerdetector|image]
### TA3 Light Detector
The light detector sends an `on` command if the light level of the block above exceeds a certain level, which can be set through the right-click menu.
If you have a TA4 Lua Controller, you can get the exact light level with $get_cmd(num, 'light_level')
[ta3_lightdetector|image]
## TA3 Machines ## TA3 Machines

View File

@ -550,6 +550,7 @@ Der TA4 Sequenzer unterstützt folgende techage Kommandos:
- `goto <num>` Zu einer Kommandozeile springen und damit den Sequenzer starten - `goto <num>` Zu einer Kommandozeile springen und damit den Sequenzer starten
- `stop` Den Sequenzer anhalten - `stop` Den Sequenzer anhalten
- `on` und `off` als Alias für `goto 1` bzw. `stop`
Das `goto` Kommando wird nur angenommen, wenn der Sequenzer gestoppt ist. Das `goto` Kommando wird nur angenommen, wenn der Sequenzer gestoppt ist.
@ -843,6 +844,7 @@ Der TA4 Schieber besitzt zwei zusätzliche Kommandos für den Lua Controller:
- `config` dient zur Konfiguration des Schiebers, analog zum manuellen Konfiguration über das Menü. - `config` dient zur Konfiguration des Schiebers, analog zum manuellen Konfiguration über das Menü.
Beispiel: `$send_cmnd(1234, "config", "default:dirt")` Beispiel: `$send_cmnd(1234, "config", "default:dirt")`
Mit `$send_cmnd(1234, "config", "")` wird die Konfiguration gelöscht
- `pull` dient zum Absetzen eines Auftrags an den Schieber: - `pull` dient zum Absetzen eines Auftrags an den Schieber:
Beispiel: `$send_cmnd(1234, "pull", "default:dirt 8")` Beispiel: `$send_cmnd(1234, "pull", "default:dirt 8")`
Als Nummer sind Werte von 1 bis 12 zulässig. Danach geht der Schieber wieder in den `stopped` Mode und sendet ein "off" Kommando zurück an den Sender des "pull" Kommandos. Als Nummer sind Werte von 1 bis 12 zulässig. Danach geht der Schieber wieder in den `stopped` Mode und sendet ein "off" Kommando zurück an den Sender des "pull" Kommandos.

View File

@ -542,6 +542,7 @@ The TA4 sequencer supports the following techage commands:
- `goto <num>` Jump to a command line and start the sequencer - `goto <num>` Jump to a command line and start the sequencer
- `stop` Stop the sequencer - `stop` Stop the sequencer
- `on` and `off` as aliases for `goto 1` resp. `stop`
The `goto` command is only accepted when the sequencer is stopped. The `goto` command is only accepted when the sequencer is stopped.
@ -835,6 +836,7 @@ The TA4 pusher has two additional commands for the Lua controller:
- `config` is used to configure the pusher, analogous to manual configuration via the menu. - `config` is used to configure the pusher, analogous to manual configuration via the menu.
Example: `$send_cmnd(1234, "config", "default: dirt")` Example: `$send_cmnd(1234, "config", "default: dirt")`
With `$send_cmnd(1234, "config", "")` the configuration is deleted
- `pull` is used to send an order to the pusher: - `pull` is used to send an order to the pusher:
Example: `$send_cmnd(1234, "pull", "default: dirt 8")` Example: `$send_cmnd(1234, "pull", "default: dirt 8")`
Values from 1 to 12 are permitted as numbers. Then the pusher goes back to `stopped` mode and sends an" off "command back to the transmitter of the" pull "command. Values from 1 to 12 are permitted as numbers. Then the pusher goes back to `stopped` mode and sends an" off "command back to the transmitter of the" pull "command.

View File

@ -374,7 +374,9 @@ Please note, that this is not a technical distinction, only a logical.
| "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). | | "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only one inventory slot (1..8, from left to right). |
| "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $send_cmnd("223", "itemstring", 1) | | "itemstring" | item string of the given slot | Specific command for the TA4 8x2000 Chest to read the item type (technical name) of one chest slot, specified via `add_data` (1..8).<br />Example: s = $send_cmnd("223", "itemstring", 1) |
| "output" | recipe output string, <br />e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" | | "output" | recipe output string, <br />e.g.: "default:glass" | Only for the Industrial Furnace. If no recipe is active, the command returns "unknown" |
| "input" | `<index>` | Read a recipe from the TA4 Recipe Block. `<index>` is the number of the recipe. The block return a list of recipe items. | | "input" | \<index> | Read a recipe from the TA4 Recipe Block. `<index>` is the number of the recipe. The block return a list of recipe items. |
| "name" | \<player name> | Player name of the TA3/TA4 Player Detector or TA4 Button |
| "time" | number | Time in system ticks (norm. 100 ms) when the TA4 Button is clicked |
@ -390,14 +392,19 @@ Please note, that this is not a technical distinction, only a logical.
| "red, "amber", "green", "off" | nil | set Signal Tower color | | "red, "amber", "green", "off" | nil | set Signal Tower color |
| "red, "amber", "green", "off" | lamp number (1..4) | Set the signal lamp color. Valid for "TA4 2x Signal Lamp" and "TA4 4x Signal Lamp" | | "red, "amber", "green", "off" | lamp number (1..4) | Set the signal lamp color. Valid for "TA4 2x Signal Lamp" and "TA4 4x Signal Lamp" |
| "port" | string<br />`<color>=on/off` | Enable/disable a Distributor filter slot..<br />Example: `"yellow=on"`<br />colors: red, green, blue, yellow | | "port" | string<br />`<color>=on/off` | Enable/disable a Distributor filter slot..<br />Example: `"yellow=on"`<br />colors: red, green, blue, yellow |
| "config" | "\<slot> \<item list>" | Configure a Distributor filter slot, like: "red default:dirt dye:blue" |
| "text" | text string | Text to be used for the Sensor Chest menu | | "text" | text string | Text to be used for the Sensor Chest menu |
| "reset" | nil | Reset the item counter of the TA4 Item Detector block | | "reset" | nil | Reset the item counter of the TA4 Item Detector block |
| "pull" | item string | Start the TA4 pusher to pull/push items.<br /> Example: `default:dirt 8` | | "pull" | item string | Start the TA4 pusher to pull/push items.<br /> Example: `default:dirt 8` |
| "config" | item string | Configure the TA4 pusher.<br />Example: `wool:blue` | | "config" | item string | Configure the TA4 pusher.<br />Example: `wool:blue` |
| "exchange" | inventory slot number | place/remove/exchange an block by means of the TA3 Door Controller II (techage:ta3_doorcontroller2) | | "exchange" | inventory slot number | TA3 Door Controller II (techage:ta3_doorcontroller2)<br />Exchange a block<br />*idx* is the inventory slot number (1..n) of/for the block to be exchanged |
| "set" | inventory slot number | TA3 Door Controller II (techage:ta3_doorcontroller2)<br />Set/add a block<br />*idx* is the inventory slot number (1..n) with the block to be set |
| "dig" | inventory slot number | TA3 Door Controller II (techage:ta3_doorcontroller2)<br />Dig/remove a block<br />*idx* is the empty inventory slot number (1..n) for the block |
| "a2b" | nil | TA4 Move Controller command to move the block(s) from position A to B | | "a2b" | nil | TA4 Move Controller command to move the block(s) from position A to B |
| "b2a" | nil | TA4 Move Controller command to move the block(s) from position B to A | | "b2a" | nil | TA4 Move Controller command to move the block(s) from position B to A |
| "move" | nil | TA4 Move Controller command to move the block(s) to the opposite position | | "move" | nil | TA4 Move Controller command to move the block(s) to the opposite position |
| "move2" | x,y,z | TA4 Move Controller command to move the block(s) by the given<br /> x/y/z-distance. Valid ranges for x, y, and z are -100 to 100. |
| "reset" | nil | Reset TA4 Move Controller (move block(s) to start position) |
| "left" | nil | TA4 Turn Controller command to turn the block(s) to the left | | "left" | nil | TA4 Turn Controller command to turn the block(s) to the left |
| "right" | nil | TA4 Turn Controller command to turn the block(s) to the right | | "right" | nil | TA4 Turn Controller command to turn the block(s) to the right |
| "uturn" | nil | TA4 Turn Controller command to turn the block(s) 180 degrees | | "uturn" | nil | TA4 Turn Controller command to turn the block(s) 180 degrees |

85
techage/manuals/ta_iom.md Normal file
View File

@ -0,0 +1,85 @@
# Techage/Beduino I/O Module
I/O modules support the following functions:
### event
Every signal that is sent to an I/O module triggers an event on the controller.
Events can be queried using the `event()` function.
If the function returns the value `1`, one or more signals have been received.
Calling `event()` resets the event flag.
```c
event()
```
### read
Read a value from a remote techage block.
- *port* is the I/O module port number
- *cmnd* is the command, like `IO_STATE` (see example code "ta_cmnd.c")
```c
read(port, cmnd)
```
### send_cmnd
Send a command to a techage block (see [commands](https://github.com/joe7575/beduino/blob/main/BEPs/bep-005_ta_cmnd.md)).
- *port* is the I/O module port number
- *topic* is a number from the list of [Beduino commands](https://github.com/joe7575/beduino/blob/main/BEPs/bep-005_ta_cmnd.md)
- *payload* is an array or a string with additional information, depending on the command. If no additional commands are required, "" can be used.
```c
send_cmnd(port, topic, payload)
```
### request_data
Request information from a techage block (see [commands](https://github.com/joe7575/beduino/blob/main/BEPs/bep-005_ta_cmnd.md)).
- *port* is the I/O module port number
- *topic* is a number from the list of [Beduino commands](https://github.com/joe7575/beduino/blob/main/BEPs/bep-005_ta_cmnd.md)
- *payload* is an array or a string with additional information, depending on the command. If no additional commands are required, "" can be used.
- *resp* is an array for the response data. The array must be defined large enough to hold the response data.
```c
request_data(port, topic, payload, resp)
```
## Functions for TA4 Display and TA4 Display XL
### clear_screen
Clear the display.
- *port* is the I/O module port number
```c
clear_screen(port)
```
### append_line
Add a new line to the display.
- *port* is the I/O module port number
- *text* is the text for one line
```c
append_line(port, text)
```
### write_line
Overwrite a text line with the given string.
- *port* is the I/O module port number
- *row* ist the display line/row (1-5)
- *text* is the text for one line
```c
write_line(port, row, text)
```

Some files were not shown because too many files have changed in this diff Show More