init, changed a few things for GEIGERnet-Server, added sounds for receiving RDS message

This commit is contained in:
Rainer 2026-02-12 12:41:24 +01:00
commit fe76810459
38 changed files with 1059 additions and 0 deletions

0
.README.md.kate-swp Normal file
View file

7
LICENSE.txt Normal file
View file

@ -0,0 +1,7 @@
Copyright 2019 Serhii "techniX" Mozhaiskyi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

103
README.md Normal file
View file

@ -0,0 +1,103 @@
# Ham Radio
![Ham Radio screenshot](screenshot.png?raw=true)
This mod brings radio transmitters and receivers to the Minetest world.
Dependencies:
```
default
basic_materials?
technic?
digilines?
```
Craft recipes depend of the mods installed.
## Transmitter
Craft a transmitter and place it in the world. Right click on transmitter to open configuration dialog, then set frequency and RDS message.
- Empty frequency turns transmitter off.
- Transmitter information is displayed as info text when player points at it.
- RDS message can be multiline. However, it is transmitted line by line.
- RDS message and frequency can be set via digiline. Also, you can read transmitter configuration via digiline too.
## Beacon
Beacon is a simplified transmitter. After placement it automatically tunes on a random unoccupied frequency from predefined range. Beacon frequency range is determined by `beacon_frequency` setting.
- Beacon frequency is displayed as info text when player points at it.
## Receiver
Handheld receiver is a wielded tool.
- Left click opens configuration dialog to set frequency. Empty string turns receiver off.
- Shift + left click toggles reception of RDS messages.
When receiver is tuned to a frequency where at least one transmitter is present, HUD signal meter bar shows signal power. The signal power depends on distance and direction to the transmitter.
If RDS reception is toggled on, the RDS messages from all transmitters on this frequency are enqueued and will be send one by one as a chat messages to the player with 10 seconds interval. When RDS message queue becomes empty, it refills and starts over again.
## Stationary Receiver
Right click on receiver opens configuration window to set frequency. Receiver displays RDS messages as infotext in the same way as handheld receiver. It does not have signal power meter.
- You can operate the receiver via digiline in the same way as the transmitter.
## Digiline
```lua
-- channel "ham_radio_rds" accepts plain text
digiline.send('ham_radio_rds', 'new RDS message')
-- get transmitter info
digiline.send('ham_radio', { command = 'get' })
-- returns { frequency = 12345, rds_message = 'text' }
-- set frequency
digiline.send('ham_radio', { command = 'set_frequency', value = '12345' })
-- returns { update = 'frequency', success = true/false, message = errorMessage }
-- set RDS message
digiline.send('ham_radio', { command = 'set_rds_message', value = 'new RDS message' })
-- returns { update = 'rds_message', success = true }
-- get receiver info
digiline.send('ham_radio_receiver', { command = 'get' })
-- returns { frequency = 12345, rds_message = 'text' }
-- set receiver frequency
digiline.send('ham_radio_receiver', { command = 'set_frequency', value = '12345' })
-- returns { update = 'frequency', success = true/false, message = errorMessage }
```
## Config
See `config.lua` to see current parameters. You can edit this file to change them.
Default parameters:
- Frequency range: 0 - 9999999
- Locked frequency range: 100000 - 9999999
- Only one transmitter is allowed for the frequency in this range.
- Beacon frequency range: 1000000 - 99999999
- Beacon frequency is auto-assigned from this range.
- Please note, this range overlaps with locked frequency range to ensure each beacon receives unique frequency.
- RDS interval: 10 seconds
- This setting affects handheld receivers only. The interval should be high enough to avoid spamming chat with repeated messages.
- RDS interval for stationary receiver is 5 seconds and can't be changed.
## What's next?
- Place beacons or transmitters anywhere in the world, give frequency to other players and let them search for them
- Pick a frequency which all players can use for their announcements to organize radio bulletin board
- Operate your transmitters with digiline to receive notification on radio
- ???
- PROFIT
## Author and license
(c) techniX 2019
Source code: MIT
Textures: CC BY-SA 3.0
Sounds: cut from "G32-20-Tuning Radio" by craigsmith, CC 0

41
beacon.lua Normal file
View file

@ -0,0 +1,41 @@
minetest.register_node("ham_radio:beacon", {
description = "Radio Beacon",
tiles = {
"ham_radio_transmitter_top.png",
"ham_radio_transmitter_top.png",
"ham_radio_transmitter_side.png",
"ham_radio_transmitter_side.png",
"ham_radio_transmitter_side.png",
"ham_radio_beacon_front.png"
},
groups = {cracky=2,oddly_breakable_by_hand=2},
sounds = default.node_sound_metal_defaults(),
paramtype2 = "facedir",
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
},
light_source = 3,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
if minetest.is_player(placer) then
local name = placer:get_player_name()
meta:set_string('operated_by', name)
ham_radio.play_tuning_sound(placer)
end
meta:set_string("frequency", ham_radio.find_free_frequency(ham_radio.settings.beacon_frequency))
ham_radio.transmitter_update_infotext(meta)
ham_radio.save_transmitter(pos, meta)
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
local name = player:get_player_name()
return inv:is_empty("main") and not minetest.is_protected(pos, name)
end,
after_dig_node = function(pos, oldnode, oldmetadata, player)
ham_radio.delete_transmitter(pos)
end,
});

32
config.lua Normal file
View file

@ -0,0 +1,32 @@
ham_radio.settings = {
-- color of RDS messages
rds_color = '#4863A0',
-- interval between RDS messages (seconds)
rds_interval = 10,
-- receiver hud position
hud_pos = { x = 0.5, y = 0.8 },
-- hud message color
hud_color = {
active = "0xFCAD00",
inactive = "0x999999"
},
-- radio frequency range
frequency = {
min = 100000,
max = 999999
},
-- range where only one transmitter is permitted
locked_frequency = {
min = 200000,
max = 999999
},
-- sub-range of locked frequency range
beacon_frequency = {
min = 500000,
max = 999999
},
-- digiline config
digiline_channel = "ham_radio",
digiline_rds_channel = "ham_radio_rds",
digiline_receiver_channel = "ham_radio_receiver",
}

67
craft.lua Normal file
View file

@ -0,0 +1,67 @@
local circuit = 'default:mese_crystal'
local body = 'default:steel_ingot'
local wires = 'default:copper_ingot'
local glass = 'default:glass'
local antenna = wires
local battery = 'default:mese_crystal'
if minetest.get_modpath("basic_materials") then
circuit = 'basic_materials:ic'
body = 'basic_materials:plastic_sheet'
wires = 'basic_materials:copper_wire'
antenna = wires
battery = 'basic_materials:energy_crystal_simple'
end
if minetest.get_modpath("technic") then
antenna = 'technic:copper_coil'
battery = 'technic:battery'
end
minetest.register_craftitem("ham_radio:circuit", {
description = "Radio Circuit",
inventory_image = "ham_radio_circuit.png",
})
minetest.register_craft({
output = "ham_radio:circuit",
recipe = {
{circuit, wires, circuit},
{body, battery, body},
}
})
minetest.register_craft({
output = "ham_radio:handheld_receiver",
recipe = {
{'', antenna, ''},
{'','ham_radio:circuit', ''},
{body, body, body}
}
})
minetest.register_craft({
output = "ham_radio:receiver",
recipe = {
{body, antenna, body},
{glass,'ham_radio:circuit', glass},
{body, body, body}
}
})
minetest.register_craft({
output = "ham_radio:transmitter",
recipe = {
{wires, antenna, wires},
{glass, 'ham_radio:circuit', glass},
{body, body, body}
}
})
minetest.register_craft({
output = "ham_radio:beacon",
recipe = {
{antenna, body},
{wires, 'ham_radio:circuit'},
}
})

4
depends.txt Normal file
View file

@ -0,0 +1,4 @@
default
basic_materials?
technic?
digilines?

93
digiline.lua Normal file
View file

@ -0,0 +1,93 @@
ham_radio.digiline_effector_transmitter = function(pos, _, channel, msg)
-- static channels for transmitter
local command_channel = ham_radio.settings.digiline_channel
local rds_channel = ham_radio.settings.digiline_rds_channel
if channel ~= command_channel and channel ~= rds_channel then
return
end
local meta = minetest.get_meta(pos)
-- RDS channel - text message
if channel == rds_channel then
if type(msg) == "string" then
meta:set_string("rds_message", msg)
ham_radio.transmitter_update_infotext(meta)
ham_radio.save_transmitter(pos, meta)
end
return
end
-- command channel
if type(msg) ~= "table" then
return
end
if msg.command == "get" then
digilines.receptor_send(pos, digilines.rules.default, command_channel, {
frequency = meta:get_string("frequency"),
rds_message = meta:get_string("rds_message"),
})
elseif msg.command == "frequency" or msg.command == "set_frequency" then
local new_frequency = msg.value
local validate = ham_radio.validate_frequency(new_frequency)
if validate.result then
meta:set_string("frequency", new_frequency)
ham_radio.transmitter_update_infotext(meta)
ham_radio.save_transmitter(pos, meta)
end
digilines.receptor_send(pos, digilines.rules.default, command_channel, {
update = 'frequency',
success = validate.result,
message = validate.message
})
elseif msg.command == "rds" or msg.command == "message" or msg.command == "rds_message" or msg.command == "set_rds_message" then
meta:set_string("rds_message", msg.value)
ham_radio.transmitter_update_infotext(meta)
ham_radio.save_transmitter(pos, meta)
digilines.receptor_send(pos, digilines.rules.default, command_channel, {
update = 'rds_message',
success = true
})
end
end
ham_radio.digiline_effector_receiver = function(pos, _, channel, msg)
-- static channel for receiver
local command_channel = ham_radio.settings.digiline_receiver_channel
if channel ~= command_channel or type(msg) ~= "table" then
return
end
local meta = minetest.get_meta(pos)
if msg.command == "get" then
digilines.receptor_send(pos, digilines.rules.default, command_channel, {
frequency = meta:get_string("frequency"),
rds_message = meta:get_string("rds_message"),
})
elseif msg.command == "frequency" or msg.command == "set_frequency" then
local new_frequency = msg.value
local validate = ham_radio.validate_frequency(new_frequency, true)
if validate.result then
meta:set_string("frequency", new_frequency)
-- load new RDS messages
local poshash = minetest.pos_to_string(pos, 0)
ham_radio.receiver_rds[poshash] = ham_radio.get_rds_messages(new_frequency, true)
ham_radio.get_next_rds_message(poshash, meta)
end
digilines.receptor_send(pos, digilines.rules.default, command_channel, {
update = 'frequency',
success = validate.result,
message = validate.message
})
end
end

43
helpers.lua Normal file
View file

@ -0,0 +1,43 @@
function ham_radio.validate_frequency(frequency, is_receiver)
if frequency == "" then
return { result = true, message = '' } -- empty frequency is allowed to disable transmitter/receiver
end
local transmission_is_allowed = true
local num_freq = tonumber(frequency)
local freq = tostring(num_freq)
if is_receiver == nil and next(ham_radio.find_transmitters(frequency)) then
if num_freq >= ham_radio.settings.locked_frequency.min
and num_freq <= ham_radio.settings.locked_frequency.max then
-- transmitter is in locked frequency range
transmission_is_allowed = false
end
end
local result = true
local message = ''
if freq ~= frequency or num_freq ~= math.floor(num_freq) then
result = false
message = 'Error: invalid frequency value.'
elseif num_freq == nil then
result = false
message = 'Error: frequency should be numeric.'
elseif num_freq < ham_radio.settings.frequency.min or num_freq > ham_radio.settings.frequency.max then
result = false
message = 'Error: frequency is out of range.'
elseif transmission_is_allowed == false then
result = false
message = 'Error: frequency is occupied by other transmitter.'
end
return { result = result, message = message }
end
function ham_radio.find_free_frequency(range)
local frequency = -1
while frequency == -1 do
frequency = tostring(math.floor(math.random(range.min, range.max)));
local are_there_transmitters = ham_radio.find_transmitters(frequency)
if next(are_there_transmitters) then
frequency = -1
end
end
return frequency
end

128
hud.lua Normal file
View file

@ -0,0 +1,128 @@
function ham_radio.toggle_hud(player)
local name = player:get_player_name()
local item = player:get_wielded_item()
-- remove hud and RDS if user does not wield a receiver
if item:get_name() ~= "ham_radio:handheld_receiver" then
if ham_radio.is_receiver_wielded[name] then
for hud_id, hud_handler in pairs(ham_radio.playerhuds[name]) do
player:hud_remove(hud_handler)
end
ham_radio.playerhuds[name] = nil
ham_radio.is_receiver_wielded[name] = false
ham_radio.player_rds[name] = nil
end
return false
end
-- if hud is already enabled, pass
if ham_radio.is_receiver_wielded[name] then
return true
end
-- create hud
ham_radio.is_receiver_wielded[name] = true
local hud_pos = ham_radio.settings.hud_pos
local hud_color = ham_radio.settings.hud_color
ham_radio.playerhuds[name] = {
background = player:hud_add({
hud_elem_type = "image",
position = hud_pos,
offset = { x = -250, y = 20 },
text = "ham_radio_hud_bg.png",
scale = { x = 2, y = 2 },
alignment = { x = 1, y = 0 },
}),
frequency = player:hud_add({
hud_elem_type = "text",
text = "",
position = hud_pos,
offset = { x = -220, y = 5 },
alignment = { x = 1, y = 0},
number = hud_color.inactive,
scale= { x = 100, y = 20 },
}),
rds = player:hud_add({
hud_elem_type = "text",
text = "",
position = hud_pos,
offset = { x = 220, y = 5 },
alignment = { x = -1, y = 0},
number = hud_color.inactive,
scale= { x = 100, y = 20 },
}),
signal_meter = player:hud_add({
hud_elem_type = "image",
position = hud_pos,
offset = { x = -220, y = 35 },
text = "ham_radio_hud_indicator_empty.png",
scale = { x = 2, y = 1 },
alignment = { x = 1, y = 0 },
}),
signal_level = player:hud_add({
hud_elem_type = "image",
position = hud_pos,
offset = { x = -220, y = 35 },
text = "ham_radio_hud_indicator_full.png",
scale = { x = 0, y = 1 },
alignment = { x = 1, y = 0 },
})
}
return true
end
function ham_radio:update_hud_display(player)
if not ham_radio.toggle_hud(player) then
return
end
local signal_power = 0
local name = player:get_player_name()
local meta = player:get_wielded_item():get_meta()
local frequency = meta:get_string("frequency")
if frequency ~= nil and frequency ~= "" then
local transmitters = self.find_transmitters(frequency)
for position, transmitter in pairs(transmitters) do
local transmitter_signal = self:locate_transmitter(player, minetest.string_to_pos(position))
if transmitter_signal > signal_power then
-- use max power from transmitters nearby
signal_power = transmitter_signal
end
end
end
local hud_color = ham_radio.settings.hud_color
-- update frequency hud
local frequency_text = "FQ ---"
local frequency_color = hud_color.inactive
if frequency ~= "" then
frequency_text = "FQ "..frequency
frequency_color = hud_color.active
end
player:hud_change(self.playerhuds[name].frequency, "text", frequency_text)
player:hud_change(self.playerhuds[name].frequency, "number", frequency_color)
-- update RDS hud
local rds_text = "RDS off"
local rds_color = hud_color.inactive
if meta:get_string("rds_disabled") == "" then
rds_text = "RDS ON"
rds_color = hud_color.active
end
player:hud_change(self.playerhuds[name].rds, "text", rds_text)
player:hud_change(self.playerhuds[name].rds, "number", rds_color)
-- update signal level hud
player:hud_change(
self.playerhuds[name].signal_level,
"scale",
{ x = signal_power/50 or 0.1, y = 1 } -- x scale should be 0-2
)
end

101
init.lua Normal file
View file

@ -0,0 +1,101 @@
local modpath = minetest.get_modpath("ham_radio")
local mod_storage = minetest.get_mod_storage()
ham_radio = rawget(_G, "ham_radio") or {}
ham_radio = {
playerhuds = {},
player_rds = {},
receiver_rds = {},
is_receiver_wielded = {},
transmitters = {},
}
function ham_radio.find_transmitters(frequency)
local transmitter_list = {}
local all_transmitters = mod_storage:to_table().fields
for key, transmitter_data in pairs(all_transmitters) do
local transmitter = minetest.parse_json(transmitter_data)
if transmitter.frequency == frequency then
transmitter_list[key] = transmitter
end
end
return transmitter_list
end
function ham_radio.save_transmitter(pos, meta)
local transmitter_properties = {
frequency = meta:get_string("frequency"),
rds_message = meta:get_string("rds_message"),
operated_by = meta:get_string("operated_by")
}
local key = minetest.pos_to_string(pos, 0)
mod_storage:set_string(key, minetest.write_json(transmitter_properties)) -- storage
end
function ham_radio.delete_transmitter(pos)
local key = minetest.pos_to_string(pos, 0)
mod_storage:set_string(key, '') -- storage
end
function ham_radio.play_tuning_sound(player)
minetest.sound_play(
{name = "ham_radio_tuning"..math.random(1,5)},
{to_player = player:get_player_name()}
)
end
function ham_radio.play_rds_sound(player)
minetest.sound_play(
{name = "ham_radio_rds_msg"},
{to_player = player:get_player_name()}
)
end
function ham_radio.errormsg(player, message)
minetest.chat_send_player(player:get_player_name(), minetest.colorize("#FCAD00", message))
end
dofile(modpath.."/config.lua")
dofile(modpath.."/helpers.lua")
dofile(modpath.."/craft.lua")
dofile(modpath.."/digiline.lua")
dofile(modpath.."/transmitter.lua")
dofile(modpath.."/receiver.lua")
dofile(modpath.."/beacon.lua")
dofile(modpath.."/rds.lua")
dofile(modpath.."/receiver_station.lua")
dofile(modpath.."/hud.lua")
-- globals
minetest.register_on_newplayer(ham_radio.toggle_hud)
minetest.register_on_joinplayer(ham_radio.toggle_hud)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
ham_radio.is_receiver_wielded[name] = false
ham_radio.playerhuds[name] = nil
end)
local updatetimer = 0
local rds_timer = 0
minetest.register_globalstep(function(dtime)
updatetimer = updatetimer + dtime
rds_timer = rds_timer + dtime
if updatetimer > 0.1 then
local players = minetest.get_connected_players()
for i=1, #players do
ham_radio:update_hud_display(players[i])
end
updatetimer = 0
-- rds update timer
if rds_timer > ham_radio.settings.rds_interval then
for i=1, #players do
ham_radio:update_rds(players[i])
end
rds_timer = 0
end
end
end)

7
mod.conf Normal file
View file

@ -0,0 +1,7 @@
name = ham_radio
description = Adds radio transmitters, beacons, and receivers.
depends = default
optional_depends = basic_materials, technic, digilines
release = 5373
author = techniX
title = Ham Radio

3
patches/README.md Normal file
View file

@ -0,0 +1,3 @@
# jumpdrive_compat
Compat patch for jumpdrive mod to make transmitters and beacons work correctly on jumpdrive ships.

View file

@ -0,0 +1,28 @@
--- compat.lua 2019-12-09 17:28:52.811852063 +0000
+++ compat.lua 2019-12-09 17:29:24.255956113 +0000
@@ -8,6 +8,7 @@
local has_pipeworks_mod = minetest.get_modpath("pipeworks")
local has_beds_mod = minetest.get_modpath("beds")
local has_ropes_mod = minetest.get_modpath("ropes")
+local has_ham_radio_mod = minetest.get_modpath("ham_radio")
dofile(MP.."/compat/travelnet.lua")
dofile(MP.."/compat/locator.lua")
@@ -18,6 +19,7 @@
dofile(MP.."/compat/telemosaic.lua")
dofile(MP.."/compat/beds.lua")
dofile(MP.."/compat/ropes.lua")
+dofile(MP.."/compat/ham_radio.lua")
if has_pipeworks_mod then
dofile(MP.."/compat/teleporttube.lua")
@@ -37,6 +39,9 @@
elseif name == "telemosaic:beacon" or name == "telemosaic:beacon_protected" then
jumpdrive.telemosaic_compat(source_pos, target_pos)
+ elseif (name == "ham_radio:transmitter" or name == "ham_radio:beacon") and has_ham_radio_mod then
+ jumpdrive.ham_radio_compat(source_pos, target_pos)
+
end
end

View file

@ -0,0 +1,7 @@
jumpdrive.ham_radio_compat = function(from, to)
local meta = minetest.get_meta(to)
ham_radio.delete_transmitter(from)
ham_radio.save_transmitter(to, meta)
end

64
rds.lua Normal file
View file

@ -0,0 +1,64 @@
function ham_radio.get_rds_messages(frequency, is_receiver_station)
local transmitters = ham_radio.find_transmitters(frequency)
local rds_messages = {}
for position, transmitter in pairs(transmitters) do
if transmitter.rds_message ~= "" and transmitter.rds_message ~= nil then
for rds_message_line in transmitter.rds_message:gmatch("[^\n]+") do
-- construct message
local message = table.concat({
'[ Radio ] ',
rds_message_line,
}, "")
if is_receiver_station then
message = table.concat({
'[ Radio ] ',
rds_message_line
}, "")
end
table.insert(rds_messages, 1, message)
end
end
end
return rds_messages
end
function ham_radio:update_rds(player)
local name = player:get_player_name()
local item = player:get_wielded_item()
if item:get_name() ~= "ham_radio:handheld_receiver" then
return
end
local meta = item:get_meta()
local frequency = meta:get_string("frequency")
local rds_disabled = meta:get_string("rds_disabled")
if frequency == "" then
return
end
if rds_disabled == "true" then
-- disabled receiving RDS messages
ham_radio.player_rds[name] = nil
return
end
if ham_radio.player_rds[name] == nil then
ham_radio.player_rds[name] = ham_radio.get_rds_messages(frequency)
end
local message = table.remove(ham_radio.player_rds[name])
if message ~= nil then
minetest.chat_send_player(player:get_player_name(), minetest.colorize(ham_radio.settings.rds_color, message))
-- play radio sound
ham_radio.play_rds_sound(player)
-- when all RDS messages are shown, reload them again
if not next(ham_radio.player_rds[name]) then
ham_radio.player_rds[name] = ham_radio.get_rds_messages(frequency)
end
end
end

86
receiver.lua Normal file
View file

@ -0,0 +1,86 @@
minetest.register_tool("ham_radio:handheld_receiver", {
description = "Handheld Radio Receiver",
wield_image = "ham_radio_receiver_handheld.png",
inventory_image = "ham_radio_receiver_handheld.png",
groups = { disable_repair = 1 },
-- left click - change frequency
on_use = function(itemstack, user, pointed_thing)
local keys = user:get_player_control()
local meta = itemstack:get_meta()
if keys.sneak then
-- left click with shift - RDS on/off
local is_rds_disabled = meta:get_string("rds_disabled")
if is_rds_disabled == "" then
meta:set_string("rds_disabled", "true")
else
meta:set_string("rds_disabled", "")
end
return itemstack
end
local frequency = meta:get_string("frequency")
minetest.show_formspec(user:get_player_name(), "ham_radio:configure_handheld_receiver",
table.concat({
"size[3,4]",
"image[1,0;1,1;ham_radio_receiver_handheld.png]",
"field[0.25,2;3,1;frequency;Frequency;",tostring(frequency),"]",
"tooltip[frequency;Integer number ",
ham_radio.settings.frequency.min,"-",
ham_radio.settings.frequency.max, "]",
"button_exit[0,3.5;3,1;;Done]"
},'')
)
return itemstack
end
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "ham_radio:configure_handheld_receiver" or not minetest.is_player(player) then
return false
end
if fields.frequency == nil then
-- form is not sent
return
end
local is_frequency_valid = ham_radio.validate_frequency(fields.frequency, true)
if is_frequency_valid.result == false then
ham_radio.errormsg(player, is_frequency_valid.message)
return false
end
local item = player:get_wielded_item()
local meta = item:get_meta()
meta:set_string("frequency", fields.frequency)
-- play radio sound
ham_radio.play_tuning_sound(player)
-- replace wielded item with new metadata
player:set_wielded_item(item)
-- reset rds messages
ham_radio.player_rds[player:get_player_name()] = nil
return true
end)
function ham_radio:locate_transmitter(player, transmitter_pos)
local player_pos = player:get_pos()
local player_look_vector = player:get_look_dir()
local player_direction = vector.add(player_pos, player_look_vector)
local coeff = 0.9
local distance_to_target = 0
local distance = vector.distance(player_pos, transmitter_pos)
if distance < 3 then
distance_to_target = 100
coeff = 0.99
else
distance_to_target = -0.0000000001*math.pow(distance,3)+0.00000145*math.pow(distance,2)-0.03*distance+100
if distance_to_target < 3 then
distance_to_target = 3
end
end
local distance2 = vector.distance(player_direction, transmitter_pos)
local signal_power = distance - distance2;
-- 0-100
return distance_to_target * coeff + distance_to_target * (1 - coeff) * signal_power;
end

136
receiver_station.lua Normal file
View file

@ -0,0 +1,136 @@
ham_radio.receiver_update_infotext = function(meta, pos)
local frequency = meta:get_string("frequency")
local rds_message = meta:get_string("rds_message")
local display_freq = (frequency ~= "") and frequency or "---"
local infotext = "Radio Receiver [" .. display_freq .. " kHz]"
if rds_message ~= "" then
infotext = infotext .. "\n" .. rds_message
-- play rds receiving sound
minetest.sound_play("ham_radio_rds_msg", {
pos = pos,
max_hear_distance = 8,
gain = 0.8,
})
end
meta:set_string("infotext", infotext)
end
minetest.register_node("ham_radio:receiver", {
description = "Ham Radio Receiver",
tiles = {
"ham_radio_receiver_top.png",
"ham_radio_receiver_top.png",
"ham_radio_receiver_side.png",
"ham_radio_receiver_side.png",
"ham_radio_receiver_side.png",
"ham_radio_receiver_front.png"
},
groups = {cracky=2,oddly_breakable_by_hand=2},
sounds = default.node_sound_metal_defaults(),
paramtype2 = "facedir",
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
},
light_source = 3,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
local name = placer:get_player_name()
meta:set_string("formspec",
table.concat({
"size[7,4]",
"image[0,0;1,1;ham_radio_receiver_front.png]",
"field[0.25,2;7,1;frequency;Frequency;${frequency}]",
"tooltip[frequency;Integer number ",
ham_radio.settings.frequency.min,"-",
ham_radio.settings.frequency.max, "]",
"button_exit[2,3.5;3,1;;Done]"
},'')
)
meta:set_string("infotext", 'Radio Receiver')
end,
on_receive_fields = function(pos, formname, fields, sender)
if not minetest.is_player(sender) then
return
end
if (
fields.quit ~= "true"
or minetest.is_protected(pos, sender:get_player_name())
) then
return
end
if fields.frequency ~= nil then
local is_frequency_valid = ham_radio.validate_frequency(fields.frequency, true)
if is_frequency_valid.result == false then
ham_radio.errormsg(sender, is_frequency_valid.message)
else
local meta = minetest.get_meta(pos)
meta:set_string("frequency", fields.frequency)
meta:set_string("rds_message", "")
ham_radio.reset_receiver(pos)
ham_radio.receiver_update_infotext(meta)
ham_radio.play_tuning_sound(sender)
end
end
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
local name = player:get_player_name()
return inv:is_empty("main") and not minetest.is_protected(pos, name)
end,
-- digiline
digiline = {
receptor = {action = function() end},
effector = {
action = ham_radio.digiline_effector_receiver
},
},
});
ham_radio.reset_receiver = function (pos)
local poshash = minetest.pos_to_string(pos, 0)
ham_radio.receiver_rds[poshash] = nil
end
minetest.register_abm(
{
label = "Listen Ham Radion Broadcast",
nodenames = {"ham_radio:receiver"},
interval = 10,
chance = 1,
catch_up = false,
action = function(pos, node)
local meta = minetest.get_meta(pos)
local frequency = meta:get_string("frequency")
if frequency == "" then
return
end
local poshash = minetest.pos_to_string(pos, 0)
if ham_radio.receiver_rds[poshash] == nil or not next(ham_radio.receiver_rds[poshash]) then
-- when all RDS messages are shown, reload them again
ham_radio.receiver_rds[poshash] = ham_radio.get_rds_messages(frequency, true)
end
ham_radio.get_next_rds_message(poshash, meta, pos)
end
}
);
ham_radio.get_next_rds_message = function (poshash, meta, pos)
local message = table.remove(ham_radio.receiver_rds[poshash])
if message ~= nil then
meta:set_string('rds_message', message)
ham_radio.receiver_update_infotext(meta, pos)
end
end

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

109
transmitter.lua Normal file
View file

@ -0,0 +1,109 @@
ham_radio.transmitter_update_infotext = function(meta)
local operated_by = meta:get_string("operated_by")
local frequency = meta:get_string("frequency")
local rds_message = meta:get_string("rds_message")
if frequency == "" then
frequency = "--"
rds_message = ""
end
local infotext = {
'Radio Transmitter\n',
'Operated by: ', operated_by, '\n',
'Frequency: ', frequency
}
if rds_message ~= "" then
table.insert(infotext, '\nRDS message: "')
table.insert(infotext, rds_message)
table.insert(infotext, '"')
end
meta:set_string("infotext", table.concat(infotext, ''))
end
minetest.register_node("ham_radio:transmitter", {
description = "Radio Transmitter",
tiles = {
"ham_radio_transmitter_top.png",
"ham_radio_transmitter_top.png",
"ham_radio_transmitter_side.png",
"ham_radio_transmitter_side.png",
"ham_radio_transmitter_side.png",
"ham_radio_transmitter_front.png"
},
groups = {cracky=2,oddly_breakable_by_hand=2},
sounds = default.node_sound_metal_defaults(),
paramtype2 = "facedir",
light_source = 3,
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
local name = placer:get_player_name()
meta:set_string('operated_by', name)
meta:set_string('rds_message', "")
meta:set_string("formspec",
table.concat({
"size[7,8]",
"image[0,0;1,1;ham_radio_transmitter_front.png]",
"label[1,0;Transmitter operated by: ",minetest.formspec_escape(name),"]",
"field[0.25,2;7,1;frequency;Frequency;${frequency}]",
"tooltip[frequency;Integer number ",
ham_radio.settings.frequency.min,"-",
ham_radio.settings.frequency.max, "]",
"textarea[0.25,3.5;7,4;rds_message;RDS message;${rds_message}]",
"button_exit[2,7.5;3,1;;Done]"
},'')
)
ham_radio.transmitter_update_infotext(meta)
end,
on_receive_fields = function(pos, formname, fields, sender)
if not minetest.is_player(sender) then
return
end
if (
fields.quit ~= "true"
or minetest.is_protected(pos, sender:get_player_name())
) then
return
end
local meta = minetest.get_meta(pos)
local transmitter_is_updated = false
if fields.frequency ~= nil and fields.frequency ~= meta:get_string("frequency") then
local is_frequency_valid = ham_radio.validate_frequency(fields.frequency)
if is_frequency_valid.result == false then
ham_radio.errormsg(sender, is_frequency_valid.message)
else
meta:set_string("frequency", fields.frequency)
transmitter_is_updated = true
end
end
if fields.rds_message ~= nil and fields.rds_message ~= meta:get_string("rds_message") then
meta:set_string("rds_message", fields.rds_message)
transmitter_is_updated = true
end
if transmitter_is_updated then
ham_radio.transmitter_update_infotext(meta)
ham_radio.save_transmitter(pos, meta)
ham_radio.play_tuning_sound(sender)
end
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
local name = player:get_player_name()
return inv:is_empty("main") and not minetest.is_protected(pos, name)
end,
after_dig_node = function(pos, oldnode, oldmetadata, player)
ham_radio.delete_transmitter(pos)
end,
-- digiline
digiline = {
receptor = {action = function() end},
effector = {
action = ham_radio.digiline_effector_transmitter
},
},
});