Sound
A world that makes no noise feels like a screenshot. One line of Python fixes that, and nothing about a sound can be got wrong the way a misplaced block can — it plays, it ends, and the map is exactly as it was.
Start here
>>> lt.sound.play("miney_power_up_1")
<Luanti PlayingSound "sound-1">
Everybody hears it, equally loudly, wherever they are. Give it a place and it behaves like a real sound instead — quieter the further away you stand:
lt.sound.play("miney_power_up_1", point=Point(10, 20, 30))
Sounds Miney brings along
miney_power_up_1 works on any server, in any game, because Miney’s mod ships it. 47
of them come along: lasers, zaps, power-ups, beeps and chimes, all named miney_
something and all listed under lt.assets.sounds like every
other sound the server knows.
lt.sound.play(lt.assets.sounds.miney.laser_3)
lt.sound.play(lt.assets.sounds.miney.zap_two_tone)
lt.sound.play(lt.assets.sounds.miney.three_tone_1)
Nine lasers, twelve power-ups and five of most other things are numbered, so picking one at random is a line of ordinary Python:
import random
lt.sound.play(f"miney_laser_{random.randint(1, 9)}")
Finding a name
Every game brings its own sounds too, and there is no way to guess one of those:
"mcl_portals_open" exists in VoxeLibre and nowhere else.
lt.assets.sounds has every name this server knows,
sorted by the mod it came from and discoverable with TAB:
lt.sound.play(lt.assets.sounds.mcl_portals.open)
Note
A sound name is not a file name. default_dig_stone is played by that name, while
the game may hold it as default_dig_stone.ogg or as a whole set of
default_dig_stone.0.ogg to .9.ogg — one of which is picked at random each
time, so the same footstep never sounds quite the same twice.
Who hears it, and where it comes from
Two parameters sound alike and are not:
player— who hears it. Only that one person, and nobody standing next to them.follow— where it comes from. The sound travels with that player, and everybody in earshot hears it move.
lt.sound.play("miney_zap_1", player=lt.players.Steve) # in Steve's ears
lt.sound.play("miney_zap_1", follow=lt.players.Steve) # from Steve
They combine, so one player can hear a sound that another player carries.
Music
loop=True is what turns a sound into a soundtrack — and it is the one thing here that
keeps going after your script has stopped:
music = lt.sound.play("miney_low_random", loop=True, gain=0.4)
# ... the whole show ...
music.fade_out(3)
A looped miney_ sound makes a hum or a pulse, because they are all short effects. Real
music is a file of your own, and that is the next section.
Important
Somebody has to end a loop: fade_out(),
stop(), or lt.sound.stop_all() for everything at once. Miney’s mod stops what your session
left playing when the session ends, so a forgotten loop does not haunt the world
forever — but inside a long script it is yours to stop.
fade_out() is the kinder one. Cutting music off dead is
something a player notices.
Your own music
Any Ogg file on your computer goes into the world the same way a picture does:
from pathlib import Path
fanfare = lt.assets.upload(Path("fanfare.ogg"))
lt.sound.play(fanfare)
lt.assets.upload() hands back miney_3f9a1c7b2e04.ogg
and play() drops the .ogg for you, so the name goes straight from
one to the other. It also waits until the file has really reached the players, so the
next line can use it.
A moment worth hearing
Everything together:
import miney
import time
lt = miney.Luanti()
point = lt.players[0].position
music = lt.sound.play(lt.assets.sounds.miney.low_random, loop=True, gain=0.3)
for i in range(5):
lt.sound.play("miney_power_up_1", point=point, pitch=1 + i / 4, distance=16)
lt.particles.spawn(point + miney.Point(0, 2, 0), color="#ffcc00", amount=200)
time.sleep(0.5)
music.fade_out(2)
- class miney.Sound(luanti: Luanti)[source]
Noise: a click, a chime, or music that plays until you stop it.
Reached through
lt.soundand never created directly:>>> lt.sound.play("miney_power_up_1") <Luanti PlayingSound "sound-1">
A sound is named, not filed:
"default_dig_stone"is a name the game answers to, andlt.assets.soundsis where to find one with TAB. Given aPointit comes from that place and fades with distance; without one it is equally loud everywhere, which is what music wants.Every name beginning with
miney_comes with Miney’s own mod and works in any game - 47 CC0 effects by Kenney Vleugels, so an example has something to play before you have gone looking for a name.Important
A sound with
loop=Truekeeps playing after your script has ended. Somebody has to stop it -PlayingSound.stop(),stop_all(), or your session ending, because Miney’s mod clears out what a connection left behind.- play(name: str, *, gain: float = 1.0, pitch: float = 1.0, loop: bool = False, point: Point | None = None, player: Player | str | None = None, follow: Player | str | None = None, fade: float = 0.0, start: float = 0.0, distance: float | None = None, **extra: Any) PlayingSound[source]
Play a sound.
Everywhere, once:
>>> lt.sound.play("miney_power_up_1")
At a place, so it gets quieter the further away you are:
>>> lt.sound.play("miney_power_up_1", point=Point(10, 20, 30))
Music, until you stop it:
>>> music = lt.sound.play("miney_low_random", loop=True, gain=0.4) >>> music.fade_out(3)
In one player’s ears only, half as deep:
>>> lt.sound.play("miney_power_up_1", player=lt.players.Steve, pitch=0.5)
Travelling with a player, for everybody to hear:
>>> lt.sound.play("miney_power_up_1", follow=lt.players.Steve)
Your own:
>>> lt.sound.play(lt.assets.upload(Path("fanfare.ogg")))
playerandfollowsound alike and are not:playeris who hears it,followis where it comes from. They combine, so one player can hear a sound that another player carries.- Parameters:
name – The sound, from
lt.assets.soundsor fromlt.assets.upload(). A trailing.oggis dropped for you.gain – How loud, where
1is the sound’s own level. Above1a placed sound does not get louder, it gets further - the volume is measured three blocks away.pitch – How deep.
0.5is an octave down,2an octave up.loop – Start again at the end, for ever. Needs
PlayingSound.stop().point – Where it comes from. Without one it is equally loud everywhere and follows nobody, which is what music wants.
player – Only this player hears it. A
Playeror a name.follow – The sound travels with this player. A
Playeror a name. Cannot be combined withpoint.fade – Fade in over this long, in gain per second.
0.5takes two seconds to reachgain.start – Start this many seconds into the sound instead of at the beginning.
distance – How far away it can still be heard, in blocks. Luanti’s own answer is 32. Needs
pointorfollow.extra – Anything else Luanti’s sound parameter table takes, passed straight through -
exclude_player, for example. A name the engine does not know is ignored without a word, so check it against Luanti’s lua_api.md if nothing happens.
- Returns:
A
PlayingSound, to stop it with.- Raises:
TypeError – If a value is of the wrong kind.
ValueError – If a number is out of range, if
pointandfolloware given together, ifdistancehas no place to measure from, or ifextrarepeats something a parameter above already says.
- class miney.PlayingSound(sound: Sound, key: str, gain: float)[source]
A sound that is playing, and the way to end it.
You never make one of these -
Sound.play()hands it back:>>> music = lt.sound.play("miney_low_random", loop=True) >>> music.fade_out(3)
It is also a context manager, which is the tidier way to say the same thing:
>>> with lt.sound.play("miney_low_random", loop=True): ... build_the_thing() ... # silent again on the way out, come what may
- fade_out(seconds: float = 1.0) None[source]
Turn it down to nothing over this many seconds, then stop it.
Kinder than
stop()for anything a player has been listening to:>>> music = lt.sound.play("miney_low_random", loop=True, gain=0.5) >>> music.fade_out(3)
- Parameters:
seconds – How long the fade takes. Must be more than 0 - to end it at once use
stop().- Raises:
ValueError – If
secondsis 0 or less.
- gain
How loud it was started.
- key
How the server knows this sound.