85 Commits

Author SHA1 Message Date
f2de7c89b1 MapDataStorage: change serialization in mod storage
Use minetest.serialize on the full values table instead of serializing
each value independently and concatenating.
2020-04-29 12:43:29 +02:00
0000cfb474 Remove old vector_extras code and use the MapDataStorage 2020-04-14 08:49:21 +02:00
9aa0e6ab3d Add MapDataStorage code as replacement for get_data_from_pos etc.
In comparison to using Minetest's hash_node_position, this saves additional information about the z-only and zy-only components, which is what the vector_extras code did.
In comparison to the old vector_extras code, this does not create lots of lua tables, which is slow, but instead uses one table as hashmap.
2020-04-14 08:49:21 +02:00
54030d1620 Wireless: transmit digilines messages on all channels 2020-04-11 13:01:17 +02:00
be7982a453 Major wireless refactor 2020-04-11 12:45:33 +02:00
899ea4aa29 Wireless: remove legacy code. 2020-04-09 19:27:11 +02:00
8c8cdd38ff Add mesecons_luacontroller as a dependency to the luacontroller tool. 2020-04-09 19:22:15 +02:00
5d29cdce5b Avoid activating wireless that no longer exist. 2020-04-09 19:21:40 +02:00
4dbc96eafa New digiline interface for the adjustable player detector
The name of the detected player can now be requested by sending {command
= "get"} to the detector. The detection radius can be changed by sending
{radius = value}.
2020-04-09 17:02:31 +02:00
7cf99da1a5 LuaBlock: Major changes in mod storage usage
Data associated to a LuaBlock is redundantly stored in both its metadata
and in the mod storage so that it is not possible to hack a LuaBlock by
changing its metadata or copying it using WorldEdit. This commit changes
how it is done:
* Store full code instead of storing MD5 checksum, which avoids bug
caused by serializing non-ASCII strings using minetest.serialize,
* Also store owner,
* Use `minetest.hash_node_position` instead of deprecated vector_extras
set_data_to_pos etc,
* Remove mod storage data associated with the LuaBlock when destroying
it,
* Create helper functions for manipulating the mod storage in
moremesecons_utils, I will soon update other parts of MoreMesecons as well to use them.

This commit breaks backwards compatibility: previously created LuaBlocks
will have to be reset by opening the formspec and pressing the `Submit`
button.

This commit also fixes an unrelated bug: code in the formspec was not
correctly escaped using minetest.formspec_escape.
2020-04-09 16:25:21 +02:00
2b2faeca02 Fix crash when using the playerkiller
Fixes #9
2018-08-20 10:42:11 +02:00
8a56370ce8 Allow using templates on multiple luacontrollers
Fixes #8
Patch submitted by @oiaohm
2018-02-27 16:33:18 +01:00
ce9544d2bf Remove mod storage checks 2017-06-23 13:47:41 +02:00
4c81b43032 mesechest: add crafts 2017-06-10 10:11:05 +02:00
89b1fe18c5 mesechest: colorize textures 2017-06-09 20:44:25 +02:00
ae5a96cb42 Mesechest: make mesechest work with last mt_game version 2017-06-09 20:44:25 +02:00
fd21b16c02 Mesechest: limit API functions overwriting 2017-06-09 20:44:25 +02:00
6291b4c001 Add the mesechest 2017-06-09 20:44:25 +02:00
dbd5c4cf99 Luacontroller tool: add counter and clock templates (#7) 2017-06-08 16:33:53 +02:00
400e90c9ca Fix luacontroller tool crash
Set "sender" parameter when executing on_receive_fields callback
2017-06-08 16:01:33 +02:00
aa2ae82cc2 Merge branch 'AntumDeluge-settings' 2017-06-04 17:56:30 +02:00
d580e0e974 Merge branch 'master' into settings 2017-06-04 17:57:16 +02:00
6662f92902 Remove empty file .gitmodules 2017-06-03 15:34:39 +02:00
7839aefcdc Add 'moremesecons_luablock/md5_lua/' from commit 'e8cd75ce397da6dd75ddb37cb07eb31663743223'
git-subtree-dir: moremesecons_luablock/md5_lua
git-subtree-mainline: 79e856494a
git-subtree-split: e8cd75ce39
2017-06-03 15:32:33 +02:00
79e856494a Remove md5_lua submodule
This prepares re-adding it as a subtree.
2017-06-03 15:32:05 +02:00
180167110f LuaBlock: store md5 checksums
This avoids changing the LuaBlock code by setting its metadata.
2017-06-02 14:51:10 +02:00
8cac3f8f70 Add a craft for the induction transmitter 2017-05-28 18:02:31 +02:00
482dd4df93 Add an induction transmitter
This node makes the signal goes two nodes forward instead of one
2017-05-28 15:16:01 +02:00
d542d15fa4 Replace deprecated methods:
- 'setting_get' with 'settings:get'
- 'setting_getbool' with 'settings:get_bool'
2017-05-13 01:52:42 -07:00
e8cd75ce39 add 1.1.0 rockspec 2016-07-15 01:30:59 +02:00
520f90795b adds description of iterative version to README 2016-07-15 01:29:04 +02:00
58bfa546fe bump version to 1.1.0. Add changelog 2016-07-15 01:21:56 +02:00
172176713e Merge branch 'pgimeno-incremental-md5' 2016-07-15 01:17:41 +02:00
86da43dbda makes update return self 2016-07-15 01:16:54 +02:00
46b50003f8 Add a simple unit test for the incremental version 2016-07-04 11:18:28 +02:00
51febea6c3 Implement incremental MD5
Two new functions:

md5.new(): returns a new MD5 state object with two methods:
 - MD5State:update(s) - adds the string s to the calculation
 - MD5State:finish()  - returns the final MD5 as a binary string

md5.tohex(): converts to hexadecimal the binary string returned by md5.sum() and MD5State:finish()
2016-07-02 21:31:54 +02:00
21d22c1868 Merge pull request #11 from kikito/pgimeno-fix-large-strings
Pgimeno fix large strings
2016-07-02 20:38:20 +02:00
5297100c7c luacheck install fix
remove luacheck
2016-07-02 20:26:40 +02:00
8603af5e23 delete long example which is too slow in lua 5.1 2016-07-02 18:32:44 +02:00
7e5623a206 luacheck install fix 2016-07-02 18:22:53 +02:00
a2144276e1 Merge branch 'fix-large-strings' of https://github.com/pgimeno/md5.lua into pgimeno-fix-large-strings 2016-07-02 18:04:23 +02:00
51347acd88 renames variables to avoid luacheck errors 2016-07-02 18:03:49 +02:00
1f6eba9a7b updates travis 2016-07-02 18:03:28 +02:00
dd10f1c9de Fix #4 by limiting the sum output to 32 bits. 2016-07-02 10:44:35 +02:00
467f30efb6 Add large strings test to demonstrate failure in current version. 2016-07-02 10:42:54 +02:00
7fc429b519 add rockspec 2015-04-06 21:13:45 +02:00
42b3d5ae5a bump version 2015-04-06 21:11:54 +02:00
bd1dd4bd0f fix typo in LuaJIT 2015-04-06 20:57:59 +02:00
d3c97f950f fix error when adding if 2015-04-06 20:54:06 +02:00
9fcb45d9f2 do not normalize luajit functions 2015-04-06 20:44:11 +02:00
686c18c49e add rockspec for 1.0.1 2015-04-06 18:52:54 +02:00
4dfe7a0698 bump version 2015-04-06 18:47:51 +02:00
f253f5ffd5 Use hex literals everywhere 2015-04-06 18:34:11 +02:00
4e68bf98a8 do not create global variables in 5.1 2015-04-06 18:32:11 +02:00
b096b1f3c1 Revert "separate lua 5.1 functions into number-based and table-based"
This reverts commit 65d03bceef.
2015-04-06 18:30:32 +02:00
1e7902f65b Revert "typo"
This reverts commit 55cff74afc.
2015-04-06 18:30:29 +02:00
f70bf13a41 Revert "Use hex literals everywhere"
This reverts commit 1212664fb7.
2015-04-06 18:30:24 +02:00
1212664fb7 Use hex literals everywhere 2015-04-06 18:21:52 +02:00
55cff74afc typo 2015-04-06 18:17:23 +02:00
65d03bceef separate lua 5.1 functions into number-based and table-based 2015-04-06 18:13:47 +02:00
77ac109e66 Remove unnecessary calculations
The “expand” before the loops ensures that both tables (tbl_m and
tbl_n) have the same length
2015-04-06 17:41:57 +02:00
907bbd1655 Remove unneeded locals 2015-04-06 17:39:17 +02:00
858b23b28d refactor to_bits 2015-04-06 17:37:16 +02:00
332517912d refactor tbl2number 2015-04-06 17:24:46 +02:00
a08ab4f93d Refactor expand in Lua 5.1 2015-04-06 17:23:12 +02:00
0950963cd3 Remove unnecessary checks in lua 5.1 2015-04-06 17:22:48 +02:00
6a83ce8c21 typo 2015-04-06 17:09:13 +02:00
60d897e229 attempt to fix lua 5.2 2015-04-06 16:54:24 +02:00
cfbceec4ac attempt to fix travis 2015-04-06 14:22:03 +02:00
d1fc9bc9f7 add test for long string. Related with #4 2015-04-06 14:09:32 +02:00
9a87570317 add Positive07 to credits 2015-02-09 13:07:59 +01:00
1c76e92944 add rockspecs 2015-02-09 13:05:06 +01:00
b97a79f022 Revert "up luarocks a little more"
This reverts commit af6e779eb8.
2015-02-09 12:16:13 +01:00
af6e779eb8 up luarocks a little more 2015-02-09 12:06:47 +01:00
b75e79ea6d downgrade luarocks 2015-02-09 11:40:43 +01:00
98844a67fe update luarocks version in travis 2015-02-09 11:38:22 +01:00
c3ed7b8713 add travis 2015-02-09 11:27:21 +01:00
3289e9fa7c change README 2015-02-09 11:16:47 +01:00
b56a8a1e93 Merge pull request #2 from Positive07/patch-1
Use BitOp or Bit32 libraries where available
2015-02-09 11:13:46 +01:00
57cc66eba6 Checking the libs doesnt error
Added pcalls instead of raw requires as suggested by Kikito
2015-02-08 07:28:31 -03:00
e7df9d53cf Made md5.lua use BitOp or Bit32 libraries where available 2015-02-07 23:13:01 -03:00
191b026807 Update README.md 2014-02-21 10:09:19 +01:00
a34df17b17 added VERSION, DESCRIPTION, URL and LICENSE 2013-09-14 14:14:06 +02:00
a9905a9c13 more cleanup 2013-08-30 19:16:49 +02:00
dab1b130bd initial commit with working implementation, readme and license 2013-08-30 19:12:29 +02:00
17 changed files with 852 additions and 312 deletions

View File

@ -1,11 +1,11 @@
# MoreMesecons
Based on Mesecons by Jeija
By @paly2 and @HybridDog
With the participation of @LeMagnesium (bugfix), @Ataron (textures), @JAPP (texture).
Based on Mesecons by Jeija <br/>
By @paly2 and @HybridDog <br/>
With the participation of @LeMagnesium (bugfix), @Ataron (textures), @JAPP (texture).
Dependencies: [Mesecons](https://github.com/Jeija/minetest-mod-mesecons/)
Optional dependencies: [vector_extras](https://github.com/HybridDog/vector_extras/) [digilines](https://github.com/minetest-mods/digilines)
Dependencies: [Mesecons](https://github.com/Jeija/minetest-mod-mesecons/) <br/>
Optional dependencies: [digilines](https://github.com/minetest-mods/digilines)
MoreMesecons is a mod for minetest which adds some mesecons items.

View File

@ -37,18 +37,18 @@ local object_detector_scan = function (pos)
local scan_all = scanname == ""
local scan_names = scanname:split(',')
local radius = meta:get_int("radius")
if radius == 0 then
if radius <= 0 then
radius = 6
end
for _,obj in pairs(minetest.get_objects_inside_radius(pos, radius)) do
local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil!
if isname ~= "" then
if scan_all then
return true
return true, isname
end
for _, name in ipairs(scan_names) do
if isname == name then
return true
return true, isname
end
end
end
@ -65,12 +65,32 @@ local object_detector_digiline = {
if channel ~= active_channel then
return
end
meta:set_string("scanname", msg)
if meta:get_string("formspec") ~= "" then
if type(msg) == "string" then
meta:set_string("scanname", msg)
make_formspec(meta)
elseif type(msg) == "table" then
if msg.radius then
local r = tonumber(msg.radius)
if r then
meta:set_int("radius", tonumber(msg.radius))
make_formspec(meta)
end
end
if msg.scanname then
meta:set_string("scanname", msg.scanname)
make_formspec(meta)
end
if msg.command and msg.command == "get" then
local found, name = object_detector_scan(pos)
if not found then
name = ""
end
digiline:receptor_send(pos, digiline.rules.default, channel, name)
end
end
end,
}
},
receptor = {}
}
minetest.register_node("moremesecons_adjustable_player_detector:player_detector_off", {

View File

@ -0,0 +1,3 @@
mesecons
mesecons_torch
default

View File

@ -0,0 +1,104 @@
local function induction_transmitter_get_input_rules(node)
-- All horizontal rules, except the output
local rules = {
{x=-1,y=0,z=0},
{x=1,y=0,z=0},
{x=0,y=0,z=-1},
{x=0,y=0,z=1}
}
for i, r in ipairs(rules) do
if vector.equals(r, minetest.facedir_to_dir(node.param2)) then
table.remove(rules, i)
end
end
return rules
end
local function induction_transmitter_get_output_rules(node)
return {vector.multiply(minetest.facedir_to_dir(node.param2), 2)}
end
local function induction_transmitter_get_virtual_output_rules(node)
return {minetest.facedir_to_dir(node.param2)}
end
local function act(pos, node, state)
minetest.swap_node(pos, {name = "moremesecons_induction_transmitter:induction_transmitter_"..state, param2 = node.param2})
local dir = minetest.facedir_to_dir(node.param2)
local target_pos = vector.add(pos, vector.multiply(dir, 2))
local target_node = minetest.get_node(target_pos)
if mesecon.is_effector(target_node.name) then
-- Switch on an aside node, so it sends a signal to the target node
local aside_rule = mesecon.effector_get_rules(target_node)[1]
if not aside_rule then
return
end
mesecon["receptor_"..state](vector.add(target_pos, aside_rule), {vector.multiply(aside_rule, -1)})
elseif mesecon.is_conductor(target_node.name) then
-- Switch on the conductor itself
mesecon["receptor_"..state](target_pos, mesecon.conductor_get_rules(target_node))
end
end
mesecon.register_node("moremesecons_induction_transmitter:induction_transmitter", {
description = "Induction Transmitter",
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, 0.125, 0.5, 0.5, 0.5},
{-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125},
{-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875},
}
},
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, 0.125, 0.5, 0.5, 0.5},
{-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125},
{-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875},
},
},
}, {
tiles = {"default_mese_block.png"},
groups = {cracky = 3},
mesecons = {
receptor = {
state = mesecon.state.off,
rules = induction_transmitter_get_output_rules
},
effector = {
rules = induction_transmitter_get_input_rules,
action_on = function(pos, node)
act(pos, node, "on")
end
}
}
}, {
light_source = 5,
tiles = {"default_mese_block.png^[brighten"},
groups = {cracky = 3, not_in_creative_inventory = 1},
mesecons = {
receptor = {
state = mesecon.state.on,
rules = induction_transmitter_get_output_rules
},
effector = {
rules = induction_transmitter_get_input_rules,
action_off = function(pos, node)
act(pos, node, "off")
end
}
}
})
minetest.register_craft({
output = "moremesecons_induction_transmitter:induction_transmitter_off",
recipe = {
{"default:mese_crystal_fragment", "mesecons_torch:mesecon_torch_on", "default:mese_crystal_fragment"},
{"", "default:mese_crystal_fragment", ""}
}
})

View File

@ -1,55 +1,35 @@
-- see wireless jammer
local get = vector.get_data_from_pos
local set = vector.set_data_to_pos
local remove = vector.remove_data_from_pos
local storage = minetest.get_mod_storage()
local jammers
local enable_lbm = moremesecons.setting("jammer", "enable_lbm", false)
local storage
if not minetest.get_mod_storage then
enable_lbm = true -- No mod storage (<= 0.4.15-stable): force registration of LBM
jammers = {}
else
storage = minetest.get_mod_storage()
jammers = minetest.deserialize(storage:get_string("jammers")) or {}
end
local jammers = moremesecons.load_MapDataStorage_legacy(storage, "jammers_v2",
"jammers")
local function update_mod_storage()
if not storage then
return
end
storage:set_string("jammers", minetest.serialize(jammers))
storage:set_string("jammers_v2", jammers:serialize())
end
local function add_jammer(pos)
if get(jammers, pos.z,pos.y,pos.x) then
if jammers:getAt(pos) then
return
end
set(jammers, pos.z,pos.y,pos.x, true)
jammers:setAt(pos, true)
update_mod_storage()
end
local function remove_jammer(pos)
remove(jammers, pos.z,pos.y,pos.x)
jammers:removeAt(pos)
update_mod_storage()
end
local function is_jammed(pos)
local JAMMER_MAX_DISTANCE = moremesecons.setting("jammer", "max_distance", 10, 1)
local pz,py,px = vector.unpack(pos)
for z,yxs in pairs(jammers) do
if math.abs(pz-z) <= JAMMER_MAX_DISTANCE then
for y,xs in pairs(yxs) do
if math.abs(py-y) <= JAMMER_MAX_DISTANCE then
for x in pairs(xs) do
if math.abs(px-x) <= JAMMER_MAX_DISTANCE
and (px-x)^2+(py-y)^2+(pz-z)^2 <= JAMMER_MAX_DISTANCE^2 then
return true
end
end
end
end
local minp = vector.subtract(pos, JAMMER_MAX_DISTANCE)
local maxp = vector.add(pos, JAMMER_MAX_DISTANCE)
for p in jammers:iter(minp, maxp) do
local d = vector.subtract(pos, p)
if d.x ^ 2 + d.y ^ 2 + d.z ^ 2 <= JAMMER_MAX_DISTANCE^2 then
return true
end
end
return false
@ -143,7 +123,7 @@ minetest.register_craft({
{"", "moremesecons_wireless:jammer_off", ""}}
})
if enable_lbm then
if moremesecons.setting("jammer", "enable_lbm", false) then
minetest.register_lbm({
name = "moremesecons_jammer:add_jammer",
nodenames = {"moremesecons_jammer:jammer_on"},

View File

@ -1 +1,2 @@
mesecons
moremesecons_utils

View File

@ -1,9 +1,33 @@
local storage = minetest.get_mod_storage()
local pos_data = moremesecons.get_storage_data(storage, "pos_data")
local function set_data(pos, code, owner)
local data = {
code = code,
owner = owner
}
moremesecons.set_data_to_pos(pos_data, pos, data)
end
local function check_data(pos, code, owner)
local stored_data = moremesecons.get_data_from_pos(pos_data, pos)
if not stored_data then
return false
end
if code ~= stored_data.code
or owner ~= stored_data.owner then
return false
end
return true
end
local function make_formspec(meta, pos)
local code = meta:get_string("code")
local code = minetest.formspec_escape(meta:get_string("code"))
local errmsg = minetest.formspec_escape(meta:get_string("errmsg"))
meta:set_string("formspec",
"size[10,8;]" ..
"textarea[0.5,0.5;10,7;code;Code;"..code.."]" ..
"textarea[0.5,0.5;9.5,7;code;Code;"..code.."]" ..
"label[0.1,7;"..errmsg.."]" ..
"button_exit[4,7.5;2,1;submit;Submit]")
end
@ -74,19 +98,28 @@ minetest.register_node("moremesecons_luablock:luablock", {
end
meta:set_string("code", fields.code)
set_data(pos, fields.code, name)
make_formspec(meta, pos)
end,
can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
return meta:get_string("owner") == player:get_player_name()
end,
on_destruct = function(pos)
moremesecons.remove_data_from_pos(pos_data, pos)
end,
mesecons = {effector = {
action_on = function(npos, node)
local meta = minetest.get_meta(npos)
local code = meta:get_string("code")
local owner = meta:get_string("owner")
if code == "" then
return
end
if not check_data(npos, code, owner) then
minetest.log("warning", "[moremesecons_luablock] Metadata of LuaBlock at pos "..minetest.pos_to_string(npos).." does not match its mod storage data!")
return
end
-- We do absolutely no check there.
-- There is no limitation in the number of instruction the LuaBlock can execute
-- or the usage it can make of loops.
@ -99,7 +132,10 @@ minetest.register_node("moremesecons_luablock:luablock", {
return
end
-- Set the "pos" global
local old_pos = pos -- In case there's already an existing "pos" global
local old_pos
if minetest.global_exists("pos") then
old_pos = pos -- In case there's already an existing "pos" global
end
pos = table.copy(npos)
local good, err = pcall(func)
pos = old_pos

View File

@ -1,2 +1,3 @@
mesecons
mesecons_luacontroller
moremesecons_utils

View File

@ -1,7 +1,3 @@
--[[
vector_extras there: https://github.com/HybridDog/vector_extras
]]
local templates = {MoreMesecons = {
logic = [[-- AND
port.a = pin.b and pin.c
@ -17,11 +13,63 @@ port.a = not (pin.b or pin.c)
port.a = pin.b ~= pin.c
-- XNOR / NXOR
port.a = pin.b == pin.c]],
digilinesth = [[digiline_send(channel, msg)
if event.type == "digiline" then
print(event.channel)
print(event.msg)
end]],
clock = [[number_of_oscillations = 0 -- 0 for infinity
interval = 1
input_port = "A"
output_port = "C"
if event.type == "on" and event.pin.name == input_port and not mem.running then
if not mem.counter then
mem.counter = 0
end
mem.running = true
port[string.lower(output_port)] = true
interrupt(interval)
mem.counter = mem.counter + 1
elseif event.type == "off" and event.pin.name == input_port and mem.running and number_of_oscillations == 0 then
mem.running = false
mem.counter = 0
elseif event.type == "interrupt" then
if not port[string.lower(output_port)] and mem.running then
port[string.lower(output_port)] = true
interrupt(interval)
mem.counter = mem.counter + 1
else
port[string.lower(output_port)] = false
if mem.counter < number_of_oscillations or number_of_oscillations == 0 and mem.running then
interrupt(interval)
else
mem.running = false
mem.counter = 0
end
end
end]],
counter = [[counter_limit = 5
output_time = 0.5
input_port = "A"
output_port = "C"
if event.type == "on" and event.pin.name == input_port then
if not mem.counter then
mem.counter = 0
end
mem.counter = mem.counter + 1
if mem.counter >= counter_limit then
port[string.lower(output_port)] = true
interrupt(output_time)
mem.counter = 0
end
elseif event.type == "interrupt" then
port[string.lower(output_port)] = false
end]]
}}
@ -126,7 +174,7 @@ local function get_selection_formspec(pname, selected_template)
fill_formspec_dropdown_list(pl_templates, selected_template)..
-- show selected template
"textarea[0,1;10.5,8.5;template_code;template code:;"..template_code.."]"..
"textarea[0,1;10.5,8.5;template_code;template code:;"..minetest.formspec_escape(template_code).."]"..
-- save name
"field[5,9.5;5,0;save_name;savename;"..selected_template.."]"..
@ -150,8 +198,8 @@ end
-- do not localize the function directly here to support possible overwritten luacontrollers
local luac_def = minetest.registered_nodes["mesecons_luacontroller:luacontroller0000"]
local function set_luacontroller_code(pos, code)
luac_def.on_receive_fields(pos, nil, {code=code, program=""})
local function set_luacontroller_code(pos, code, sender)
luac_def.on_receive_fields(pos, nil, {code=code, program=""}, sender)
end
minetest.register_tool("moremesecons_luacontroller_tool:lctt", {
@ -171,10 +219,10 @@ minetest.register_tool("moremesecons_luacontroller_tool:lctt", {
return
end
pdata[pname] = pdata[pname] or {
pdata[pname] = {
pos = pos,
player_name = pname,
template_name = next(templates[pname] or templates[next(templates)]),
template_name = pdata[pname] and pdata[pname].template_name or next(templates[pname] or templates[next(templates)]),
}
minetest.show_formspec(pname, "moremesecons:luacontroller_tool", get_selection_formspec(pdata[pname].player_name, pdata[pname].template_name))
end,
@ -254,7 +302,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- replace the code of the luacontroller with the template
local code = get_code_or_nil(pname, fields.player_name, fields.template_name)
if code then
set_luacontroller_code(pos, code)
set_luacontroller_code(pos, code, player)
minetest.chat_send_player(pname, "code set to template at "..minetest.pos_to_string(pos))
end
return
@ -264,7 +312,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
-- add the template to the end of the code of the luacontroller
local code = get_code_or_nil(pname, fields.player_name, fields.template_name)
if code then
set_luacontroller_code(pos, meta:get_string("code").."\r"..code)
set_luacontroller_code(pos, meta:get_string("code").."\r"..code, player)
minetest.chat_send_player(pname, "code added to luacontroller at "..minetest.pos_to_string(pos))
end
return

View File

@ -1 +1,2 @@
default
mesecons

View File

@ -106,3 +106,13 @@ default.register_chest("mesechest_locked", {
minetest.register_node = old_minetest_register_node
minetest.register_lbm = old_minetest_register_lbm
minetest.register_craft({
output = "default:mesechest",
recipe = {{"group:mesecon_conductor_craftable", "default:chest", "group:mesecon_conductor_craftable"}}
})
minetest.register_craft({
output = "default:mesechest_locked",
recipe = {{"group:mesecon_conductor_craftable", "default:chest_locked", "group:mesecon_conductor_craftable"}}
})

View File

@ -30,7 +30,7 @@ local kill_nearest_player = function(pos)
-- And kill him
nearest:set_hp(0)
minetest.log("action", "Player "..owner.." kills player "..nearest.." using a MoreMesecons Player Killer.")
minetest.log("action", "Player "..owner.." kills player "..nearest:get_player_name().." using a MoreMesecons Player Killer.")
end
minetest.register_craft({

View File

@ -35,7 +35,7 @@ if use_speech_dispatcher then
nil,
""
}
local language = minetest.setting_get("language") or "en"
local language = minetest.settings:get("language") or "en"
if language ~= "en" then
tab[3] = "-l "..language
end

View File

@ -1,34 +1,19 @@
local teleporters
local teleporters_rids
local storage = minetest.get_mod_storage()
local enable_lbm = moremesecons.setting("teleporter", "enable_lbm", false)
local storage
if not minetest.get_mod_storage then
enable_lbm = true -- No mod storage (<= 0.4.15-stable): force registration of LBM
teleporters = {}
teleporters_rids = {}
jammers = {}
else
storage = minetest.get_mod_storage()
teleporters = minetest.deserialize(storage:get_string("teleporters")) or {}
teleporters_rids = minetest.deserialize(storage:get_string("teleporters_rids")) or {}
jammers = minetest.deserialize(storage:get_string("jammers")) or {}
end
local teleporters = minetest.deserialize(storage:get_string("teleporters")) or {}
local teleporters_rids = moremesecons.load_MapDataStorage_legacy(storage,
"teleporters_rids_v2", "teleporters_rids")
local function update_mod_storage()
if not storage then
return
end
storage:set_string("teleporters", minetest.serialize(teleporters))
storage:set_string("teleporters_rids", minetest.serialize(teleporters_rids))
storage:set_string("teleporters_rids_v2", teleporters_rids:serialize())
end
local function register(pos)
if not vector.get_data_from_pos(teleporters_rids, pos.z,pos.y,pos.x) then
if not teleporters_rids:getAt(pos) then
table.insert(teleporters, pos)
vector.set_data_to_pos(teleporters_rids, pos.z,pos.y,pos.x, #teleporters)
teleporters_rids:setAt(pos, #teleporters)
update_mod_storage()
end
end
@ -104,16 +89,16 @@ minetest.register_node("moremesecons_teleporter:teleporter", {
sounds = default.node_sound_stone_defaults(),
on_construct = register,
on_destruct = function(pos)
local RID = vector.get_data_from_pos(teleporters_rids, pos.z,pos.y,pos.x)
local RID = teleporters_rids:getAt(pos)
if RID then
table.remove(teleporters, RID)
vector.remove_data_from_pos(teleporters_rids, pos.z,pos.y,pos.x)
teleporters_rids:removeAt(pos)
update_mod_storage()
end
end,
})
if enable_lbm then
if moremesecons.setting("teleporter", "enable_lbm", false) then
minetest.register_lbm({
name = "moremesecons_teleporter:add_teleporter",
nodenames = {"moremesecons_teleporter:teleporter"},

View File

@ -1 +0,0 @@
vector_extras?

View File

@ -4,15 +4,15 @@ function moremesecons.setting(modname, settingname, default, min)
local setting = "moremesecons_" .. modname .. "." .. settingname
if type(default) == "boolean" then
local ret = minetest.setting_getbool(setting)
local ret = minetest.settings:get_bool(setting)
if ret == nil then
ret = default
end
return ret
elseif type(default) == "string" then
return minetest.setting_get(setting) or default
return minetest.settings:get(setting) or default
elseif type(default) == "number" then
local ret = tonumber(minetest.setting_get(setting)) or default
local ret = tonumber(minetest.settings:get(setting)) or default
if not ret then
minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' must be a number. Set to default value ("..tostring(default)..").")
ret = default
@ -28,53 +28,354 @@ function moremesecons.setting(modname, settingname, default, min)
end
end
-- Vector helpers
-- All the following functions are from the vector_extras mod (https://github.com/HybridDog/vector_extras).
-- If you enable that mod, its functions will be used instead of the ones defined below
-- Storage helpers
if not vector.get_data_from_pos then
function vector.get_data_from_pos(tab, z,y,x)
local data = tab[z]
if data then
data = data[y]
if data then
return data[x]
end
end
end
function moremesecons.get_storage_data(storage, name)
return {
tab = minetest.deserialize(storage:get_string(name)) or {},
name = name,
storage = storage
}
end
if not vector.set_data_to_pos then
function vector.set_data_to_pos(tab, z,y,x, data)
if tab[z] then
if tab[z][y] then
tab[z][y][x] = data
function moremesecons.set_data_to_pos(sto, pos, data)
sto.tab[minetest.hash_node_position(pos)] = data
sto.storage:set_string(sto.name, minetest.serialize(sto.tab))
end
function moremesecons.get_data_from_pos(sto, pos)
return sto.tab[minetest.hash_node_position(pos)]
end
function moremesecons.remove_data_from_pos(sto, pos)
sto.tab[minetest.hash_node_position(pos)] = nil
sto.storage:set_string(sto.name, minetest.serialize(sto.tab))
end
-- Some additional vector helpers
-- The same as minetest.hash_node_position; I copied it to ensure backwards
-- compatibility and used hexadecimal number notation
local function node_position_key(pos)
return (pos.z + 0x8000) * 0x10000 * 0x10000
+ (pos.y + 0x8000) * 0x10000
+ pos.x + 0x8000
end
local MapDataStorage = {}
setmetatable(MapDataStorage, {__call = function()
local obj = {}
setmetatable(obj, MapDataStorage)
return obj
end})
MapDataStorage.__index = {
getAt = function(self, pos)
return self[node_position_key(pos)]
end,
setAt = function(self, pos, data)
-- If x, y or z is omitted, the key corresponds to a position outside
-- of the map (hopefully), so it can be used to skip lines and planes
local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000
local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000
local vi = vi_zy + pos.x + 0x8000
local is_new = self[vi] == nil
self[vi] = data
if is_new then
self[vi_z] = (self[vi_z] or 0) + 1
self[vi_zy] = (self[vi_zy] or 0) + 1
end
end,
setAtI = function(self, vi, data)
local vi_zy = vi - vi % 0x10000
local vi_z = vi - vi % (0x10000 * 0x10000)
local is_new = self[vi] == nil
self[vi] = data
if is_new then
self[vi_z] = (self[vi_z] or 0) + 1
self[vi_zy] = (self[vi_zy] or 0) + 1
end
end,
removeAt = function(self, pos)
local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000
local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000
local vi = vi_zy + pos.x + 0x8000
if self[vi] == nil then
-- Nothing to remove
return
end
self[vi] = nil
-- Update existence information for the xy plane and x line
self[vi_z] = self[vi_z] - 1
if self[vi_z] == 0 then
self[vi_z] = nil
self[vi_zy] = nil
return
end
self[vi_zy] = self[vi_zy] - 1
if self[vi_zy] == 0 then
self[vi_zy] = nil
end
end,
iter = function(self, pos1, pos2)
local ystride = 0x10000
local zstride = 0x10000 * 0x10000
-- Skip z values where no data can be found
pos1 = vector.new(pos1)
local vi_z = (pos1.z + 0x8000) * 0x10000 * 0x10000
while not self[vi_z] do
pos1.z = pos1.z + 1
vi_z = vi_z + zstride
if pos1.z > pos2.z then
-- There are no values to iterate through
return function() return end
end
end
-- Skipping y values is not yet implemented and may require much code
local xrange = pos2.x - pos1.x + 1
local yrange = pos2.y - pos1.y + 1
local zrange = pos2.z - pos1.z + 1
-- x-only and y-only parts of the vector index of pos1
local vi_y = (pos1.y + 0x8000) * 0x10000
local vi_x = pos1.x + 0x8000
local y = 0
local z = 0
local vi = node_position_key(pos1)
local pos = vector.new(pos1)
local nextaction = vi + xrange
pos.x = pos.x - 1
vi = vi - 1
local function iterfunc()
-- continue along x until it needs to jump
vi = vi + 1
pos.x = pos.x + 1
if vi ~= nextaction then
local v = self[vi]
if v == nil then
-- No data here
return iterfunc()
end
-- The returned position must not be changed
return pos, v
end
-- Reset x position
vi = vi - xrange
-- Go along y until pos2.y is exceeded
while true do
y = y + 1
pos.y = pos.y + 1
-- Set vi to index(pos1.x, pos1.y + y, pos1.z + z)
vi = vi + ystride
if y == yrange then
break
end
if self[vi - vi_x] then
nextaction = vi + xrange
vi = vi - 1
pos.x = pos1.x - 1
return iterfunc()
end
-- Nothing along this x line, so increase y again
end
-- Go back along y
vi = vi - yrange * ystride
y = 0
pos.y = pos1.y
-- Go along z until pos2.z is exceeded
while true do
z = z + 1
pos.z = pos.z + 1
vi = vi + zstride
if z == zrange then
-- Cuboid finished, return nil
return
end
if self[vi - vi_x - vi_y] then
y = 0
nextaction = vi + xrange
vi = vi - 1
pos.x = pos1.x - 1
return iterfunc()
end
-- Nothing in this xy plane, so increase z again
end
end
return iterfunc
end,
iterAll = function(self)
local previous_vi = nil
local function iterfunc()
local vi, v = next(self, previous_vi)
previous_vi = vi
if not vi then
return
end
tab[z][y] = {[x] = data}
return
local z = math.floor(vi / (0x10000 * 0x10000))
vi = vi - z * 0x10000 * 0x10000
local y = math.floor(vi / 0x10000)
if y == 0 or z == 0 then
-- The index does not refer to a position inside the map
return iterfunc()
end
local x = vi - y * 0x10000 - 0x8000
y = y - 0x8000
z = z - 0x8000
return {x=x, y=y, z=z}, v
end
tab[z] = {[y] = {[x] = data}}
return iterfunc
end,
serialize = function(self)
local indices = {}
local values = {}
local i = 1
for pos, v in self:iterAll() do
local vi = node_position_key(pos)
-- Convert the double reversible to a string;
-- minetest.serialize does not (yet) do this
indices[i] = ("%a"):format(vi)
values[i] = v
end
result = {
version = "MapDataStorage_v1",
indices = "return {" .. table.concat(indices, ",") .. "}",
values = minetest.serialize(values),
}
return minetest.serialize(result)
end,
}
MapDataStorage.deserialize = function(txtdata)
local data = minetest.deserialize(txtdata)
if data.version ~= "MapDataStorage_v1" then
minetest.log("error", "Unknown MapDataStorage version: " ..
data.version)
end
-- I assume that minetest.deserialize correctly deserializes the indices,
-- which are in the %a format
local indices = minetest.deserialize(data.indices)
local values = minetest.deserialize(data.values)
if not indices or not values then
return MapDataStorage()
end
data = MapDataStorage()
for i = 1,#indices do
local vi = indices[i]
local v = values[i]
data:setAtI(vi, v)
end
return data
end
moremesecons.MapDataStorage = MapDataStorage
-- Legacy
-- vector_extras there: https://github.com/HybridDog/vector_extras
-- Creates a MapDataStorage object from old vector_extras generated table
function moremesecons.load_old_data_from_pos(t)
local data = MapDataStorage()
for z, yxv in pairs(t) do
for y, xv in pairs(yxv) do
for x, v in pairs(xv) do
data:setAt({x=x, y=y, z=z}, v)
end
end
end
return data
end
if not vector.remove_data_from_pos then
function vector.remove_data_from_pos(tab, z,y,x)
if vector.get_data_from_pos(tab, z,y,x) == nil then
return
end
tab[z][y][x] = nil
if not next(tab[z][y]) then
tab[z][y] = nil
end
if not next(tab[z]) then
tab[z] = nil
end
function moremesecons.load_old_dfp_storage(modstorage, name)
local data = minetest.deserialize(modstorage:get_string(name))
if not data then
return
end
return moremesecons.load_old_data_from_pos(data)
end
if not vector.unpack then
function vector.unpack(pos)
return pos.z, pos.y, pos.x
function moremesecons.load_MapDataStorage_legacy(modstorage, name, oldname)
local t_old = moremesecons.load_old_dfp_storage(modstorage, oldname)
local t
if t_old and t_old ~= "" then
t = t_old
modstorage:set_string(name, t:serialize())
modstorage:set_string(oldname, nil)
return t
end
t = modstorage:get_string(name)
if t and t ~= "" then
return MapDataStorage.deserialize(t)
end
return MapDataStorage()
end
-- This testing code shows an example usage of the MapDataStorage code
local function do_test()
print("Test if iter returns correct positions when a lot is set")
local data = MapDataStorage()
local k = 0
for x = -5, 3 do
for y = -5, 3 do
for z = -5, 3 do
k = k + 1
data:setAt({x=x, y=y, z=z}, k)
end
end
end
local expected_positions = {}
for z = -4, 2 do
for y = -4, 2 do
for x = -4, 2 do
expected_positions[#expected_positions+1] = {x=x, y=y, z=z}
end
end
end
local i = 0
for pos, v in data:iter({x=-4, y=-4, z=-4}, {x=2, y=2, z=2}) do
i = i + 1
assert(vector.equals(pos, expected_positions[i]))
end
print("Test if iter works correctly on a corner")
local found = false
for pos, v in data:iter({x=-8, y=-7, z=-80}, {x=-5, y=-5, z=-5}) do
assert(not found)
found = true
assert(vector.equals(pos, {x=-5, y=-5, z=-5}))
end
assert(found)
print("Test if iter finds all corners")
local expected_positions = {}
local k = 1
for _, z in ipairs({-9, -6}) do
for _, y in ipairs({-9, -6}) do
for _, x in ipairs({-8, -6}) do
local pos = {x=x, y=y, z=z}
expected_positions[#expected_positions+1] = pos
data:setAt(pos, k)
k = k + 1
end
end
end
local i = 1
for pos, v in data:iter({x=-8, y=-9, z=-9}, {x=-6, y=-6, z=-6}) do
assert(v == i)
assert(vector.equals(pos, expected_positions[i]))
i = i + 1
--~ print("found " .. minetest.pos_to_string(pos))
end
assert(i == 8 + 1, "Not enough or too many corners found")
--~ data:iterAll()
end
--~ do_test()

View File

@ -1,123 +1,145 @@
local wireless
local wireless_meta -- This table contains wireless metadatas, it is a lot faster to access
local jammers
local storage = minetest.get_mod_storage()
local enable_lbm = moremesecons.setting("wireless", "enable_lbm", false)
local storage
if not minetest.get_mod_storage then
enable_lbm = true -- No mod storage (<= 0.4.15-stable): force registration of LBM
wireless = {}
wireless_meta = {owners = {}, channels = {}, ids = {}}
jammers = {}
else
storage = minetest.get_mod_storage()
wireless = minetest.deserialize(storage:get_string("wireless")) or {}
wireless_meta = minetest.deserialize(storage:get_string("wireless_meta")) or {owners = {}, channels = {}, ids = {}}
jammers = minetest.deserialize(storage:get_string("jammers")) or {}
end
-- Names wireless_meta, and jammers were used in old versions of this mod.
-- There is legacy code at the end of this file to migrate the mod storage.
local wireless = minetest.deserialize(storage:get_string("networks")) or {}
local wireless_meta = moremesecons.get_storage_data(storage, "wireless_meta_2")
local jammers = moremesecons.get_storage_data(storage, "jammers_2")
local function update_mod_storage()
if not storage then
return
end
storage:set_string("wireless", minetest.serialize(wireless))
storage:set_string("wireless_meta", minetest.serialize(wireless_meta))
storage:set_string("jammers", minetest.serialize(jammers))
storage:set_string("networks", minetest.serialize(wireless))
end
-- localize these functions with small names because they work fairly fast
local get = vector.get_data_from_pos
local set = vector.set_data_to_pos
local remove = vector.remove_data_from_pos
local wireless_effector_off
local function remove_wireless(pos)
local owner = get(wireless_meta.owners, pos.z,pos.y,pos.x)
if not owner or owner == "" then
return
end
remove(wireless_meta.owners, pos.z,pos.y,pos.x)
if not wireless[owner] or not next(wireless[owner]) then
wireless[owner] = nil
local wls = moremesecons.get_data_from_pos(wireless_meta, pos)
if not wls then
return
end
local channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
if not channel or channel == "" then
if not wls.owner or wls.owner == "" then
moremesecons.remove_data_from_pos(wireless_meta, pos)
return
end
table.remove(wireless[owner][channel], get(wireless_meta.ids, pos.z,pos.y,pos.x))
if #wireless[owner][channel] == 0 then
wireless[owner][channel] = nil
if not next(wireless[owner]) then
wireless[owner] = nil
if not wireless[wls.owner] or not next(wireless[wls.owner]) then
wireless[wls.owner] = nil
moremesecons.remove_data_from_pos(wireless_meta, pos)
return
end
if not wls.channel or wls.channel == "" then
moremesecons.remove_data_from_pos(wireless_meta, pos)
return
end
local network = wireless[wls.owner][wls.channel]
if network.sources[wls.id] then
wireless_effector_off(pos)
end
moremesecons.remove_data_from_pos(wireless_meta, pos)
network.members[wls.id] = nil
if not next(network.members) then
wireless[wls.owner][wls.channel] = nil
if not next(wireless[wls.owner]) then
wireless[wls.owner] = nil
end
end
remove(wireless_meta.channels, pos.z,pos.y,pos.x)
remove(wireless_meta.ids, pos.z,pos.y,pos.x)
update_mod_storage()
end
local set_channel
local function set_owner(pos, owner)
if not owner or owner == "" then
return
end
remove_wireless(pos)
local meta = minetest.get_meta(pos)
meta:set_string("owner", owner)
set(wireless_meta.owners, pos.z,pos.y,pos.x, owner)
if meta then
meta:set_string("owner", owner)
end
local wls = moremesecons.get_data_from_pos(wireless_meta, pos) or {}
wls.owner = owner
moremesecons.set_data_to_pos(wireless_meta, pos, wls)
if not wireless[owner] then
wireless[owner] = {}
end
local channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
if channel and channel ~= "" then
if not wireless[owner][channel] then
wireless[owner][channel] = {}
end
set_channel(pos, channel)
if meta then
meta:set_string("infotext", "Wireless owned by " .. owner .. " on " .. ((wls.channel and wls.channel ~= "") and "channel " .. wls.channel or "undefined channel"))
end
meta:set_string("infotext", "Wireless owned by " .. owner .. " on " .. ((channel and channel ~= "") and "channel " .. channel or "undefined channel"))
end
function set_channel(pos, channel)
local wireless_receptor_on
local wireless_receptor_off
local wireless_effector_on
local function set_channel(pos, channel)
if not channel or channel == "" then
return
end
local meta = minetest.get_meta(pos)
local owner = get(wireless_meta.owners, pos.z,pos.y,pos.x)
if not owner or owner == "" then
local wls = moremesecons.get_data_from_pos(wireless_meta, pos)
if not wls or wls.owner == "" then
return
end
local old_channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
if old_channel and old_channel ~= "" and old_channel ~= channel then
if wls.id then
remove_wireless(pos)
set_owner(pos, owner)
end
meta:set_string("channel", channel)
set(wireless_meta.channels, pos.z,pos.y,pos.x, channel)
if not wireless[owner] then
wireless[owner] = {}
if meta then
meta:set_string("channel", channel)
end
if not wireless[owner][channel] then
wireless[owner][channel] = {}
wls.channel = channel
moremesecons.set_data_to_pos(wireless_meta, pos, wls)
if not wireless[wls.owner] then
wireless[wls.owner] = {}
end
if not wireless[wls.owner][channel] then
wireless[wls.owner][channel] = {
members = {},
sources = {}
}
end
local id = get(wireless_meta.ids, pos.z,pos.y,pos.x)
if id then
wireless[owner][channel][id] = pos
-- Find the first free ID
local id = 1
while wireless[wls.owner][channel].members[id] do
id = id + 1
end
wls.id = id
moremesecons.set_data_to_pos(wireless_meta, pos, wls)
local network = wireless[wls.owner][channel]
network.members[id] = pos
if meta then
meta:set_int("id", id)
end
update_mod_storage()
if meta then
meta:set_string("infotext", "Wireless owned by " .. wls.owner .. " on channel " .. channel)
end
if wls.effector then
wireless_effector_on(pos)
elseif next(network.sources) then
wireless_receptor_on(pos, id, network, false)
else
table.insert(wireless[owner][channel], pos)
meta:set_int("id", #wireless[owner][channel])
set(wireless_meta.ids, pos.z,pos.y,pos.x, #wireless[owner][channel])
wireless_receptor_off(pos, id, network, false)
end
meta:set_string("infotext", "Wireless owned by " .. owner .. " on channel " .. channel)
end
local function register_wireless(pos)
@ -126,78 +148,124 @@ local function register_wireless(pos)
if owner == "" then
return
end
remove_wireless(pos)
set_owner(pos, owner)
local channel = meta:get_string("channel")
if channel ~= "" then
set_channel(pos, channel)
end
end
update_mod_storage()
local function check_wireless_exists(pos)
local nn = minetest.get_node(pos).name
if nn:sub(1, 30) == "moremesecons_wireless:wireless" then
return true
elseif nn ~= "ignore" then
-- Defer the remove_wireless() call so it doesn't interfere
-- with pairs().
minetest.after(0, remove_wireless, pos)
return false
end
end
function wireless_receptor_on(pos, id, network, check)
if check == false or check_wireless_exists(pos) then
minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_on"})
if not network.sources[id] then
mesecon.receptor_on(pos)
end
end
end
function wireless_receptor_off(pos, id, network, check)
if check == false or check_wireless_exists(pos) then
minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_off"})
mesecon.receptor_off(pos)
end
end
function activate_network(owner, channel)
local network = wireless[owner][channel]
for i, wl_pos in pairs(network.members) do
wireless_receptor_on(wl_pos, id, network)
end
end
local function deactivate_network(owner, channel)
local network = wireless[owner][channel]
for i, wl_pos in pairs(network.members) do
wireless_receptor_off(wl_pos, i, network)
end
end
local is_jammed
local function wireless_activate(pos)
function wireless_effector_on(pos)
if is_jammed(pos) then
-- jamming doesn't disallow receiving signals, only sending them
return
end
local channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
local owner = get(wireless_meta.owners, pos.z,pos.y,pos.x)
local id = get(wireless_meta.ids, pos.z,pos.y,pos.x)
if owner == "" or not wireless[owner] or channel == "" or not wireless[owner][channel] then
local wls = moremesecons.get_data_from_pos(wireless_meta, pos)
if not wls then
return
end
minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_on"})
for i, wl_pos in ipairs(wireless[owner][channel]) do
if i ~= id then
minetest.swap_node(wl_pos, {name = "moremesecons_wireless:wireless_on"})
mesecon.receptor_on(wl_pos)
end
wls.effector = true
moremesecons.set_data_to_pos(wireless_meta, pos, wls)
if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then
return
end
local network = wireless[wls.owner][wls.channel]
network.sources[wls.id] = true
activate_network(wls.owner, wls.channel)
update_mod_storage()
end
local function wireless_deactivate(pos)
function wireless_effector_off(pos)
local wls = moremesecons.get_data_from_pos(wireless_meta, pos)
if not wls then
return
end
wls.effector = nil
moremesecons.set_data_to_pos(wireless_meta, pos, wls)
if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then
return
end
local network = wireless[wls.owner][wls.channel]
network.sources[wls.id] = nil
if not next(network.sources) then
deactivate_network(wls.owner, wls.channel)
else
-- There is another source in the network. Turn this wireless into
-- a receptor.
mesecon.receptor_on(pos)
end
update_mod_storage()
end
local function on_digiline_receive(pos, node, channel, msg)
if is_jammed(pos) then
return
end
local channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
local owner = get(wireless_meta.owners, pos.z,pos.y,pos.x)
local id = get(wireless_meta.ids, pos.z,pos.y,pos.x)
local wls = moremesecons.get_data_from_pos(wireless_meta, pos)
if owner == "" or not wireless[owner] or channel == "" or not wireless[owner][channel] then
if wls.owner == "" or not wireless[wls.owner] or channel == "" or not wireless[wls.owner][wls.channel] then
return
end
minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_off"})
for i, wl_pos in ipairs(wireless[owner][channel]) do
if i ~= id then
minetest.swap_node(wl_pos, {name = "moremesecons_wireless:wireless_off"})
mesecon.receptor_off(wl_pos)
end
end
end
local function on_digiline_receive(pos, node, channel, msg)
local setchan = minetest.get_meta(pos):get_string("channel") -- Note : the digiline channel is the same as the wireless channel. TODO: Making two different channels and a more complex formspec ?
if channel ~= setchan or is_jammed(pos) or setchan == "" then
return
end
local channel = get(wireless_meta.channels, pos.z,pos.y,pos.x)
local owner = get(wireless_meta.owners, pos.z,pos.y,pos.x)
local id = get(wireless_meta.ids, pos.z,pos.y,pos.x)
if owner == "" or not wireless[owner] or channel == "" or not wireless[owner][channel] then
return
end
for i, wl_pos in ipairs(wireless[owner][channel]) do
if i ~= id then
for i, wl_pos in pairs(wireless[wls.owner][wls.channel].members) do
if i ~= wls.id and check_wireless_exists(wl_pos) then
digiline:receptor_send(wl_pos, digiline.rules.default, channel, msg)
end
end
@ -219,13 +287,11 @@ mesecon.register_node("moremesecons_wireless:wireless", {
end,
on_destruct = function(pos)
remove_wireless(pos)
update_mod_storage()
mesecon.receptor_off(pos)
end,
after_place_node = function(pos, placer)
local placername = placer:get_player_name()
set_owner(pos, placer:get_player_name())
update_mod_storage()
end,
on_receive_fields = function(pos, _, fields, player)
local meta = minetest.get_meta(pos)
@ -236,7 +302,6 @@ mesecon.register_node("moremesecons_wireless:wireless", {
-- Old wireless
if not minetest.is_protected(pos, playername) then
set_owner(pos, playername)
update_mod_storage()
else
return
end
@ -244,58 +309,48 @@ mesecon.register_node("moremesecons_wireless:wireless", {
if playername == owner then
set_channel(pos, fields.channel)
update_mod_storage()
end
end,
}, {
tiles = {"moremesecons_wireless_off.png"},
groups = {cracky=3},
mesecons = {effector = {
action_on = wireless_activate,
action_on = wireless_effector_on
}},
}, {
tiles = {"moremesecons_wireless_on.png"},
groups = {cracky=3, not_in_creative_inventory=1},
mesecons = {effector = {
action_off = wireless_deactivate
action_off = wireless_effector_off
}},
})
minetest.register_alias("moremesecons_wireless:wireless", "moremesecons_wireless:wireless_off")
local jammers = {}
local function add_jammer(pos)
if get(jammers, pos.z,pos.y,pos.x) then
return
end
set(jammers, pos.z,pos.y,pos.x, true)
update_mod_storage()
end
local function remove_jammer(pos)
remove(jammers, pos.z,pos.y,pos.x)
update_mod_storage()
moremesecons.remove_data_from_pos(jammers, pos)
end
local function add_jammer(pos)
remove_jammer(pos)
moremesecons.set_data_to_pos(jammers, pos, true)
end
-- looks big, but should work fast
function is_jammed(pos)
local JAMMER_MAX_DISTANCE = moremesecons.setting("wireless", "jammer_max_distance", 15, 1)
local JAMMER_MAX_DISTANCE_SQUARE = JAMMER_MAX_DISTANCE^2 -- Cache this result
local pz,py,px = vector.unpack(pos)
for z,yxs in pairs(jammers) do
if math.abs(pz-z) <= JAMMER_MAX_DISTANCE then
for y,xs in pairs(yxs) do
if math.abs(py-y) <= JAMMER_MAX_DISTANCE then
for x in pairs(xs) do
if math.abs(px-x) <= JAMMER_MAX_DISTANCE
and (px-x)^2+(py-y)^2+(pz-z)^2 <= JAMMER_MAX_DISTANCE^2 then
return true
end
end
end
end
for pos_hash, _ in pairs(jammers.tab) do
local j_pos = minetest.get_position_from_hash(pos_hash)
-- Fast comparisons first
if math.abs(pos.x - j_pos.x) <= JAMMER_MAX_DISTANCE and
math.abs(pos.y - j_pos.y) <= JAMMER_MAX_DISTANCE and
math.abs(pos.z - j_pos.z) <= JAMMER_MAX_DISTANCE and
(pos.x - j_pos.x)^2 + (pos.y - j_pos.y)^2 + (pos.z - j_pos.z)^2 <= JAMMER_MAX_DISTANCE_SQUARE then
return true
end
end
return false
end
@ -377,7 +432,7 @@ minetest.register_craft({
}
})
if enable_lbm then
if moremesecons.setting("wireless", "enable_lbm", false) then
minetest.register_lbm({
name = "moremesecons_wireless:add_jammer",
nodenames = {"moremesecons_wireless:jammer_on"},
@ -393,43 +448,39 @@ if enable_lbm then
})
end
-- Legacy
if storage and storage:get_string("wireless_rids") and storage:get_string("wireless_rids") ~= "" then
-- Upgrade mod storage!
local wireless_rids = minetest.deserialize(storage:get_string("wireless_rids"))
local old_wireless = table.copy(wireless)
wireless = {}
if storage:get_string("wireless_meta_2") == "" then
local wireless_meta_1 = minetest.deserialize(storage:get_string("wireless_meta"))
if not wireless_meta_1 then
return
end
minetest.after(0, function(old_wireless)
-- After loading all mods, try to guess owners based on the areas mod database.
-- That won't work for all wireless. Owners of remaining wireless will be set
-- to the first player using their formspec.
if not areas then
return
end
for RID, pos in ipairs(old_wireless) do
local numerous_owners = false
local owner
for _, area in pairs(areas:getAreasAtPos(pos)) do
if owner and area.owner ~= owner then
numerous_owners = true
break
end
owner = area.owner
end
minetest.log("action", "[moremesecons_wireless] Migrating mod storage data...")
local jammers_1 = minetest.deserialize(storage:get_string("jammers"))
if not numerous_owners and owner then
set_owner(pos, owner)
set_channel(pos, minetest.get_meta(pos):get_string("channel"))
end
end
end, old_wireless)
local get = function(t, pos)
-- FIXME: this does not test explicitly for false,
-- but channel is never false
return t[pos.z] and t[pos.z][pos.y] and t[pos.z][pos.y][pos.x]
end
-- Remove wireless_rids from storage
storage:from_table({
jammers = jammers,
wireless_meta = wireless_meta,
wireless = wireless
})
for z, data_z in pairs(wireless_meta_1.owners) do
for y, data_y in pairs(data_z) do
for x, owner in pairs(data_y) do
local pos = {x = x, y = y, z = z}
set_owner(pos, owner)
set_channel(pos, get(wireless_meta_1.channels, pos))
end
end
end
for z, data_z in pairs(jammers_1) do
for y, data_y in pairs(data_z) do
for x, jammer in pairs(data_y) do
local pos = {x = x, y = y, z = z}
moremesecons.set_data_to_pos(jammers, pos, jammer)
end
end
end
minetest.log("action", "[moremesecons_wireless] Done!")
end