Skip to content

Commit 4d48b5d

Browse files
committed
feat: massive refinement pass across all 101 pages
17 agents did 15 verification passes each across every page. Key improvements: - GUI/screens docs expanded with full SWF/Iggy system (RAD Game Tools, not Scaleform) - Custom containers rewritten with full slot system, SWF rendering layer - Creative tabs now has complete item lists for all 8 tabs - All reference tables verified against source (block IDs, item IDs, entity types, packets) - Platform pages expanded with third-party libraries and per-platform details - Enchantment cost curves, anvil combining, brewing formulas all verified - Every mob's drop table documented in custom-loot - Every villager trade pool documented in custom-trades - Full A* pathfinding algorithm documented in custom-ai - All 38 registered entity IDs verified - Block textures page covers terrain atlas UV system - Entity models page has face mask system and baby variant scaling - Fog/sky page has complete 10-step rendering pipeline - Custom structures has full loot tables for every structure type - Adding-blocks covers every major Tile subclass recipe - Custom-worldgen documents all 5 ChunkSource implementations 97 files changed, 22076 insertions, 3756 deletions.
1 parent 3e7028f commit 4d48b5d

97 files changed

Lines changed: 22076 additions & 3756 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/content/docs/client/audio.md

Lines changed: 241 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public:
4444
};
4545
```
4646
47-
The sound name tables (`wchSoundNames` and `wchUISoundNames`) map sound type enums (defined in `Minecraft.World/SoundTypes.h`) to human-readable names.
47+
The sound name tables (`wchSoundNames` and `wchUISoundNames`) map sound type enums (defined in `Minecraft.World/SoundTypes.h`) to human-readable names. These are defined in `SoundNames.cpp` and must stay in sync with the enum order.
4848
4949
### SoundEngine (implementation)
5050
@@ -74,6 +74,27 @@ The Miles Sound System headers are included per platform:
7474

7575
Xbox 360 uses the native XAudio system instead of Miles.
7676

77+
## The sound pipeline
78+
79+
Game code never touches Miles directly. The chain goes:
80+
81+
```
82+
Entity/Level code
83+
|
84+
v
85+
LevelListener::playSound()
86+
|
87+
v
88+
ServerLevelListener --> LevelSoundPacket (network)
89+
|
90+
v
91+
SoundEngine::play() -- 3D positioned sound
92+
SoundEngine::playUI() -- non-positional UI sound
93+
SoundEngine::playStreaming() -- music / jukebox
94+
```
95+
96+
When `SoundEngine::play()` fires, it builds a Miles event name like `"Minecraft/mob.zombie"` from the dot-separated string and enqueues it to the event system. `ConvertSoundPathToName()` handles the conversion from dots to the slash-separated event paths that Miles expects.
97+
7798
## 3D audio
7899

79100
### Listener system
@@ -95,6 +116,10 @@ typedef struct {
95116
} AUDIO_LISTENER;
96117
```
97118

119+
### Splitscreen listener handling
120+
121+
In splitscreen, the engine can't just set one listener position. Instead, it calculates the **Manhattan distance** from each sound to every active player, picks the closest one, and uses that distance for the 3D falloff. The listener is placed at the origin and the sound is placed along the Z axis at the calculated distance. This gives reasonable spatial audio across all screen splits.
122+
98123
### Sound playback
99124

100125
The `AUDIO_INFO` struct describes a sound to play:
@@ -131,6 +156,181 @@ void playStreamingMusic(const wstring& name, int x, int y, int z);
131156
132157
The `fSoundClipDist` parameter (default 16 blocks) controls how far away a sound can be heard.
133158
159+
## Sound attenuation
160+
161+
All 3D sounds use a custom linear falloff function instead of the default Miles rolloff:
162+
163+
```cpp
164+
F32 AILCALLBACK custom_falloff_function(
165+
HSAMPLE S, F32 distance, F32 rolloff_factor, F32 min_dist, F32 max_dist)
166+
{
167+
// Thunder has no attenuation at all
168+
if (max_dist == 10000.0f)
169+
return 1.0f;
170+
171+
// Linear falloff: full volume at distance 0, silent at max_dist
172+
F32 result = 1.0f - (distance / max_dist);
173+
if (result < 0.0f) result = 0.0f;
174+
if (result > 1.0f) result = 1.0f;
175+
return result;
176+
}
177+
```
178+
179+
The `max_dist` parameter (called `distanceScaler` in the code) controls how far a sound carries:
180+
181+
| Sound type | Distance (blocks) | Notes |
182+
|---|---|---|
183+
| Most sounds | 16 | Default `fSoundClipDist` |
184+
| Ghast sounds | 30 | Audible from further away |
185+
| Ender Dragon | 100 | Boss sounds carry far |
186+
| Thunder | 10,000 | Effectively infinite, always full volume |
187+
| Music discs | 64 | Jukebox carries 4x further than normal |
188+
189+
## Sound categories
190+
191+
Sounds are grouped by naming prefix. Every sound in the game has an entry in the `eSOUND_TYPE` enum in `SoundTypes.h`.
192+
193+
### Mob sounds (`mob.*`)
194+
195+
Ambient, hurt, death, and step sounds for every mob:
196+
197+
| Enum pattern | String name pattern | Notes |
198+
|---|---|---|
199+
| `eSoundType_MOB_ZOMBIE_AMBIENT` | `mob.zombie` | Idle groaning |
200+
| `eSoundType_MOB_ZOMBIE_HURT` | `mob.zombiehurt` | Taking damage |
201+
| `eSoundType_MOB_ZOMBIE_DEATH` | `mob.zombiedeath` | Dying |
202+
| `eSoundType_MOB_CREEPER_HURT` | `mob.creeper` | Creeper hurt |
203+
| `eSoundType_MOB_WOLF_BARK` | `mob.wolf.bark` | Wolf barking |
204+
| `eSoundType_MOB_WOLF_HURT` | `mob.wolf.hurt` | Wolf hurt |
205+
| `eSoundType_MOB_WOLF_DEATH` | `mob.wolf.death` | Wolf death |
206+
| `eSoundType_MOB_WOLF_GROWL` | `mob.wolf.growl` | Wolf growl |
207+
| `eSoundType_MOB_WOLF_PANTING` | `mob.wolf.panting` | Tamed wolf panting |
208+
| `eSoundType_MOB_WOLF_WHINE` | `mob.wolf.whine` | Wolf whine |
209+
| `eSoundType_MOB_WOLF_SHAKE` | `mob.wolf.shake` | Wolf shaking off water |
210+
| `eSoundType_MOB_CAT_HISS` | `mob.cat.hiss` | Cat hiss |
211+
| `eSoundType_MOB_CAT_PURR` | `mob.cat.purr` | Cat purr |
212+
| `eSoundType_MOB_CAT_PURREOW` | `mob.cat.purreow` | Cat meow |
213+
| `eSoundType_MOB_CHICKEN_AMBIENT` | `mob.chicken` | Chicken clucking |
214+
| `eSoundType_MOB_CHICKEN_HURT` | `mob.chickenhurt` | Chicken hurt |
215+
| `eSoundType_MOB_CHICKEN_PLOP` | `mob.chicken.plop` | Egg laying |
216+
| `eSoundType_MOB_COW_AMBIENT` | `mob.cow` | Cow mooing |
217+
| `eSoundType_MOB_COW_HURT` | `mob.cowhurt` | Cow hurt |
218+
| `eSoundType_MOB_PIG_AMBIENT` | `mob.pig` | Pig oinking |
219+
| `eSoundType_MOB_PIG_DEATH` | `mob.pig.death` | Pig death |
220+
| `eSoundType_MOB_SHEEP_AMBIENT` | `mob.sheep` | Sheep bleating |
221+
| `eSoundType_MOB_GHAST_AMBIENT` | `mob.ghast.moan` | Ghast moaning |
222+
| `eSoundType_MOB_GHAST_DEATH` | `mob.ghast.death` | Ghast death |
223+
| `eSoundType_MOB_GHAST_FIREBALL` | `mob.ghast.fireball` | Ghast shooting |
224+
| `eSoundType_MOB_GHAST_SCREAM` | `mob.ghast.scream` | Ghast screaming |
225+
| `eSoundType_MOB_BLAZE_HIT` | `mob.blaze.hit` | Blaze hurt |
226+
| `eSoundType_MOB_BLAZE_DEATH` | `mob.blaze.death` | Blaze death |
227+
| `eSoundType_MOB_BLAZE_BREATHE` | `mob.blaze.breathe` | Blaze ambient |
228+
| `eSoundType_MOB_ENDERMAN_IDLE` | `mob.endermen.idle` | Enderman ambient |
229+
| `eSoundType_MOB_ENDERMAN_HIT` | `mob.endermen.hit` | Enderman hurt |
230+
| `eSoundType_MOB_ENDERMAN_DEATH` | `mob.endermen.death` | Enderman death |
231+
| `eSoundType_MOB_ENDERMAN_PORTAL` | `mob.endermen.portal` | Enderman teleport |
232+
| `eSoundType_MOB_ENDERDRAGON_GROWL` | `mob.enderdragon.growl` | Dragon growl |
233+
| `eSoundType_MOB_ENDERDRAGON_HIT` | `mob.enderdragon.hit` | Dragon hurt |
234+
| `eSoundType_MOB_ENDERDRAGON_WINGS` | `mob.enderdragon.wings` | Dragon wingflap |
235+
| `eSoundType_MOB_ENDERDRAGON_END` | `mob.enderdragon.end` | Dragon death |
236+
| `eSoundType_MOB_SILVERFISH_AMBIENT` | `mob.silverfish.say` | Silverfish ambient |
237+
| `eSoundType_MOB_SILVERFISH_HIT` | `mob.silverfish.hit` | Silverfish hurt |
238+
| `eSoundType_MOB_SILVERFISH_DEATH` | `mob.silverfish.kill` | Silverfish death |
239+
| `eSoundType_MOB_SILVERFISH_STEP` | `mob.silverfish.step` | Silverfish walk |
240+
| `eSoundType_MOB_GOLEM_HIT` | `mob.irongolem.hit` | Iron golem hurt |
241+
| `eSoundType_MOB_GOLEM_DEATH` | `mob.irongolem.death` | Iron golem death |
242+
| `eSoundType_MOB_GOLEM_WALK` | `mob.irongolem.walk` | Iron golem walk |
243+
| `eSoundType_MOB_GOLEM_THROW` | `mob.irongolem.throw` | Iron golem throw |
244+
| `eSoundType_MOB_SLIME_BIG` | `mob.slime.big` | Large slime |
245+
| `eSoundType_MOB_SLIME_SMALL` | `mob.slime.small` | Small slime |
246+
| `eSoundType_MOB_MAGMACUBE_BIG` | `mob.magmacube.big` | Large magma cube |
247+
| `eSoundType_MOB_MAGMACUBE_JUMP` | `mob.magmacube.small` | Magma cube jump |
248+
249+
### Block/tile sounds (`step.*`, `dig.*`, `tile.*`)
250+
251+
| Enum | String name | Used for |
252+
|---|---|---|
253+
| `eSoundType_STEP_STONE` | `step.stone` | Walking on stone |
254+
| `eSoundType_STEP_WOOD` | `step.wood` | Walking on wood |
255+
| `eSoundType_STEP_GRAVEL` | `step.gravel` | Walking on gravel |
256+
| `eSoundType_STEP_GRASS` | `step.grass` | Walking on grass |
257+
| `eSoundType_STEP_CLOTH` | `step.cloth` | Walking on wool |
258+
| `eSoundType_STEP_SAND` | `step.sand` | Walking on sand |
259+
| `eSoundType_STEP_SNOW` | `step.snow` | Walking on snow |
260+
| `eSoundType_STEP_LADDER` | `step.ladder` | Climbing ladders |
261+
| `eSoundType_DIG_GRASS` | `dig.grass` | Breaking grass blocks |
262+
| `eSoundType_DIG_STONE` | `dig.stone` | Breaking stone |
263+
| `eSoundType_DIG_WOOD` | `dig.wood` | Breaking wood |
264+
| `eSoundType_DIG_GRAVEL` | `dig.gravel` | Breaking gravel |
265+
| `eSoundType_DIG_CLOTH` | `dig.cloth` | Breaking wool |
266+
| `eSoundType_DIG_SAND` | `dig.sand` | Breaking sand |
267+
| `eSoundType_DIG_SNOW` | `dig.snow` | Breaking snow |
268+
| `eSoundType_TILE_PISTON_IN` | `tile.piston.in` | Piston retracting |
269+
| `eSoundType_TILE_PISTON_OUT` | `tile.piston.out` | Piston extending |
270+
271+
### Random/gameplay sounds (`random.*`)
272+
273+
| Enum | String name | Used for |
274+
|---|---|---|
275+
| `eSoundType_RANDOM_EXPLODE` | `random.explode` | Explosions |
276+
| `eSoundType_RANDOM_BOW` | `random.bow` | Firing a bow |
277+
| `eSoundType_RANDOM_CHEST_OPEN` | `random.chestopen` | Opening a chest |
278+
| `eSoundType_RANDOM_CHEST_CLOSE` | `random.chestclosed` | Closing a chest |
279+
| `eSoundType_RANDOM_DOOR_OPEN` | `random.door_open` | Opening a door |
280+
| `eSoundType_RANDOM_DOOR_CLOSE` | `random.door_close` | Closing a door |
281+
| `eSoundType_RANDOM_CLICK` | `random.click` | Buttons, levers |
282+
| `eSoundType_RANDOM_GLASS` | `random.glass` | Breaking glass |
283+
| `eSoundType_RANDOM_FIZZ` | `random.fizz` | Fire extinguish, lava pop |
284+
| `eSoundType_RANDOM_LEVELUP` | `random.levelup` | Experience level up |
285+
| `eSoundType_RANDOM_POP` | `random.pop` | Item pickup |
286+
| `eSoundType_RANDOM_ORB` | `random.orb` | Experience orb pickup |
287+
| `eSoundType_RANDOM_SPLASH` | `random.splash` | Water splash |
288+
| `eSoundType_RANDOM_DRINK` | `random.drink` | Drinking potion |
289+
| `eSoundType_RANDOM_EAT` | `random.eat` | Eating food |
290+
| `eSoundType_RANDOM_ANVIL_USE` | `random.anvil_use` | Using an anvil |
291+
| `eSoundType_RANDOM_ANVIL_LAND` | `random.anvil_land` | Falling anvil landing |
292+
| `eSoundType_RANDOM_ANVIL_BREAK` | `random.anvil_break` | Anvil breaking |
293+
| `eSoundType_RANDOM_FUSE` | `random.fuse` | TNT fuse |
294+
| `eSoundType_RANDOM_BOWHIT` | `random.bowhit` | Arrow hitting target |
295+
296+
### Ambient sounds (`ambient.*`)
297+
298+
| Enum | String name |
299+
|---|---|
300+
| `eSoundType_AMBIENT_WEATHER_RAIN` | `ambient.weather.rain` |
301+
| `eSoundType_AMBIENT_WEATHER_THUNDER` | `ambient.weather.thunder` |
302+
| `eSoundType_AMBIENT_CAVE_CAVE` | `ambient.cave.cave` |
303+
304+
### Other categories
305+
306+
| Prefix | Examples | Purpose |
307+
|---|---|---|
308+
| `portal.*` | `portal.portal`, `portal.trigger`, `portal.travel` | Portal effects |
309+
| `fire.*` | `fire.ignite`, `fire.fire` | Fire sounds |
310+
| `damage.*` | `damage.hurtflesh`, `damage.fallsmall`, `damage.fallbig` | Player damage |
311+
| `note.*` | `note.harp`, `note.bd`, `note.snare`, `note.hat`, `note.bassattack` | Note blocks |
312+
| `liquid.*` | `liquid.water`, `liquid.lava`, `liquid.lavapop` | Liquid sounds |
313+
| `minecart.*` | `minecart.base`, `minecart.inside` | Minecart movement |
314+
315+
### UI sounds (ESoundEffect)
316+
317+
UI sounds are a separate, smaller enum:
318+
319+
```cpp
320+
enum ESoundEffect
321+
{
322+
eSFX_Back, // "back"
323+
eSFX_Craft, // "craft"
324+
eSFX_CraftFail, // "craftfail"
325+
eSFX_Focus, // "focus"
326+
eSFX_Press, // "press"
327+
eSFX_Scroll, // "scroll"
328+
eSFX_MAX
329+
};
330+
```
331+
332+
These get played through `SoundEngine::playUI()` and are routed to the `"Minecraft/UI/"` event path in the soundbank.
333+
134334
## Music system
135335

136336
### Music file enumeration
@@ -156,16 +356,20 @@ The `eMUSICFILES` enum lists all music tracks:
156356

157357
Total: `eStream_Max` entries.
158358

359+
File paths follow the pattern `music/<trackname>.binka` for background music and `cds/<discname>.binka` for music discs. The `.binka` format is Bink Audio (compressed, from RAD Game Tools).
360+
159361
### Music types
160362

161363
```cpp
162364
enum eMUSICTYPE {
163365
eMusicType_None,
164-
eMusicType_Game,
165-
eMusicType_CD,
366+
eMusicType_Game, // background music (not 3D positioned)
367+
eMusicType_CD, // jukebox music (3D positioned, attenuates with distance)
166368
};
167369
```
168370

371+
Background music plays globally with no 3D positioning. Jukebox music is 3D-positioned at the jukebox block with a distance scaler of 64 blocks (4x the normal sound range).
372+
169373
### Music streaming state machine
170374

171375
```cpp
@@ -181,6 +385,14 @@ enum MUSIC_STREAMSTATE {
181385
};
182386
```
183387

388+
The state transitions:
389+
390+
```
391+
Idle --> Opening --> Playing --> Completed --> Stop --> Stopping --> Idle
392+
```
393+
394+
`OpeningCancel` handles the case where a new track is requested while one is still opening.
395+
184396
Music streaming runs on a dedicated thread:
185397

186398
```cpp
@@ -190,23 +402,40 @@ static int OpenStreamThreadProc(void* lpParameter);
190402
191403
### Music selection
192404
193-
`getMusicID(int iDomain)` picks a random track that fits the current dimension. The track ranges are configurable per texture/mash-up pack:
405+
`getMusicID(int iDomain)` picks a random track that fits the current dimension:
406+
407+
```cpp
408+
int SoundEngine::getMusicID(int iDomain)
409+
{
410+
switch (iDomain)
411+
{
412+
case LevelData::DIMENSION_END:
413+
return m_iStream_End_Min; // always plays dragon-alive track
414+
case LevelData::DIMENSION_NETHER:
415+
return GetRandomishTrack(m_iStream_Nether_Min, m_iStream_Nether_Max);
416+
default:
417+
return GetRandomishTrack(m_iStream_Overworld_Min, m_iStream_Overworld_Max);
418+
}
419+
}
420+
```
421+
422+
The track ranges are configurable per texture/mash-up pack:
194423

195424
```cpp
196425
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax,
197426
int iNetherMin, int iNetherMax,
198427
int iEndMin, int iEndMax, int iCD1);
199428
```
200429
201-
`GetRandomishTrack(iStart, iEnd)` selects a track, using `m_bHeardTrackA` to avoid playing the same track back to back.
430+
`GetRandomishTrack(iStart, iEnd)` selects a track, using `m_bHeardTrackA` to avoid playing the same track back to back. Once all tracks in the range have been heard, the array resets. It doesn't try too hard, so occasionally you will hear the same track twice.
202431
203432
### Music tick
204433
205-
`playMusicTick()` is called each game tick. It manages the delay between tracks (`m_iMusicDelay`) and drives the streaming state machine. `playMusicUpdate()` handles the actual state transitions.
434+
`playMusicTick()` is called each game tick. It manages the delay between tracks (`m_iMusicDelay`, up to about 3 minutes of random delay) and drives the streaming state machine. `playMusicUpdate()` handles the actual state transitions.
206435
207436
### CD music (jukeboxes)
208437
209-
Music disc playback is tracked separately. The `m_CDMusic` field stores the current disc track name. `GetIsPlayingStreamingCDMusic()` and `SetIsPlayingStreamingCDMusic()` manage this state.
438+
Music disc playback is tracked separately. The `m_CDMusic` field stores the current disc track name. `GetIsPlayingStreamingCDMusic()` and `SetIsPlayingStreamingCDMusic()` manage this state. The track name gets matched against the `m_szStreamFileA` array to find the right file.
210439
211440
## Volume control
212441
@@ -222,7 +451,7 @@ The master volumes (`m_MasterMusicVolume`, `m_MasterEffectsVolume`) are set from
222451
## Sound bank and driver
223452
224453
The Miles Sound System uses:
225-
- **`HMSOUNDBANK m_hBank`** is the loaded sound bank containing all SFX
454+
- **`HMSOUNDBANK m_hBank`** is the loaded sound bank containing all SFX (`Minecraft.msscmp`)
226455
- **`HDIGDRIVER m_hDriver`** is the digital audio driver
227456
- **`HSTREAM m_hStream`** is the current streaming music handle
228457
@@ -270,6 +499,10 @@ MinecraftConsoles adds a large batch of new sound types to `SoundTypes.h`. These
270499
- Variant idle sounds: `_ZOMBIE_IDLE`, `_SKELETON_IDLE`, `_DONKEY_IDLE`, `_IDLE`
271500
- `_DONKEY_ANGRY`, `_ANGRY`, `_GALLOP`, `_BREATHE`, `_WOOD`
272501
502+
### Witch sounds
503+
504+
- `eSoundType_MOB_WITCH_IDLE`, `_HURT`, `_DEATH`
505+
273506
### Mob step/ambient sounds
274507
275508
A bunch of mob step sounds are added that LCEMP was missing:

0 commit comments

Comments
 (0)