mirror of
https://github.com/minetest/minetest.git
synced 2024-06-30 21:20:36 +02:00
Compare commits
3 Commits
9a1c3d4e65
...
342ed4d665
Author | SHA1 | Date | |
---|---|---|---|
|
342ed4d665 | ||
|
9a1501ae89 | ||
|
0da16f9937 |
@ -42,6 +42,7 @@ core.features = {
|
||||
node_interaction_actor = true,
|
||||
moveresult_new_pos = true,
|
||||
override_item_remove_fields = true,
|
||||
sounds_updating = true,
|
||||
}
|
||||
|
||||
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`.
|
||||
|
||||
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,
|
||||
-- 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`.
|
||||
|
||||
max_hear_distance = 32,
|
||||
-- Only play for players that are at most this far away when the sound
|
||||
-- starts playing.
|
||||
-- Only play for players that are at most this far away.
|
||||
-- Needs `pos` or `object` to be set.
|
||||
-- `32` is the default.
|
||||
-- See `sounds_updating`.
|
||||
}
|
||||
```
|
||||
|
||||
@ -5452,6 +5457,9 @@ Utilities
|
||||
moveresult_new_pos = true,
|
||||
-- Allow removing definition fields in `minetest.override_item`
|
||||
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,
|
||||
}
|
||||
```
|
||||
|
||||
@ -6652,6 +6660,8 @@ Sounds
|
||||
------
|
||||
|
||||
* `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`
|
||||
* `parameters` is a sound parameter table
|
||||
* `ephemeral` is a boolean (default: false)
|
||||
|
@ -15,6 +15,7 @@ local meta_keys = {
|
||||
"sparam.pitch",
|
||||
"sparam.fade",
|
||||
"sparam.start_time",
|
||||
"sparam.resend_time",
|
||||
"sparam.loop",
|
||||
"sparam.pos",
|
||||
"sparam.object",
|
||||
@ -40,7 +41,8 @@ local function get_all_metadata(meta)
|
||||
gain = meta:get_string("sparam.gain"),
|
||||
pitch = meta:get_string("sparam.pitch"),
|
||||
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"),
|
||||
pos = meta:get_string("sparam.pos"),
|
||||
object = meta:get_string("sparam.object"),
|
||||
@ -88,7 +90,7 @@ local function show_formspec(pos, player)
|
||||
|
||||
fs_add([[
|
||||
formspec_version[6]
|
||||
size[14,12]
|
||||
size[14,13]
|
||||
]])
|
||||
|
||||
-- SimpleSoundSpec
|
||||
@ -120,17 +122,19 @@ local function show_formspec(pos, player)
|
||||
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.start_time;start_time;%s]
|
||||
field[0,3.50;4,0.75;sparam.loop;loop;%s]
|
||||
field[0,4.75;4,0.75;sparam.pos;pos;%s]
|
||||
field[0,6.00;4,0.75;sparam.object;object;%s]
|
||||
field[0,7.25;4,0.75;sparam.to_player;to_player;%s]
|
||||
field[0,8.50;4,0.75;sparam.exclude_player;exclude_player;%s]
|
||||
field[0,9.75;4,0.75;sparam.max_hear_distance;max_hear_distance;%s]
|
||||
field[0,3.50;4,0.75;sparam.resend_time;resend_time;%s]
|
||||
field[0,4.75;4,0.75;sparam.loop;loop;%s]
|
||||
field[0,6.00;4,0.75;sparam.pos;pos;%s]
|
||||
field[0,7.25;4,0.75;sparam.object;object;%s]
|
||||
field[0,8.50;4,0.75;sparam.to_player;to_player;%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[]
|
||||
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.start_time;false]
|
||||
field_close_on_enter[sparam.resend_time;false]
|
||||
field_close_on_enter[sparam.loop;false]
|
||||
field_close_on_enter[sparam.pos;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]
|
||||
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.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.max_hear_distance)))
|
||||
|
||||
@ -192,7 +197,7 @@ local function show_formspec(pos, player)
|
||||
|
||||
-- save and quit button
|
||||
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(),
|
||||
@ -216,6 +221,7 @@ minetest.register_node("soundstuff:jukebox", {
|
||||
meta:set_string("sparam.pitch", "")
|
||||
meta:set_string("sparam.fade", "")
|
||||
meta:set_string("sparam.start_time", "")
|
||||
meta:set_string("sparam.resend_time", "")
|
||||
meta:set_string("sparam.loop", "")
|
||||
meta:set_string("sparam.pos", pos:to_string())
|
||||
meta:set_string("sparam.object", "")
|
||||
@ -274,6 +280,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
pitch = tonumber(md.sparam.pitch),
|
||||
fade = tonumber(md.sparam.fade),
|
||||
start_time = tonumber(md.sparam.start_time),
|
||||
resend_time = tonumber(md.sparam.resend_time),
|
||||
loop = minetest.is_yes(md.sparam.loop),
|
||||
pos = vector.from_string(md.sparam.pos),
|
||||
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)",
|
||||
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, 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}",
|
||||
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.to_player, sparam.exclude_player,
|
||||
sparam.max_hear_distance),
|
||||
|
@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
|
||||
{
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
// keys which are known to have safe special character interpretation
|
||||
// could need changes over time (removals and additions!)
|
||||
case KEY_RETURN:
|
||||
@ -189,24 +189,68 @@ bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
}
|
||||
}
|
||||
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock)
|
||||
{
|
||||
switch (irrlichtKey) {
|
||||
// special cases that always return a char regardless of how the SDL keycode
|
||||
// looks
|
||||
switch (key) {
|
||||
case KEY_RETURN:
|
||||
case KEY_ESCAPE:
|
||||
return (int)key;
|
||||
return (int)irrlichtKey;
|
||||
|
||||
// This is necessary for keys on the numpad because they don't use the same
|
||||
// keycodes as their non-numpad versions (whose keycodes correspond to chars),
|
||||
// but have their own SDL keycodes and their own Irrlicht keycodes (which
|
||||
// don't correspond to chars).
|
||||
case KEY_MULTIPLY:
|
||||
return '*';
|
||||
case KEY_ADD:
|
||||
return '+';
|
||||
case KEY_SUBTRACT:
|
||||
return '-';
|
||||
case KEY_DIVIDE:
|
||||
return '/';
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (numlock) {
|
||||
// Number keys on the numpad are also affected, but we only want them
|
||||
// to produce number chars when numlock is enabled.
|
||||
switch (irrlichtKey) {
|
||||
case KEY_NUMPAD0:
|
||||
return '0';
|
||||
case KEY_NUMPAD1:
|
||||
return '1';
|
||||
case KEY_NUMPAD2:
|
||||
return '2';
|
||||
case KEY_NUMPAD3:
|
||||
return '3';
|
||||
case KEY_NUMPAD4:
|
||||
return '4';
|
||||
case KEY_NUMPAD5:
|
||||
return '5';
|
||||
case KEY_NUMPAD6:
|
||||
return '6';
|
||||
case KEY_NUMPAD7:
|
||||
return '7';
|
||||
case KEY_NUMPAD8:
|
||||
return '8';
|
||||
case KEY_NUMPAD9:
|
||||
return '9';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SDL in-place ORs values with no character representation with 1<<30
|
||||
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
||||
if (assumedChar & (1 << 30))
|
||||
// This also affects the numpad keys btw.
|
||||
if (sdlKey & (1 << 30))
|
||||
return 0;
|
||||
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
case KEY_PRIOR:
|
||||
case KEY_NEXT:
|
||||
case KEY_HOME:
|
||||
@ -218,7 +262,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
case KEY_NUMLOCK:
|
||||
return 0;
|
||||
default:
|
||||
return assumedChar;
|
||||
return sdlKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,7 +869,8 @@ bool CIrrDeviceSDL::run()
|
||||
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
||||
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key);
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key,
|
||||
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
|
||||
postEventFromUser(irrevent);
|
||||
} break;
|
||||
|
||||
|
@ -273,10 +273,10 @@ class CIrrDeviceSDL : public CIrrDeviceStub
|
||||
|
||||
#endif
|
||||
// Check if a key is a known special character with no side effects on text boxes.
|
||||
static bool keyIsKnownSpecial(EKEY_CODE key);
|
||||
static bool keyIsKnownSpecial(EKEY_CODE irrlichtKey);
|
||||
|
||||
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
||||
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
|
||||
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
|
||||
|
||||
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||
void resetReceiveTextInputEvents();
|
||||
|
@ -1339,10 +1339,39 @@ void Server::handleCommand_RemovedSounds(NetworkPacket* pkt)
|
||||
if (i == m_playing_sounds.end())
|
||||
continue;
|
||||
|
||||
session_t peer_id = pkt->getPeerId();
|
||||
|
||||
ServerPlayingSound &psound = i->second;
|
||||
psound.clients.erase(pkt->getPeerId());
|
||||
if (psound.clients.empty())
|
||||
psound.clients.erase(peer_id);
|
||||
verbosestream << "Server: Sound " << id << " erase peer "
|
||||
<< peer_id << "." << std::endl;
|
||||
if (!psound.allow_resend && psound.clients.empty()) {
|
||||
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, "pitch", params.spec.pitch);
|
||||
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);
|
||||
|
||||
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.
|
||||
*/
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
|
||||
@ -2159,6 +2227,8 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
||||
if(pos_exists != (params.type != SoundLocation::Local))
|
||||
return -1;
|
||||
|
||||
params.allow_resend = pos_exists;
|
||||
|
||||
// Filter destination clients
|
||||
std::vector<session_t> dst_clients;
|
||||
if (!params.to_player.empty()) {
|
||||
@ -2169,6 +2239,7 @@ s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
||||
return -1;
|
||||
}
|
||||
dst_clients.push_back(player->getPeerId());
|
||||
params.allow_resend = false;
|
||||
} else {
|
||||
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;
|
||||
|
||||
// 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)
|
||||
return 0;
|
||||
|
||||
float gain = params.gain * params.spec.gain;
|
||||
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
|
||||
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;
|
||||
params.start_time = m_playing_sounds_time;
|
||||
params.resend_time = m_playing_sounds_time + params.spec.resend_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) {
|
||||
if (!ephemeral)
|
||||
params.clients.insert(peer_id);
|
||||
m_clients.sendCustom(peer_id, 0, &pkt, as_reliable);
|
||||
const bool as_reliable = !ephemeral;
|
||||
|
||||
for (const session_t peer_id : dst_clients) {
|
||||
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);
|
||||
verbosestream << "Server:playSound: Create sound "
|
||||
<< id << "." << std::endl;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
void Server::stopSound(s32 handle)
|
||||
@ -2237,6 +2315,9 @@ void Server::stopSound(s32 handle)
|
||||
|
||||
// Remove sound reference
|
||||
m_playing_sounds.erase(it);
|
||||
|
||||
verbosestream << "Server:stopSound: Stop sound "
|
||||
<< handle << "." << std::endl;
|
||||
}
|
||||
|
||||
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);
|
||||
// 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(); ) {
|
||||
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);
|
||||
}
|
||||
else
|
||||
++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,
|
||||
float far_d_nodes)
|
||||
{
|
||||
|
13
src/server.h
13
src/server.h
@ -119,6 +119,16 @@ struct ServerPlayingSound
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@ -242,6 +252,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
// Stop all sounds attached to given objects, for a certain client
|
||||
void stopAttachedSounds(session_t peer_id,
|
||||
const std::vector<u16> &object_ids);
|
||||
void createSoundPacket(NetworkPacket &pkt, s32 sound_id, const ServerPlayingSound ¶ms, const v3f &pos, bool ephemeral = false);
|
||||
|
||||
// Envlock
|
||||
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 SendActiveObjectMessages(session_t peer_id, const std::string &datas,
|
||||
bool reliable = true);
|
||||
void SendSound(session_t peer_id, s32 sound_id, const ServerPlayingSound ¶ms, const v3f &pos);
|
||||
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;
|
||||
s32 m_playing_sounds_id_last_used = 0; // positive values only
|
||||
s32 nextSoundId();
|
||||
float m_playing_sounds_time = 0.0f;
|
||||
|
||||
ModStorageDatabase *m_mod_storage_database = nullptr;
|
||||
float m_mod_storage_save_timer = 10.0f;
|
||||
|
@ -71,6 +71,9 @@ struct SoundSpec
|
||||
float fade = 0.0f;
|
||||
float pitch = 1.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;
|
||||
// If true, a local fallback (ie. from the user's sound pack) is used if the
|
||||
// sound-group does not exist.
|
||||
|
Loading…
Reference in New Issue
Block a user