2017-06-23 13:47:41 +02:00
local storage = minetest.get_mod_storage ( )
2020-04-11 12:45:33 +02:00
-- 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 " )
2017-04-17 11:17:09 +02:00
local function update_mod_storage ( )
2020-04-11 12:45:33 +02:00
storage : set_string ( " networks " , minetest.serialize ( wireless ) )
2017-04-17 11:17:09 +02:00
end
2015-09-01 10:51:53 +02:00
2020-04-11 12:45:33 +02:00
local wireless_effector_off
2017-04-21 13:56:37 +02:00
local function remove_wireless ( pos )
2020-04-11 12:45:33 +02:00
local wls = moremesecons.get_data_from_pos ( wireless_meta , pos )
if not wls then
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
if not wls.owner or wls.owner == " " then
moremesecons.remove_data_from_pos ( wireless_meta , pos )
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
if not wireless [ wls.owner ] or not next ( wireless [ wls.owner ] ) then
wireless [ wls.owner ] = nil
moremesecons.remove_data_from_pos ( wireless_meta , pos )
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
if not wls.channel or wls.channel == " " then
moremesecons.remove_data_from_pos ( wireless_meta , pos )
return
2017-04-21 13:56:37 +02:00
end
2020-04-11 12:45:33 +02:00
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
update_mod_storage ( )
2017-04-21 13:56:37 +02:00
end
local function set_owner ( pos , owner )
2017-04-22 21:17:06 +02:00
if not owner or owner == " " then
return
end
2020-04-11 12:45:33 +02:00
remove_wireless ( pos )
2017-04-21 13:56:37 +02:00
local meta = minetest.get_meta ( pos )
2020-04-11 12:45:33 +02:00
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 )
2017-04-21 13:56:37 +02:00
if not wireless [ owner ] then
wireless [ owner ] = { }
end
2020-04-11 12:45:33 +02:00
if meta then
meta : set_string ( " infotext " , " Wireless owned by " .. owner .. " on " .. ( ( wls.channel and wls.channel ~= " " ) and " channel " .. wls.channel or " undefined channel " ) )
2017-04-21 13:56:37 +02:00
end
end
2020-04-11 12:45:33 +02:00
local wireless_receptor_on
local wireless_receptor_off
local wireless_effector_on
local function set_channel ( pos , channel )
2017-04-21 13:56:37 +02:00
if not channel or channel == " " then
return
end
local meta = minetest.get_meta ( pos )
2020-04-11 12:45:33 +02:00
local wls = moremesecons.get_data_from_pos ( wireless_meta , pos )
if not wls or wls.owner == " " then
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
if wls.id then
2017-04-21 13:56:37 +02:00
remove_wireless ( pos )
end
2020-04-11 12:45:33 +02:00
if meta then
meta : set_string ( " channel " , channel )
end
wls.channel = channel
moremesecons.set_data_to_pos ( wireless_meta , pos , wls )
if not wireless [ wls.owner ] then
wireless [ wls.owner ] = { }
2017-04-21 13:56:37 +02:00
end
2020-04-11 12:45:33 +02:00
if not wireless [ wls.owner ] [ channel ] then
wireless [ wls.owner ] [ channel ] = {
members = { } ,
sources = { }
}
2017-04-21 13:56:37 +02:00
end
2017-04-27 17:42:59 +02:00
2020-04-11 12:45:33 +02:00
-- 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 )
2017-04-27 17:42:59 +02:00
end
2017-04-21 13:56:37 +02:00
2020-04-11 12:45:33 +02:00
if wls.effector then
wireless_effector_on ( pos )
elseif next ( network.sources ) then
wireless_receptor_on ( pos , id , network , false )
else
wireless_receptor_off ( pos , id , network , false )
end
2017-04-21 13:56:37 +02:00
end
local function register_wireless ( pos )
2017-04-27 17:01:35 +02:00
local meta = minetest.get_meta ( pos )
local owner = meta : get_string ( " owner " )
if owner == " " then
2015-09-10 21:45:08 +02:00
return
2015-08-28 12:24:33 +02:00
end
2020-04-11 12:45:33 +02:00
remove_wireless ( pos )
2017-04-22 21:17:06 +02:00
set_owner ( pos , owner )
2017-04-21 13:56:37 +02:00
2017-04-27 17:01:35 +02:00
local channel = meta : get_string ( " channel " )
if channel ~= " " then
2017-04-21 13:56:37 +02:00
set_channel ( pos , channel )
end
2015-08-28 12:24:33 +02:00
end
2020-04-09 19:21:40 +02:00
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
2020-04-11 12:45:33 +02:00
-- with pairs().
2020-04-09 19:21:40 +02:00
minetest.after ( 0 , remove_wireless , pos )
return false
end
end
2020-04-11 12:45:33 +02:00
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
2015-09-10 21:45:08 +02:00
local is_jammed
2020-04-11 12:45:33 +02:00
function wireless_effector_on ( pos )
2015-09-10 21:45:08 +02:00
if is_jammed ( pos ) then
-- jamming doesn't disallow receiving signals, only sending them
return
end
2016-04-27 18:42:20 +02:00
2020-04-11 12:45:33 +02:00
local wls = moremesecons.get_data_from_pos ( wireless_meta , pos )
if not wls then
2016-04-27 14:04:39 +02:00
return
end
2016-04-27 18:42:20 +02:00
2020-04-11 12:45:33 +02:00
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
2015-09-10 21:45:08 +02:00
end
2020-04-11 12:45:33 +02:00
local network = wireless [ wls.owner ] [ wls.channel ]
network.sources [ wls.id ] = true
activate_network ( wls.owner , wls.channel )
update_mod_storage ( )
2015-08-28 12:24:33 +02:00
end
2020-04-11 12:45:33 +02:00
function wireless_effector_off ( pos )
local wls = moremesecons.get_data_from_pos ( wireless_meta , pos )
if not wls then
2015-09-10 21:45:08 +02:00
return
end
2017-04-21 13:56:37 +02:00
2020-04-11 12:45:33 +02:00
wls.effector = nil
moremesecons.set_data_to_pos ( wireless_meta , pos , wls )
2017-04-21 13:56:37 +02:00
2020-04-11 12:45:33 +02:00
if wls.owner == " " or not wireless [ wls.owner ] or wls.channel == " " or not wireless [ wls.owner ] [ wls.channel ] then
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
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 )
2015-09-10 21:45:08 +02:00
end
2020-04-11 12:45:33 +02:00
update_mod_storage ( )
2015-08-28 12:24:33 +02:00
end
2016-04-24 14:19:51 +02:00
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 ?
2016-04-27 14:04:39 +02:00
if channel ~= setchan or is_jammed ( pos ) or setchan == " " then
2016-04-24 14:19:51 +02:00
return
end
2017-04-21 13:56:37 +02:00
2020-04-11 12:45:33 +02:00
local wls = moremesecons.get_data_from_pos ( wireless_meta , pos )
2017-04-21 13:56:37 +02:00
2020-04-11 12:45:33 +02:00
if wls.owner == " " or not wireless [ wls.owner ] or channel == " " or not wireless [ wls.owner ] [ wls.channel ] then
2017-04-21 13:56:37 +02:00
return
end
2020-04-11 12:45:33 +02:00
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 , wls.channel , msg )
2016-04-24 14:19:51 +02:00
end
end
end
2017-04-27 18:15:47 +02:00
mesecon.register_node ( " moremesecons_wireless:wireless " , {
2015-08-28 12:24:33 +02:00
paramtype = " light " ,
paramtype2 = " facedir " ,
description = " Wireless " ,
2016-04-24 14:19:51 +02:00
digiline = {
receptor = { } ,
effector = {
action = on_digiline_receive
} ,
} ,
2015-08-28 12:24:33 +02:00
sounds = default.node_sound_stone_defaults ( ) ,
on_construct = function ( pos )
2016-04-27 18:42:20 +02:00
minetest.get_meta ( pos ) : set_string ( " formspec " , " field[channel;channel;${channel}] " )
2015-08-28 12:24:33 +02:00
end ,
2015-08-31 11:25:29 +02:00
on_destruct = function ( pos )
2017-04-21 13:56:37 +02:00
remove_wireless ( pos )
2015-09-10 21:52:49 +02:00
mesecon.receptor_off ( pos )
2015-08-31 11:25:29 +02:00
end ,
2017-04-21 13:56:37 +02:00
after_place_node = function ( pos , placer )
local placername = placer : get_player_name ( )
set_owner ( pos , placer : get_player_name ( ) )
end ,
2016-04-27 18:42:20 +02:00
on_receive_fields = function ( pos , _ , fields , player )
2017-04-21 13:56:37 +02:00
local meta = minetest.get_meta ( pos )
local playername = player : get_player_name ( )
local owner = meta : get_string ( " owner " )
if not owner or owner == " " then
-- Old wireless
if not minetest.is_protected ( pos , playername ) then
set_owner ( pos , playername )
else
return
end
end
if playername == owner then
set_channel ( pos , fields.channel )
2016-04-27 18:42:20 +02:00
end
2015-08-28 12:24:33 +02:00
end ,
2017-04-27 18:15:47 +02:00
} , {
tiles = { " moremesecons_wireless_off.png " } ,
groups = { cracky = 3 } ,
mesecons = { effector = {
2020-04-11 12:45:33 +02:00
action_on = wireless_effector_on
2017-04-27 18:15:47 +02:00
} } ,
} , {
tiles = { " moremesecons_wireless_on.png " } ,
groups = { cracky = 3 , not_in_creative_inventory = 1 } ,
mesecons = { effector = {
2020-04-11 12:45:33 +02:00
action_off = wireless_effector_off
2017-04-27 18:15:47 +02:00
} } ,
2015-08-28 12:24:33 +02:00
} )
2017-04-27 18:15:47 +02:00
minetest.register_alias ( " moremesecons_wireless:wireless " , " moremesecons_wireless:wireless_off " )
2020-04-11 12:45:33 +02:00
local function remove_jammer ( pos )
moremesecons.remove_data_from_pos ( jammers , pos )
2015-09-10 21:45:08 +02:00
end
2020-04-11 12:45:33 +02:00
local function add_jammer ( pos )
remove_jammer ( pos )
moremesecons.set_data_to_pos ( jammers , pos , true )
2015-09-10 21:45:08 +02:00
end
function is_jammed ( pos )
2017-04-19 11:08:58 +02:00
local JAMMER_MAX_DISTANCE = moremesecons.setting ( " wireless " , " jammer_max_distance " , 15 , 1 )
2020-04-11 12:45:33 +02:00
local JAMMER_MAX_DISTANCE_SQUARE = JAMMER_MAX_DISTANCE ^ 2 -- Cache this result
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
2015-09-10 21:45:08 +02:00
end
end
2020-04-11 12:45:33 +02:00
2015-09-10 21:45:08 +02:00
return false
end
2015-09-10 18:33:07 +02:00
mesecon.register_node ( " moremesecons_wireless:jammer " , {
2015-09-10 22:46:27 +02:00
description = " Wireless Jammer " ,
2015-09-10 18:33:07 +02:00
paramtype = " light " ,
2015-09-10 22:46:27 +02:00
drawtype = " nodebox " ,
2015-09-10 18:33:07 +02:00
} , {
2015-09-10 22:46:27 +02:00
tiles = { " mesecons_wire_off.png^moremesecons_jammer_top.png " , " moremesecons_jammer_bottom.png " , " mesecons_wire_off.png^moremesecons_jammer_side_off.png " } ,
node_box = {
type = " fixed " ,
fixed = {
-- connection
{ - 1 / 16 , - 0.5 , - 0.5 , 1 / 16 , - 7 / 16 , 0.5 } ,
{ - 0.5 , - 0.5 , - 1 / 16 , 0.5 , - 7 / 16 , 1 / 16 } ,
--stabilization
{ - 1 / 16 , - 7 / 16 , - 1 / 16 , 1 / 16 , - 6 / 16 , 1 / 16 } ,
-- fields
{ - 7 / 16 , - 6 / 16 , - 7 / 16 , 7 / 16 , - 4 / 16 , 7 / 16 } ,
{ - 5 / 16 , - 4 / 16 , - 5 / 16 , 5 / 16 , - 3 / 16 , 5 / 16 } ,
{ - 3 / 16 , - 3 / 16 , - 3 / 16 , 3 / 16 , - 2 / 16 , 3 / 16 } ,
{ - 1 / 16 , - 2 / 16 , - 1 / 16 , 1 / 16 , - 1 / 16 , 1 / 16 } ,
} ,
} ,
2015-09-10 18:33:07 +02:00
groups = { dig_immediate = 2 } ,
mesecons = { effector = {
2016-04-23 11:52:15 +02:00
rules = mesecon.rules . flat ,
2015-09-10 18:33:07 +02:00
action_on = function ( pos )
2015-09-10 21:45:08 +02:00
add_jammer ( pos )
2015-09-10 18:33:07 +02:00
minetest.swap_node ( pos , { name = " moremesecons_wireless:jammer_on " } )
2015-09-10 21:45:08 +02:00
end
} }
2015-09-10 18:33:07 +02:00
} , {
2015-09-10 22:46:27 +02:00
tiles = { " mesecons_wire_on.png^moremesecons_jammer_top.png " , " moremesecons_jammer_bottom.png " , " mesecons_wire_on.png^moremesecons_jammer_side_on.png " } ,
node_box = {
type = " fixed " ,
fixed = {
-- connection
{ - 1 / 16 , - 0.5 , - 0.5 , 1 / 16 , - 7 / 16 , 0.5 } ,
{ - 0.5 , - 0.5 , - 1 / 16 , 0.5 , - 7 / 16 , 1 / 16 } ,
--stabilization
{ - 1 / 16 , - 7 / 16 , - 1 / 16 , 1 / 16 , 5 / 16 , 1 / 16 } ,
-- fields
{ - 7 / 16 , - 6 / 16 , - 7 / 16 , 7 / 16 , - 4 / 16 , 7 / 16 } ,
{ - 5 / 16 , - 3 / 16 , - 5 / 16 , 5 / 16 , - 1 / 16 , 5 / 16 } ,
{ - 3 / 16 , 0 , - 3 / 16 , 3 / 16 , 2 / 16 , 3 / 16 } ,
{ - 1 / 16 , 3 / 16 , - 1 / 16 , 1 / 16 , 5 / 16 , 1 / 16 } ,
} ,
} ,
2015-09-10 18:33:07 +02:00
groups = { dig_immediate = 2 , not_in_creative_inventory = 1 } ,
mesecons = { effector = {
2016-04-23 11:52:15 +02:00
rules = mesecon.rules . flat ,
2015-09-10 18:33:07 +02:00
action_off = function ( pos )
2015-09-10 21:45:08 +02:00
remove_jammer ( pos )
2015-09-10 18:33:07 +02:00
minetest.swap_node ( pos , { name = " moremesecons_wireless:jammer_off " } )
2015-09-10 21:45:08 +02:00
end
} } ,
on_destruct = remove_jammer ,
on_construct = add_jammer ,
2015-09-10 18:33:07 +02:00
} )
minetest.register_craft ( {
output = " moremesecons_wireless:jammer_off " ,
recipe = {
{ " moremesecons_wireless:wireless " , " mesecons_torch:mesecon_torch_on " , " moremesecons_wireless:wireless " }
}
} )
2015-08-28 12:24:33 +02:00
minetest.register_craft ( {
2017-04-27 18:15:47 +02:00
output = " moremesecons_wireless:wireless_off 2 " ,
2015-08-28 12:24:33 +02:00
recipe = {
{ " group:mesecon_conductor_craftable " , " " , " group:mesecon_conductor_craftable " } ,
2015-08-30 11:49:32 +02:00
{ " " , " mesecons_torch:mesecon_torch_on " , " " } ,
2015-08-28 12:24:33 +02:00
{ " group:mesecon_conductor_craftable " , " " , " group:mesecon_conductor_craftable " } ,
}
} )
2017-04-19 10:36:33 +02:00
2017-06-23 13:47:41 +02:00
if moremesecons.setting ( " wireless " , " enable_lbm " , false ) then
2017-04-19 10:36:33 +02:00
minetest.register_lbm ( {
name = " moremesecons_wireless:add_jammer " ,
nodenames = { " moremesecons_wireless:jammer_on " } ,
run_at_every_load = true ,
action = add_jammer
} )
minetest.register_lbm ( {
name = " moremesecons_wireless:add_wireless " ,
nodenames = { " moremesecons_wireless:wireless " } ,
run_at_every_load = true ,
2017-04-21 13:56:37 +02:00
action = register_wireless
} )
end
2020-04-11 12:45:33 +02:00
-- Legacy
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.log ( " action " , " [moremesecons_wireless] Migrating mod storage data... " )
local jammers_1 = minetest.deserialize ( storage : get_string ( " jammers " ) )
local get = vector.get_data_from_pos
local set = vector.set_data_to_pos
local remove = vector.remove_data_from_pos
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 , z , y , x ) )
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