mirror of
https://github.com/minetest/minetest.git
synced 2024-07-04 15:05:27 +02:00
Send sound to players which comes to hear distance.
This commit is contained in:
parent
9ab447843b
commit
0da16f9937
@ -42,6 +42,7 @@ core.features = {
|
|||||||
node_interaction_actor = true,
|
node_interaction_actor = true,
|
||||||
moveresult_new_pos = true,
|
moveresult_new_pos = true,
|
||||||
override_item_remove_fields = true,
|
override_item_remove_fields = true,
|
||||||
|
sounds_updating = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function core.has_feature(arg)
|
function core.has_feature(arg)
|
||||||
|
@ -1101,6 +1101,11 @@ Table used to specify how a sound is played:
|
|||||||
|
|
||||||
-- Available since feature `sound_params_start_time`.
|
-- Available since feature `sound_params_start_time`.
|
||||||
|
|
||||||
|
resend_time = 0.0,
|
||||||
|
-- Approximate playback duration (from `start_time` to end) in seconds.
|
||||||
|
-- This is needed to re-send sounds to new players in hearing distance.
|
||||||
|
-- Unused for looped sounds.
|
||||||
|
|
||||||
loop = false,
|
loop = false,
|
||||||
-- If true, sound is played in a loop.
|
-- If true, sound is played in a loop.
|
||||||
|
|
||||||
@ -1136,10 +1141,10 @@ Table used to specify how a sound is played:
|
|||||||
-- Can't be used together with `to_player`.
|
-- Can't be used together with `to_player`.
|
||||||
|
|
||||||
max_hear_distance = 32,
|
max_hear_distance = 32,
|
||||||
-- Only play for players that are at most this far away when the sound
|
-- Only play for players that are at most this far away.
|
||||||
-- starts playing.
|
|
||||||
-- Needs `pos` or `object` to be set.
|
-- Needs `pos` or `object` to be set.
|
||||||
-- `32` is the default.
|
-- `32` is the default.
|
||||||
|
-- See `sounds_updating`.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -5448,6 +5453,9 @@ Utilities
|
|||||||
moveresult_new_pos = true,
|
moveresult_new_pos = true,
|
||||||
-- Allow removing definition fields in `minetest.override_item`
|
-- Allow removing definition fields in `minetest.override_item`
|
||||||
override_item_remove_fields = true,
|
override_item_remove_fields = true,
|
||||||
|
-- Sounds can be send to players which comes to hear distance.
|
||||||
|
-- Field `resend_time` added to sound parameters. (5.9.0)
|
||||||
|
sounds_updating = true,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -6648,6 +6656,8 @@ Sounds
|
|||||||
------
|
------
|
||||||
|
|
||||||
* `minetest.sound_play(spec, parameters, [ephemeral])`: returns a handle
|
* `minetest.sound_play(spec, parameters, [ephemeral])`: returns a handle
|
||||||
|
* Returned handle is positive number if function sucessufully
|
||||||
|
create sound and `ephernal` if `false`.
|
||||||
* `spec` is a `SimpleSoundSpec`
|
* `spec` is a `SimpleSoundSpec`
|
||||||
* `parameters` is a sound parameter table
|
* `parameters` is a sound parameter table
|
||||||
* `ephemeral` is a boolean (default: false)
|
* `ephemeral` is a boolean (default: false)
|
||||||
|
@ -15,6 +15,7 @@ local meta_keys = {
|
|||||||
"sparam.pitch",
|
"sparam.pitch",
|
||||||
"sparam.fade",
|
"sparam.fade",
|
||||||
"sparam.start_time",
|
"sparam.start_time",
|
||||||
|
"sparam.resend_time",
|
||||||
"sparam.loop",
|
"sparam.loop",
|
||||||
"sparam.pos",
|
"sparam.pos",
|
||||||
"sparam.object",
|
"sparam.object",
|
||||||
@ -40,7 +41,8 @@ local function get_all_metadata(meta)
|
|||||||
gain = meta:get_string("sparam.gain"),
|
gain = meta:get_string("sparam.gain"),
|
||||||
pitch = meta:get_string("sparam.pitch"),
|
pitch = meta:get_string("sparam.pitch"),
|
||||||
fade = meta:get_string("sparam.fade"),
|
fade = meta:get_string("sparam.fade"),
|
||||||
start_time = meta:get_string("sparam.start_time"),
|
start_time = meta:get_string("sparam.start_time"),
|
||||||
|
resend_time = meta:get_string("sparam.resend_time"),
|
||||||
loop = meta:get_string("sparam.loop"),
|
loop = meta:get_string("sparam.loop"),
|
||||||
pos = meta:get_string("sparam.pos"),
|
pos = meta:get_string("sparam.pos"),
|
||||||
object = meta:get_string("sparam.object"),
|
object = meta:get_string("sparam.object"),
|
||||||
@ -88,7 +90,7 @@ local function show_formspec(pos, player)
|
|||||||
|
|
||||||
fs_add([[
|
fs_add([[
|
||||||
formspec_version[6]
|
formspec_version[6]
|
||||||
size[14,12]
|
size[14,13]
|
||||||
]])
|
]])
|
||||||
|
|
||||||
-- SimpleSoundSpec
|
-- SimpleSoundSpec
|
||||||
@ -120,17 +122,19 @@ local function show_formspec(pos, player)
|
|||||||
field[1.25,1;1,0.75;sparam.pitch;pitch;%s]
|
field[1.25,1;1,0.75;sparam.pitch;pitch;%s]
|
||||||
field[2.50,1;1,0.75;sparam.fade;fade;%s]
|
field[2.50,1;1,0.75;sparam.fade;fade;%s]
|
||||||
field[0,2.25;4,0.75;sparam.start_time;start_time;%s]
|
field[0,2.25;4,0.75;sparam.start_time;start_time;%s]
|
||||||
field[0,3.50;4,0.75;sparam.loop;loop;%s]
|
field[0,3.50;4,0.75;sparam.resend_time;resend_time;%s]
|
||||||
field[0,4.75;4,0.75;sparam.pos;pos;%s]
|
field[0,4.75;4,0.75;sparam.loop;loop;%s]
|
||||||
field[0,6.00;4,0.75;sparam.object;object;%s]
|
field[0,6.00;4,0.75;sparam.pos;pos;%s]
|
||||||
field[0,7.25;4,0.75;sparam.to_player;to_player;%s]
|
field[0,7.25;4,0.75;sparam.object;object;%s]
|
||||||
field[0,8.50;4,0.75;sparam.exclude_player;exclude_player;%s]
|
field[0,8.50;4,0.75;sparam.to_player;to_player;%s]
|
||||||
field[0,9.75;4,0.75;sparam.max_hear_distance;max_hear_distance;%s]
|
field[0,9.75;4,0.75;sparam.exclude_player;exclude_player;%s]
|
||||||
|
field[0,11.00;4,0.75;sparam.max_hear_distance;max_hear_distance;%s]
|
||||||
container_end[]
|
container_end[]
|
||||||
field_close_on_enter[sparam.gain;false]
|
field_close_on_enter[sparam.gain;false]
|
||||||
field_close_on_enter[sparam.pitch;false]
|
field_close_on_enter[sparam.pitch;false]
|
||||||
field_close_on_enter[sparam.fade;false]
|
field_close_on_enter[sparam.fade;false]
|
||||||
field_close_on_enter[sparam.start_time;false]
|
field_close_on_enter[sparam.start_time;false]
|
||||||
|
field_close_on_enter[sparam.resend_time;false]
|
||||||
field_close_on_enter[sparam.loop;false]
|
field_close_on_enter[sparam.loop;false]
|
||||||
field_close_on_enter[sparam.pos;false]
|
field_close_on_enter[sparam.pos;false]
|
||||||
field_close_on_enter[sparam.object;false]
|
field_close_on_enter[sparam.object;false]
|
||||||
@ -139,7 +143,8 @@ local function show_formspec(pos, player)
|
|||||||
field_close_on_enter[sparam.max_hear_distance;false]
|
field_close_on_enter[sparam.max_hear_distance;false]
|
||||||
tooltip[sparam.object;Get a name with the Branding Iron.]
|
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.gain), F(md.sparam.pitch), F(md.sparam.fade),
|
||||||
F(md.sparam.start_time), F(md.sparam.loop), F(md.sparam.pos),
|
F(md.sparam.start_time), F(md.sparam.resend_time),
|
||||||
|
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.object), F(md.sparam.to_player), F(md.sparam.exclude_player),
|
||||||
F(md.sparam.max_hear_distance)))
|
F(md.sparam.max_hear_distance)))
|
||||||
|
|
||||||
@ -192,7 +197,7 @@ local function show_formspec(pos, player)
|
|||||||
|
|
||||||
-- save and quit button
|
-- save and quit button
|
||||||
fs_add([[
|
fs_add([[
|
||||||
button_exit[10.75,11;3,0.75;btn_save_quit;Save & Quit]
|
button_exit[10.75,11.5;3,0.75;btn_save_quit;Save & Quit]
|
||||||
]])
|
]])
|
||||||
|
|
||||||
minetest.show_formspec(player:get_player_name(), "soundstuff:jukebox@"..pos:to_string(),
|
minetest.show_formspec(player:get_player_name(), "soundstuff:jukebox@"..pos:to_string(),
|
||||||
@ -216,6 +221,7 @@ minetest.register_node("soundstuff:jukebox", {
|
|||||||
meta:set_string("sparam.pitch", "")
|
meta:set_string("sparam.pitch", "")
|
||||||
meta:set_string("sparam.fade", "")
|
meta:set_string("sparam.fade", "")
|
||||||
meta:set_string("sparam.start_time", "")
|
meta:set_string("sparam.start_time", "")
|
||||||
|
meta:set_string("sparam.resend_time", "")
|
||||||
meta:set_string("sparam.loop", "")
|
meta:set_string("sparam.loop", "")
|
||||||
meta:set_string("sparam.pos", pos:to_string())
|
meta:set_string("sparam.pos", pos:to_string())
|
||||||
meta:set_string("sparam.object", "")
|
meta:set_string("sparam.object", "")
|
||||||
@ -274,6 +280,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
pitch = tonumber(md.sparam.pitch),
|
pitch = tonumber(md.sparam.pitch),
|
||||||
fade = tonumber(md.sparam.fade),
|
fade = tonumber(md.sparam.fade),
|
||||||
start_time = tonumber(md.sparam.start_time),
|
start_time = tonumber(md.sparam.start_time),
|
||||||
|
resend_time = tonumber(md.sparam.resend_time),
|
||||||
loop = minetest.is_yes(md.sparam.loop),
|
loop = minetest.is_yes(md.sparam.loop),
|
||||||
pos = vector.from_string(md.sparam.pos),
|
pos = vector.from_string(md.sparam.pos),
|
||||||
object = testtools.get_branded_object(md.sparam.object),
|
object = testtools.get_branded_object(md.sparam.object),
|
||||||
@ -287,9 +294,10 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
"[soundstuff:jukebox] Playing sound: minetest.sound_play(%s, %s, %s)",
|
"[soundstuff:jukebox] Playing sound: minetest.sound_play(%s, %s, %s)",
|
||||||
string.format("{name=\"%s\", gain=%s, pitch=%s, fade=%s}",
|
string.format("{name=\"%s\", gain=%s, pitch=%s, fade=%s}",
|
||||||
sss.name, sss.gain, sss.pitch, sss.fade),
|
sss.name, sss.gain, sss.pitch, sss.fade),
|
||||||
string.format("{gain=%s, pitch=%s, fade=%s, start_time=%s, loop=%s, pos=%s, "
|
string.format("{gain=%s, pitch=%s, fade=%s, start_time=%s, resend_time=%s, loop=%s, pos=%s, "
|
||||||
.."object=%s, to_player=\"%s\", exclude_player=\"%s\", max_hear_distance=%s}",
|
.."object=%s, to_player=\"%s\", exclude_player=\"%s\", max_hear_distance=%s}",
|
||||||
sparam.gain, sparam.pitch, sparam.fade, sparam.start_time,
|
sparam.gain, sparam.pitch, sparam.fade,
|
||||||
|
sparam.start_time, sparam.resend_time,
|
||||||
sparam.loop, sparam.pos, sparam.object and "<objref>",
|
sparam.loop, sparam.pos, sparam.object and "<objref>",
|
||||||
sparam.to_player, sparam.exclude_player,
|
sparam.to_player, sparam.exclude_player,
|
||||||
sparam.max_hear_distance),
|
sparam.max_hear_distance),
|
||||||
|
@ -1339,10 +1339,39 @@ void Server::handleCommand_RemovedSounds(NetworkPacket* pkt)
|
|||||||
if (i == m_playing_sounds.end())
|
if (i == m_playing_sounds.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
session_t peer_id = pkt->getPeerId();
|
||||||
|
|
||||||
ServerPlayingSound &psound = i->second;
|
ServerPlayingSound &psound = i->second;
|
||||||
psound.clients.erase(pkt->getPeerId());
|
psound.clients.erase(peer_id);
|
||||||
if (psound.clients.empty())
|
verbosestream << "Server: Sound " << id << " erase peer "
|
||||||
|
<< peer_id << "." << std::endl;
|
||||||
|
if (!psound.allow_resend && psound.clients.empty()) {
|
||||||
m_playing_sounds.erase(i);
|
m_playing_sounds.erase(i);
|
||||||
|
verbosestream << "Server: Erase sound " << id << "." << std::endl;
|
||||||
|
}
|
||||||
|
else if (psound.allow_resend && !psound.spec.loop) {
|
||||||
|
if (psound.resend_time < m_playing_sounds_time) {
|
||||||
|
/* Sound resend time reached, done_clients do not need to be updated. */
|
||||||
|
verbosestream << "Server: Done sound " << id << " for peer "
|
||||||
|
<< peer_id << "." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerSAO *plrsao = getPlayerSAO(peer_id);
|
||||||
|
if (!plrsao)
|
||||||
|
continue;
|
||||||
|
bool pos_exists;
|
||||||
|
v3f pos = psound.getPos(m_env, &pos_exists);
|
||||||
|
assert(pos_exists);
|
||||||
|
|
||||||
|
if (pos.getDistanceFrom(plrsao->getBasePosition()) <= psound.max_hear_distance) {
|
||||||
|
/* If client remove sound in hear distance,
|
||||||
|
we are sure, that sound has been fully played. */
|
||||||
|
psound.done_clients.insert(peer_id);
|
||||||
|
verbosestream << "Server: Done sound " << id << " for peer "
|
||||||
|
<< peer_id << "." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1179,6 +1179,7 @@ void read_server_sound_params(lua_State *L, int index,
|
|||||||
getfloatfield(L, index, "fade", params.spec.fade);
|
getfloatfield(L, index, "fade", params.spec.fade);
|
||||||
getfloatfield(L, index, "pitch", params.spec.pitch);
|
getfloatfield(L, index, "pitch", params.spec.pitch);
|
||||||
getfloatfield(L, index, "start_time", params.spec.start_time);
|
getfloatfield(L, index, "start_time", params.spec.start_time);
|
||||||
|
getfloatfield(L, index, "resend_time", params.spec.resend_time);
|
||||||
getboolfield(L, index, "loop", params.spec.loop);
|
getboolfield(L, index, "loop", params.spec.loop);
|
||||||
|
|
||||||
getfloatfield(L, index, "gain", params.gain);
|
getfloatfield(L, index, "gain", params.gain);
|
||||||
|
127
src/server.cpp
127
src/server.cpp
@ -915,6 +915,65 @@ void Server::AsyncRunStep(float dtime, bool initial_step)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send sounds if needed
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
m_playing_sounds_time += dtime;
|
||||||
|
|
||||||
|
MutexAutoLock lock(m_env_mutex);
|
||||||
|
|
||||||
|
ClientInterface::AutoLock clientlock(m_clients);
|
||||||
|
const RemoteClientMap &clients = m_clients.getClientList();
|
||||||
|
|
||||||
|
for (auto it = m_playing_sounds.begin(); it != m_playing_sounds.end(); it++) {
|
||||||
|
ServerPlayingSound &sound = it->second;
|
||||||
|
|
||||||
|
if (!sound.allow_resend)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!sound.spec.loop && (sound.resend_time < m_playing_sounds_time)) {
|
||||||
|
sound.allow_resend = false;
|
||||||
|
verbosestream << "Server: Marking sound " << it->first
|
||||||
|
<< " as expired." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should be never called for sound not attached to pos or object
|
||||||
|
bool pos_exists;
|
||||||
|
v3f pos = sound.getPos(m_env, &pos_exists);
|
||||||
|
assert(pos_exists);
|
||||||
|
|
||||||
|
for (const auto &client_it : clients) {
|
||||||
|
RemoteClient *client = client_it.second;
|
||||||
|
|
||||||
|
if (client->getState() < CS_DefinitionsSent)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PlayerSAO *playersao = getPlayerSAO(client->peer_id);
|
||||||
|
if (!playersao)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sound.clients.find(client->peer_id) != sound.clients.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sound.done_clients.find(client->peer_id) != sound.clients.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!sound.exclude_player.empty() &&
|
||||||
|
sound.exclude_player == client->getName())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pos.getDistanceFrom(playersao->getBasePosition()) <= sound.max_hear_distance) {
|
||||||
|
SendSound(client->peer_id, it->first, sound, pos);
|
||||||
|
sound.clients.insert(client->peer_id);
|
||||||
|
verbosestream << "Server: Sound " << it->first << " add peer "
|
||||||
|
<< client->peer_id << "." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send queued-for-sending map edit events.
|
Send queued-for-sending map edit events.
|
||||||
*/
|
*/
|
||||||
@ -2118,6 +2177,15 @@ void Server::SendActiveObjectMessages(session_t peer_id, const std::string &data
|
|||||||
m_clients.sendCustom(pkt.getPeerId(), reliable ? ccf.channel : 1, &pkt, reliable);
|
m_clients.sendCustom(pkt.getPeerId(), reliable ? ccf.channel : 1, &pkt, reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::SendSound(session_t peer_id, s32 sound_id,
|
||||||
|
const ServerPlayingSound ¶ms, const v3f &pos)
|
||||||
|
{
|
||||||
|
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0, peer_id);
|
||||||
|
createSoundPacket(pkt, sound_id, params, pos);
|
||||||
|
|
||||||
|
Send(&pkt);
|
||||||
|
}
|
||||||
|
|
||||||
void Server::SendCSMRestrictionFlags(session_t peer_id)
|
void Server::SendCSMRestrictionFlags(session_t peer_id)
|
||||||
{
|
{
|
||||||
NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
|
NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
|
||||||
@ -2159,6 +2227,8 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
|||||||
if(pos_exists != (params.type != SoundLocation::Local))
|
if(pos_exists != (params.type != SoundLocation::Local))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
params.allow_resend = pos_exists;
|
||||||
|
|
||||||
// Filter destination clients
|
// Filter destination clients
|
||||||
std::vector<session_t> dst_clients;
|
std::vector<session_t> dst_clients;
|
||||||
if (!params.to_player.empty()) {
|
if (!params.to_player.empty()) {
|
||||||
@ -2169,6 +2239,7 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dst_clients.push_back(player->getPeerId());
|
dst_clients.push_back(player->getPeerId());
|
||||||
|
params.allow_resend = false;
|
||||||
} else {
|
} else {
|
||||||
std::vector<session_t> clients = m_clients.getClientIDs();
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
||||||
|
|
||||||
@ -2193,7 +2264,10 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dst_clients.empty())
|
// lets finish only for ephmeral sounds, non-looped sounds and
|
||||||
|
// sounds without resend_time if no clients in hear distance.
|
||||||
|
if (dst_clients.empty() &&
|
||||||
|
(ephemeral || (params.spec.resend_time == 0 && !params.spec.loop)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// old clients will still use this, so pick a reserved ID (-1)
|
// old clients will still use this, so pick a reserved ID (-1)
|
||||||
@ -2201,23 +2275,27 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
|||||||
if (id == 0)
|
if (id == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
float gain = params.gain * params.spec.gain;
|
params.start_time = m_playing_sounds_time;
|
||||||
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
|
params.resend_time = m_playing_sounds_time + params.spec.resend_time;
|
||||||
pkt << id << params.spec.name << gain
|
|
||||||
<< (u8) params.type << pos << params.object
|
|
||||||
<< params.spec.loop << params.spec.fade << params.spec.pitch
|
|
||||||
<< ephemeral << params.spec.start_time;
|
|
||||||
|
|
||||||
const bool as_reliable = !ephemeral;
|
if (!dst_clients.empty()) {
|
||||||
|
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
|
||||||
|
createSoundPacket(pkt, id, params, pos, ephemeral);
|
||||||
|
|
||||||
for (const session_t peer_id : dst_clients) {
|
const bool as_reliable = !ephemeral;
|
||||||
if (!ephemeral)
|
|
||||||
params.clients.insert(peer_id);
|
for (const session_t peer_id : dst_clients) {
|
||||||
m_clients.sendCustom(peer_id, 0, &pkt, as_reliable);
|
if (!ephemeral)
|
||||||
|
params.clients.insert(peer_id);
|
||||||
|
m_clients.sendCustom(peer_id, 0, &pkt, as_reliable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ephemeral)
|
if (!ephemeral) {
|
||||||
m_playing_sounds[id] = std::move(params);
|
m_playing_sounds[id] = std::move(params);
|
||||||
|
verbosestream << "Server:playSound: Create sound "
|
||||||
|
<< id << "." << std::endl;
|
||||||
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
void Server::stopSound(s32 handle)
|
void Server::stopSound(s32 handle)
|
||||||
@ -2237,6 +2315,9 @@ void Server::stopSound(s32 handle)
|
|||||||
|
|
||||||
// Remove sound reference
|
// Remove sound reference
|
||||||
m_playing_sounds.erase(it);
|
m_playing_sounds.erase(it);
|
||||||
|
|
||||||
|
verbosestream << "Server:stopSound: Stop sound "
|
||||||
|
<< handle << "." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::fadeSound(s32 handle, float step, float gain)
|
void Server::fadeSound(s32 handle, float step, float gain)
|
||||||
@ -2280,17 +2361,33 @@ void Server::stopAttachedSounds(session_t peer_id,
|
|||||||
|
|
||||||
sound.clients.erase(clients_it);
|
sound.clients.erase(clients_it);
|
||||||
// delete if client list empty
|
// delete if client list empty
|
||||||
return sound.clients.empty();
|
return !sound.allow_resend && sound.clients.empty();
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto it = m_playing_sounds.begin(); it != m_playing_sounds.end(); ) {
|
for (auto it = m_playing_sounds.begin(); it != m_playing_sounds.end(); ) {
|
||||||
if (cb(it->first, it->second))
|
if (cb(it->first, it->second)) {
|
||||||
|
// Remove sound reference
|
||||||
|
verbosestream << "Server:stopAttachedSounds: Stop sound "
|
||||||
|
<< it->first << "." << std::endl;
|
||||||
it = m_playing_sounds.erase(it);
|
it = m_playing_sounds.erase(it);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::createSoundPacket(NetworkPacket &pkt, s32 sound_id,
|
||||||
|
const ServerPlayingSound ¶ms, const v3f &pos, bool ephemeral)
|
||||||
|
{
|
||||||
|
float gain = params.gain * params.spec.gain;
|
||||||
|
float start_time = params.spec.start_time +
|
||||||
|
m_playing_sounds_time - params.start_time;
|
||||||
|
pkt << sound_id << params.spec.name << gain
|
||||||
|
<< (u8) params.type << pos << params.object
|
||||||
|
<< params.spec.loop << params.spec.fade << params.spec.pitch
|
||||||
|
<< ephemeral << start_time;
|
||||||
|
}
|
||||||
|
|
||||||
void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
|
void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
|
||||||
float far_d_nodes)
|
float far_d_nodes)
|
||||||
{
|
{
|
||||||
|
13
src/server.h
13
src/server.h
@ -119,6 +119,16 @@ struct ServerPlayingSound
|
|||||||
|
|
||||||
SoundSpec spec;
|
SoundSpec spec;
|
||||||
|
|
||||||
|
// server processing values
|
||||||
|
|
||||||
|
// relative server time when sound has been added
|
||||||
|
// used for update spec.start_time when sending sound to new client
|
||||||
|
float start_time;
|
||||||
|
// hold time limit for sound sending to new clients
|
||||||
|
float resend_time;
|
||||||
|
bool allow_resend = false;
|
||||||
|
|
||||||
|
std::unordered_set<session_t> done_clients; // peer ids
|
||||||
std::unordered_set<session_t> clients; // peer ids
|
std::unordered_set<session_t> clients; // peer ids
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -242,6 +252,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
|||||||
// Stop all sounds attached to given objects, for a certain client
|
// Stop all sounds attached to given objects, for a certain client
|
||||||
void stopAttachedSounds(session_t peer_id,
|
void stopAttachedSounds(session_t peer_id,
|
||||||
const std::vector<u16> &object_ids);
|
const std::vector<u16> &object_ids);
|
||||||
|
void createSoundPacket(NetworkPacket &pkt, s32 sound_id, const ServerPlayingSound ¶ms, const v3f &pos, bool ephemeral = false);
|
||||||
|
|
||||||
// Envlock
|
// Envlock
|
||||||
std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
|
std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
|
||||||
@ -568,6 +579,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
|||||||
void SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao);
|
void SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao);
|
||||||
void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
|
void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
|
||||||
bool reliable = true);
|
bool reliable = true);
|
||||||
|
void SendSound(session_t peer_id, s32 sound_id, const ServerPlayingSound ¶ms, const v3f &pos);
|
||||||
void SendCSMRestrictionFlags(session_t peer_id);
|
void SendCSMRestrictionFlags(session_t peer_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -733,6 +745,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
|||||||
std::unordered_map<s32, ServerPlayingSound> m_playing_sounds;
|
std::unordered_map<s32, ServerPlayingSound> m_playing_sounds;
|
||||||
s32 m_playing_sounds_id_last_used = 0; // positive values only
|
s32 m_playing_sounds_id_last_used = 0; // positive values only
|
||||||
s32 nextSoundId();
|
s32 nextSoundId();
|
||||||
|
float m_playing_sounds_time = 0.0f;
|
||||||
|
|
||||||
ModStorageDatabase *m_mod_storage_database = nullptr;
|
ModStorageDatabase *m_mod_storage_database = nullptr;
|
||||||
float m_mod_storage_save_timer = 10.0f;
|
float m_mod_storage_save_timer = 10.0f;
|
||||||
|
@ -71,6 +71,9 @@ struct SoundSpec
|
|||||||
float fade = 0.0f;
|
float fade = 0.0f;
|
||||||
float pitch = 1.0f;
|
float pitch = 1.0f;
|
||||||
float start_time = 0.0f;
|
float start_time = 0.0f;
|
||||||
|
// keep time defines a time windows, where sound cannot be removed
|
||||||
|
// and can be resend, takes no effect for looped sounds
|
||||||
|
float resend_time = 0.0f;
|
||||||
bool loop = false;
|
bool loop = false;
|
||||||
// If true, a local fallback (ie. from the user's sound pack) is used if the
|
// If true, a local fallback (ie. from the user's sound pack) is used if the
|
||||||
// sound-group does not exist.
|
// sound-group does not exist.
|
||||||
|
Loading…
Reference in New Issue
Block a user