diff --git a/VERSION b/VERSION index ccbccc3..c043eea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0 +2.2.1 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index fef2fc4..5018b78 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +**2.2.1** +* Prevent `random.burp` Sound From Crashing Game +* Always Cleanup Media Layer, Even On Crash +* Resolve All Sounds On Startup + **2.2.0** * Sound Support * Split Off "Allow Joining Survival Servers" From Game-Mode Mod diff --git a/images/start.png b/images/start.png index 189cbc7..d3e926e 100644 Binary files a/images/start.png and b/images/start.png differ diff --git a/media-layer/core/src/audio/api.cpp b/media-layer/core/src/audio/api.cpp index 9d1f5db..1aceb04 100644 --- a/media-layer/core/src/audio/api.cpp +++ b/media-layer/core/src/audio/api.cpp @@ -43,17 +43,27 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) { std::vector::iterator it = get_sources().begin(); while (it != get_sources().end()) { ALuint source = *it; + bool remove = false; // Check - ALint source_state; - alGetSourcei(source, AL_SOURCE_STATE, &source_state); - AL_ERROR_CHECK(); - if (source_state != AL_PLAYING) { - // Finished - it = get_sources().erase(it); - alDeleteSources(1, &source); + if (source && alIsSource(source)) { + // Is Valid Source + ALint source_state; + alGetSourcei(source, AL_SOURCE_STATE, &source_state); AL_ERROR_CHECK(); + if (source_state != AL_PLAYING) { + // Finished Playing + remove = true; + alDeleteSources(1, &source); + AL_ERROR_CHECK(); + } + } else { + // Not A Source + remove = true; + } + // Remove If Needed + if (remove) { + it = get_sources().erase(it); } else { - // Still Playing ++it; } } @@ -62,7 +72,7 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) { void media_audio_play(const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui) { // Load Sound ALuint buffer = _media_audio_get_buffer(source, name); - if (buffer) { + if (volume > 0.0f && buffer) { // Create Source ALuint al_source; alGenSources(1, &al_source); diff --git a/media-layer/core/src/audio/file.cpp b/media-layer/core/src/audio/file.cpp index 9bbba33..f3bad10 100644 --- a/media-layer/core/src/audio/file.cpp +++ b/media-layer/core/src/audio/file.cpp @@ -224,7 +224,7 @@ ALuint _media_audio_get_buffer(const char *source, const char *name) { return _media_audio_get_buffer(source, name); } } else { - return 0; + ERR("%s", "Audio Engine Isn't Loaded"); } } diff --git a/media-layer/core/src/media.c b/media-layer/core/src/media.c index e9898ea..3fa4889 100644 --- a/media-layer/core/src/media.c +++ b/media-layer/core/src/media.c @@ -310,6 +310,9 @@ void media_cleanup() { if (is_running) { // GLFW And Audio Are Disabled In Headless Mode #ifndef MCPI_HEADLESS_MODE + // Ignore GLFW Errors During Termination + glfwSetErrorCallback(NULL); + // Terminate GLFW glfwDestroyWindow(glfw_window); glfwTerminate(); @@ -322,6 +325,10 @@ void media_cleanup() { is_running = 0; } } +// Always Cleanup Media Layer +__attribute__((destructor)) static void always_cleanup() { + media_cleanup(); +} // Store Cursor State static int cursor_grabbed = 0; diff --git a/mods/src/sound/repository.cpp b/mods/src/sound/repository.cpp index 55f1c7f..fdc0cf5 100644 --- a/mods/src/sound/repository.cpp +++ b/mods/src/sound/repository.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "sound.h" @@ -314,6 +315,12 @@ static std::unordered_map> repository = { { "PCM_fuse" } + }, + { + "random.burp", + { + "PCM_burp" + } } } }; @@ -333,3 +340,16 @@ std::string _sound_pick(std::string sound) { ERR("Invalid Sound: %s", sound.c_str()); } } + +// Resolve All Sounds +void _sound_resolve_all() { + std::string source = _sound_get_source_file(); + if (source.size() > 0) { + for (auto it : repository) { + for (std::string name : it.second) { + // Zero Volume Prevents An OpenAL Source From Being Allocated While Still Resolving The Sound + media_audio_play(source.c_str(), name.c_str(), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f); + } + } + } +} diff --git a/mods/src/sound/sound.cpp b/mods/src/sound/sound.cpp index 3060e0b..a438d2d 100644 --- a/mods/src/sound/sound.cpp +++ b/mods/src/sound/sound.cpp @@ -11,7 +11,7 @@ // Resolve Source File Path #define SOURCE_FILE_BASE "data/libminecraftpe.so" -static std::string get_source_file() { +std::string _sound_get_source_file() { static bool source_loaded = false; static std::string source; @@ -56,24 +56,20 @@ static std::string get_source_file() { source_loaded = true; // Return - return get_source_file(); + return _sound_get_source_file(); } } -// Resolve On Startup -__attribute__((constructor)) static void resolve_source_file() { - get_source_file(); -} // Play Sound // The pitch value is unsued because it causes glitchy sounds, it is seemingly unused in MCPE as well. static void SoundEngine_playUI_injection(__attribute__((unused)) unsigned char *sound_engine, std::string const& name, __attribute__((unused)) float pitch, float volume) { - std::string source = get_source_file(); + std::string source = _sound_get_source_file(); if (source.size() > 0) { media_audio_play(source.c_str(), _sound_pick(name).c_str(), 0.0f, 0.0f, 0.0f, 1.0f, volume, 1); } } static void SoundEngine_play_injection(__attribute__((unused)) unsigned char *sound_engine, std::string const& name, float x, float y, float z, __attribute__((unused)) float pitch, float volume) { - std::string source = get_source_file(); + std::string source = _sound_get_source_file(); if (source.size() > 0) { media_audio_play(source.c_str(), _sound_pick(name).c_str(), x, y, z, 1.0f, volume, 0); } @@ -108,6 +104,16 @@ static void SoundEngine_update_injection(unsigned char *sound_engine, unsigned c media_audio_update(volume, x, y, z, yaw); } +// Resolve All Sounds On Init +// SoundEngine::init Is Called After The Audio Engine Has Been Loaded +static void SoundEngine_init_injection(unsigned char *sound_engine, unsigned char *minecraft, unsigned char *options) { + // Call Original Method + (*SoundEngine_init)(sound_engine, minecraft, options); + + // Resolve Sounds + _sound_resolve_all(); +} + // Init void init_sound() { // Implement Sound Engine @@ -115,5 +121,6 @@ void init_sound() { overwrite_calls((void *) SoundEngine_playUI, (void *) SoundEngine_playUI_injection); overwrite_calls((void *) SoundEngine_play, (void *) SoundEngine_play_injection); overwrite_calls((void *) SoundEngine_update, (void *) SoundEngine_update_injection); + overwrite_calls((void *) SoundEngine_init, (void *) SoundEngine_init_injection); } } diff --git a/mods/src/sound/sound.h b/mods/src/sound/sound.h index f20c1bf..66c0f99 100644 --- a/mods/src/sound/sound.h +++ b/mods/src/sound/sound.h @@ -2,4 +2,6 @@ #include +__attribute__((visibility("internal"))) std::string _sound_get_source_file(); +__attribute__((visibility("internal"))) void _sound_resolve_all(); __attribute__((visibility("internal"))) std::string _sound_pick(std::string sound); diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index 5e27d2d..97ec0ae 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -499,6 +499,9 @@ static Tesselator_color_t Tesselator_color = (Tesselator_color_t) 0x52a48; // SoundEngine +typedef void (*SoundEngine_init_t)(unsigned char *sound_engine, unsigned char *minecraft, unsigned char *options); +static SoundEngine_init_t SoundEngine_init = (SoundEngine_init_t) 0x67760; + typedef void (*SoundEngine_enable_t)(unsigned char *sound_engine, bool state); static SoundEngine_enable_t SoundEngine_enable = (SoundEngine_enable_t) 0x6776c;