]> git.lizzy.rs Git - minetest.git/commitdiff
Devtest: Add jukebox
authorDesour <vorunbekannt75@web.de>
Wed, 14 Sep 2022 18:02:46 +0000 (20:02 +0200)
committerx2048 <codeforsmile@gmail.com>
Fri, 6 Jan 2023 21:38:35 +0000 (22:38 +0100)
.gitignore
LICENSE.txt
games/devtest/mods/soundstuff/init.lua [new file with mode: 0644]
games/devtest/mods/soundstuff/jukebox.lua [new file with mode: 0644]
games/devtest/mods/soundstuff/mod.conf
games/devtest/mods/soundstuff/sounds/gitignored_sounds/custom_sounds_here.txt [new file with mode: 0644]
games/devtest/mods/soundstuff/textures/soundstuff_jukebox.png [new file with mode: 0644]

index 647b2ed00cabc51cbce40ba95692ede8f4041122..551a34c07ec6139ec899b4761b4bb46d7d47a693 100644 (file)
@@ -43,6 +43,8 @@ build/.cmake/
 /bin/
 /games/*
 !/games/devtest/
+/games/devtest/mods/soundstuff/sounds/gitignored_sounds/*
+!/games/devtest/mods/soundstuff/sounds/gitignored_sounds/custom_sounds_here.txt
 /cache
 /textures/*
 !/textures/base/
index 77228684aba2eda15dfaf9c1a8eb8df042297931..7c30a1d2c83a7c4840b420e172e9698a795c93ad 100644 (file)
@@ -77,6 +77,7 @@ SmallJoker:
   textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
 
 DS:
+  games/devtest/mods/soundstuff/textures/soundstuff_jukebox.png
   games/devtest/mods/testtools/textures/testtools_branding_iron.png
 
 License of Minetest source code
diff --git a/games/devtest/mods/soundstuff/init.lua b/games/devtest/mods/soundstuff/init.lua
new file mode 100644 (file)
index 0000000..07458ae
--- /dev/null
@@ -0,0 +1,4 @@
+
+local path = minetest.get_modpath("soundstuff") .. "/"
+dofile(path .. "sound_event_items.lua")
+dofile(path .. "jukebox.lua")
diff --git a/games/devtest/mods/soundstuff/jukebox.lua b/games/devtest/mods/soundstuff/jukebox.lua
new file mode 100644 (file)
index 0000000..ecba5ba
--- /dev/null
@@ -0,0 +1,323 @@
+local F = minetest.formspec_escape
+
+-- hashed node pos -> sound handle
+local played_sounds = {}
+
+-- all of these can be set via the formspec
+local meta_keys = {
+       -- SimpleSoundSpec
+       "sss.name",
+       "sss.gain",
+       "sss.pitch",
+       "sss.fade",
+       -- sound parameters
+       "sparam.gain",
+       "sparam.pitch",
+       "sparam.fade",
+       "sparam.loop",
+       "sparam.pos",
+       "sparam.object",
+       "sparam.to_player",
+       "sparam.exclude_player",
+       "sparam.max_hear_distance",
+       -- fade
+       "fade.step",
+       "fade.gain",
+       -- other
+       "ephemeral",
+}
+
+local function get_all_metadata(meta)
+       return {
+               sss = {
+                       name  = meta:get_string("sss.name"),
+                       gain  = meta:get_string("sss.gain"),
+                       pitch = meta:get_string("sss.pitch"),
+                       fade  = meta:get_string("sss.fade"),
+               },
+               sparam = {
+                       gain              = meta:get_string("sparam.gain"),
+                       pitch             = meta:get_string("sparam.pitch"),
+                       fade              = meta:get_string("sparam.fade"),
+                       loop              = meta:get_string("sparam.loop"),
+                       pos               = meta:get_string("sparam.pos"),
+                       object            = meta:get_string("sparam.object"),
+                       to_player         = meta:get_string("sparam.to_player"),
+                       exclude_player    = meta:get_string("sparam.exclude_player"),
+                       max_hear_distance = meta:get_string("sparam.max_hear_distance"),
+               },
+               fade = {
+                       gain = meta:get_string("fade.gain"),
+                       step = meta:get_string("fade.step"),
+               },
+               ephemeral = meta:get_string("ephemeral"),
+       }
+end
+
+local function log_msg(msg)
+       minetest.log("action", msg)
+       minetest.chat_send_all(msg)
+end
+
+local function try_call(f, ...)
+       local function log_on_err(success, errmsg, ...)
+               if not success then
+                       log_msg("[soundstuff:jukebox] Call failed: "..errmsg)
+               else
+                       return errmsg, ...
+               end
+       end
+
+       return log_on_err(pcall(f, ...))
+end
+
+local function show_formspec(pos, player)
+       local meta = minetest.get_meta(pos)
+
+       local md = get_all_metadata(meta)
+
+       local pos_hash = minetest.hash_node_position(pos)
+       local sound_handle = played_sounds[pos_hash]
+
+       local fs = {}
+       local function fs_add(str)
+               table.insert(fs, str)
+       end
+
+       fs_add([[
+               formspec_version[6]
+               size[14,11]
+       ]])
+
+       -- SimpleSoundSpec
+       fs_add(string.format([[
+               container[0.5,0.5]
+               box[-0.1,-0.1;4.2,3.2;#EBEBEB20]
+               style[*;font=mono,bold]
+               label[0,0.25;SimpleSoundSpec]
+               style[*;font=mono]
+               field[0.00,1.00;4,0.75;sss.name;name;%s]
+               field[0.00,2.25;1,0.75;sss.gain;gain;%s]
+               field[1.25,2.25;1,0.75;sss.pitch;pitch;%s]
+               field[2.50,2.25;1,0.75;sss.fade;fade;%s]
+               container_end[]
+               field_close_on_enter[sss.name;false]
+               field_close_on_enter[sss.gain;false]
+               field_close_on_enter[sss.pitch;false]
+               field_close_on_enter[sss.fade;false]
+       ]], F(md.sss.name), F(md.sss.gain), F(md.sss.pitch), F(md.sss.fade)))
+
+       -- sound parameter table
+       fs_add(string.format([[
+               container[5.5,0.5]
+               box[-0.1,-0.1;4.2,10.2;#EBEBEB20]
+               style[*;font=mono,bold]
+               label[0,0.25;sound parameter table]
+               style[*;font=mono]
+               field[0.00,1;1,0.75;sparam.gain;gain;%s]
+               field[1.25,1;1,0.75;sparam.pitch;pitch;%s]
+               field[2.50,1;1,0.75;sparam.fade;fade;%s]
+               field[0,2.25;4,0.75;sparam.loop;loop;%s]
+               field[0,3.50;4,0.75;sparam.pos;pos;%s]
+               field[0,4.75;4,0.75;sparam.object;object;%s]
+               field[0,6.00;4,0.75;sparam.to_player;to_player;%s]
+               field[0,7.25;4,0.75;sparam.exclude_player;exclude_player;%s]
+               field[0,8.50;4,0.75;sparam.max_hear_distance;max_hear_distance;%s]
+               container_end[]
+               field_close_on_enter[sparam.gain;false]
+               field_close_on_enter[sparam.pitch;false]
+               field_close_on_enter[sparam.fade;false]
+               field_close_on_enter[sparam.loop;false]
+               field_close_on_enter[sparam.pos;false]
+               field_close_on_enter[sparam.object;false]
+               field_close_on_enter[sparam.to_player;false]
+               field_close_on_enter[sparam.exclude_player;false]
+               field_close_on_enter[sparam.max_hear_distance;false]
+               tooltip[sparam.object;Get a name with the Branding Iron.]
+       ]], F(md.sparam.gain), F(md.sparam.pitch), F(md.sparam.fade), F(md.sparam.loop),
+                       F(md.sparam.pos), F(md.sparam.object), F(md.sparam.to_player),
+                       F(md.sparam.exclude_player), F(md.sparam.max_hear_distance)))
+
+       -- fade
+       fs_add(string.format([[
+               container[10.75,3]
+               box[-0.1,-0.1;3.2,3.2;#EBEBEB20]
+               style[*;font=mono,bold]
+               label[0,0.25;fade]
+               style[*;font=mono]
+               field[0.00,1;1,0.75;fade.step;step;%s]
+               field[1.25,1;1,0.75;fade.gain;gain;%s]
+       ]], F(md.fade.step), F(md.fade.gain)))
+       if not sound_handle then
+               fs_add([[
+                       box[0,2;3,0.75;#363636FF]
+                       label[0.25,2.375;no sound]
+               ]])
+       else
+               fs_add([[
+                       button[0,2;3,0.75;btn_fade;Fade]
+               ]])
+       end
+       fs_add([[
+               container_end[]
+               field_close_on_enter[fade.step;false]
+               field_close_on_enter[fade.gain;false]
+       ]])
+
+       -- ephemeral
+       fs_add(string.format([[
+               checkbox[0.5,5;ephemeral;ephemeral;%s]
+       ]], md.ephemeral))
+
+       -- play/stop and release buttons
+       if not sound_handle then
+               fs_add([[
+                       container[10.75,0.5]
+                       button[0,0;3,0.75;btn_play;Play]
+                       container_end[]
+               ]])
+       else
+               fs_add([[
+                       container[10.75,0.5]
+                       button[0,0;3,0.75;btn_stop;Stop]
+                       button[0,1;3,0.75;btn_release;Release]
+                       container_end[]
+               ]])
+       end
+
+       -- save and quit button
+       fs_add([[
+               button_exit[10.75,10;3,0.75;btn_save_quit;Save & Quit]
+       ]])
+
+       minetest.show_formspec(player:get_player_name(), "soundstuff:jukebox@"..pos:to_string(),
+                       table.concat(fs))
+end
+
+minetest.register_node("soundstuff:jukebox", {
+       description = "Jukebox\nAllows to play arbitrary sounds.",
+       tiles = {"soundstuff_jukebox.png"},
+       groups = {dig_immediate = 2},
+
+       on_construct = function(pos)
+               local meta = minetest.get_meta(pos)
+               -- SimpleSoundSpec
+               meta:set_string("sss.name", "")
+               meta:set_string("sss.gain", "")
+               meta:set_string("sss.pitch", "")
+               meta:set_string("sss.fade", "")
+               -- sound parameters
+               meta:set_string("sparam.gain", "")
+               meta:set_string("sparam.pitch", "")
+               meta:set_string("sparam.fade", "")
+               meta:set_string("sparam.loop", "")
+               meta:set_string("sparam.pos", pos:to_string())
+               meta:set_string("sparam.object", "")
+               meta:set_string("sparam.to_player", "")
+               meta:set_string("sparam.exclude_player", "")
+               meta:set_string("sparam.max_hear_distance", "")
+               -- fade
+               meta:set_string("fade.gain", "")
+               meta:set_string("fade.step", "")
+               -- other
+               meta:set_string("ephemeral", "")
+
+               meta:mark_as_private(meta_keys)
+       end,
+
+       on_rightclick = function(pos, _node, clicker, _itemstack, _pointed_thing)
+               show_formspec(pos, clicker)
+       end,
+})
+
+minetest.register_on_player_receive_fields(function(player, formname, fields)
+       if formname:sub(1, 19) ~= "soundstuff:jukebox@" then
+               return false
+       end
+
+       local pos = vector.from_string(formname, 20)
+       if not pos or pos ~= pos:round() then
+               minetest.log("error", "[soundstuff:jukebox] Invalid formname.")
+               return true
+       end
+
+       local meta = minetest.get_meta(pos)
+
+       for _, k in ipairs(meta_keys) do
+               if fields[k] then
+                       meta:set_string(k, fields[k])
+               end
+       end
+       meta:mark_as_private(meta_keys)
+
+       local pos_hash = minetest.hash_node_position(pos)
+       local sound_handle = played_sounds[pos_hash]
+
+       if not sound_handle then
+               if fields.btn_play then
+                       local md = get_all_metadata(meta)
+
+                       local sss = {
+                               name = md.sss.name,
+                               gain  = tonumber(md.sss.gain),
+                               pitch = tonumber(md.sss.pitch),
+                               fade  = tonumber(md.sss.fade),
+                       }
+                       local sparam = {
+                               gain  = tonumber(md.sparam.gain),
+                               pitch = tonumber(md.sparam.pitch),
+                               fade  = tonumber(md.sparam.fade),
+                               loop = minetest.is_yes(md.sparam.loop),
+                               pos = vector.from_string(md.sparam.pos),
+                               object = testtools.get_branded_object(md.sparam.object),
+                               to_player = md.sparam.to_player,
+                               exclude_player = md.sparam.exclude_player,
+                               max_hear_distance = tonumber(md.sparam.max_hear_distance),
+                       }
+                       local ephemeral = minetest.is_yes(md.ephemeral)
+
+                       log_msg(string.format(
+                                       "[soundstuff:jukebox] Playing sound: minetest.sound_play(%s, %s, %s)",
+                                       string.format("{name=\"%s\", gain=%s, pitch=%s, fade=%s}",
+                                                       sss.name, sss.gain, sss.pitch, sss.fade),
+                                       string.format("{gain=%s, pitch=%s, fade=%s, loop=%s, pos=%s, "
+                                               .."object=%s, to_player=\"%s\", exclude_player=\"%s\", max_hear_distance=%s}",
+                                                       sparam.gain, sparam.pitch, sparam.fade, sparam.loop, sparam.pos,
+                                                       sparam.object and "<objref>", sparam.to_player, sparam.exclude_player,
+                                                       sparam.max_hear_distance),
+                                       tostring(ephemeral)))
+
+                       sound_handle = try_call(minetest.sound_play, sss, sparam, ephemeral)
+
+                       played_sounds[pos_hash] = sound_handle
+                       show_formspec(pos, player)
+               end
+
+       else
+               if fields.btn_stop then
+                       log_msg("[soundstuff:jukebox] Stopping sound: minetest.sound_stop(<handle>)")
+
+                       try_call(minetest.sound_stop, sound_handle)
+
+               elseif fields.btn_release then
+                       log_msg("[soundstuff:jukebox] Releasing handle.")
+
+                       played_sounds[pos_hash] = nil
+                       show_formspec(pos, player)
+
+               elseif fields.btn_fade then
+                       local md = get_all_metadata(meta)
+
+                       local step = tonumber(md.fade.step)
+                       local gain = tonumber(md.fade.gain)
+
+                       log_msg(string.format(
+                                       "[soundstuff:jukebox] Fading sound: minetest.sound_fade(<handle>, %s, %s)",
+                                       step, gain))
+
+                       try_call(minetest.sound_fade, sound_handle, step, gain)
+               end
+       end
+
+       return true
+end)
index 2c631e2da62504e5f664aef130372496838cabdc..a6ed6d45004300f41c4789874a26cfd87b1af8de 100644 (file)
@@ -1,2 +1,3 @@
 name = soundstuff
 description = Example items and nodes for testing sound effects
+depends = testtools
diff --git a/games/devtest/mods/soundstuff/sounds/gitignored_sounds/custom_sounds_here.txt b/games/devtest/mods/soundstuff/sounds/gitignored_sounds/custom_sounds_here.txt
new file mode 100644 (file)
index 0000000..f07d44b
--- /dev/null
@@ -0,0 +1,2 @@
+Put your own testing sounds here. The folder is gitignored.
+Using a sound-pack is also possible.
diff --git a/games/devtest/mods/soundstuff/textures/soundstuff_jukebox.png b/games/devtest/mods/soundstuff/textures/soundstuff_jukebox.png
new file mode 100644 (file)
index 0000000..b8c17a6
Binary files /dev/null and b/games/devtest/mods/soundstuff/textures/soundstuff_jukebox.png differ