189 lines
4.7 KiB
Lua

--[[
ITB (insidethebox) minetest game - Copyright (C) 2017-2018 sofar & nore
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1
of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
]]--
local S = minetest.get_translator("music")
--[[
Music API for itb
--]]
--
-- we require `localmusic` to provide event-to-track mappings
--
assert(localmusic, "localmusic mod missing, required to map events to tracks")
local LOOP = 7 * 60 -- seconds if looping tracks randomly
--
-- cache data
--
local streams = {}
local tracks = {}
--
-- API
--
music = {}
music.track = function(player, track)
minetest.log("action", "playing music track \"" .. track .. "\" to " .. player:get_player_name())
streams[player] = minetest.sound_play(track, {
to_player = player:get_player_name(),
loop = false,
gain = 0.3
})
tracks[player] = track
end
music.stop = function(player)
if streams[player] then
minetest.sound_stop(streams[player])
streams[player] = nil
end
tracks[player] = nil
end
music.loop = function(player, stream, add, track)
if streams[player] ~= stream or not streams[player] then
-- stream was stopped?
return
end
if not tracks[player] or tracks[player] ~= track then
-- somethign else playing?
return
end
music.stop(player)
-- pick a track from add[] and adjust streams
track = add[math.random(1, #add)]
music.track(player, track)
minetest.after(LOOP, music.loop, player, streams[player], add, track)
end
music.start = function(player, info, tag)
-- ignore if music disabled.
music.stop(player)
local pmeta = player:get_meta()
if pmeta:get_string("music") == "0" then
return
end
--TODO use info.box_id to retrieve emblem scoring for a box, then pick emblem tracks.
if not localmusic[tag] then
minetest.log("error", "missing music track mapping for \"" .. tag .. "\"")
else
local track = localmusic[tag]
music.track(player, track)
local add = localmusic[tag .. "_add"]
if add then
minetest.after(LOOP, music.loop, player, streams[player], add, track)
end
end
end
--
-- joinplayer: main lobby?
--
minetest.register_on_joinplayer(function(player)
music.start(player, nil, "join")
end)
local track_by_number = {}
for k, _ in pairs(localmusic) do
if not string.find(k, "_add") then
table.insert(track_by_number, k)
end
end
minetest.register_node("music:jukebox", {
description = S("Jukebox").."\n"..S("Left/right-click to select track"),
tiles = {"jukebox_top.png", "jukebox_top.png", "jukebox_side.png"},
groups = {node = 1, unbreakable = 1, trigger = 1},
sounds = sounds.metal,
on_punch = function(pos, node, puncher, pointed_thing)
local name = puncher:get_player_name()
if not puncher or not boxes.players_editing_boxes[name] then
return
end
local meta = minetest.get_meta(pos)
local track = meta:get_int("track") + 1
if track >= #track_by_number then
track = 0
end
minetest.chat_send_player(name, "track = " .. track_by_number[track + 1])
meta:set_int("track", track)
end,
on_rightclick = function(pos, node, puncher, itemstack, pointed_thing)
local name = puncher:get_player_name()
if not puncher or not boxes.players_editing_boxes[name] then
return
end
local meta = minetest.get_meta(pos)
local track = meta:get_int("track") - 1
if track < 0 then
track = #track_by_number - 1
end
minetest.chat_send_player(name, "track = " .. track_by_number[track + 1])
meta:set_int("track", track)
end,
on_trigger = function(pos)
local box = boxes.find_box(pos)
if not box then
return
end
local p = minetest.get_player_by_name(box.name)
if not p then
return
end
local meta = minetest.get_meta(pos)
local track = meta:get_int("track")
music.start(p, nil, track_by_number[track + 1])
end,
on_untrigger = function(pos)
local box = boxes.find_box(pos)
if not box then
return
end
local p = minetest.get_player_by_name(box.name)
if not p then
return
end
music.stop(p)
end,
on_reveal = function(name, pos)
local meta = minetest.get_meta(pos)
local track = meta:get_int("track")
minetest.chat_send_player(name, minetest.colorize( "#4444ff",
"> track = " .. (track_by_number[track + 1] or "default")))
end,
})