diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/beacon.lua b/beacon.lua index 1275a7b..e112388 100644 --- a/beacon.lua +++ b/beacon.lua @@ -1,3 +1,37 @@ +local mod_storage = minetest.get_mod_storage() +local beacon_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 Beacon\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 + +local function save_beacon(pos, meta) + local transmitter_properties = { + frequency = meta:get_string("frequency"), + rds_message = meta:get_string("rds_message"), + operated_by = meta:get_string("operated_by"), + handheld = false, + is_beacon = true + } + local key = minetest.pos_to_string(pos, 0) + mod_storage:set_string(key, minetest.write_json(transmitter_properties)) -- storage +end + minetest.register_node("ham_radio:beacon", { description = "Radio Beacon", tiles = { @@ -8,7 +42,39 @@ minetest.register_node("ham_radio:beacon", { "ham_radio_transmitter_side.png", "ham_radio_beacon_front.png" }, - use_texture_alpha = "clip", + 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 + local gpsbutton = false + if(fields.engps == "Enable GPS") then + gpsbutton = true + end + + meta:set_string("GPS_enabled", "false") + meta:set_string("rds_message" , "This is a beacon at: GPS is disabled") + if gpsbutton == true then + meta:set_string("GPS_enabled", "true") + meta:set_string("rds_message", "This is a beacon at:" .. minetest.pos_to_string(pos)) + end + transmitter_is_updated = true + + if transmitter_is_updated then + beacon_update_infotext(meta) + save_beacon(pos, meta) + ham_radio.play_tuning_sound(sender) + end + end, groups = {cracky=2,oddly_breakable_by_hand=2}, sounds = default.node_sound_metal_defaults(), paramtype2 = "facedir", @@ -21,14 +87,31 @@ minetest.register_node("ham_radio:beacon", { light_source = 3, after_place_node = function(pos, placer) local meta = minetest.get_meta(pos); + local name = "anonymous" if minetest.is_player(placer) then - local name = placer:get_player_name() + name = placer:get_player_name() + if name == "" then + name = "anonymous" + end 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) + local freq = ham_radio.find_free_frequency(ham_radio.settings.beacon_frequency) + meta:set_string("frequency", freq) + meta:set_string("rds_message" , "This is a beacon at: GPS is disabled") + meta:set_string("GPS_enabled", "false") + meta:set_string("formspec", + table.concat({ + "size[7,6]", + "image[0.25,-1;4,4;ham_radio_beacon_front.png]", + "label[0.25,0;Beacon operated by: ",minetest.formspec_escape(name),"]", + "label[0.25,2.75;Frequency: ", minetest.formspec_escape(freq), "]", + "button_exit[2,4;3,1;engps;Disable GPS]", + "button_exit[2,5;3,1;engps;Enable GPS]" + },'') + ) + beacon_update_infotext(meta) + save_beacon(pos, meta) end, can_dig = function(pos,player) local meta = minetest.get_meta(pos); diff --git a/config.lua b/config.lua index 7db8ab8..70cba15 100644 --- a/config.lua +++ b/config.lua @@ -29,4 +29,5 @@ ham_radio.settings = { digiline_channel = "ham_radio", digiline_rds_channel = "ham_radio_rds", digiline_receiver_channel = "ham_radio_receiver", + digiline_scanner_channel = "ham_radio_scanner", } diff --git a/craft.lua b/craft.lua index 849d892..2b30562 100644 --- a/craft.lua +++ b/craft.lua @@ -40,6 +40,15 @@ minetest.register_craft({ } }) +minetest.register_craft({ + output = "ham_radio:handheld_transmitter", + recipe = { + {antenna, antenna, antenna}, + {'ham_radio:circuit','ham_radio:circuit', 'ham_radio:circuit'}, + {body, body, body} + } +}) + minetest.register_craft({ output = "ham_radio:receiver", recipe = { @@ -49,6 +58,16 @@ minetest.register_craft({ } }) + +minetest.register_craft({ + output = "ham_radio:scanner", + recipe = { + {antenna, antenna, antenna}, + {'ham_radio:circuit',antenna, 'ham_radio:circuit'}, + {body, body, body} + } +}) + minetest.register_craft({ output = "ham_radio:transmitter", recipe = { diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..06ffbfd --- /dev/null +++ b/depends.txt @@ -0,0 +1,4 @@ +default +basic_materials? +technic? +digilines? \ No newline at end of file diff --git a/digiline.lua b/digiline.lua index 91fc776..3a96087 100644 --- a/digiline.lua +++ b/digiline.lua @@ -1,13 +1,28 @@ 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 + -- static channels for transmitter + local meta = minetest.get_meta(pos) + + local rds_channel = meta:get_string("digiline_channel_rds") + local command_channel = meta:get_string("digiline_channel_command") + + if rds_channel == nil or rds_channel == "" then + rds_channel = ham_radio.settings.digiline_rds_channel + end + + if command_channel == nil or command_channel == "" then + command_channel = ham_radio.settings.digiline_channel + end + if meta:get_string("digiline_channel_command") ~= "" and meta:get_string("digiline_channel_command") ~= nil then + command_channel = meta:get_string("digiline_channel_command") + end + if meta:get_string("digiline_channel_rds") ~= "" and meta:get_string("digiline_channel_rds") ~= nil then + rds_channel = meta:get_string("digiline_channel_rds") + end 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 @@ -59,18 +74,24 @@ end ham_radio.digiline_effector_receiver = function(pos, _, channel, msg) -- static channel for receiver + local meta = minetest.get_meta(pos) + local command_channel = ham_radio.settings.digiline_receiver_channel + local block_command_channel = meta:get_string("digiline_channel_command") + if block_command_channel ~= "" and block_command_channel ~= nil then + command_channel = block_command_channel + end 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"), + signal = meta:get_int("signal"), }) elseif msg.command == "frequency" or msg.command == "set_frequency" then @@ -78,6 +99,7 @@ ham_radio.digiline_effector_receiver = function(pos, _, channel, msg) local validate = ham_radio.validate_frequency(new_frequency, true) if validate.result then meta:set_string("frequency", new_frequency) + ham_radio.receiver_update_infotext(meta) -- 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) @@ -90,4 +112,28 @@ ham_radio.digiline_effector_receiver = function(pos, _, channel, msg) }) end +end + +ham_radio.digiline_effector_scanner = function(pos, _, channel, msg) + -- static channel for scanner + local meta = minetest.get_meta(pos) + + local command_channel = ham_radio.settings.digiline_scanner_channel + local block_command_channel = meta:get_string("digiline_channel_command") + + if block_command_channel ~= "" and block_command_channel ~= nil then + command_channel = block_command_channel + end + + if channel ~= command_channel or type(msg) ~= "table" then + return + end + + if msg.command == "get" then + digilines.receptor_send(pos, digilines.rules.default, command_channel, { + active_frequencies = meta:get_string("active_frequencies"), + transmitter_db = minetest.parse_json(meta:get_string("transmitter_db")) + }) + end + end \ No newline at end of file diff --git a/init.lua b/init.lua index 113469a..e89f941 100644 --- a/init.lua +++ b/init.lua @@ -27,7 +27,9 @@ 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") + operated_by = meta:get_string("operated_by"), + handheld = false, + is_beacon = false } local key = minetest.pos_to_string(pos, 0) mod_storage:set_string(key, minetest.write_json(transmitter_properties)) -- storage @@ -54,11 +56,13 @@ dofile(modpath.."/config.lua") dofile(modpath.."/helpers.lua") dofile(modpath.."/craft.lua") dofile(modpath.."/digiline.lua") +dofile(modpath.."/transmitter_station.lua") dofile(modpath.."/transmitter.lua") dofile(modpath.."/receiver.lua") dofile(modpath.."/beacon.lua") dofile(modpath.."/rds.lua") dofile(modpath.."/receiver_station.lua") +dofile(modpath.."/scanning_station.lua") dofile(modpath.."/hud.lua") -- globals diff --git a/mod.conf b/mod.conf index 4aef0d8..c4a667c 100644 --- a/mod.conf +++ b/mod.conf @@ -2,3 +2,6 @@ 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 diff --git a/rds.lua b/rds.lua index 42e3270..201a882 100644 --- a/rds.lua +++ b/rds.lua @@ -6,16 +6,10 @@ function ham_radio.get_rds_messages(frequency, is_receiver_station) for rds_message_line in transmitter.rds_message:gmatch("[^\n]+") do -- construct message local message = table.concat({ - '[ Radio | ', - transmitter.operated_by, - ' ] ', rds_message_line, }, "") if is_receiver_station then message = table.concat({ - '[ ', - transmitter.operated_by, - ' ] ', rds_message_line }, "") end diff --git a/receiver_station.lua b/receiver_station.lua index 4b5b3a7..1fb61b8 100644 --- a/receiver_station.lua +++ b/receiver_station.lua @@ -1,9 +1,9 @@ ham_radio.receiver_update_infotext = function(meta) - local rds_message = meta:get_string("rds_message") - local infotext = 'Radio receiver' - if rds_message ~= "" then - infotext = rds_message - end + local infotext = 'Radio receiver\n' + infotext = infotext .. 'Frequency: ' .. meta:get_string("frequency") .. '\n' + infotext = infotext .. 'Signal: ' .. meta:get_int("signal") .. '\n' + infotext = infotext .. 'Digiline channel: ' .. meta:get_string("digiline_channel_command") .. '\n' + infotext = infotext .. 'Message: ' .. meta:get_string("rds_message") meta:set_string("infotext", infotext) end @@ -17,7 +17,6 @@ minetest.register_node("ham_radio:receiver", { "ham_radio_receiver_side.png", "ham_radio_receiver_front.png" }, - use_texture_alpha = "clip", groups = {cracky=2,oddly_breakable_by_hand=2}, sounds = default.node_sound_metal_defaults(), paramtype2 = "facedir", @@ -31,15 +30,17 @@ minetest.register_node("ham_radio:receiver", { after_place_node = function(pos, placer) local meta = minetest.get_meta(pos); local name = placer:get_player_name() + meta:set_string('digiline_channel_command', ham_radio.settings.digiline_receiver_channel) meta:set_string("formspec", table.concat({ - "size[7,4]", + "size[7,5]", "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]" + "field[0.25,3.5;7,1;command_channel;Digiline command channel;${digiline_channel_command}]", + "button_exit[2,4.5;3,1;;Done]" },'') ) meta:set_string("infotext", 'Radio Receiver') @@ -55,6 +56,11 @@ minetest.register_node("ham_radio:receiver", { ) then return end + + local meta = minetest.get_meta(pos) + if fields.command_channel ~= nil and fields.command_channel ~= "" then + meta:set_string("digiline_channel_command", fields.command_channel) + end if fields.frequency ~= nil then local is_frequency_valid = ham_radio.validate_frequency(fields.frequency, true) @@ -64,11 +70,12 @@ minetest.register_node("ham_radio:receiver", { local meta = minetest.get_meta(pos) meta:set_string("frequency", fields.frequency) meta:set_string("rds_message", "") + meta:set_int("signal", -1) ham_radio.reset_receiver(pos) - ham_radio.receiver_update_infotext(meta) ham_radio.play_tuning_sound(sender) end end + ham_radio.receiver_update_infotext(meta) end, can_dig = function(pos,player) local meta = minetest.get_meta(pos); @@ -90,11 +97,32 @@ ham_radio.reset_receiver = function (pos) ham_radio.receiver_rds[poshash] = nil end +local function locate_transmitter(pos, transmitter_pos) + + local coeff = 0.9 + local distance_to_target = 0 + + local distance = vector.distance(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 + + -- 0-100 + return distance_to_target * coeff + distance_to_target * (1 - coeff); +end + + minetest.register_abm( { label = "Listen Ham Radion Broadcast", nodenames = {"ham_radio:receiver"}, - interval = 5, + interval = 1, chance = 1, catch_up = false, action = function(pos, node) @@ -106,6 +134,19 @@ minetest.register_abm( end local poshash = minetest.pos_to_string(pos, 0) + + local signal_power = 0 + local transmitters = ham_radio.find_transmitters(frequency) + for position, transmitter in pairs(transmitters) do + local transmitter_signal = locate_transmitter(pos, minetest.string_to_pos(position)) + if transmitter_signal > signal_power then + -- use max power from transmitters nearby + signal_power = transmitter_signal + end + end + meta:set_int("signal", signal_power) + + 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) @@ -117,8 +158,9 @@ minetest.register_abm( ham_radio.get_next_rds_message = function (poshash, meta) 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) + if message == nil then + message = "No message" end + meta:set_string('rds_message', message) + ham_radio.receiver_update_infotext(meta) end diff --git a/scanning_station.lua b/scanning_station.lua new file mode 100644 index 0000000..1b9dde2 --- /dev/null +++ b/scanning_station.lua @@ -0,0 +1,146 @@ +local mod_storage = minetest.get_mod_storage() +local function tablelength(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count + end + +ham_radio.scanner_update_infotext = function(meta) + local infotext = 'Radio Scanner\n' + infotext = infotext .. 'Active frequencies: ' .. meta:get_int("active_frequencies") .. '\n' + infotext = infotext .. 'Digiline channel: ' .. meta:get_string("digiline_channel_command") .. '\n' + --infotext = infotext .. '\nActive frequencies: ' .. meta:get_string("transmitter_db") + meta:set_string("infotext", infotext) + end + + local function updateform() + return table.concat({ + "size[30,16]", + "image[0,0;1,1;ham_radio_scanner_front.png]", + "field[0.25,2;7,1;command_channel;Digiline command channel;${digiline_channel_command}]", + "textarea[0.25,3;30,13;stations;Stations;${stations_readable}]", + "button_exit[13.5,15;3,1;;Done]" + },'') + end + + minetest.register_node("ham_radio:scanner", { + description = "Ham Radio Scanner", + tiles = { + "ham_radio_scanner_top.png", + "ham_radio_scanner_top.png", + "ham_radio_scanner_side.png", + "ham_radio_scanner_side.png", + "ham_radio_scanner_side.png", + "ham_radio_scanner_front.png" + }, + groups = {cracky=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_metal_defaults(), + paramtype2 = "facedir", + drawtype = "nodebox", + paramtype = "light", + light_source = 3, + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", 'Radio Scanner') + meta:set_string("digiline_channel_command", ham_radio.settings.digiline_scanner_channel) + meta:set_string("formspec", updateform()) + 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) + + if fields.command_channel ~= nil and fields.command_channel ~= "" then + meta:set_string("digiline_channel_command", fields.command_channel) + end + ham_radio.scanner_update_infotext(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, + -- digiline + digiline = { + receptor = {action = function() end}, + effector = { + action = ham_radio.digiline_effector_scanner + }, + }, + }); + + local function locate_transmitter(pos, transmitter_pos) + + local coeff = 0.9 + local distance_to_target = 0 + + local distance = vector.distance(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 + + -- 0-100 + return distance_to_target * coeff + distance_to_target * (1 - coeff); + end + + + minetest.register_abm( + { + label = "Scan Ham Radio Broadcasts", + nodenames = {"ham_radio:scanner"}, + interval = 1, + chance = 1, + catch_up = false, + action = function(pos, node) + local meta = minetest.get_meta(pos) + + local transmitter_db = {} + local all_transmitters = mod_storage:to_table().fields + local readable_stations = "" + local i = 0 + for key, transmitter_data in pairs(all_transmitters) do + local transmitter = minetest.parse_json(transmitter_data) + local transmitter_signal = locate_transmitter(pos, minetest.string_to_pos(key)) + local this_transmitter = { + frequency = transmitter.frequency, + rds_message = transmitter.rds_message, + operated_by = transmitter.operated_by, + handheld = transmitter.handheld, + is_beacon = transmitter.is_beacon, + signal = transmitter_signal} + readable_stations = readable_stations .. "Transmitter " .. tostring(i) .. ":\n" + readable_stations = readable_stations .. " - Frequency:" .. tostring(transmitter.frequency) .. "\n" + readable_stations = readable_stations .. " - RDS message:" .. tostring(transmitter.rds_message) .. "\n" + readable_stations = readable_stations .. " - Operated by:" .. tostring(transmitter.operated_by) .. "\n" + readable_stations = readable_stations .. " - Handheld:" .. tostring(transmitter.handheld) .. "\n" + readable_stations = readable_stations .. " - Is beacon:" .. tostring(transmitter.is_beacon) .. "\n" + table.insert(transmitter_db, this_transmitter) + i = i + 1 + end + local transmitter_db_serialized = minetest.write_json(transmitter_db) + meta:set_string("transmitter_db", transmitter_db_serialized) + local active_frequencies = tablelength(transmitter_db) + meta:set_int("active_frequencies", active_frequencies) + meta:set_string("stations_readable", readable_stations) + meta:set_string("formspec", updateform()) + ham_radio.scanner_update_infotext(meta) + + + end + } + ); \ No newline at end of file diff --git a/textures/ham_radio_scanner_front.png b/textures/ham_radio_scanner_front.png new file mode 100644 index 0000000..0255414 Binary files /dev/null and b/textures/ham_radio_scanner_front.png differ diff --git a/textures/ham_radio_scanner_side.png b/textures/ham_radio_scanner_side.png new file mode 100644 index 0000000..8505c29 Binary files /dev/null and b/textures/ham_radio_scanner_side.png differ diff --git a/textures/ham_radio_scanner_top.png b/textures/ham_radio_scanner_top.png new file mode 100644 index 0000000..3654319 Binary files /dev/null and b/textures/ham_radio_scanner_top.png differ diff --git a/textures/ham_radio_transmitter_handheld.png b/textures/ham_radio_transmitter_handheld.png new file mode 100644 index 0000000..c94fd37 Binary files /dev/null and b/textures/ham_radio_transmitter_handheld.png differ diff --git a/transmitter.lua b/transmitter.lua index 4a00f0f..af128a5 100644 --- a/transmitter.lua +++ b/transmitter.lua @@ -1,109 +1,111 @@ - -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 +local mod_storage = minetest.get_mod_storage() +minetest.register_tool("ham_radio:handheld_transmitter", { + description = "Handheld Radio Transmitter", + wield_image = "ham_radio_transmitter_handheld.png", + inventory_image = "ham_radio_transmitter_handheld.png", + groups = { disable_repair = 1 }, + on_use = function(itemstack, user, pointed_thing) + local meta = itemstack:get_meta() + local frequency = meta:get_string("frequency") + minetest.show_formspec(user:get_player_name(), "ham_radio:configure_handheld_transmitter", + table.concat({ + "size[7,8]", + "image[1,0;1,1;ham_radio_transmitter_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, "]", + "textarea[0.25,3.5;7,4;rds_message;RDS message;This is a handheld transmitter in the hands of " .. minetest.formspec_escape(user:get_player_name()) .. "]", + "button_exit[2,7.2;3,1;;Done]" + },'') + ) + return itemstack end +}) - if ( - fields.quit ~= "true" - or minetest.is_protected(pos, sender:get_player_name()) - ) then +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "ham_radio:configure_handheld_transmitter" 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) + meta:set_string("rds_message", fields.rds_message) + -- 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) - 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 +local function save_transmitter(pos, frequency, rds_message, player_name) + local player = minetest.get_player_by_name(player_name) + local transmitter_properties = { + frequency = frequency, + rds_message = rds_message, + operated_by = player_name, + handheld = true, + is_beacon = false, + ss_pos = pos, + ss_look_vector = player:get_look_dir() + } + local key = minetest.pos_to_string(pos, 0) + if not mod_storage:contains(key) then + mod_storage:set_string(key, minetest.write_json(transmitter_properties)) -- storage + end +end + +local function delete_transmitters(player) + 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.handheld == true then + if transmitter.operated_by == player:get_player_name() then + mod_storage:set_string(key, "") + end + end 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 +local function delete_inactive_transmitters() + 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.handheld == true then + if minetest.get_player_by_name(transmitter.operated_by):get_wielded_item():get_name() ~= "ham_radio:handheld_transmitter" then + mod_storage:set_string(key, "") + end + end end +end + - if transmitter_is_updated then - ham_radio.transmitter_update_infotext(meta) - ham_radio.save_transmitter(pos, meta) - ham_radio.play_tuning_sound(sender) + minetest.register_globalstep(function (dtime) + delete_inactive_transmitters() + for _, player in pairs(minetest.get_connected_players()) do + local pos = player:get_pos() + local inv = player:get_inventory() + if player:get_wielded_item():get_name() == "ham_radio:handheld_transmitter" then + local meta = player:get_wielded_item():get_meta() + local frequency = meta:get_string("frequency") + local rds_message = meta:get_string("rds_message") + local player_name = player:get_player_name() + if frequency == "" then + frequency = "1" + end + delete_transmitters(player) + save_transmitter(pos, frequency, rds_message, player_name) + 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, - 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 - }, - }, -}); + end) \ No newline at end of file diff --git a/transmitter_station.lua b/transmitter_station.lua new file mode 100644 index 0000000..bcb2483 --- /dev/null +++ b/transmitter_station.lua @@ -0,0 +1,124 @@ + +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") + local rds_channel = meta:get_string("digiline_channel_rds") + local command_channel = meta:get_string("digiline_channel_command") + if frequency == "" then + frequency = "--" + rds_message = "" + end + local infotext = { + 'Radio Transmitter\n', + 'Operated by: ', operated_by, '\n', + 'Frequency: ', frequency, '\n', + 'Digiline control channel: ', command_channel, '\n', + 'Digiline RDS channel: ', rds_channel, + } + 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('digiline_channel_rds', ham_radio.settings.digiline_rds_channel) + meta:set_string('digiline_channel_command', ham_radio.settings.digiline_channel) + meta:set_string("formspec", + table.concat({ + "size[7,10]", + "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}]", + "field[0.25,7.5;7,1;command_channel;Digiline command channel;${digiline_channel_command}]", + "field[0.25,8.5;7,1;rds_channel;Digiline RDS channel;${digiline_channel_rds}]", + "button_exit[2,9.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.command_channel ~= nil and fields.command_channel ~= "" then + meta:set_string("digiline_channel_command", fields.command_channel) + end + + if fields.rds_channel ~= nil and fields.rds_channel ~= "" then + meta:set_string("digiline_channel_rds", fields.rds_channel) + end + + 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.save_transmitter(pos, meta) + ham_radio.play_tuning_sound(sender) + end + ham_radio.transmitter_update_infotext(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, + -- digiline + digiline = { + receptor = {action = function() end}, + effector = { + action = ham_radio.digiline_effector_transmitter + }, + }, +});