Skip to content

Commit ace3c76

Browse files
committedFeb 1, 2020
Improve core.sound_play with ephemeral sounds and player exclusion
1 parent ea5e231 commit ace3c76

File tree

9 files changed

+78
-29
lines changed

9 files changed

+78
-29
lines changed
 

Diff for: ‎doc/lua_api.txt

+17-3
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ Examples of sound parameter tables:
826826
gain = 1.0, -- default
827827
loop = true,
828828
}
829-
-- Play in a location
829+
-- Play at a location
830830
{
831831
pos = {x = 1, y = 2, z = 3},
832832
gain = 1.0, -- default
@@ -839,13 +839,22 @@ Examples of sound parameter tables:
839839
max_hear_distance = 32, -- default, uses an euclidean metric
840840
loop = true,
841841
}
842+
-- Play at a location, heard by anyone *but* the given player
843+
{
844+
pos = {x = 32, y = 0, z = 100},
845+
max_hear_distance = 40,
846+
exclude_player = name,
847+
}
842848

843849
Looped sounds must either be connected to an object or played locationless to
844-
one player using `to_player = name,`.
850+
one player using `to_player = name`.
845851

846852
A positional sound will only be heard by players that are within
847853
`max_hear_distance` of the sound position, at the start of the sound.
848854

855+
`exclude_player = name` can be applied to locationless, positional and object-
856+
bound sounds to exclude a single player from hearing them.
857+
849858
`SimpleSoundSpec`
850859
-----------------
851860

@@ -4929,10 +4938,15 @@ Defaults for the `on_punch` and `on_dig` node definition callbacks
49294938
Sounds
49304939
------
49314940

4932-
* `minetest.sound_play(spec, parameters)`: returns a handle
4941+
* `minetest.sound_play(spec, parameters, [ephemeral])`: returns a handle
49334942
* `spec` is a `SimpleSoundSpec`
49344943
* `parameters` is a sound parameter table
4944+
* `ephemeral` is a boolean (default: false)
4945+
Ephemeral sounds will not return a handle and can't be stopped or faded.
4946+
It is recommend to use this for short sounds that happen in response to
4947+
player actions (e.g. door closing).
49354948
* `minetest.sound_stop(handle)`
4949+
* `handle` is a handle returned by `minetest.sound_play`
49364950
* `minetest.sound_fade(handle, step, gain)`
49374951
* `handle` is a handle returned by `minetest.sound_play`
49384952
* `step` determines how fast a sound will fade.

Diff for: ‎src/client/client.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ void Client::sendRemovedSounds(std::vector<s32> &soundList)
11061106

11071107
pkt << (u16) (server_ids & 0xFFFF);
11081108

1109-
for (int sound_id : soundList)
1109+
for (s32 sound_id : soundList)
11101110
pkt << sound_id;
11111111

11121112
Send(&pkt);

Diff for: ‎src/client/client.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
561561
std::unordered_map<s32, int> m_sounds_server_to_client;
562562
// And the other way!
563563
std::unordered_map<int, s32> m_sounds_client_to_server;
564-
// And relations to objects
564+
// Relation of client id to object id
565565
std::unordered_map<int, u16> m_sounds_to_objects;
566566

567567
// Map server hud ids to client hud ids

Diff for: ‎src/network/clientpackethandler.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,7 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
778778
[25 + len] bool loop
779779
[26 + len] f32 fade
780780
[30 + len] f32 pitch
781+
[34 + len] bool ephemeral
781782
*/
782783

783784
s32 server_id;
@@ -790,12 +791,14 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
790791
bool loop;
791792
float fade = 0.0f;
792793
float pitch = 1.0f;
794+
bool ephemeral = false;
793795

794796
*pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
795797

796798
try {
797799
*pkt >> fade;
798800
*pkt >> pitch;
801+
*pkt >> ephemeral;
799802
} catch (PacketError &e) {};
800803

801804
// Start playing
@@ -813,16 +816,18 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
813816
if (cao)
814817
pos = cao->getPosition();
815818
client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
816-
// TODO: Set up sound to move with object
817819
break;
818820
}
819821
default:
820822
break;
821823
}
822824

823825
if (client_id != -1) {
824-
m_sounds_server_to_client[server_id] = client_id;
825-
m_sounds_client_to_server[client_id] = server_id;
826+
// for ephemeral sounds, server_id is not meaningful
827+
if (!ephemeral) {
828+
m_sounds_server_to_client[server_id] = client_id;
829+
m_sounds_client_to_server[client_id] = server_id;
830+
}
826831
if (object_id != 0)
827832
m_sounds_to_objects[client_id] = object_id;
828833
}

Diff for: ‎src/network/networkprotocol.h

+2
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
200200
Unknown inventory serialization fields no longer throw an error
201201
Mod-specific formspec version
202202
Player FOV override API
203+
"ephemeral" added to TOCLIENT_PLAY_SOUND
203204
*/
204205

205206
#define LATEST_PROTOCOL_VERSION 38
@@ -450,6 +451,7 @@ enum ToClientCommand
450451
s32[3] pos_nodes*10000
451452
u16 object_id
452453
u8 loop (bool)
454+
u8 ephemeral (bool)
453455
*/
454456

455457
TOCLIENT_STOP_SOUND = 0x40,

Diff for: ‎src/script/common/c_content.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,7 @@ void read_server_sound_params(lua_State *L, int index,
10191019
params.max_hear_distance = BS*getfloatfield_default(L, index,
10201020
"max_hear_distance", params.max_hear_distance/BS);
10211021
getboolfield(L, index, "loop", params.loop);
1022+
getstringfield(L, index, "exclude_player", params.exclude_player);
10221023
}
10231024
}
10241025

Diff for: ‎src/script/lua_api/l_server.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -429,24 +429,30 @@ int ModApiServer::l_get_worldpath(lua_State *L)
429429
return 1;
430430
}
431431

432-
// sound_play(spec, parameters)
432+
// sound_play(spec, parameters, [ephemeral])
433433
int ModApiServer::l_sound_play(lua_State *L)
434434
{
435435
NO_MAP_LOCK_REQUIRED;
436436
SimpleSoundSpec spec;
437437
read_soundspec(L, 1, spec);
438438
ServerSoundParams params;
439439
read_server_sound_params(L, 2, params);
440-
s32 handle = getServer(L)->playSound(spec, params);
441-
lua_pushinteger(L, handle);
440+
bool ephemeral = lua_gettop(L) > 2 && readParam<bool>(L, 3);
441+
if (ephemeral) {
442+
getServer(L)->playSound(spec, params, true);
443+
lua_pushnil(L);
444+
} else {
445+
s32 handle = getServer(L)->playSound(spec, params);
446+
lua_pushinteger(L, handle);
447+
}
442448
return 1;
443449
}
444450

445451
// sound_stop(handle)
446452
int ModApiServer::l_sound_stop(lua_State *L)
447453
{
448454
NO_MAP_LOCK_REQUIRED;
449-
int handle = luaL_checkinteger(L, 1);
455+
s32 handle = luaL_checkinteger(L, 1);
450456
getServer(L)->stopSound(handle);
451457
return 0;
452458
}

Diff for: ‎src/server.cpp

+33-15
Original file line numberDiff line numberDiff line change
@@ -2013,8 +2013,18 @@ void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
20132013
Send(&pkt);
20142014
}
20152015

2016+
inline s32 Server::nextSoundId()
2017+
{
2018+
s32 ret = m_next_sound_id;
2019+
if (m_next_sound_id == INT32_MAX)
2020+
m_next_sound_id = 0; // signed overflow is undefined
2021+
else
2022+
m_next_sound_id++;
2023+
return ret;
2024+
}
2025+
20162026
s32 Server::playSound(const SimpleSoundSpec &spec,
2017-
const ServerSoundParams &params)
2027+
const ServerSoundParams &params, bool ephemeral)
20182028
{
20192029
// Find out initial position of sound
20202030
bool pos_exists = false;
@@ -2025,7 +2035,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
20252035

20262036
// Filter destination clients
20272037
std::vector<session_t> dst_clients;
2028-
if(!params.to_player.empty()) {
2038+
if (!params.to_player.empty()) {
20292039
RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
20302040
if(!player){
20312041
infostream<<"Server::playSound: Player \""<<params.to_player
@@ -2045,6 +2055,9 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
20452055
RemotePlayer *player = m_env->getPlayer(client_id);
20462056
if (!player)
20472057
continue;
2058+
if (!params.exclude_player.empty() &&
2059+
params.exclude_player == player->getName())
2060+
continue;
20482061

20492062
PlayerSAO *sao = player->getPlayerSAO();
20502063
if (!sao)
@@ -2063,27 +2076,32 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
20632076
return -1;
20642077

20652078
// Create the sound
2066-
s32 id = m_next_sound_id++;
2067-
// The sound will exist as a reference in m_playing_sounds
2068-
m_playing_sounds[id] = ServerPlayingSound();
2069-
ServerPlayingSound &psound = m_playing_sounds[id];
2070-
psound.params = params;
2071-
psound.spec = spec;
2079+
s32 id;
2080+
ServerPlayingSound *psound = nullptr;
2081+
if (ephemeral) {
2082+
id = -1; // old clients will still use this, so pick a reserved ID
2083+
} else {
2084+
id = nextSoundId();
2085+
// The sound will exist as a reference in m_playing_sounds
2086+
m_playing_sounds[id] = ServerPlayingSound();
2087+
psound = &m_playing_sounds[id];
2088+
psound->params = params;
2089+
psound->spec = spec;
2090+
}
20722091

20732092
float gain = params.gain * spec.gain;
20742093
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
20752094
pkt << id << spec.name << gain
20762095
<< (u8) params.type << pos << params.object
2077-
<< params.loop << params.fade << params.pitch;
2096+
<< params.loop << params.fade << params.pitch
2097+
<< ephemeral;
20782098

2079-
// Backwards compability
2080-
bool play_sound = gain > 0;
2099+
bool as_reliable = !ephemeral;
20812100

20822101
for (const u16 dst_client : dst_clients) {
2083-
if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
2084-
psound.clients.insert(dst_client);
2085-
m_clients.send(dst_client, 0, &pkt, true);
2086-
}
2102+
if (psound)
2103+
psound->clients.insert(dst_client);
2104+
m_clients.send(dst_client, 0, &pkt, as_reliable);
20872105
}
20882106
return id;
20892107
}

Diff for: ‎src/server.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct ServerSoundParams
9898
v3f pos;
9999
u16 object = 0;
100100
std::string to_player = "";
101+
std::string exclude_player = "";
101102

102103
v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
103104
};
@@ -209,7 +210,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
209210

210211
// Returns -1 if failed, sound handle on success
211212
// Envlock
212-
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
213+
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params,
214+
bool ephemeral=false);
213215
void stopSound(s32 handle);
214216
void fadeSound(s32 handle, float step, float gain);
215217

@@ -646,7 +648,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
646648
Sounds
647649
*/
648650
std::unordered_map<s32, ServerPlayingSound> m_playing_sounds;
649-
s32 m_next_sound_id = 0;
651+
s32 m_next_sound_id = 0; // positive values only
652+
s32 nextSoundId();
650653

651654
/*
652655
Detached inventories (behind m_env_mutex)

0 commit comments

Comments
 (0)
Please sign in to comment.