built on 08/08/2020 12:52:38

This commit is contained in:
Joachim Stolberg 2020-08-08 12:52:38 +02:00
parent 8bede73d11
commit 080aed2f69
44 changed files with 742 additions and 255 deletions

View File

@ -13,6 +13,7 @@
2020-07-02 v0.04 further slope nodes added 2020-07-02 v0.04 further slope nodes added
]]-- ]]--
local S = minetest.get_translator("autobahn")
autobahn = {} autobahn = {}
@ -215,7 +216,7 @@ end
local function register_node(name, tiles, drawtype, mesh, box, drop) local function register_node(name, tiles, drawtype, mesh, box, drop)
minetest.register_node("autobahn:"..name, { minetest.register_node("autobahn:"..name, {
description = "Autobahn", description = S("Autobahn"),
tiles = tiles, tiles = tiles,
drawtype = drawtype, drawtype = drawtype,
mesh = mesh, mesh = mesh,
@ -290,7 +291,7 @@ end
minetest.register_craftitem("autobahn:stripes", { minetest.register_craftitem("autobahn:stripes", {
description = "Autobahn Stripe", description = S("Autobahn Stripe"),
inventory_image = 'autobahn_stripes.png', inventory_image = 'autobahn_stripes.png',
}) })
@ -337,7 +338,7 @@ else
recipe = "default:pine_tree", recipe = "default:pine_tree",
}) })
minetest.register_node("autobahn:tar", { minetest.register_node("autobahn:tar", {
description = "Tar", description = S("Tar"),
tiles = {"autobahn1.png^[colorize:#000000:80"}, tiles = {"autobahn1.png^[colorize:#000000:80"},
is_ground_content = false, is_ground_content = false,
groups = {cracky = 2}, groups = {cracky = 2},

View File

@ -0,0 +1,5 @@
# textdomain: autobahn
Autobahn=Шоссе
Autobahn Stripe=Дорожная Разметка
Tar=Дёготь

View File

@ -0,0 +1,5 @@
# textdomain: autobahn
Autobahn=
Autobahn Stripe=
Tar=

View File

@ -1,3 +1,5 @@
local S = minetest.get_translator("compost")
compost = {} compost = {}
-- Version for compatibility checks -- Version for compatibility checks
@ -112,7 +114,7 @@ local function minecart_hopper_untakeitem(pos, in_dir, stack)
end end
minetest.register_node("compost:wood_barrel", { minetest.register_node("compost:wood_barrel", {
description = "Wood Barrel", description = S("Wood Barrel"),
tiles = {"default_wood.png"}, tiles = {"default_wood.png"},
drawtype = "nodebox", drawtype = "nodebox",
node_box = { node_box = {
@ -143,7 +145,7 @@ minetest.register_node("compost:wood_barrel", {
}) })
minetest.register_node("compost:wood_barrel_1", { minetest.register_node("compost:wood_barrel_1", {
description = "Wood Barrel with compost", description = S("Wood Barrel with compost"),
tiles = {"default_wood.png^compost_compost_1.png", "default_wood.png"}, tiles = {"default_wood.png^compost_compost_1.png", "default_wood.png"},
drawtype = "nodebox", drawtype = "nodebox",
node_box = { node_box = {
@ -164,7 +166,7 @@ minetest.register_node("compost:wood_barrel_1", {
}) })
minetest.register_node("compost:wood_barrel_2", { minetest.register_node("compost:wood_barrel_2", {
description = "Wood Barrel with compost", description = S("Wood Barrel with compost"),
tiles = {"default_wood.png^compost_compost_2.png", "default_wood.png"}, tiles = {"default_wood.png^compost_compost_2.png", "default_wood.png"},
drawtype = "nodebox", drawtype = "nodebox",
node_box = { node_box = {
@ -185,7 +187,7 @@ minetest.register_node("compost:wood_barrel_2", {
}) })
minetest.register_node("compost:wood_barrel_3", { minetest.register_node("compost:wood_barrel_3", {
description = "Wood Barrel", description = S("Wood Barrel"),
tiles = {"default_wood.png^compost_compost_3.png", "default_wood.png"}, tiles = {"default_wood.png^compost_compost_3.png", "default_wood.png"},
drawtype = "nodebox", drawtype = "nodebox",
node_box = { node_box = {
@ -238,14 +240,14 @@ minetest.register_craft({
}) })
minetest.register_node("compost:compost", { minetest.register_node("compost:compost", {
description = "Compost", description = S("Compost"),
tiles = {"compost_compost.png"}, tiles = {"compost_compost.png"},
groups = {crumbly = 3}, groups = {crumbly = 3},
sounds = default.node_sound_dirt_defaults(), sounds = default.node_sound_dirt_defaults(),
}) })
minetest.register_node("compost:garden_soil", { minetest.register_node("compost:garden_soil", {
description = "Garden Soil", description = S("Garden Soil"),
tiles = {"compost_garden_soil.png"}, tiles = {"compost_garden_soil.png"},
groups = {crumbly = 3, soil=3, grassland = 1, wet = 1}, groups = {crumbly = 3, soil=3, grassland = 1, wet = 1},
sounds = default.node_sound_dirt_defaults(), sounds = default.node_sound_dirt_defaults(),

View File

@ -0,0 +1,6 @@
# textdomain: compost
Wood Barrel=Деревянная Бочка
Wood Barrel with compost=Деревянная Бочка с компостом
Compost=Компост
Garden Soil=Садовая Почва

View File

@ -0,0 +1,6 @@
# textdomain: compost
Wood Barrel=
Wood Barrel with compost=
Compost=
Garden Soil=

79
hyperloop/zh_CN.txt Normal file
View File

@ -0,0 +1,79 @@
Station data is corrupted. Please rebuild the station!=站点数据已损坏。请重建车站!
Station is still blocked. Please try again in a few seconds!=车站仍被封锁。请稍后再试!
Additional station information=附加电台信息
Hyperloop Booking Machine=超级高铁订票机
Invalid station name!=站名无效!
Please enter the station name to@nwhich this booking machine belongs.=请输入站名致@nwhich这台订票机属于。
Station has already a booking machine!=车站已经有一台订票机了!
Station name=车站名称
Select your destination=选择您的目的地
<unknown>=<未知>
Hyperloop Promo Poster =Hyperloop促销海报
Hyperloop Station Sign=超级高铁站标志
Hyperloop Station Sign Left=超级高铁站左标志
Hyperloop Station Sign Right=右超级高铁线车站标志
Hyperloop Door Bottom=Hyperloop门底
Hyperloop Door Top=Hyperloop门套
The Booking Machine for this station is missing!=这个车站的订票机不见了!
(current position)=(当前位置)
Base=基地
Destination=目的地
Floor=地板
Floor name=楼层名称
Hyperloop Elevator=超级高铁行电梯
Hyperloop Elevator Shaft=超级高铁行电梯井
Please insert floor name=请插入楼层名称
Save=保存
Hyperloop Junction Block=超级高铁型接线盒
Hyperloop Pillar=超级高铁带支柱
Junction connected with =连接
Station connected with =连接的站点
Junction=接合
Hyperloop Display=超级高铁显示屏
| | << Hyperloop >> | be anywhere=| | << 超级高铁 >>|随时随地
Close=关闭
Conn. with=连接
Dist.=距离。
Hyperloop Station Book=超级高铁线站点列表
Owner=所有者
Position=位置
Station/Junction=车站/路口
Hyperloop Legacy Tube=超级高铁传统管
unknown=未知的
Hypersteel Ingot=高铁钢锭
| Welcome at | | =| 欢迎光临 ||
Arrival in:=到达时间:
Destination:=目的地:
Distance:=距离:
Hyperloop Pod Seat=Hyperloop吊舱座椅
Thank you | for | travelling | with | Hyperloop.=感谢您乘坐Hyperloop旅行。
[Hyperloop] No booking entered!=[Hyperloop]没有预订!
Area is protected!=区域受到保护!
Blue Wool=蓝色羊毛
Build Station=建立站点
Destroy Station=摧毁站点
Glass=玻璃
Hyperloop Pod Shell=超级高铁吊舱外壳
Hyperloop Station Block=超级高铁车站方块
Hyperloop Station Pod Builder=超级高铁吊舱建造者
Not enough inventory items to build the station!=没有足够的库存物品来建造车站!
Not enough space to build the station!=没有足够的空间建造车站!
Station=车站
Station completed. Now place the Booking Machine!=车站已完工。现在把订票机放好!
Do you really want to start a new network?!=你真的想建立一个新的网络吗?!
Hyperloop Tube=超级高铁行管
Junction at =交叉口
Open end at =开口端在
Station '=车站'
Station at =车站
There is no station/junction on this level. =这一层没有车站/交叉口。
left: remove node@n=左:移除节点@n
right: repair tube/shaft line@n=右:维修管/轴线@n
Hyperloop Tube Crowbar=高铁管子撬棍
Repair via WorldEdit placed Hyperloop tubes by reusing WorldEdit pos1/pos2=通过重用WorldEdit pos1/pos2通过WorldEdit放置的超循环管进行修复
Rights to remove tube nodes by means of the crowbar=使用撬棍移除管节点的权限
You don't have the necessary privs!=你没有必要的权限!
[Crowbar Help]@n=【撬棍帮助】@n
Hyperloop Waypoint=超级高铁航线路点
Enter channel string=输入通道字符串
Hyperloop WiFi Tube=Hyperloop WiFi管

View File

@ -68,7 +68,7 @@ local function get_next_char(text, pos)
end end
-- 2 bytes char (little endian) -- 2 bytes char (little endian)
if char >= 0xC2 then if char >= 0xC2 and #text > pos then
pos = pos + 1 pos = pos + 1
return (char - 0xC2) * 0x40 + text:sub(pos, pos):byte(), pos return (char - 0xC2) * 0x40 + text:sub(pos, pos):byte(), pos
end end

View File

@ -115,4 +115,5 @@ History
2020-05-14 v1.05 API changed to be able to register carts 2020-05-14 v1.05 API changed to be able to register carts
2020-06-14 v1.06 API changed and chat command added 2020-06-14 v1.06 API changed and chat command added
2020-06-27 v1.07 Route storage and cart command bugfixes 2020-06-27 v1.07 Route storage and cart command bugfixes
2020-07-24 V1.08 Adapted to new techage ICTA style

View File

@ -309,7 +309,7 @@ local function rail_on_step(self, dtime)
end end
-- Slow down or speed up.. -- Slow down or speed up..
local acc = dir.y * -2.0 local acc = dir.y * -1.5
-- Get rail for corrected position -- Get rail for corrected position
railparams = get_railparams(pos) railparams = get_railparams(pos)

View File

@ -13,7 +13,7 @@
minecart = {} minecart = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
minecart.version = 1.07 minecart.version = 1.08
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false

View File

@ -289,9 +289,14 @@ minetest.register_on_mods_loaded(function()
return 'cart_state('..number..')' return 'cart_state('..number..')'
end, end,
code = function(data, environ) code = function(data, environ)
local s = 'minecart.cmnd_cart_state("%s", %u)' local condition = function(env, idx)
local number = tonumber(data.number) or 0 local number = tonumber(data.number) or 0
return string.format(s, environ.owner, number), "~= 0" return minecart.cmnd_cart_state(environ.owner, number)
end
local result = function(val)
return val ~= 0
end
return condition, result
end, end,
}) })
techage.icta_register_condition("cart_location", { techage.icta_register_condition("cart_location", {
@ -314,9 +319,14 @@ minetest.register_on_mods_loaded(function()
return 'cart_loc('..number..')' return 'cart_loc('..number..')'
end, end,
code = function(data, environ) code = function(data, environ)
local s = 'minecart.cmnd_cart_location("%s", %u, env.pos)' local condition = function(env, idx)
local number = tonumber(data.number) or 0 local number = tonumber(data.number) or 0
return string.format(s, environ.owner, number), "~= 0" return minecart.cmnd_cart_location(environ.owner, number, env.pos)
end
local result = function(val)
return val ~= 0
end
return condition, result
end, end,
}) })
techage.lua_ctlr.register_function("cart_state", { techage.lua_ctlr.register_function("cart_state", {

View File

@ -14,7 +14,7 @@
safer_lua.MaxCodeSize = 5000 -- size if source code in bytes safer_lua.MaxCodeSize = 5000 -- size if source code in bytes
safer_lua.MaxTableSize = 1000 -- sum over all table sizes safer_lua.MaxTableSize = 1000 -- sum over all table sizes
safer_lua.MaxExeTime = 5000 -- max. execution time in us safer_lua.MaxExeTime = 20000 -- max. execution time in us
local function memsize() local function memsize()
return safer_lua.MaxTableSize return safer_lua.MaxTableSize
@ -57,7 +57,10 @@ local BASE_ENV = {
rep = string.rep, rep = string.rep,
sub = string.sub, sub = string.sub,
upper = string.upper, upper = string.upper,
split = string.split, split = function(str, separator, include_empty, max_splits, sep_is_pattern)
if separator == "" then separator = " " end
return safer_lua.Array(unpack(string.split(str, separator, include_empty, max_splits, sep_is_pattern)))
end,
trim = string.trim, trim = string.trim,
}, },
tonumber = tonumber, tonumber = tonumber,

View File

@ -47,6 +47,7 @@ local function formspec1(meta)
default.gui_bg.. default.gui_bg..
default.gui_bg_img.. default.gui_bg_img..
default.gui_slots.. default.gui_slots..
"style_type[textarea,table;font=mono]"..
"tabheader[0,0;tab;"..I("Commands,Help")..";1;;true]".. "tabheader[0,0;tab;"..I("Commands,Help")..";1;;true]"..
"field[0.3,0.5;9,1;name;"..I("Sign name:")..";"..name.."]".. "field[0.3,0.5;9,1;name;"..I("Sign name:")..";"..name.."]"..
"textarea[0.3,1.2;9,7.2;cmnd;;"..cmnd.."]".. "textarea[0.3,1.2;9,7.2;cmnd;;"..cmnd.."]"..
@ -60,6 +61,7 @@ local function formspec2(pos, text)
default.gui_bg.. default.gui_bg..
default.gui_bg_img.. default.gui_bg_img..
default.gui_slots.. default.gui_slots..
"style_type[textarea,table;font=mono]"..
"tabheader[0,0;tab;"..I("Commands,Help")..";2;;true]".. "tabheader[0,0;tab;"..I("Commands,Help")..";2;;true]"..
"table[0.1,0;8.6,4;command;"..sCmnds..";"..pos.."]".. "table[0.1,0;8.6,4;command;"..sCmnds..";"..pos.."]"..
"textarea[0.3,4.5;9,3.5;help;Help:;"..text.."]".. "textarea[0.3,4.5;9,3.5;help;Help:;"..text.."]"..

View File

@ -69,7 +69,7 @@ if minetest.get_modpath("techage") then
mod = "techage", mod = "techage",
params = "<percent>", params = "<percent>",
num_param = 1, num_param = 1,
description = S("Turn the bot off if the\nbattery power is below the\ngiven value (1..99)"), description = S("Turns the bot off if the\nbattery power is below the\ngiven value in percent (1..99)"),
check = function(val) check = function(val)
val = tonumber(val) or 5 val = tonumber(val) or 5
return val and val > 0 and val < 100 return val and val > 0 and val < 100
@ -81,7 +81,7 @@ if minetest.get_modpath("techage") then
signs_bot.stop_robot(base_pos, mem) signs_bot.stop_robot(base_pos, mem)
return signs_bot.TURN_OFF return signs_bot.TURN_OFF
end end
return true return signs_bot.DONE
end, end,
}) })

View File

@ -31,6 +31,8 @@ Copyright (C) 2019-2020 Joachim Stolberg
Code: Licensed under the GNU GPL version 3 or later. See LICENSE.txt Code: Licensed under the GNU GPL version 3 or later. See LICENSE.txt
Textures: CC BY-SA 3.0 Textures: CC BY-SA 3.0
Many thanks to Thomas-S for his contributions
### Dependencies ### Dependencies
Required: default, doors, bucket, stairs, screwdriver, basic_materials, tubelib2, minecart, lcdlib, safer_lua Required: default, doors, bucket, stairs, screwdriver, basic_materials, tubelib2, minecart, lcdlib, safer_lua
@ -75,6 +77,23 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
### History ### History
**2020-08-08 V0.21**
- Pull request #18: Add a simple Digtron battery (from Thomas-S)
- Pull request #23: Lua Controller: Fix $item_description() documentation and translation (from Thomas-S)
- Pull request #24: Distributor: improve fairness by using random spread (from realmicu)
- Bugfix: TA1 meridian hammer did not glow (from realmicu)
- Bugfix: power.power_available() did not check the network state
**2020-07-31 V0.20**
- Pull request #21: Lua Controller: Allow to get itemstring and description of 8x2000 chest contents (from Thomas-S)
- Pull request #22: Trowel: Prevent hidden nodes from being dug (from Thomas-S)
- Improvement: TA3 Power Terminal: Outputs max needed power in addition
- Bugfix: Quarry: Shall not dig Techage Light Blocks
**2020-07-24 V0.19**
- Pull request #19: Refactor ICTA to use functions instead of loadstring (from Thomas-S)
- State command added for cart-, node-, and player detectors
**2020-07-21 V0.18** **2020-07-21 V0.18**
- Pull request #13: Use Monospace Font for Code-Related Formspecs (from Thomas-S) - Pull request #13: Use Monospace Font for Code-Related Formspecs (from Thomas-S)
- Pull request #14: Don't allow to put items with meta or wear information into the 8x2000 chest (from Thomas-S) - Pull request #14: Don't allow to put items with meta or wear information into the 8x2000 chest (from Thomas-S)

View File

@ -176,6 +176,10 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
meta:set_int("push_dir", techage.side_to_indir("L", node.param2)) meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
meta:set_int("pull_dir", techage.side_to_indir("R", node.param2)) meta:set_int("pull_dir", techage.side_to_indir("R", node.param2))
-- Delete existing node number. Needed for Digtron compatibility.
if (meta:contains("node_number")) then
meta:set_string("node_number", "")
end
local number = "-" local number = "-"
if stage > 2 then if stage > 2 then
number = techage.add_node(pos, name_pas) number = techage.add_node(pos, name_pas)
@ -240,6 +244,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
paramtype = tNode.paramtype, paramtype = tNode.paramtype,
paramtype2 = "facedir", paramtype2 = "facedir",
drop = tNode.drop,
groups = table.copy(tNode.groups), groups = table.copy(tNode.groups),
is_ground_content = false, is_ground_content = false,
sounds = tNode.sounds, sounds = tNode.sounds,

View File

@ -35,6 +35,19 @@ local SlotColors = {"red", "green", "blue", "yellow"}
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
-- Permutation table to improve distribution between ports (number of ports: 1-4)
-- Usage: permIdx[num_ports][math.random(1, #permIdx[num_ports])][idx]
local permIdx = {
{ { 1 } },
{ { 1, 2 }, { 2, 1 } },
{ { 1, 2, 3 }, { 1, 3, 2 }, { 2, 1, 3 }, { 2, 3, 1 }, { 3, 1, 2 }, { 3, 2, 1 } },
{ { 1, 2, 3, 4 }, { 1, 2, 4, 3 }, { 1, 3, 2, 4 }, { 1, 3, 4, 2 }, { 1, 4, 2, 3 },
{ 1, 4, 3, 2 }, { 2, 1, 3, 4 }, { 2, 1, 4, 3 }, { 2, 3, 1, 4 }, { 2, 3, 4, 1 },
{ 2, 4, 1, 3 }, { 2, 4, 3, 1 }, { 3, 1, 2, 4 }, { 3, 1, 4, 2 }, { 3, 2, 1, 4 },
{ 3, 2, 4, 1 }, { 3, 4, 1, 2 }, { 3, 4, 2, 1 }, { 4, 1, 2, 3 }, { 4, 1, 3, 2 },
{ 4, 2, 1, 3 }, { 4, 2, 3, 1 }, { 4, 3, 1, 2 }, { 4, 3, 2, 1 }, }
}
local function filter_settings(pos) local function filter_settings(pos)
local meta = M(pos) local meta = M(pos)
local param2 = techage.get_node_lvm(pos).param2 local param2 = techage.get_node_lvm(pos).param2
@ -206,11 +219,12 @@ local function push_item(pos, filter, item_name, num_items, nvm)
local idx = 1 local idx = 1
local num_pushed = 0 local num_pushed = 0
local num_ports = #filter local num_ports = #filter
local randidx = permIdx[num_ports][math.random(1, #permIdx[num_ports])]
local amount = math.floor(math.max((num_items + 1) / num_ports, 1)) local amount = math.floor(math.max((num_items + 1) / num_ports, 1))
local num_of_trials = 0 local num_of_trials = 0
while num_pushed < num_items and num_of_trials <= 8 do while num_pushed < num_items and num_of_trials <= 8 do
num_of_trials = num_of_trials + 1 num_of_trials = num_of_trials + 1
local push_dir = filter[idx] local push_dir = filter[randidx[idx]]
local num_to_push = math.min(amount, num_items - num_pushed) local num_to_push = math.min(amount, num_items - num_pushed)
if techage.push_items(pos, push_dir, ItemStack(item_name.." "..num_to_push)) then if techage.push_items(pos, push_dir, ItemStack(item_name.." "..num_to_push)) then
num_pushed = num_pushed + num_to_push num_pushed = num_pushed + num_to_push

View File

@ -26,7 +26,7 @@ local networks = techage.networks
local STANDBY_TICKS = 4 local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4 local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2 local CYCLE_TIME = 2
local PWR_CAPA = 20 local PWR_CAPA = 100
local function formspec(self, pos, nvm) local function formspec(self, pos, nvm)
return "size[4,4]".. return "size[4,4]"..

View File

@ -65,6 +65,16 @@ local function get_count(nvm, idx)
end end
end end
local function get_itemstring(nvm, idx)
if idx and idx > 0 then
nvm.inventory = nvm.inventory or {}
if nvm.inventory[idx] then
return nvm.inventory[idx].name or ""
end
end
return ""
end
local function inv_empty(nvm) local function inv_empty(nvm)
for _,item in ipairs(nvm.inventory or {}) do for _,item in ipairs(nvm.inventory or {}) do
if item.count and item.count > 0 then if item.count and item.count > 0 then
@ -552,6 +562,9 @@ techage.register_node({"techage:ta4_chest"}, {
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 0)
elseif topic == "itemstring" then
local nvm = techage.get_nvm(pos)
return get_itemstring(nvm, tonumber(payload) or 0)
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)

View File

@ -219,7 +219,7 @@ end
function techage.remove_node(pos, oldnode, oldmetadata) function techage.remove_node(pos, oldnode, oldmetadata)
local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number local number = oldmetadata and oldmetadata.fields and oldmetadata.fields.node_number
number = number or get_number(pos) number = number or get_number(pos)
if number then if number and tonumber(number) then
local key = minetest.hash_node_position(pos) local key = minetest.hash_node_position(pos)
NumbersToBeRecycled[key] = number NumbersToBeRecycled[key] = number
local ninfo = NodeInfoCache[number] or update_nodeinfo(number) local ninfo = NodeInfoCache[number] or update_nodeinfo(number)

View File

@ -164,6 +164,7 @@ end
function techage.dropped_node(node, ndef) function techage.dropped_node(node, ndef)
if node.name == "air" then return end if node.name == "air" then return end
--if ndef.buildable_to == true then return end --if ndef.buildable_to == true then return end
if not ndef.diggable then return end
if ndef.drop == "" then return end if ndef.drop == "" then return end
if type(ndef.drop) == "table" then if type(ndef.drop) == "table" then
return handle_drop(ndef.drop) return handle_drop(ndef.drop)

182
techage/digtron/battery.lua Normal file
View File

@ -0,0 +1,182 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2020 Thomas S.
GPL v3
See LICENSE.txt for more information
Electricity powered battery for Digtron
]]--
-- for lazy programmers
local M = minetest.get_meta
local S = techage.S
-- Consumer Related Data
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
local power = techage.power
local STANDBY_TICKS = 3
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 4
local INV_SIZE = 4
local FUEL = "default:coal_lump"
local FUEL_STACK_MAX = ItemStack(FUEL):get_stack_max()
local TOTAL_MAX = INV_SIZE * FUEL_STACK_MAX
local function count_coal(metadata)
local total = 0
for _,stack in pairs(metadata.inventory.fuel) do
total = total + stack:get_count()
end
return total
end
local function formspec(self, pos, nvm)
local meta = M(pos):to_table()
local total = 0
if meta.inventory then
total = count_coal(meta)
end
return "size[5,4]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize("#000000", S("Digtron Battery")).."]"..
power.formspec_label_bar(0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
"image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.6,2;1,1;"..self:get_state_tooltip(nvm).."]"..
"image[3.75,2;1,1;"..techage.get_power_image(pos, nvm).."]"
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
return 0
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
return 0
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
return 0
end
local function produce_coal(pos, crd, nvm, inv)
local stack = ItemStack(FUEL)
if inv:room_for_item("fuel", stack) then
inv:add_item("fuel", stack)
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
else
crd.State:idle(pos, nvm)
end
end
local function keep_running(pos, elapsed)
local nvm = techage.get_nvm(pos)
local crd = CRD(pos)
local inv = M(pos):get_inventory()
produce_coal(pos, crd, nvm, inv)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
end
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local nvm = techage.get_nvm(pos)
CRD(pos).State:state_button_event(pos, nvm, fields)
end
local tiles = {}
-- '#' will be replaced by the stage number
-- '{power}' will be replaced by the power PNG
tiles = {
-- up, down, right, left, back, front
"digtron_plate.png^digtron_core.png",
"digtron_plate.png^digtron_core.png",
"digtron_plate.png^digtron_battery.png",
"digtron_plate.png^digtron_battery.png",
"digtron_plate.png^digtron_battery.png",
"digtron_plate.png^digtron_battery.png",
}
local tubing = {
on_recv_message = function(pos, src, topic, payload)
return CRD(pos).State:on_receive_message(pos, topic, payload)
end,
}
local node_name_ta2, node_name_ta3, node_name_ta4 =
techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles, pas = tiles }, {
drawtype = "normal",
paramtype = "light",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec = formspec,
tubing = tubing,
after_place_node = function(pos, placer, itemstack)
local inv = M(pos):get_inventory()
inv:set_size('fuel', INV_SIZE)
if itemstack then
local stack_meta = itemstack:get_meta()
if stack_meta then
local coal_amount = techage.in_range(stack_meta:get_int("coal"), 0, TOTAL_MAX)
while coal_amount > 0 do
local amount = math.min(coal_amount, FUEL_STACK_MAX)
inv:add_item("fuel", ItemStack(FUEL.." "..amount))
coal_amount = coal_amount - amount;
end
end
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local node = ItemStack(oldnode.name)
if oldmetadata.inventory then
local total = count_coal(oldmetadata)
local meta = node:get_meta()
meta:set_int("coal", total)
local text = S("Digtron Battery").." ("..math.floor(total/TOTAL_MAX * 100).." %)"
meta:set_string("description", text)
end
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
local left_over = inv:add_item("main", node)
if left_over:get_count() > 0 then
minetest.add_item(pos, node)
end
end,
on_rightclick = function(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
end,
drop = "",
node_timer = keep_running,
on_receive_fields = on_receive_fields,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
groups = {choppy=2, cracky=2, crumbly=2, digtron=5},
sounds = default.node_sound_wood_defaults(),
power_consumption = {0,25,25,25},
power_sides = techage.networks.AllSides,
}, {false, false, true, false})
minetest.register_craft({
output = node_name_ta3,
recipe = {
{"group:wood", "default:copper_ingot", "group:wood"},
{"techage:electric_cableS", "default:tin_ingot", "digtron:digtron_core"},
{"group:wood", "default:copper_ingot", "group:wood"},
},
})

View File

@ -99,9 +99,10 @@ techage.icta_register_action("print", {
return 'print("'..data.text:sub(1,12)..'")' return 'print("'..data.text:sub(1,12)..'")'
end, end,
code = function(data, environ) code = function(data, environ)
local s1 = 'local text = string.gsub("'..(techage.icta_escape(data.text))..'", "*", env.result[#])' return function(env, output, idx)
local s2 = 'output(env.pos, text)' local text = string.gsub(data.text, "*", tostring(env.result[idx]))
return s1.."\n\t"..s2 output(env.pos, text)
end
end, end,
}) })

View File

@ -17,31 +17,18 @@ local M = minetest.get_meta
local S = techage.S local S = techage.S
local logic = techage.logic local logic = techage.logic
local function send_single_string(environ, number, topic, payload) function techage.compare(op1, op2, method)
payload = payload or "nil" if method == "is" then
local s = 'techage.send_single("%s", "%s", "%s", %s)' return op1 == op2
return string.format(s, environ.number, number, topic, payload) elseif method == "is not" then
end return op1 ~= op2
elseif method == "greater" then
local function send_multi_string(environ, numbers, topic, payload) return op1 > op2
payload = payload or "nil" elseif method == "less" then
local s = 'techage.send_multi("%s", "%s", "%s", %s)' return op1 < op2
return string.format(s, environ.number, numbers, topic, payload)
end
function techage.operand(s)
if s == "is" then
return "== "
elseif s == "is not" then
return "~= "
elseif s == "greater" then
return "> "
elseif s == "less" then
return "< "
end end
end end
function techage.fmt_number(num) function techage.fmt_number(num)
local mtch = num:match('^(%d+).*') local mtch = num:match('^(%d+).*')
if mtch and num ~= mtch then if mtch and num ~= mtch then
@ -50,13 +37,6 @@ function techage.fmt_number(num)
return num return num
end end
-- '#' is used as placeholder for rule numbers and has to be escaped
function techage.icta_escape(s)
s = tostring(s)
s = s:gsub('"', '\\"') -- to prevent code injection!!!
return s:gsub("#", '"..string.char(35).."')
end
techage.icta_register_condition("initial", { techage.icta_register_condition("initial", {
title = "initial", title = "initial",
@ -70,7 +50,13 @@ techage.icta_register_condition("initial", {
-- Return two chunks of executable Lua code for the controller, according: -- Return two chunks of executable Lua code for the controller, according:
-- return <read condition>, <expected result> -- return <read condition>, <expected result>
code = function(data, environ) code = function(data, environ)
return 'env.ticks', '== 1' local condition = function(env, idx)
return env.ticks
end
local result = function(val)
return val == 1
end
return condition, result
end, end,
button = function(data, environ) return "Initial after start" end, button = function(data, environ) return "Initial after start" end,
}) })
@ -85,7 +71,13 @@ techage.icta_register_condition("true", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
return '"true"', '== "true"' local condition = function(env, idx)
return true
end
local result = function(val)
return val == true
end
return condition, result
end, end,
button = function(data, environ) return "true" end, button = function(data, environ) return "true" end,
}) })
@ -114,12 +106,14 @@ techage.icta_register_condition("condition", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
local idx = data.condition:byte(-1) - 0x30 local condition = function(env, idx)
local expected_result = "== false" local index = data.condition:byte(-1) - 0x30
if data.operand == "was true" then return env.condition[index]
expected_result = "== true"
end end
return "env.condition["..idx.."]", expected_result local result = function(val)
return val == (data.operand == "was true")
end
return condition, result
end, end,
button = function(data, environ) return "cond("..data.condition:sub(-1,-1)..","..data.operand..")" end, button = function(data, environ) return "cond("..data.condition:sub(-1,-1)..","..data.operand..")" end,
}) })
@ -155,8 +149,13 @@ techage.icta_register_condition("input", {
return 'inp('..techage.fmt_number(data.number)..','..data.operand.." "..data.value..')' return 'inp('..techage.fmt_number(data.number)..','..data.operand.." "..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return 'env.input["'..data.number..'"]', local condition = function(env, idx)
techage.operand(data.operand)..'"'..data.value..'"' return env.input[data.number]
end
local result = function(val)
return techage.compare(val, data.value, data.operand)
end
return condition, result
end, end,
}) })
@ -193,8 +192,13 @@ techage.icta_register_condition("state", {
return 'sts('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'sts('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "state"), local condition = function(env, idx)
techage.operand(data.operand)..'"'..data.value..'"' return techage.send_single(environ.number, data.number, "state")
end
local result = function(val)
return techage.compare(val, data.value, data.operand)
end
return condition, result
end, end,
}) })
@ -230,8 +234,13 @@ techage.icta_register_condition("fuel", {
return 'fuel('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'fuel('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "fuel"), local condition = function(env, idx)
techage.operand(data.operand)..tonumber(data.value) return techage.send_single(environ.number, data.number, "fuel")
end
local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand)
end
return condition, result
end, end,
}) })
@ -267,8 +276,13 @@ techage.icta_register_condition("load", {
return 'load('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'load('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "load"), local condition = function(env, idx)
techage.operand(data.operand)..tonumber(data.value) return techage.send_single(environ.number, data.number, "load")
end
local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand)
end
return condition, result
end, end,
}) })
@ -304,8 +318,13 @@ techage.icta_register_condition("depth", {
return 'depth('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'depth('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "depth"), local condition = function(env, idx)
techage.operand(data.operand)..tonumber(data.value) return techage.send_single(environ.number, data.number, "depth")
end
local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand)
end
return condition, result
end, end,
}) })
@ -341,8 +360,13 @@ techage.icta_register_condition("delivered", {
return 'deliv('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'deliv('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "delivered"), local condition = function(env, idx)
techage.operand(data.operand)..tonumber(data.value) return techage.send_single(environ.number, data.number, "delivered")
end
local result = function(val)
return techage.compare(val, tonumber(data.value), data.operand)
end
return condition, result
end, end,
}) })
@ -380,8 +404,13 @@ techage.icta_register_condition("chest", {
return 'chest('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'chest('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "state"), local condition = function(env, idx)
techage.operand(data.operand)..'"'..data.value..'"' return techage.send_single(environ.number, data.number, "state")
end
local result = function(val)
return techage.compare(val, data.value, data.operand)
end
return condition, result
end, end,
}) })
@ -416,8 +445,13 @@ techage.icta_register_condition("signaltower", {
return 'tower('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')' return 'tower('..techage.fmt_number(data.number)..","..data.operand..' '..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_single_string(environ, data.number, "state"), local condition = function(env, idx)
techage.operand(data.operand)..'"'..data.value..'"' return techage.send_single(environ.number, data.number, "state")
end
local result = function(val)
return techage.compare(val, data.value, data.operand)
end
return condition, result
end, end,
}) })
@ -447,7 +481,9 @@ techage.icta_register_action("signaltower", {
return 'tower('..techage.fmt_number(data.number)..","..data.value..')' return 'tower('..techage.fmt_number(data.number)..","..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_multi_string(environ, data.number, data.value) return function(env, output, idx)
techage.send_multi(environ.number, data.number, data.value)
end
end, end,
}) })
@ -477,7 +513,9 @@ techage.icta_register_action("switch", {
return 'turn('..techage.fmt_number(data.number)..","..data.value..')' return 'turn('..techage.fmt_number(data.number)..","..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
return send_multi_string(environ, data.number, data.value) return function(env, output, idx)
techage.send_multi(environ.number, data.number, data.value)
end
end, end,
}) })
@ -510,10 +548,13 @@ techage.icta_register_action("display", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
local s1 = string.format('local text = string.gsub("%s", "*", tostring(env.result[#]))', techage.icta_escape(data.text)) return function(env, output, idx)
local s2 = string.format('local payload = {row = %s, str = text}', data.row) local text = string.gsub(data.text, "*", tostring(env.result[idx]))
local s3 = send_multi_string(environ, data.number, "set", "payload") local payload = safer_lua.Store()
return s1.."\n\t"..s2.."\n\t"..s3 payload.set("row", data.row)
payload.set("str", text)
techage.send_multi(environ.number, data.number, "set", payload)
end
end, end,
button = function(data, environ) button = function(data, environ)
return "lcd("..techage.fmt_number(data.number)..","..data.row..',"'..data.text..'")' return "lcd("..techage.fmt_number(data.number)..","..data.row..',"'..data.text..'")'
@ -531,7 +572,9 @@ techage.icta_register_action("cleardisplay", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
return send_multi_string(environ, data.number, "clear") return function(env, output, idx)
techage.send_multi(environ.number, data.number, "clear")
end
end, end,
button = function(data, environ) button = function(data, environ)
return "clear lcd("..techage.fmt_number(data.number)..")" return "clear lcd("..techage.fmt_number(data.number)..")"
@ -554,7 +597,9 @@ techage.icta_register_action("chat", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
return 'minetest.chat_send_player("'..environ.owner..'", "[TA4 ICTA Controller] '..techage.icta_escape(data.text)..' ")' return function(env, output, idx)
minetest.chat_send_player(environ.owner, "[TA4 ICTA Controller] "..data.text)
end
end, end,
button = function(data, environ) button = function(data, environ)
return 'chat("'..data.text:sub(1,12)..'")' return 'chat("'..data.text:sub(1,12)..'")'
@ -603,7 +648,9 @@ techage.icta_register_action("door", {
}, },
}, },
code = function(data, environ) code = function(data, environ)
return 'techage.icta_door_toggle("'..data.pos..'", "'..environ.owner..'", "'..data.door_state..'")' return function(env, output, idx)
techage.icta_door_toggle(data.pos, environ.owner, data.door_state)
end
end, end,
button = function(data, environ) button = function(data, environ)
return 'door("'..data.pos..'",'..data.door_state..")" return 'door("'..data.pos..'",'..data.door_state..")"
@ -645,7 +692,13 @@ techage.icta_register_condition("playerdetector", {
}, },
code = function(data, environ) code = function(data, environ)
return 'techage.icta_player_detect("'..environ.number..'", "'..data.number..'", "'..techage.icta_escape(data.name)..'")', "~= nil" local condition = function(env, idx)
return techage.icta_player_detect(environ.number, data.number, data.name)
end
local result = function(val)
return val ~= nil
end
return condition, result
end, end,
button = function(data, environ) button = function(data, environ)
return "detector("..techage.fmt_number(data.number)..","..data.name:sub(1,8)..")" return "detector("..techage.fmt_number(data.number)..","..data.name:sub(1,8)..")"
@ -685,7 +738,9 @@ techage.icta_register_action("set_filter", {
return 'turn('..techage.fmt_number(data.number)..","..data.color..","..data.value..')' return 'turn('..techage.fmt_number(data.number)..","..data.color..","..data.value..')'
end, end,
code = function(data, environ) code = function(data, environ)
local payload = '{slot = "'..data.color..'", val = "'..data.value..'"}' return function(env, output, idx)
return send_single_string(environ, data.number, "filter", payload) local payload = data.color.."="..data.value
techage.send_single(environ.number, data.number, "port", payload)
end
end, end,
}) })

View File

@ -71,7 +71,15 @@ end
techage.icta_register_condition("default", { techage.icta_register_condition("default", {
title = "", title = "",
formspec = {}, formspec = {},
code = function(data, environ) return false, false end, code = function(data, environ)
local condition = function(env, idx)
return false
end
local result = function(val)
return false
end
return condition, result
end,
button = function(data, environ) return "..." end, button = function(data, environ) return "..." end,
}) })

View File

@ -57,100 +57,51 @@ local function output(pos, text, flush_buffer)
meta:set_string("formspec", techage.formspecOutput(meta)) meta:set_string("formspec", techage.formspecOutput(meta))
end end
----------------- template -------------------------------
-- -- Rule 1
-- if env.blocked[1] == false and env.ticks % <cycle> == 0 then
-- env.result[1] = <check condition>
-- env.blocked[1] = env.result[1] <expected result>
-- if env.blocked[1] then
-- env.timer[1] = env.ticks + <after>
-- end
-- env.conditions[1] = env.blocked[1]
-- else
-- env.conditions[1] = false
-- end
-- if env.blocked[1] and env.timer[1] == env.ticks then
-- <action>
-- env.blocked[1] = false
-- end
-- -- Callback variant
-- if env.blocked[1] == false and env.ticks % <cycle> == 0 then
-- env.result[1], env.blocked[1] = <callback>
-- if env.blocked[1] then
-- env.timer[1] = env.ticks + <after>
-- end
-- env.conditions[1] = env.blocked[1]
-- else
-- env.conditions[1] = false
-- end
-- if env.blocked[1] and env.timer[1] == env.ticks then
-- <action>
-- env.blocked[1] = false
-- end
-- cyclic execution (cycle, cond, result, after, actn) -- cyclic execution (cycle, cond, result, after, actn)
local TemplCyc = [[ local function TemplCyc(cycle, cond, result, after, actn, idx)
-- Rule # return function(env, output)
if env.blocked[#] == false and env.ticks %% %s == 0 then if env.blocked[idx] == false and env.ticks % cycle == 0 then
env.result[#] = %s env.result[idx] = cond(env, idx)
env.blocked[#] = env.result[#] %s env.blocked[idx] = result(env.result[idx])
if env.blocked[#] then if env.blocked[idx] then
env.timer[#] = env.ticks + %s env.timer[idx] = env.ticks + after
end end
env.condition[#] = env.blocked[#] env.condition[idx] = env.blocked[idx]
else else
env.condition[#] = false env.condition[idx] = false
end
if env.blocked[idx] and env.timer[idx] == env.ticks then
actn(env, output, idx)
env.blocked[idx] = false
end
end end
if env.blocked[#] and env.timer[#] == env.ticks then
%s
env.blocked[#] = false
end end
]]
-- event based execution -- event based execution
local TemplEvt = [[ local function TemplEvt(cond, result, after, actn, idx)
-- Rule # return function(env, output)
if env.blocked[#] == false and env.event then if env.blocked[idx] == false and env.event then
env.result[#] = %s env.result[idx] = cond(env, idx)
env.blocked[#] = env.result[#] %s env.blocked[idx] = result(env.result[idx])
if env.blocked[#] then if env.blocked[idx] then
env.timer[#] = env.ticks + %s env.timer[idx] = env.ticks + after
end end
env.condition[#] = env.blocked[#] env.condition[idx] = env.blocked[idx]
else else
env.condition[#] = false env.condition[idx] = false
end
if env.blocked[idx] and env.timer[idx] == env.ticks then
actn(env, output, idx)
env.blocked[idx] = false
end end
if env.blocked[#] and env.timer[#] == env.ticks then
%s
env.blocked[#] = false
end end
]]
-- event based execution of callback function
local TemplEvtClbk = [[
-- Rule #
if env.blocked[#] == false and env.event then
env.result[#], env.blocked[#] = %s(env, %s)
if env.blocked[#] then
env.timer[#] = env.ticks + %s
end end
env.condition[#] = env.blocked[#]
else
env.condition[#] = false
end
if env.blocked[#] and env.timer[#] == env.ticks then
%s
env.blocked[#] = false
end
]]
-- generate the Lua code from the NUM_RULES rules -- generate the Lua code from the NUM_RULES rules
local function generate(pos, meta, environ) local function generate(pos, meta, environ)
local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
-- chunks are compiled as vararg functions. Parameters are available via: local a, b, c = ... local tbl = {}
local tbl = {"local env, output = ...\n"}
for idx = 1,techage.NUM_RULES do for idx = 1,techage.NUM_RULES do
local cycle = integer(fs_data[idx].cycle, 0, 1000) local cycle = integer(fs_data[idx].cycle, 0, 1000)
local cond, result = techage.code_condition(fs_data[idx].cond, environ) local cond, result = techage.code_condition(fs_data[idx].cond, environ)
@ -159,26 +110,21 @@ local function generate(pos, meta, environ)
-- valid rule? -- valid rule?
if cycle and cond and after and actn then if cycle and cond and after and actn then
-- add rule number -- add rule number
local s local f
if cycle == 0 then -- event? if cycle == 0 then -- event
if result then f = TemplEvt(cond, result, after, actn, idx)
s = string.format(TemplEvt, cond, result, after, actn)
else -- callback function
local data = dump(fs_data[idx].cond)
s = string.format(TemplEvtClbk, cond, data, after, actn)
end
else -- cyclic else -- cyclic
s = string.format(TemplCyc, cycle, cond, result, after, actn) f = TemplCyc(cycle, cond, result, after, actn, idx)
end end
-- add to list of rules -- add to list of rules
tbl[#tbl+1] = s:gsub("#", idx) tbl[#tbl+1] = f
elseif cond ~= nil and actn == nil then elseif cond ~= nil and actn == nil then
output(pos, "Error in action in rule "..idx) output(pos, "Error in action in rule "..idx)
elseif cond == nil and actn ~= nil then elseif cond == nil and actn ~= nil then
output(pos, "Error in condition in rule "..idx) output(pos, "Error in condition in rule "..idx)
end end
end end
return table.concat(tbl) return tbl
end end
local function runtime_environ(pos) local function runtime_environ(pos)
@ -200,21 +146,12 @@ local function compile(pos, meta, number)
number = number, number = number,
owner = meta:get_string("owner"), owner = meta:get_string("owner"),
} }
local text = generate(pos, meta, gen_environ) local functions = generate(pos, meta, gen_environ)
if text then
local code, err = loadstring(text)
if code then
Cache[number] = { Cache[number] = {
code = code, code = functions,
env = runtime_environ(pos), env = runtime_environ(pos),
} }
return true return true
else
output(pos, err)
return false
end
end
return false
end end
local function execute(pos, number, event) local function execute(pos, number, event)
@ -226,11 +163,13 @@ local function execute(pos, number, event)
env.event = false env.event = false
env.ticks = env.ticks + 1 env.ticks = env.ticks + 1
end end
local res, err = pcall(code, env, output) for _,func in ipairs(code) do
local res, err = pcall(func, env, output)
if not res then if not res then
output(pos, err) output(pos, err)
return false return false
end end
end
return true return true
end end

View File

@ -211,8 +211,8 @@ local function write_row(pos, payload, cycle_time)
local mem = techage.get_mem(pos) local mem = techage.get_mem(pos)
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.str) or "oops" local str = tostring(payload.get("str")) or "oops"
local row = tonumber(payload.row) or 1 local row = tonumber(payload.get("row")) or 1
if mem.ticks == 0 then if mem.ticks == 0 then
mem.ticks = cycle_time mem.ticks = cycle_time

View File

@ -13,7 +13,7 @@
techage = {} techage = {}
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
techage.version = 0.18 techage.version = 0.21
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!")
@ -27,8 +27,8 @@ elseif minetest.global_exists("techpack") then
elseif minetest.global_exists("tubelib2") and tubelib2.version < 1.9 then elseif minetest.global_exists("tubelib2") and tubelib2.version < 1.9 then
minetest.log("error", "[techage] Techage requires tubelib2 version 1.9 or newer!") minetest.log("error", "[techage] Techage requires tubelib2 version 1.9 or newer!")
return return
elseif minetest.global_exists("minecart") and minecart.version < 1.06 then elseif minetest.global_exists("minecart") and minecart.version < 1.08 then
minetest.log("error", "[techage] Techage requires minecart version 1.06 or newer!") minetest.log("error", "[techage] Techage requires minecart version 1.08 or newer!")
return return
elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.0 then elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.0 then
minetest.log("error", "[techage] Techage requires lcdlib version 1.0 or newer!") minetest.log("error", "[techage] Techage requires lcdlib version 1.0 or newer!")
@ -55,6 +55,14 @@ techage.S = minetest.get_translator("techage")
-- Load mod storage -- Load mod storage
techage.storage = minetest.get_mod_storage() techage.storage = minetest.get_mod_storage()
-- Ensure compatibility with older Minetest versions by providing
-- a dummy implementation of `minetest.get_translated_string`.
if not minetest.get_translated_string then
minetest.get_translated_string = function(lang_code, string)
return string
end
end
-- Basis features -- Basis features
local MP = minetest.get_modpath("techage") local MP = minetest.get_modpath("techage")
dofile(MP.."/basis/lib.lua") -- helper functions dofile(MP.."/basis/lib.lua") -- helper functions
@ -206,6 +214,11 @@ dofile(MP.."/oil/reboiler.lua")
dofile(MP.."/ta3_power/tiny_generator.lua") dofile(MP.."/ta3_power/tiny_generator.lua")
dofile(MP.."/ta3_power/akkubox.lua") dofile(MP.."/ta3_power/akkubox.lua")
-- Digtron
if minetest.global_exists("digtron") then
dofile(MP.."/digtron/battery.lua")
end
-- Logic -- Logic
dofile(MP.."/logic/lib.lua") dofile(MP.."/logic/lib.lua")
dofile(MP.."/logic/terminal.lua") dofile(MP.."/logic/terminal.lua")

View File

@ -156,6 +156,7 @@ if minetest.global_exists("wielded_light") then
damage_groups = {fleshy=4}, damage_groups = {fleshy=4},
}, },
sound = {breaks = "default_tool_breaks"}, sound = {breaks = "default_tool_breaks"},
light_source = 12,
after_use = function(itemstack, user, node, digparams) after_use = function(itemstack, user, node, digparams)
minetest.after(0.01, handler, user:get_player_name(), node) minetest.after(0.01, handler, user:get_player_name(), node)
itemstack:add_wear(digparams.wear) itemstack:add_wear(digparams.wear)

View File

@ -39,6 +39,7 @@ minetest.register_node("techage:lightblock", {
floodable = true, floodable = true,
is_ground_content = false, is_ground_content = false,
groups = {not_in_creative_inventory=1}, groups = {not_in_creative_inventory=1},
drop = "",
}) })
function techage.light_ring(center_pos, on, large) function techage.light_ring(center_pos, on, large)

View File

@ -1,5 +1,6 @@
# textdomain: techage # textdomain: techage
ku is needed!)= ku wird benötigt!)
#### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd <num> <cmnd>@n@nexample: cmd 181 on@n<num> is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set <button-num> <button-text> <command>@ne.g. 'set 1 ON cmd 123 on'@n= #### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd <num> <cmnd>@n@nexample: cmd 181 on@n<num> is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set <button-num> <button-text> <command>@ne.g. 'set 1 ON cmd 123 on'@n=
Accu Box=Akkublock Accu Box=Akkublock
Active:=Aktiv: Active:=Aktiv:
@ -35,6 +36,7 @@ Build derrick=Errichte Ölturm
Catalyst=Katalysator Catalyst=Katalysator
Cement Block=Zement Block Cement Block=Zement Block
Cement Powder=Zement Pulver Cement Powder=Zement Pulver
Coal Equivalents=Kohleeinheiten
Compressed Gravel=Komprimiertes Kies Compressed Gravel=Komprimiertes Kies
Configure up to 8 items @nto be pushed by the injector=Konfiguriere bis zu 8 Gegenstände \n die vom Injektor weitergegeben werden sollen Configure up to 8 items @nto be pushed by the injector=Konfiguriere bis zu 8 Gegenstände \n die vom Injektor weitergegeben werden sollen
Consum. 1=Konsum. 1 Consum. 1=Konsum. 1
@ -42,6 +44,7 @@ Consum. 2=Konsum. 2
Current power:=Strom aktuell: Current power:=Strom aktuell:
Depth=Tiefe Depth=Tiefe
Digging depth=Grabungstiefe Digging depth=Grabungstiefe
Digtron Battery=Digtron Akku
Dirt with Ash=Erde mit Asche Dirt with Ash=Erde mit Asche
Display no: = Display Nr. Display no: = Display Nr.
Distributor=Verteiler Distributor=Verteiler
@ -102,6 +105,7 @@ Load=Ladung
Lye=Lauge Lye=Lauge
Lye Barrel=Lauge Fass Lye Barrel=Lauge Fass
Lye Canister=Lauge Kanister Lye Canister=Lauge Kanister
Max. needed power=Max. benötigter Strom
Maximum power:=Maximalstrom: Maximum power:=Maximalstrom:
Melting Guide=Schmelzführer Melting Guide=Schmelzführer
Melting Pot active (heat@==Schmelztiegel aktiv (Hitze@= Melting Pot active (heat@==Schmelztiegel aktiv (Hitze@=
@ -147,6 +151,7 @@ Power Source=Stromquelle
Power grid total=Stromnetz gesammt Power grid total=Stromnetz gesammt
Power station=Kraftwerk Power station=Kraftwerk
Priv missing=Rechte fehlen Priv missing=Rechte fehlen
Probably too many consumers (=Vermutlich zu viele Verbraucher (
Propane Cylinder Large=Propangasflasche groß Propane Cylinder Large=Propangasflasche groß
Propane Cylinder Small=Propangasflasche klein Propane Cylinder Small=Propangasflasche klein
Pumpjack=Ölpumpe Pumpjack=Ölpumpe
@ -385,6 +390,7 @@ Type=Typ
Unlock=Entsperren Unlock=Entsperren
Unlock connected chest@nif all slots are below 2000=Nachfolgende Kiste entsperren,@nsofern alle Speicherplätze <= 2000 Unlock connected chest@nif all slots are below 2000=Nachfolgende Kiste entsperren,@nsofern alle Speicherplätze <= 2000
Update=Update Update=Update
Use a trowel to remove the node.=Verwende eine Kelle, um den Block zu entfernen.
Usmium Nuggets=Usmium Nuggets Usmium Nuggets=Usmium Nuggets
Usmium Powder=Usmium Pulver Usmium Powder=Usmium Pulver
WLAN Chip=WLAN Chip WLAN Chip=WLAN Chip

View File

@ -1,3 +1,4 @@
ku is needed!)=
#### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd <num> <cmnd>@n@nexample: cmd 181 on@n<num> is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set <button-num> <button-text> <command>@ne.g. 'set 1 ON cmd 123 on'@n= #### TA3 Terminal ####@n@nSend commands to your machines@nand output text messages from your@nmachines to the Terminal.@n@nCommand syntax:@n cmd <num> <cmnd>@n@nexample: cmd 181 on@n<num> is the number of the node to which the command is sent@n'on' is the command to turn machines/nodes on@nFurther commands can be retrieved by clicking on@nmachines/nodes with the Techage Info Tool.@n@nLocal commands:@n- clear @= clear screen@n- help @= this message@n- pub @= switch to public use@n- priv @= switch to private use@nTo program a user button with a command:@n set <button-num> <button-text> <command>@ne.g. 'set 1 ON cmd 123 on'@n=
Accu Box= Accu Box=
Active:= Active:=
@ -33,6 +34,7 @@ Build derrick=
Catalyst= Catalyst=
Cement Block= Cement Block=
Cement Powder= Cement Powder=
Coal Equivalents=
Compressed Gravel= Compressed Gravel=
Configure up to 8 items @nto be pushed by the injector= Configure up to 8 items @nto be pushed by the injector=
Consum. 1= Consum. 1=
@ -40,6 +42,7 @@ Consum. 2=
Current power:= Current power:=
Depth= Depth=
Digging depth= Digging depth=
Digtron Battery=
Dirt with Ash= Dirt with Ash=
Display no: = Display no: =
Distributor= Distributor=
@ -100,6 +103,7 @@ Load=
Lye= Lye=
Lye Barrel= Lye Barrel=
Lye Canister= Lye Canister=
Max. needed power=
Maximum power:= Maximum power:=
Melting Guide= Melting Guide=
Melting Pot active (heat@== Melting Pot active (heat@==
@ -145,6 +149,7 @@ Power Source=
Power grid total= Power grid total=
Power station= Power station=
Priv missing= Priv missing=
Probably too many consumers (=
Propane Cylinder Large= Propane Cylinder Large=
Propane Cylinder Small= Propane Cylinder Small=
Pumpjack= Pumpjack=
@ -383,6 +388,7 @@ Type=
Unlock= Unlock=
Unlock connected chest@nif all slots are below 2000= Unlock connected chest@nif all slots are below 2000=
Update= Update=
Use a trowel to remove the node.=
Usmium Nuggets= Usmium Nuggets=
Usmium Powder= Usmium Powder=
WLAN Chip= WLAN Chip=

View File

@ -136,6 +136,13 @@ techage.register_node({"techage:ta3_cartdetector_off", "techage:ta3_cartdetector
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2) local dir = minetest.facedir_to_dir(node.param2)
minecart.punch_cart(pos, nil, 1.5, dir) minecart.punch_cart(pos, nil, 1.5, dir)
elseif topic == "state" then
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_cartdetector_on" then
return "on"
else
return "off"
end
else else
return "unsupported" return "unsupported"
end end

View File

@ -187,6 +187,21 @@ 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)
if topic == "name" then
local nvm = techage.get_nvm(pos)
return nvm.player_name or ""
elseif topic == "state" then
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_nodedetector_off" then
return "on"
else
return "off"
end
else
return "unsupported"
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

@ -311,6 +311,14 @@ techage.register_node({
if topic == "name" then if topic == "name" then
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
return nvm.player_name or "" return nvm.player_name or ""
elseif topic == "state" then
local node = techage.get_node_lvm(pos)
if node.name == "techage:ta3_playerdetector_on" or
node.name == "techage:ta4_playerdetector_on" then
return "on"
else
return "off"
end
else else
return "unsupported" return "unsupported"
end end

View File

@ -39,16 +39,17 @@ techage.lua_ctlr.register_function("get_input", {
}) })
techage.lua_ctlr.register_function("read_data", { techage.lua_ctlr.register_function("read_data", {
cmnd = function(self, num, ident, add_data) cmnd = function(self, num, cmnd, data)
num = tostring(num or "") num = tostring(num or "")
return techage.send_single(self.meta.number, num, ident, add_data) cmnd = tostring(cmnd or "")
if not_protected(self.meta.owner, num) then
return techage.send_single(self.meta.number, num, cmnd, data)
end
end, end,
help = " $read_data(num, ident, add_data)\n".. help = " $read_data(num, cmnd, add_data)\n"..
" Read any kind of data from another block.\n".. " This function is deprecated.\n"..
' "num" is the block number\n'.. " It will be removed in future releases.\n"..
' "ident" specifies the data to be read\n'.. " Use $send_cmnd(num, cmnd, add_data) instead."
' "add_data" is additional data (optional)\n'..
' example: sts = $read_data("1234", "state")'
}) })
techage.lua_ctlr.register_function("time_as_str", { techage.lua_ctlr.register_function("time_as_str", {
@ -96,7 +97,7 @@ techage.lua_ctlr.register_action("set_filter", {
slot = tostring(slot or "red") slot = tostring(slot or "red")
val = tostring(val or "on") val = tostring(val or "on")
if not_protected(self.meta.owner, num) then if not_protected(self.meta.owner, num) then
techage.send_single(self.meta.number, num, "filter", {slot=slot, val=val}) techage.send_single(self.meta.number, num, "port", slot.."="..val)
end end
end, end,
help = " $set_filter(num, slot, val)\n".. help = " $set_filter(num, slot, val)\n"..
@ -119,7 +120,10 @@ techage.lua_ctlr.register_action("display", {
if row == 0 then -- add line? if row == 0 then -- add line?
techage.send_single(self.meta.number, num, "add", text) techage.send_single(self.meta.number, num, "add", text)
else else
techage.send_single(self.meta.number, num, "set", {row = row, str = text}) local payload = safer_lua.Store()
payload.set("row", row)
payload.set("str", text)
techage.send_single(self.meta.number, num, "set", payload)
end end
end end
end, end,
@ -181,6 +185,19 @@ techage.lua_ctlr.register_action("door", {
" Hint: Use the Techage Programmer to\ndetermine the door position." " Hint: Use the Techage Programmer to\ndetermine the door position."
}) })
techage.lua_ctlr.register_function("item_description", {
cmnd = function(self, itemstring)
local item_def = minetest.registered_items[itemstring]
if item_def and item_def.description then
return minetest.get_translated_string("en", item_def.description)
end
return ""
end,
help = " $item_description(itemstring)\n"..
" Get the description for a specified itemstring.\n"..
' example: desc = $item_description("default:apple")'
})
-- function not_protected(owner, number(s)) -- function not_protected(owner, number(s))
techage.lua_ctlr.not_protected = not_protected techage.lua_ctlr.not_protected = not_protected

View File

@ -351,7 +351,7 @@ In addition to Lua standard function the Lua Controller provides the following f
The result is block dependent (see table below): The result is block dependent (see table below):
| ident | returned data | comment | | ident | returned data | comment |
| ----------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| "state" | one of: "running", "stopped", "blocked", "standby", "fault", or "unloaded" | Techage machine state, used by many machines | | "state" | one of: "running", "stopped", "blocked", "standby", "fault", or "unloaded" | Techage machine state, used by many machines |
| "state" | one of: "red", "amber", "green", "off" | Signal Tower state | | "state" | one of: "red", "amber", "green", "off" | Signal Tower state |
| "state" | one of: "empty", "loaded", "full" | State of a chest or Sensor Chest | | "state" | one of: "empty", "loaded", "full" | State of a chest or Sensor Chest |
@ -363,6 +363,7 @@ In addition to Lua standard function the Lua Controller provides the following f
| "stacks" | Array with up to 4 Stores with the inventory content (see example) | only for Sensor Chests | | "stacks" | Array with up to 4 Stores with the inventory content (see example) | only for Sensor Chests |
| "count" | number | Read the item counter of the TA4 Item Detector block | | "count" | number | Read the item counter of the TA4 Item Detector block |
| "count" | number of items | Read the total amount of TA4 chest items. An optional number as `add_data` is used to address only on 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 on 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 = $read_data("223", "itemstring", 1) |
@ -410,10 +411,16 @@ Messages are used to transport data between Controllers. Messages are text strin
* `$chat(text)` - Send yourself a chat message. _text_ is a text string. * `$chat(text)` - Send yourself a chat message. _text_ is a text string.
* `$door(pos, text)` - Open/Close a door at position "pos". * `$door(pos, text)` - Open/Close a door at position "pos".
Example: `$door("123,7,-1200", "close")`. Example: `$door("123,7,-1200", "close")`.
Hint: Use the Techage Info Tool to determine the door position. Hint: Use the Techage Info Tool to determine the door position.
* `$item_description("default:apple")`
Get the description (item name) for a specified itemstring, e. g. determined via the TA4 8x2000 Chest command `itemstring`:
`str = $read_data("223", "itemstring", 1)`
`descr = $item_description(str)`
## Example Scripts ## Example Scripts

View File

@ -1,4 +1,4 @@
name = techage name = techage
depends = default,doors,flowers,tubelib2,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua depends = default,doors,flowers,tubelib2,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua
optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecon optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecon,digtron
description = Techage, go through 4 tech ages in search of wealth and power! description = Techage, go through 4 tech ages in search of wealth and power!

View File

@ -147,3 +147,16 @@ function techage.power.power_distribution(network, tlib_type, netID, cycle_time)
set_taken_values(network.con2, 0, tlib_type) set_taken_values(network.con2, 0, tlib_type)
end end
end end
-- determine the maxiumum needed power of all con1 consumers
function techage.power.get_con1_sum(network, tlib_type)
local sum = 0
for _,v in ipairs(network.con1 or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
if def and def["cstate"] ~= STOPPED then
sum = sum + v.nominal
end
end
return sum
end

View File

@ -144,7 +144,8 @@ function techage.power.power_available(pos, Cable)
local nvm = techage.get_nvm(pos) local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type local tlib_type = Cable.tube_type
local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"] local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"]
return networks.has_network(tlib_type, netID) local netw = networks.has_network(tlib_type, netID)
return netw and netw.on and netw.alive and netw.alive > 0
end end
-- this is more a try to start, the start will be performed by on_power() -- this is more a try to start, the start will be performed by on_power()

View File

@ -188,11 +188,14 @@ end
local function get_state(netw) local function get_state(netw)
local state = "" local state = ""
local needed = techage.power.get_con1_sum(netw, "ele1") or 0
if #(netw.gen1 or {}) + #(netw.gen2 or {}) == 0 then if #(netw.gen1 or {}) + #(netw.gen2 or {}) == 0 then
state = S("No power grid or running generator!") state = S("No power grid or running generator!")
elseif needed > (netw.available1 or 0) then
state = S("Probably too many consumers (")..needed..S(" ku is needed!)")
elseif (netw.num_nodes or 0) < techage.networks.MAX_NUM_NODES then elseif (netw.num_nodes or 0) < techage.networks.MAX_NUM_NODES then
state = S("Number of power grid blocks")..": "..(netw.num_nodes or 0) state = S("Number of power grid blocks")..": "..(netw.num_nodes or 0)..", "..S("Max. needed power")..": "..needed.. " ku"
else else
state = S("To many blocks in the power grid!") state = S("To many blocks in the power grid!")
end end

View File

@ -116,3 +116,35 @@ minetest.register_craft({
{"", "", "default:stick"}, {"", "", "default:stick"},
}, },
}) })
local function get_new_can_dig(old_can_dig)
return function(pos, player, ...)
if M(pos):get_string("techage_hidden_nodename") ~= "" then
if player and player.get_player_name then
minetest.chat_send_player(player:get_player_name(), S("Use a trowel to remove the node."))
end
return false
end
if old_can_dig then
return old_can_dig(pos, player, ...)
else
return true
end
end
end
-- Change can_dig for already registered nodes.
for _, ndef in pairs(minetest.registered_nodes) do
local old_can_dig = ndef.can_dig
minetest.override_item(ndef.name, {
can_dig = get_new_can_dig(old_can_dig)
})
end
-- Change can_dig for all nodes that are going to be registered in the future.
local old_register_node = minetest.register_node
minetest.register_node = function(name, def)
local old_can_dig = def.can_dig
def.can_dig = get_new_can_dig(old_can_dig)
return old_register_node(name, def)
end