minecraft-pi-reborn/mods/src/sound/sound.cpp

124 lines
4.1 KiB
C++

#include <string>
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <media-layer/audio.h>
#include "sound.h"
#include "../feature/feature.h"
#include "../override/override.h"
#include "../init/init.h"
// Resolve Source File Path
#define SOURCE_FILE_BASE "data/libminecraftpe.so"
std::string _sound_get_source_file() {
static bool source_loaded = false;
static std::string source;
// Check
if (source_loaded) {
// Already Resolved
return source;
} else {
// Resolve
// Get Binary Directory
char *binary_directory = get_mcpi_directory();
// Get Full Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory);
// Handle Overrides
char *overridden_full_path = override_get_path(full_path);
if (overridden_full_path != NULL) {
free(full_path);
full_path = overridden_full_path;
}
// Check If Sound Exists
if (access(full_path, F_OK) == -1) {
// Fail
WARN("%s", "Audio Source File Doesn't Exist: " SOURCE_FILE_BASE);
source.assign("");
} else {
// Set
source.assign(full_path);
}
// Free
free(full_path);
// Mark As Loaded
source_loaded = true;
// Return
return _sound_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 play(std::string name, float x, float y, float z, float volume, bool is_ui) {
std::string source = _sound_get_source_file();
std::string resolved_name = _sound_pick(name);
if (source.size() > 0 && resolved_name.size() > 0) {
media_audio_play(source.c_str(), resolved_name.c_str(), x, y, z, 1.0f, volume, is_ui);
}
}
static void SoundEngine_playUI_injection(__attribute__((unused)) unsigned char *sound_engine, std::string const& name, __attribute__((unused)) float pitch, float volume) {
play(name, 0, 0, 0, volume, true);
}
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) {
play(name, x, y, z, volume, false);
}
// Refresh Data
static void SoundEngine_update_injection(unsigned char *sound_engine, unsigned char *listener_mob, __attribute__((unused)) float listener_angle) {
// Variables
static float volume = 0;
static float x = 0;
static float y = 0;
static float z = 0;
static float yaw = 0;
// SoundEngine Properties
unsigned char *options = *(unsigned char **) (sound_engine + SoundEngine_options_property_offset);
// Volume
int32_t sound_enabled = *(int32_t *) (options + Options_sound_property_offset);
volume = sound_enabled ? 1 : 0;
// Position And Rotation
if (listener_mob != NULL) {
// Values
x = *(float *) (listener_mob + Entity_x_property_offset);
y = *(float *) (listener_mob + Entity_y_property_offset);
z = *(float *) (listener_mob + Entity_z_property_offset);
yaw = *(float *) (listener_mob + Entity_yaw_property_offset);
}
// Log
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
if (feature_has("Implement Sound Engine", 0)) {
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);
}
}