973 lines
32 KiB
Lua
973 lines
32 KiB
Lua
--[[
|
|
SUPER COMPLICATED STACK-BASED SYSTEM!
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
-- "pos" and "node" are the position and the node information of the scriptblock being ran.
|
|
-- "sender" would be the position of the node responsible for activating it.
|
|
-- "info" is any information the previous node has sent to it.
|
|
-- "last" is the information that "info" /was/ before it was last changed.
|
|
-- "channel" is the channel in which variables are stored.
|
|
blah blah blah
|
|
return new_info, faces, flag, flag2 -- Information to pass to the next node(s), and information on which adjacent spaces we should even try to signal to.
|
|
-- When flag is set, @last isn't updated to the prev. @info even if @info is modified.
|
|
-- When flag2 is set, @last is updated to the prev. @info even if @info isn't modified.
|
|
end
|
|
]]
|
|
|
|
-- These are aliases registered to aid various transitions (mostly changes in the node naming scheme, though).
|
|
minetest.register_alias("rmod:scriptblock_digiline", "rmod:scriptblock_digiline_receiver")
|
|
minetest.register_alias("rmod:scriptblock_mesecon", "rmod:scriptblock_mesecon_receiver")
|
|
|
|
|
|
|
|
local program_channel = "Program channel"
|
|
|
|
local do_debug = false
|
|
local function debug(text)
|
|
if do_debug then minetest.chat_send_all("[SB] " .. text) end
|
|
end
|
|
|
|
local storage = minetest.get_mod_storage()
|
|
|
|
-- Each section of the RMod gets its own storage, to prevent interference.
|
|
-- RMod sections can still affect other sections, though only when intended.
|
|
local function get_storage()
|
|
return minetest.deserialize(storage:get_string("scriptblock")) or {}
|
|
end
|
|
local function set_storage(data)
|
|
return storage:set_string("scriptblock", minetest.serialize(data))
|
|
end
|
|
|
|
local function stringify(t)
|
|
if type(t) ~= "table" then return tostring(t) end
|
|
return minetest.serialize(t):sub(("return "):len()+1, -1)
|
|
end
|
|
|
|
local function compare(a, b)
|
|
-- Compare two tables by comparing their values -
|
|
-- also make sure to support nested tables.
|
|
if type(a) ~= "table" or type(b) ~= "table" then return a == b end
|
|
|
|
for i,j in pairs(a) do
|
|
if not compare(j, b[i]) then return false end
|
|
end
|
|
for i,j in pairs(b) do
|
|
if not compare(j, a[i]) then return false end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
-- To avoid lag and stack overflows, we add the data to a queue and then execute it with a globalstep.
|
|
local queue = {}
|
|
|
|
rmod.scriptblock = {}
|
|
|
|
rmod.scriptblock.run = function (pos, sender, info, last, channel)
|
|
local local_queue = {}
|
|
|
|
-- Get information about this script block we are told to execute.
|
|
local node = minetest.get_node(pos)
|
|
local name = node.name
|
|
local def = minetest.registered_nodes[name]
|
|
|
|
-- If the block is a script block...
|
|
if def and def.scriptblock then
|
|
-- The flag tells the code NOT to update @last, even if there is a change in @info.
|
|
-- Flag2 forces the code TO update @last, even if there is NO change in @info. It overrides flag, so use with care.
|
|
-- Flag2 is used in blocks that calculate results from more than one parameter, especially when the result might accidentally equal @info.
|
|
local new_info, faces, flag, flag2 = def.scriptblock(pos, node, sender, info, last, channel)
|
|
-- if new_info == rmod.scriptblock.stop_signal then return end -- Looks like the block doesn't want to conduct.
|
|
if not faces then
|
|
faces = {true, true, true, true, true, true}
|
|
end
|
|
-- Check neighboring nodes; if they also have scriptblock and aren't the sender, execute them.
|
|
for i=1,6 do
|
|
if faces[i] then
|
|
local dir = vector.new(0, 0, 0)
|
|
if i == 1 then dir.y = 1
|
|
elseif i == 2 then dir.y = -1
|
|
elseif i == 3 then dir.x = 1
|
|
elseif i == 4 then dir.x = -1
|
|
elseif i == 5 then dir.z = 1
|
|
elseif i == 6 then dir.z = -1 end
|
|
|
|
local new_pos = vector.add(pos, dir)
|
|
|
|
-- This is required, otherwise you'd have an unintentional feedback loop.
|
|
-- Feedback loops can still be created intentionally, though.
|
|
if not vector.equals(new_pos, sender) then
|
|
local new_node = minetest.get_node(new_pos)
|
|
local new_name = new_node.name
|
|
local new_def = minetest.registered_nodes[new_name]
|
|
|
|
if new_def and new_def.scriptblock then
|
|
local new_last
|
|
if (flag or (info == new_info)) and not flag2 then
|
|
new_last = last
|
|
else
|
|
new_last = info
|
|
end
|
|
table.insert(local_queue, {new_pos, pos, new_info, new_last, channel})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return local_queue
|
|
end
|
|
rmod.scriptblock.escape = function (text, info, last)
|
|
-- We handle these separately, so that we don't need to stringify it.
|
|
local info = info
|
|
local last = last
|
|
|
|
if text == "@info" then return info end
|
|
if text == "@last" then return last end
|
|
|
|
if type(info) == "table" then info = stringify(info) or "" end
|
|
if type(last) == "table" then last = stringify(last) or "" end
|
|
return text and text:gsub("@info", tostring(info) or ""):gsub("@last", tostring(last) or "")-- or ""
|
|
end
|
|
|
|
local time = 0
|
|
minetest.register_globalstep(function (dtime)
|
|
-- time = time + dtime
|
|
-- if time > 0.05 then time = 0 else return end
|
|
|
|
local new_queue = {}
|
|
for i,data in pairs(queue) do
|
|
local new_list = rmod.scriptblock.run(unpack(data))
|
|
if new_list then
|
|
for _,new_item in pairs(new_list) do
|
|
table.insert(new_queue, new_item)
|
|
end
|
|
end
|
|
end
|
|
queue = new_queue
|
|
end)
|
|
|
|
minetest.register_node("rmod:scriptblock_set", {
|
|
description = "Scriptblock: Set",
|
|
tiles = {"rmod_scriptblock_set.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[channel;]] .. program_channel .. [[ (optional);${channel}]
|
|
field[varname;Varname;${varname}]
|
|
field[value;Value;${value}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.channel) then
|
|
minetest.get_meta(pos):set_string("channel", fields.channel)
|
|
end
|
|
if (fields.varname) then
|
|
minetest.get_meta(pos):set_string("varname", fields.varname)
|
|
end
|
|
if (fields.value) then
|
|
minetest.get_meta(pos):set_string("value", fields.value)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local channel = rmod.scriptblock.escape(meta:get_string("channel"), info, last)
|
|
local varname = rmod.scriptblock.escape(meta:get_string("varname"), info, last)
|
|
local value = rmod.scriptblock.escape(meta:get_string("value"), info, last)
|
|
|
|
local store = get_storage()
|
|
|
|
if channel == "" or not channel then channel = main_channel end
|
|
|
|
if not varname then varname = "" end
|
|
|
|
if not store[channel] then store[channel] = {} end
|
|
store[channel][varname] = value
|
|
|
|
set_storage(store)
|
|
|
|
debug("SET " .. channel .. "." .. tostring(varname) .. ": " .. tostring(value))
|
|
|
|
return info
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_get", {
|
|
description = "Scriptblock: Get",
|
|
tiles = {"rmod_scriptblock_get.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[channel;]] .. program_channel .. [[ (optional);${channel}]
|
|
field[varname;Varname;${varname}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.channel) then
|
|
minetest.get_meta(pos):set_string("channel", fields.channel)
|
|
end
|
|
if (fields.varname) then
|
|
minetest.get_meta(pos):set_string("varname", fields.varname)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local channel = rmod.scriptblock.escape(meta:get_string("channel"), info, last)
|
|
local varname = rmod.scriptblock.escape(meta:get_string("varname"), info, last)
|
|
|
|
local store = get_storage()
|
|
|
|
if channel == "" or not channel then channel = main_channel end
|
|
if not varname then return end
|
|
|
|
if not store[channel] then store[channel] = {} end
|
|
|
|
debug("GET " .. tostring(channel) .. "." .. tostring(varname) .. ": " .. tostring(store[channel][varname] or ""))
|
|
|
|
return store[channel][varname]
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_mesecon_receiver", {
|
|
description = "Scriptblock: Mesecon Receiver",
|
|
tiles = {"rmod_scriptblock_mesecon.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[channel;]] .. program_channel .. [[;${channel}]
|
|
field[info;Starting @info;${info}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.channel) then
|
|
minetest.get_meta(pos):set_string("channel", fields.channel)
|
|
end
|
|
if (fields.info) then
|
|
minetest.get_meta(pos):set_string("info", fields.info)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return info
|
|
end,
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node)
|
|
local meta = minetest.get_meta(pos)
|
|
local channel = meta:get_string("channel")
|
|
local info = meta:get_string("info")
|
|
|
|
debug("ACTIVATED")
|
|
table.insert(queue, {pos, pos, info or "", "", channel or ""})
|
|
end,
|
|
}}
|
|
})
|
|
minetest.register_node("rmod:scriptblock_print", {
|
|
description = "Scriptblock: Print",
|
|
tiles = {"rmod_scriptblock_print.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[player;Player (optional);${player}]
|
|
field[message;Message;${message}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.player) then
|
|
minetest.get_meta(pos):set_string("player", fields.player)
|
|
end
|
|
if (fields.message) then
|
|
minetest.get_meta(pos):set_string("message", fields.message)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local plr = rmod.scriptblock.escape(meta:get_string("player"), info, last)
|
|
local msg = rmod.scriptblock.escape(meta:get_string("message"), info, last)
|
|
|
|
if not plr then return info end
|
|
if not msg then return info end
|
|
|
|
if type(msg) == "table" then msg = stringify(msg) end
|
|
|
|
if plr == "" then
|
|
minetest.chat_send_all("Scriptblock -> all: " .. tostring(msg))
|
|
else
|
|
minetest.chat_send_player(plr, "Scriptblock -> you: " .. tostring(msg))
|
|
end
|
|
|
|
return info
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_if", {
|
|
description = "Scriptblock: If",
|
|
tiles = {"rmod_scriptblock_if_top.png", "rmod_scriptblock_if_bottom.png",
|
|
"rmod_scriptblock_if_right.png", "rmod_scriptblock_if_left.png",
|
|
"rmod_scriptblock_if_truth.png", "rmod_scriptblock_if_falsth.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
paramtype2 = "facedir",
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
-- compatibility for back when this was "IF EQUALS"
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
-- Y, -Y, X, -X, Z, -Z.
|
|
|
|
local truth = {}
|
|
local falsth = {}
|
|
if dir.x == 1 then truth[3] = true; falsth[4] = true
|
|
elseif dir.x == -1 then truth[4] = true; falsth[3] = true
|
|
elseif dir.z == 1 then truth[5] = true; falsth[6] = true
|
|
elseif dir.z == -1 then truth[6] = true; falsth[5] = true end
|
|
|
|
--[[if type(a) == "table" then
|
|
a = stringify(a) or a
|
|
end
|
|
if type(b) == "table" then
|
|
b = stringify(b) or b
|
|
end]]
|
|
|
|
if a == "" and b == "" then
|
|
return unpack(info and {info, truth} or {info, falsth})
|
|
else
|
|
return unpack(compare(a, b) and {info, truth} or {info, falsth})
|
|
end
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_guide", {
|
|
description = "Scriptblock: One-Way Guide",
|
|
tiles = {"rmod_scriptblock_guide_top.png", "rmod_scriptblock_guide_bottom.png",
|
|
"rmod_scriptblock_guide_right.png", "rmod_scriptblock_guide_left.png",
|
|
"rmod_scriptblock_guide_front.png", "rmod_scriptblock_guide_back.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
paramtype2 = "facedir",
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
-- Y, -Y, X, -X, Z, -Z.
|
|
|
|
local guide = {}
|
|
if dir.x == 1 then guide[3] = true
|
|
elseif dir.x == -1 then guide[4] = true
|
|
elseif dir.z == 1 then guide[5] = true
|
|
elseif dir.z == -1 then guide[6] = true end
|
|
|
|
return info, guide
|
|
end
|
|
})
|
|
|
|
minetest.register_node("rmod:scriptblock_add", {
|
|
description = "Scriptblock: Add",
|
|
tiles = {"rmod_scriptblock_add.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
return (tonumber(a) or 0) + (tonumber(b) or 0), nil, nil, true
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_subtract", {
|
|
description = "Scriptblock: Subtract",
|
|
tiles = {"rmod_scriptblock_subtract.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
return (tonumber(a) or 0) - (tonumber(b) or 0), nil, nil, true
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_multiply", {
|
|
description = "Scriptblock: Multiply",
|
|
tiles = {"rmod_scriptblock_multiply.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
return (tonumber(a) or 0) * (tonumber(b) or 0), nil, nil, true
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_divide", {
|
|
description = "Scriptblock: Divide",
|
|
tiles = {"rmod_scriptblock_divide.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
return (tonumber(a) or 0) / (tonumber(b) or 0), nil, nil, true
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_modulo", {
|
|
description = "Scriptblock: Modulo",
|
|
tiles = {"rmod_scriptblock_modulo.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
local facedir = node.param2
|
|
local dir = minetest.facedir_to_dir(facedir)
|
|
|
|
return (tonumber(a) or 0) % (tonumber(b) or 0), nil, nil, true
|
|
end
|
|
})
|
|
|
|
minetest.register_node("rmod:scriptblock_player_detector", {
|
|
description = "Scriptblock: Player Detector",
|
|
tiles = {"rmod_scriptblock_player_detector.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local players = minetest.get_connected_players()
|
|
|
|
local nearest = nil
|
|
local min_distance = math.huge
|
|
for index, player in pairs(players) do
|
|
local distance = vector.distance(pos, player:getpos())
|
|
if distance < min_distance then
|
|
min_distance = distance
|
|
nearest = player:get_player_name()
|
|
end
|
|
end
|
|
|
|
return nearest or ""
|
|
end
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("rmod:scriptblock_set_attribute", {
|
|
description = "Scriptblock: Set Attribute of Object",
|
|
tiles = {"rmod_scriptblock_set_attribute.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[propname;Attribute Name;${propname}]
|
|
field[value;Value;${value}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.propname) then
|
|
minetest.get_meta(pos):set_string("propname", fields.propname)
|
|
end
|
|
if (fields.value) then
|
|
minetest.get_meta(pos):set_string("value", fields.value)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local propname = rmod.scriptblock.escape(meta:get_string("propname"), info, last)
|
|
local value = rmod.scriptblock.escape(meta:get_string("value"), info, last)
|
|
|
|
if not propname then return end
|
|
|
|
if type(info) ~= "table" then
|
|
--[[if type(info) == "string" then
|
|
local deserialized = minetest.deserialize(info)
|
|
if deserialized then info = deserialized else return info end
|
|
else]]
|
|
return info
|
|
--end
|
|
end
|
|
|
|
-- We want to avoid problems like this:
|
|
-- serialize({nest = serialize({table})) =/= serialize({nest = {table}})
|
|
-- so we automatically deserialize the value if it can be deserialized.
|
|
--[[if type(value) == "string" then
|
|
local deserialized = minetest.deserialize(value)
|
|
if deserialized then value = deserialized end
|
|
end]]
|
|
|
|
info[propname] = value
|
|
|
|
return info, nil, true -- Flag to avoid losing @last.
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_get_attribute", {
|
|
description = "Scriptblock: Get Attribute of Object",
|
|
tiles = {"rmod_scriptblock_get_attribute.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[propname;Attribute Name;${propname}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.propname) then
|
|
minetest.get_meta(pos):set_string("propname", fields.propname)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local propname = rmod.scriptblock.escape(meta:get_string("propname"), info, last)
|
|
|
|
if not propname then return end
|
|
|
|
if type(info) ~= "table" then
|
|
--[[if type(info) == "string" then
|
|
local deserialized = minetest.deserialize(info)
|
|
if deserialized then info = deserialized else return info end
|
|
else]]
|
|
return info
|
|
--end
|
|
end
|
|
|
|
return info[propname]
|
|
end
|
|
})
|
|
minetest.register_node("rmod:scriptblock_new_object", {
|
|
description = "Scriptblock: New Object",
|
|
tiles = {"rmod_scriptblock_new_object.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return {}
|
|
end
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("rmod:scriptblock_digiline_receiver", {
|
|
description = "Scriptblock: Digiline Receiver",
|
|
tiles = {"rmod_scriptblock_digiline.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[progchannel;]] .. program_channel .. [[;${progchannel}]
|
|
field[digichannel;Digiline channel;${digichannel}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.digichannel) then
|
|
minetest.get_meta(pos):set_string("digichannel", fields.digichannel)
|
|
end
|
|
if (fields.progchannel) then
|
|
minetest.get_meta(pos):set_string("progchannel", fields.progchannel)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return info
|
|
end,
|
|
digiline = {
|
|
receptor = {},
|
|
effector = {
|
|
action = function (pos, node, msgchannel, msg)
|
|
local meta = minetest.get_meta(pos)
|
|
local progchannel = meta:get_string("progchannel")
|
|
local digichannel = meta:get_string("digichannel")
|
|
|
|
if msgchannel ~= digichannel then debug("WRONG CHANNEL"); return end
|
|
|
|
debug("ACTIVATED")
|
|
table.insert(queue, {pos, pos, msg, "", progchannel or ""})
|
|
end,
|
|
}}
|
|
})
|
|
|
|
minetest.register_node("rmod:scriptblock_not", {
|
|
description = "Scriptblock: Not Gate",
|
|
tiles = {"rmod_scriptblock_not.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return not info, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_and", {
|
|
description = "Scriptblock: And Gate",
|
|
tiles = {"rmod_scriptblock_and.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return info and last, nil, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_or", {
|
|
description = "Scriptblock: Or Gate",
|
|
tiles = {"rmod_scriptblock_or.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return info or last, nil, nil, true
|
|
end,
|
|
})
|
|
|
|
minetest.register_node("rmod:scriptblock_equals", {
|
|
description = "Scriptblock: Equals",
|
|
tiles = {"rmod_scriptblock_equals.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
return compare(a, b), nil, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_lt", {
|
|
description = "Scriptblock: Less than",
|
|
tiles = {"rmod_scriptblock_lt.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
return (tonumber(a) or 0) < (tonumber(b) or 0), nil, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_gt", {
|
|
description = "Scriptblock: Greater than",
|
|
tiles = {"rmod_scriptblock_gt.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[a;A;${a}]
|
|
field[b;B;${b}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.a) then
|
|
minetest.get_meta(pos):set_string("a", fields.a)
|
|
end
|
|
if (fields.b) then
|
|
minetest.get_meta(pos):set_string("b", fields.b)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local a = rmod.scriptblock.escape(meta:get_string("a"), info, last)
|
|
local b = rmod.scriptblock.escape(meta:get_string("b"), info, last)
|
|
|
|
return (tonumber(a) or 0) > (tonumber(b) or 0), nil, nil, true
|
|
end,
|
|
})
|
|
|
|
|
|
|
|
minetest.register_node("rmod:scriptblock_type", {
|
|
description = "Scriptblock: Get Type",
|
|
tiles = {"rmod_scriptblock_type.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
return type(info) == "table" and "object" or type(info), nil, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_number", {
|
|
description = "Scriptblock: Number Literal",
|
|
tiles = {"rmod_scriptblock_number.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[number;Number literal;${number}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.number) then
|
|
minetest.get_meta(pos):set_string("number", fields.number)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local number = meta:get_string("number")
|
|
|
|
return tonumber(number), nil, nil, true
|
|
end,
|
|
})
|
|
minetest.register_node("rmod:scriptblock_string", {
|
|
description = "Scriptblock: String Literal",
|
|
tiles = {"rmod_scriptblock_string.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[str;String literal;${str}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.str) then
|
|
minetest.get_meta(pos):set_string("str", fields.str)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
local meta = minetest.get_meta(pos)
|
|
local str = meta:get_string("str")
|
|
|
|
return str, nil, nil, true
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_node("rmod:scriptblock_digiline_sender", {
|
|
description = "Scriptblock: Digiline Sender",
|
|
tiles = {"rmod_scriptblock_digiline_sender.png"},
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
use_texture_alpha = true,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", [[
|
|
field[channel;Digiline channel;${channel}]
|
|
]])
|
|
end,
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
local name = sender:get_player_name()
|
|
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, {protection_bypass=true}) then
|
|
minetest.record_protection_violation(pos, name)
|
|
return
|
|
end
|
|
if (fields.channel) then
|
|
minetest.get_meta(pos):set_string("channel", fields.channel)
|
|
end
|
|
end,
|
|
scriptblock = function (pos, node, sender, info, last, main_channel)
|
|
if not digiline then return info end
|
|
local meta = minetest.get_meta(pos)
|
|
local channel = meta:get_string("channel")
|
|
|
|
digiline:receptor_send(pos, digiline.rules.default, channel, info)
|
|
return info
|
|
end,
|
|
digiline = {
|
|
receptor = {},
|
|
effector = {}
|
|
}
|
|
})
|