From d851a8f3e10ac83401d97a23a957aa57b362d938 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Sat, 11 Sep 2021 23:18:12 -0400 Subject: [PATCH] 2.2.0 --- CMakeLists.txt | 5 + Dockerfile | 4 +- VERSION | 2 +- debian/client-arm | 2 +- debian/client-arm64 | 2 +- debian/client-x86_64 | 2 +- docs/ARCHITECTURE.md | 6 +- docs/BUILDING.md | 2 + docs/CHANGELOG.md | 8 + docs/INSTALL.md | 14 +- docs/README.md | 1 + docs/SOUND.md | 7 + docs/TERMINOLOGY.md | 1 + images/start.png | Bin 31450 -> 31453 bytes .../available-feature-flags | 1 + launcher/src/bootstrap.c | 18 +- libreborn/CMakeLists.txt | 1 + libreborn/include/libreborn/elf.h | 38 +- libreborn/include/libreborn/exec.h | 12 - libreborn/include/libreborn/libreborn.h | 2 +- libreborn/include/libreborn/log.h | 4 +- libreborn/src/reborn.c | 4 +- media-layer/core/CMakeLists.txt | 9 +- media-layer/core/src/audio/api.cpp | 104 ++++++ media-layer/core/src/audio/engine.c | 85 +++++ media-layer/core/src/audio/engine.h | 15 + media-layer/core/src/audio/file.cpp | 241 +++++++++++++ media-layer/core/src/audio/file.h | 14 + media-layer/core/src/base.cpp | 2 +- media-layer/core/src/media.c | 45 ++- media-layer/core/src/screenshot.c | 4 +- media-layer/extras/src/SDL.c | 2 +- media-layer/include/media-layer/audio.h | 12 + .../{libreborn => }/media-layer/core.h | 0 .../{libreborn => }/media-layer/internal.h | 0 media-layer/proxy/src/common/common.c | 2 +- media-layer/proxy/src/common/common.h | 2 +- media-layer/proxy/src/media-layer-core.c | 64 +++- mods/CMakeLists.txt | 87 ++--- mods/src/atlas/atlas.cpp | 2 +- mods/src/camera/camera.cpp | 4 +- mods/src/chat/chat.cpp | 10 +- mods/src/chat/chat.h | 4 + mods/src/chat/ui.c | 2 + mods/src/compat/compat.c | 11 +- mods/src/compat/egl.c | 2 +- mods/src/compat/x11.c | 2 +- mods/src/creative/creative.cpp | 2 +- mods/src/death/death.cpp | 2 +- mods/src/game-mode/game-mode.c | 2 +- mods/src/game-mode/game-mode.cpp | 2 +- mods/src/home/home.c | 2 +- mods/src/init/init.c | 11 +- mods/src/init/init.h | 11 +- mods/src/input/attack.c | 2 +- mods/src/input/bow.c | 2 +- mods/src/input/drop.cpp | 2 +- mods/src/input/input.cpp | 2 +- mods/src/input/misc.c | 2 +- mods/src/input/toggle.c | 2 +- mods/src/misc/misc.c | 15 +- mods/src/misc/misc.cpp | 2 +- mods/src/multiplayer/multiplayer.cpp | 5 +- mods/src/options/options.c | 2 +- mods/src/override/override.c | 30 +- mods/src/override/override.h | 11 + mods/src/server/server.cpp | 2 +- mods/src/sign/sign.cpp | 2 +- mods/src/sound/README.md | 2 + mods/src/sound/repository.cpp | 335 ++++++++++++++++++ mods/src/sound/sound.cpp | 119 +++++++ mods/src/sound/sound.h | 5 + mods/src/textures/textures.cpp | 2 +- mods/src/touch/touch.c | 2 +- mods/src/version/version.cpp | 2 +- scripts/install-dependencies.sh | 5 +- scripts/package.sh | 2 +- symbols/CMakeLists.txt | 4 + .../include/symbols}/minecraft.h | 35 +- 79 files changed, 1307 insertions(+), 180 deletions(-) create mode 100644 docs/SOUND.md create mode 100644 media-layer/core/src/audio/api.cpp create mode 100644 media-layer/core/src/audio/engine.c create mode 100644 media-layer/core/src/audio/engine.h create mode 100644 media-layer/core/src/audio/file.cpp create mode 100644 media-layer/core/src/audio/file.h create mode 100644 media-layer/include/media-layer/audio.h rename media-layer/include/{libreborn => }/media-layer/core.h (100%) rename media-layer/include/{libreborn => }/media-layer/internal.h (100%) create mode 100644 mods/src/override/override.h create mode 100644 mods/src/sound/README.md create mode 100644 mods/src/sound/repository.cpp create mode 100644 mods/src/sound/sound.cpp create mode 100644 mods/src/sound/sound.h create mode 100644 symbols/CMakeLists.txt rename {libreborn/include/libreborn => symbols/include/symbols}/minecraft.h (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b301179e..2ca206e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,11 @@ if(BUILD_NATIVE_COMPONENTS) add_subdirectory(launcher) endif() +# Include Symbols +if(BUILD_ARM_COMPONENTS) + add_subdirectory(symbols) +endif() + # Build Mods if(BUILD_ARM_COMPONENTS) add_subdirectory(mods) diff --git a/Dockerfile b/Dockerfile index 51ff52f0..96baa5f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM debian:bullseye +FROM debian:bullseye-slim # Copy DEB -ADD ./out/minecraft-pi-reborn-server_*~bullseye_amd64.deb /root +ADD ./out/minecraft-pi-reborn-server_*_amd64.deb /root # Install RUN \ diff --git a/VERSION b/VERSION index ebf14b46..ccbccc3d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.8 +2.2.0 diff --git a/debian/client-arm b/debian/client-arm index 392fc8f0..7d98f969 100644 --- a/debian/client-arm +++ b/debian/client-arm @@ -4,4 +4,4 @@ Maintainer: TheBrokenRail Description: Fun with Blocks Homepage: https://www.minecraft.net/en-us/edition/pi Architecture: armhf -Depends: libc6, libstdc++6, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3 +Depends: libc6, libstdc++6, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1 diff --git a/debian/client-arm64 b/debian/client-arm64 index 95ef9bb3..d89a362a 100644 --- a/debian/client-arm64 +++ b/debian/client-arm64 @@ -4,4 +4,4 @@ Maintainer: TheBrokenRail Description: Fun with Blocks Homepage: https://www.minecraft.net/en-us/edition/pi Architecture: arm64 -Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3 +Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1 diff --git a/debian/client-x86_64 b/debian/client-x86_64 index d10adf80..59d8eafc 100644 --- a/debian/client-x86_64 +++ b/debian/client-x86_64 @@ -4,4 +4,4 @@ Maintainer: TheBrokenRail Description: Fun with Blocks Homepage: https://www.minecraft.net/en-us/edition/pi Architecture: amd64 -Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, qemu-user-static +Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1, qemu-user-static diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4fd3feac..d88e0838 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -36,6 +36,7 @@ This sub-component re-implements a subset of SDL 1.2 calls with GLFW. It also pr The utility functions include: * Taking Screenshots * Fullscreen +* Audio * Etc This is always compiled for the host system's architecture. @@ -87,17 +88,20 @@ This component contains various utility functions including: * Code Patching (ARM Only) * Logging -* MCPI Symbols * Etc The code patching is ARM only because it relies on hard-coded ARM instructions. However, this is irrelevant since code patching is only needed in ARM code (to patch MCPI). +### ``symbols`` +This component contains all MCPI symbols. + ## Dependencies MCPI-Reborn has several dependencies: * MCPI (Bundled) * GLFW (Only In Client Mode) * Open GL ES 1.1 * EGL +* OpenAL (Only In Client Mode) * ZLib (Required By LibPNG; Bundled) * LibPNG (Bundled) * FreeImage (Only In Client Mode) diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 640f566c..cd805878 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -24,6 +24,7 @@ * Client Mode Only * GLFW * FreeImage + * OpenAL ## Runtime Dependencies * Non-ARM Host Architectures @@ -33,6 +34,7 @@ * OpenGL ES 1.1 * GLFW * FreeImage + * OpenAL * Zenity ## Two-Step Build diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3fc226b9..fef2fc49 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +**2.2.0** +* Sound Support +* Split Off "Allow Joining Survival Servers" From Game-Mode Mod +* Separate Headless Code From Server Code +* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened +* Clean-Up Code +* Remove Support For Debian Buster + **2.1.8** * Fix Crash On ARM Systems diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 4a001d2f..1d63d43f 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,25 +1,21 @@ # Manual Installation [Download Packages Here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/) +## Supported Distributions +* Ubuntu 20.04+ +* Debian Bullseye+ + ## Picking A Package ### Name Format ``` -minecraft-pi-reborn-_X.Y.Z~_ +minecraft-pi-reborn-_X.Y.Z_ ``` ### Picking A Variant * ``client``: Client mode, use this if you want to play MCPI * ``server``: Server mode, use this if you want to host a dedicated MCPI server -### Picking A Distribution -This specifies which version of Debian MCPI-Reborn was built against. Which one you should use depends on your current distribution. If your distribution supports it, you should use ``bullseye`` for better mouse sensitivity. - -* Ubuntu 20.04+: ``bullseye`` -* Raspberry Pi OS Buster: ``buster`` -* Debian Bullseye+: ``bullseye`` -* Debian Buster: ``buster`` - ### Picking An Architecture * ``amd64``: x86_64, use this if you are using a device with an AMD or Intel processor * ``armhf``: ARM 32-Bit, use this if you are using an ARM device (like a Raspberry Pi) diff --git a/docs/README.md b/docs/README.md index 92b055c2..a62d74f9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,4 +8,5 @@ * [View Architecture](ARCHITECTURE.md) * [View Command Line Arguments](COMMAND_LINE.md) * [View Multiplayer](MULTIPLAYER.md) +* [View Sound](SOUND.md) * [View Changelog](CHANGELOG.md) diff --git a/docs/SOUND.md b/docs/SOUND.md new file mode 100644 index 00000000..f438a1d8 --- /dev/null +++ b/docs/SOUND.md @@ -0,0 +1,7 @@ +# Sound +One of MCPI-Reborn's main modifications is a sound-engine since MCPI doesn't include one by default[^1]. However, it can't be used out-of-box because MCPI doesn't contain any sound data and MCPI-Reborn can't include it because of copyright. + +MCPE's sound data can be extracted from any MCPE v0.6.1[^2] APK file, just place its `libminecraftpe.so` into `~/.minecraft-pi/overrides` and you should have sound! + +[^1]: The mute button is just leftover code from MCPE, it doesn't actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine. +[^2]: This isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it. diff --git a/docs/TERMINOLOGY.md b/docs/TERMINOLOGY.md index c8274d50..cbfd0cb8 100644 --- a/docs/TERMINOLOGY.md +++ b/docs/TERMINOLOGY.md @@ -2,6 +2,7 @@ | Name | Description | | --- | --- | | MCPI | Shorthand for Minecraft: Pi Edition | +| MCPE | Shorthand for Minecraft: Pocket Edition | | Host Architecture | The native architecture of the CPU that MCPi-Reborn will be running on | | Native Component | A component that *can* be compiled for the host architecture | | ARM Component | A component that *must* be compiled for ARM | diff --git a/images/start.png b/images/start.png index 7c7cd97045abb386ed4beb175b7a9d4bc9106f4d..189cbc74dc49c85c9fc2d71fba62d4286e6aec0f 100644 GIT binary patch delta 8400 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 delta 8425 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 F{{V|eb;1Au diff --git a/launcher/client-data/opt/minecraft-pi-reborn-client/available-feature-flags b/launcher/client-data/opt/minecraft-pi-reborn-client/available-feature-flags index 440e76bd..c961bf6d 100644 --- a/launcher/client-data/opt/minecraft-pi-reborn-client/available-feature-flags +++ b/launcher/client-data/opt/minecraft-pi-reborn-client/available-feature-flags @@ -25,3 +25,4 @@ TRUE Bind Common Toggleable Options To Function Keys TRUE Render Selected Item Text TRUE External Server Support TRUE Load Language Files +TRUE Implement Sound Engine diff --git a/launcher/src/bootstrap.c b/launcher/src/bootstrap.c index 813c5ae9..4f7f46f9 100644 --- a/launcher/src/bootstrap.c +++ b/launcher/src/bootstrap.c @@ -8,7 +8,6 @@ #include #include -#define FORCE_PROC_FOR_ROOT_PATH #include #include "bootstrap.h" @@ -190,14 +189,6 @@ void bootstrap(int argc, char *argv[]) { setenv("QEMU_LD_PREFIX", "/usr/arm-linux-gnueabihf", 1); #endif - // Select Executable Interpreter -#ifdef __ARM_ARCH -#define EXE_INTERPRETER "/lib/ld-linux-armhf.so.3" -#else - // Use Static QEMU So It Isn't Affected By LD_* Variables -#define EXE_INTERPRETER "qemu-arm-static" -#endif - // Create Full Path char *full_path = NULL; safe_asprintf(&full_path, "%s/" MCPI_NAME, binary_directory); @@ -205,6 +196,14 @@ void bootstrap(int argc, char *argv[]) { // Free Binary Directory free(binary_directory); +#ifdef __ARM_ARCH + // Mark argc As Used + (void) argc; + // Run + safe_execvpe(full_path, argv, environ); +#else + // Use Static QEMU So It Isn't Affected By LD_* Variables +#define EXE_INTERPRETER "qemu-arm-static" // Create Arguments List char *new_argv[argc + 2]; for (int i = 1; i <= argc; i++) { @@ -214,4 +213,5 @@ void bootstrap(int argc, char *argv[]) { new_argv[1] = full_path; // Path To MCPI // Run safe_execvpe(EXE_INTERPRETER, new_argv, environ); +#endif } diff --git a/libreborn/CMakeLists.txt b/libreborn/CMakeLists.txt index 3a2bbcd2..8eea982f 100644 --- a/libreborn/CMakeLists.txt +++ b/libreborn/CMakeLists.txt @@ -6,6 +6,7 @@ target_include_directories(reborn-headers INTERFACE include) if(BUILD_ARM_COMPONENTS) add_library(reborn SHARED src/reborn.c) target_link_libraries(reborn dl reborn-headers) + target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE) # Install install(TARGETS reborn DESTINATION "${MCPI_LIB_DIR}") endif() diff --git a/libreborn/include/libreborn/elf.h b/libreborn/include/libreborn/elf.h index e6a94af0..1a3fd488 100644 --- a/libreborn/include/libreborn/elf.h +++ b/libreborn/include/libreborn/elf.h @@ -4,53 +4,46 @@ #include #include #include +#include #include "log.h" #include "exec.h" // Find And Iterate Over All .text Sections In Current Binary -typedef void (*text_section_callback_t)(Elf32_Addr section, Elf32_Word size, void *data); +typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data); static inline void iterate_text_sections(text_section_callback_t callback, void *data) { - // Find Main Binary - char *real_path = NULL; - { - char *binary_directory = get_binary_directory(); - safe_asprintf(&real_path, "%s/minecraft-pi", binary_directory); - free(binary_directory); - } - // Load Main Binary - FILE *file_obj = fopen(real_path, "rb"); + FILE *file_obj = fopen("/proc/self/exe", "rb"); // Verify Binary if (!file_obj) { - ERR("Unable To Open Binary: %s", real_path); + ERR("%s", "Unable To Open Current Binary"); } // Get File Size fseek(file_obj, 0L, SEEK_END); - long int size = ftell(file_obj); + long int file_size = ftell(file_obj); fseek(file_obj, 0L, SEEK_SET); // Map File To Pointer - unsigned char *file_map = (unsigned char *) mmap(0, size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0); + unsigned char *file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0); // Parse ELF - Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map; - Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff); + ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_map; + ElfW(Shdr) *elf_section_headers = (ElfW(Shdr) *) (file_map + elf_header->e_shoff); int elf_section_header_count = elf_header->e_shnum; // Locate Section Names - Elf32_Shdr elf_strtab = elf_section_headers[elf_header->e_shstrndx]; - unsigned char *elf_strtab_p = file_map + elf_strtab.sh_offset; + ElfW(Shdr) elf_shstrtab = elf_section_headers[elf_header->e_shstrndx]; + unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset; // Track .text Sections int text_sections = 0; // Iterate Sections for (int i = 0; i < elf_section_header_count; ++i) { - Elf32_Shdr header = elf_section_headers[i]; - char *name = (char *) (elf_strtab_p + header.sh_name); + ElfW(Shdr) header = elf_section_headers[i]; + char *name = (char *) (elf_shstrtab_p + header.sh_name); // Check Section Type if (strcmp(name, ".text") == 0) { // .text Section @@ -61,13 +54,10 @@ static inline void iterate_text_sections(text_section_callback_t callback, void // Ensure At Least .text Section Was Scanned if (text_sections < 1) { - ERR("Unable To Find .text Sectons On: %s", real_path); + ERR("%s", "Unable To Find .text Sectons"); } - // Free Binary Path - free(real_path); - // Unmap And Close File - munmap(file_map, size); + munmap(file_map, file_size); fclose(file_obj); } diff --git a/libreborn/include/libreborn/exec.h b/libreborn/include/libreborn/exec.h index 76250b1d..85628c0c 100644 --- a/libreborn/include/libreborn/exec.h +++ b/libreborn/include/libreborn/exec.h @@ -21,15 +21,6 @@ __attribute__((noreturn)) static inline void safe_execvpe(const char *pathname, } // Get Binary Directory (Remember To Free) static inline char *get_binary_directory() { -#ifndef FORCE_PROC_FOR_ROOT_PATH - { - // Check Environment - char *specified_root = getenv("MCPI_ROOT_PATH"); - if (specified_root != NULL) { - return strdup(specified_root); - } - } -#endif // Get Path To Current Executable char *exe = realpath("/proc/self/exe", NULL); ALLOC_CHECK(exe); @@ -43,9 +34,6 @@ static inline char *get_binary_directory() { } } - // Set Environment - setenv("MCPI_ROOT_PATH", exe, 1); - // Return return exe; } diff --git a/libreborn/include/libreborn/libreborn.h b/libreborn/include/libreborn/libreborn.h index 6852a8ad..93771b2b 100644 --- a/libreborn/include/libreborn/libreborn.h +++ b/libreborn/include/libreborn/libreborn.h @@ -10,7 +10,7 @@ extern "C" { #include "exec.h" #include "elf.h" -#ifdef __arm__ +#ifdef REBORN_HAS_COMPILED_CODE // Patching Functions diff --git a/libreborn/include/libreborn/log.h b/libreborn/include/libreborn/log.h index 7350d034..9333b21f 100644 --- a/libreborn/include/libreborn/log.h +++ b/libreborn/include/libreborn/log.h @@ -6,5 +6,5 @@ // Logging #define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", __VA_ARGS__); } #define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", __VA_ARGS__); } -#define ERR(format, ...) { fprintf(stderr, "[ERR]: " format "\n", __VA_ARGS__); exit(EXIT_FAILURE); } -#define IMPOSSIBLE() ERR("(%s:%i) This Should Never Be Called", __FILE__, __LINE__) +#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, __VA_ARGS__); exit(EXIT_FAILURE); } +#define IMPOSSIBLE() ERR("%s", "This Should Never Be Called") diff --git a/libreborn/src/reborn.c b/libreborn/src/reborn.c index 9b2fa658..80efe15f 100644 --- a/libreborn/src/reborn.c +++ b/libreborn/src/reborn.c @@ -44,7 +44,7 @@ struct overwrite_data { void *replacement; int found; }; -static void overwrite_calls_callback(Elf32_Addr section_addr, Elf32_Word size, void *data) { +static void overwrite_calls_callback(ElfW(Addr) section_addr, ElfW(Word) size, void *data) { struct overwrite_data *args = (struct overwrite_data *) data; void *section = (void *) section_addr; @@ -122,12 +122,14 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) { // Increment Code Block Position increment_code_block(); + // Check if (data.found < 1) { ERR("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) start); } } // Overwrite Function +// NOTE: "start" Must Be At Least 8 Bytes Long void _overwrite(const char *file, int line, void *start, void *target) { unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]" diff --git a/media-layer/core/CMakeLists.txt b/media-layer/core/CMakeLists.txt index bd702376..bd2f4e74 100644 --- a/media-layer/core/CMakeLists.txt +++ b/media-layer/core/CMakeLists.txt @@ -2,6 +2,9 @@ project(media-layer-core) # Configuration set(CORE_SRC src/base.cpp src/media.c src/screenshot.c) # SDL Re-Implementation Using GLFW +if(NOT MCPI_HEADLESS_MODE) + list(APPEND CORE_SRC src/audio/api.cpp src/audio/engine.c src/audio/file.cpp) +endif() # Build if(MCPI_USE_MEDIA_LAYER_PROXY AND BUILD_NATIVE_COMPONENTS) @@ -23,8 +26,10 @@ if(TARGET media-layer-core) find_package(glfw3 3.3 REQUIRED) # Find FreeImage find_library(FREEIMAGE_LIBRARY NAMES freeimage libfreeimage.so.3 REQUIRED) - # Not Needed In Server Mode - target_link_libraries(media-layer-core "${FREEIMAGE_LIBRARY}" GLESv1_CM glfw) + # OpenAL + find_library(OPENAL_LIBRARY NAMES openal REQUIRED) + # Link + target_link_libraries(media-layer-core "${FREEIMAGE_LIBRARY}" "${OPENAL_LIBRARY}" m GLESv1_CM glfw) endif() endif() diff --git a/media-layer/core/src/audio/api.cpp b/media-layer/core/src/audio/api.cpp new file mode 100644 index 00000000..9d1f5db6 --- /dev/null +++ b/media-layer/core/src/audio/api.cpp @@ -0,0 +1,104 @@ +#include +#include + +#include + +#include +#include + +#include "file.h" +#include "engine.h" + +// Store Audio Sources +static std::vector &get_sources() { + static std::vector sources; + return sources; +} + +#define AL_ERROR_CHECK() \ + { \ + ALenum err = alGetError(); \ + if (err != AL_NO_ERROR) { \ + ERR("OpenAL Error: %s", alGetString(err)); \ + } \ + } + +// Update Listener +void media_audio_update(float volume, float x, float y, float z, float yaw) { + // Update Listener Volume + alListenerf(AL_GAIN, volume); + AL_ERROR_CHECK(); + + // Update Listener Position + alListener3f(AL_POSITION, x, y, z); + AL_ERROR_CHECK(); + + // Update Listener Orientation + float radian_yaw = yaw * (M_PI / 180); + ALfloat orientation[] = {-sinf(radian_yaw), 0.0f, cosf(radian_yaw), 0.0f, 1.0f, 0.0f}; + alListenerfv(AL_ORIENTATION, orientation); + AL_ERROR_CHECK(); + + // Clear Finished Sources + std::vector::iterator it = get_sources().begin(); + while (it != get_sources().end()) { + ALuint source = *it; + // 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); + AL_ERROR_CHECK(); + } else { + // Still Playing + ++it; + } + } +} + +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) { + // Create Source + ALuint al_source; + alGenSources(1, &al_source); + AL_ERROR_CHECK(); + + // Set Properties + alSourcef(al_source, AL_PITCH, pitch); + AL_ERROR_CHECK(); + alSourcef(al_source, AL_GAIN, volume); + AL_ERROR_CHECK(); + alSource3f(al_source, AL_POSITION, x, y, z); + AL_ERROR_CHECK(); + alSource3f(al_source, AL_VELOCITY, 0, 0, 0); + AL_ERROR_CHECK(); + alSourcei(al_source, AL_LOOPING, AL_FALSE); + AL_ERROR_CHECK(); + alSourcei(al_source, AL_SOURCE_RELATIVE, is_ui ? AL_TRUE : AL_FALSE); + AL_ERROR_CHECK(); + + // Set Attenuation + alSourcei(al_source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE); + AL_ERROR_CHECK(); + alSourcef(al_source, AL_MAX_DISTANCE, 16.0f); + AL_ERROR_CHECK(); + alSourcef(al_source, AL_ROLLOFF_FACTOR, 1.0f); + AL_ERROR_CHECK(); + alSourcef(al_source, AL_REFERENCE_DISTANCE, 0.0f); + AL_ERROR_CHECK(); + + // Set Buffer + alSourcei(al_source, AL_BUFFER, buffer); + AL_ERROR_CHECK(); + + // Play + alSourcePlay(al_source); + AL_ERROR_CHECK(); + get_sources().push_back(al_source); + } +} diff --git a/media-layer/core/src/audio/engine.c b/media-layer/core/src/audio/engine.c new file mode 100644 index 00000000..18ee667a --- /dev/null +++ b/media-layer/core/src/audio/engine.c @@ -0,0 +1,85 @@ +#include +#include +#include + +#include + +#include "engine.h" +#include "file.h" + +// Store Device +static ALCdevice *device = NULL; +static ALCcontext *context = NULL; + +// Store State +static int is_loaded = 0; +int _media_audio_is_loaded() { + return is_loaded; +} + +// Init +void _media_audio_init() { + // Open Device + device = alcOpenDevice(NULL); + if (!device) { + WARN("%s", "Unable To Load Audio Engine"); + return; + } + + // Create Context + context = alcCreateContext(device, NULL); + ALCenum err = alcGetError(device); + if (err != ALC_NO_ERROR) { + ERR("Unable To Open Audio Context: %s", alcGetString(device, err)); + } + + // Select Context + alcMakeContextCurrent(context); + err = alcGetError(device); + if (err != ALC_NO_ERROR) { + ERR("Unable To Select Audio Context: %s", alcGetString(device, err)); + } + + // Enable AL_SOURCE_DISTANCE_MODEL + alEnable(AL_SOURCE_DISTANCE_MODEL); + ALenum al_err = alGetError(); + if (al_err != AL_NO_ERROR) { + ERR("Unable To Enable AL_SOURCE_DISTANCE_MODEL: %s", alGetString(al_err)); + } + + // Log + INFO("%s", "Loaded Audio Engine"); + is_loaded = 1; +} + +// De-Init +void _media_audio_cleanup() { + if (_media_audio_is_loaded()) { + // Delete Audio Buffers + _media_audio_delete_buffers(); + + // Deselect Context + alcMakeContextCurrent(NULL); + ALCenum err = alcGetError(device); + if (err != ALC_NO_ERROR) { + ERR("Unable To Deselect Audio Context: %s", alcGetString(device, err)); + } + + // Destroy Context + alcDestroyContext(context); + err = alcGetError(device); + if (err != ALC_NO_ERROR) { + ERR("Unable To Destroy Audio Context: %s", alcGetString(device, err)); + } + + // Close Device + alcCloseDevice(device); + err = alcGetError(device); + if (err != ALC_NO_ERROR) { + ERR("Unable To Close Audio Device: %s", alcGetString(device, err)); + } + + // Log + INFO("%s", "Unloaded Audio Engine"); + } +} diff --git a/media-layer/core/src/audio/engine.h b/media-layer/core/src/audio/engine.h new file mode 100644 index 00000000..69e70f0c --- /dev/null +++ b/media-layer/core/src/audio/engine.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((visibility("internal"))) void _media_audio_init(); +__attribute__((visibility("internal"))) void _media_audio_cleanup(); +__attribute__((visibility("internal"))) int _media_audio_is_loaded(); + +#ifdef __cplusplus +} +#endif diff --git a/media-layer/core/src/audio/file.cpp b/media-layer/core/src/audio/file.cpp new file mode 100644 index 00000000..9bbba331 --- /dev/null +++ b/media-layer/core/src/audio/file.cpp @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "file.h" +#include "engine.h" + +// Load Symbol From ELF File +static void load_symbol(const char *source, const char *name, std::function callback) { + // File Data + FILE *file_obj = NULL; + unsigned char *file_map = NULL; + long int file_size = 0; + + // Code + { + // Load Main Binary + file_obj = fopen(source, "rb"); + + // Verify Binary + if (!file_obj) { + WARN("Unable To Open: %s", source); + goto end; + } + + // Get File Size + fseek(file_obj, 0L, SEEK_END); + file_size = ftell(file_obj); + fseek(file_obj, 0L, SEEK_SET); + + // Map File To Pointer + file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0); + + // Check ELF Magic + if (file_map[EI_MAG0] != ELFMAG0 || file_map[EI_MAG1] != ELFMAG1 || file_map[EI_MAG2] != ELFMAG2 || file_map[EI_MAG3] != ELFMAG3) { + WARN("Not An ELF File: %s", source); + goto end; + } + if (file_map[EI_CLASS] != ELFCLASS32) { + WARN("ELF File Isn't 32-Bit: %s", source); + goto end; + } + if (file_map[EI_DATA] != ELFDATA2LSB) { + WARN("ELF File Isn't Little-Endian: %s", source); + goto end; + } + + // Parse ELF + Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map; + Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff); + int elf_section_header_count = elf_header->e_shnum; + + // Locate Section Names + Elf32_Shdr elf_shstrtab = elf_section_headers[elf_header->e_shstrndx]; + unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset; + + // Locate String Table + unsigned char *elf_strtab_p = NULL; + for (int i = 0; i < elf_section_header_count; ++i) { + Elf32_Shdr header = elf_section_headers[i]; + // Check Section Type + if (header.sh_type == SHT_STRTAB) { + // Check Section Name + char *section_name = (char *) (elf_shstrtab_p + header.sh_name); + if (strcmp(section_name, ".dynstr") == 0) { + // Found + elf_strtab_p = file_map + header.sh_offset; + break; + } + } + } + if (elf_strtab_p == NULL) { + WARN("Unable To Find String Table In: %s", source); + goto end; + } + + // Locate Symbol Tables + Elf32_Sym *symbol = NULL; + for (int i = 0; i < elf_section_header_count; ++i) { + // Exit Loop If Finished + if (symbol != NULL) { + break; + } + // Get Section Header + Elf32_Shdr header = elf_section_headers[i]; + // Check Section Type + if (header.sh_type == SHT_DYNSYM) { + // Symbol Table + Elf32_Sym *table = (Elf32_Sym *) (file_map + header.sh_offset); + for (int j = 0; (j * sizeof (Elf32_Sym)) < header.sh_size; j++) { + // Check Symbol Name + char *symbol_name = (char *) (elf_strtab_p + table[j].st_name); + if (strcmp(symbol_name, name) == 0) { + // Found + symbol = &table[j]; + break; + } + } + } + } + + // Check Symbol + if (symbol != NULL) { + // Convert Virtual Address To File Offset + Elf32_Shdr symbol_section_header = elf_section_headers[symbol->st_shndx]; + int vaddr_to_offset = -symbol_section_header.sh_addr + symbol_section_header.sh_offset; + Elf32_Off symbol_offset = symbol->st_value + vaddr_to_offset; + // Access Symbol + unsigned char *value = file_map + symbol_offset; + uint32_t size = symbol->st_size; + callback(value, size); + } else { + // Unable To Find Symbol + WARN("Unable To Find Symbol: %s", name); + } + } + + end: + // Unmap And Close File + if (file_map != NULL) { + munmap(file_map, file_size); + } + if (file_obj != NULL) { + fclose(file_obj); + } +} + +// Audio Metadata +struct audio_metadata { + int32_t channels; + int32_t frame_size; + int32_t sample_rate; + int32_t frames; +}; + +// Load Sound Symbol Into ALunit +static ALuint load_sound(const char *source, const char *name) { + // Check OpenAL + if (!_media_audio_is_loaded()) { + return 0; + } + + // Store Result + ALuint buffer = 0; + + // Load Symbol + load_symbol(source, name, [name, &buffer](unsigned char *symbol, uint32_t size) { + // Load Metadata + if (size < sizeof (audio_metadata)) { + WARN("Symbol Too Small To Contain Audio Metadata: %s", name); + return; + } + audio_metadata *meta = (audio_metadata *) symbol; + + // Check Frame Size + if (meta->frame_size != 1 && meta->frame_size != 2) { + WARN("Unsupported Frame Size: %s: %i", name, meta->frame_size); + return; + } + + // Get Audio Format + ALenum format = AL_NONE; + if (meta->channels == 1) { + format = meta->frame_size == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8; + } else if (meta->channels == 2) { + format = meta->frame_size == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8; + } else { + WARN("Unsupported Channel Count: %s: %i", name, meta->channels); + return; + } + + // Load Data + int remaining_size = size - sizeof (audio_metadata); + int data_size = meta->channels * meta->frames * meta->frame_size; + if (remaining_size < data_size) { + WARN("Symbol Too Small To Contain Specified Audio Data: %s", name); + return; + } + unsigned char *data = symbol + sizeof (audio_metadata); + + // Create Buffer + alGenBuffers(1, &buffer); + alBufferData(buffer, format, data, data_size, meta->sample_rate); + + // Check OpenAL Error + ALenum err = alGetError(); + if (err != AL_NO_ERROR) { + WARN("Unable To Store Audio Buffer: %s", alGetString(err)); + if (buffer && alIsBuffer(buffer)) { + alDeleteBuffers(1, &buffer); + } + buffer = 0; + } + }); + + // Return + return buffer; +} + +// Store Buffers +static std::unordered_map &get_buffers() { + static std::unordered_map buffers; + return buffers; +} + +// Get Buffer For Sound +ALuint _media_audio_get_buffer(const char *source, const char *name) { + // Check + if (_media_audio_is_loaded()) { + if (get_buffers().count(name) > 0) { + // Return + return get_buffers()[name]; + } else { + // Load And Return + get_buffers()[name] = load_sound(source, name); + return _media_audio_get_buffer(source, name); + } + } else { + return 0; + } +} + +// Delete Buffers +void _media_audio_delete_buffers() { + if (_media_audio_is_loaded()) { + for (auto it : get_buffers()) { + if (it.second && alIsBuffer(it.second)) { + alDeleteBuffers(1, &it.second); + } + } + } + get_buffers().clear(); +} diff --git a/media-layer/core/src/audio/file.h b/media-layer/core/src/audio/file.h new file mode 100644 index 00000000..f68f8cbf --- /dev/null +++ b/media-layer/core/src/audio/file.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((visibility("internal"))) ALuint _media_audio_get_buffer(const char *source, const char *name); +__attribute__((visibility("internal"))) void _media_audio_delete_buffers(); + +#ifdef __cplusplus +} +#endif diff --git a/media-layer/core/src/base.cpp b/media-layer/core/src/base.cpp index 9b17b1d8..491d5724 100644 --- a/media-layer/core/src/base.cpp +++ b/media-layer/core/src/base.cpp @@ -4,7 +4,7 @@ #include -#include +#include // SDL Is Replaced With GLFW diff --git a/media-layer/core/src/media.c b/media-layer/core/src/media.c index f23c821e..e9898ea6 100644 --- a/media-layer/core/src/media.c +++ b/media-layer/core/src/media.c @@ -9,10 +9,12 @@ #endif // #ifndef MCPI_HEADLESS_MODE #include -#include -#include +#include +#include -// GLFW Code Not Needed In Server Mode +#include "audio/engine.h" + +// GLFW Code Not Needed In Headless Mode #ifndef MCPI_HEADLESS_MODE static GLFWwindow *glfw_window; @@ -196,10 +198,14 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_ #endif // #ifndef MCPI_HEADLESS_MODE -// Init GLFW +// Track Media Layer State +static int is_running = 0; + +// Init Media Layer void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *icon) { - // Don't Enable GLFW In Server Mode + // Don't Enable GLFW In Headless Mode #ifndef MCPI_HEADLESS_MODE + // Init GLFW glfwSetErrorCallback(glfw_error); if (!glfwInit()) { @@ -221,7 +227,7 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic ERR("%s", "Unable To Create GLFW Window"); } - // Don't Process Events In Server Mode + // Don't Process Events In Headless Mode glfwSetKeyCallback(glfw_window, glfw_key); glfwSetCharCallback(glfw_window, glfw_char); glfwSetCursorPosCallback(glfw_window, glfw_motion); @@ -229,9 +235,15 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic glfwSetScrollCallback(glfw_window, glfw_scroll); glfwMakeContextCurrent(glfw_window); + + // Init OpenAL + _media_audio_init(); #else // #ifndef MCPI_HEADLESS_MODE (void) title; // Mark As Used #endif // #ifndef MCPI_HEADLESS_MODE + + // Set State + is_running = 1; } void media_swap_buffers() { @@ -241,7 +253,7 @@ void media_swap_buffers() { #endif // #ifndef MCPI_HEADLESS_MODE } -// Fullscreen Not Needed In Server Mode +// Fullscreen Not Needed In Headless Mode #ifndef MCPI_HEADLESS_MODE static int is_fullscreen = 0; @@ -278,7 +290,7 @@ void media_toggle_fullscreen() { // Intercept SDL Events void _media_handle_SDL_PollEvent() { - // GLFW Is Disabled In Server Mode + // GLFW And Audio Are Disabled Disabled In Headless Mode #ifndef MCPI_HEADLESS_MODE // Process GLFW Events glfwPollEvents(); @@ -293,13 +305,22 @@ void _media_handle_SDL_PollEvent() { #endif // #ifndef MCPI_HEADLESS_MODE } -// Terminate GLFW +// Cleanup Media Layer void media_cleanup() { - // GLFW Is Disabled In Server Mode + if (is_running) { + // GLFW And Audio Are Disabled In Headless Mode #ifndef MCPI_HEADLESS_MODE - glfwDestroyWindow(glfw_window); - glfwTerminate(); + // Terminate GLFW + glfwDestroyWindow(glfw_window); + glfwTerminate(); + + // Cleanup OpenAL + _media_audio_cleanup(); #endif // #ifndef MCPI_HEADLESS_MODE + + // Update State + is_running = 0; + } } // Store Cursor State diff --git a/media-layer/core/src/screenshot.c b/media-layer/core/src/screenshot.c index d388980e..22c6c368 100644 --- a/media-layer/core/src/screenshot.c +++ b/media-layer/core/src/screenshot.c @@ -1,4 +1,4 @@ -// Screenshot Code Is Useless In Server Mode +// Screenshot Code Is Useless In Headless Mode #ifndef MCPI_HEADLESS_MODE #include @@ -14,7 +14,7 @@ #include #include -#include +#include // Ensure Screenshots Folder Exists static void ensure_screenshots_folder(char *screenshots) { diff --git a/media-layer/extras/src/SDL.c b/media-layer/extras/src/SDL.c index 8b302365..e7a6b4b7 100644 --- a/media-layer/extras/src/SDL.c +++ b/media-layer/extras/src/SDL.c @@ -4,7 +4,7 @@ #include #include -#include +#include // SDL Stub void *SDL_SetVideoMode(__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags) { diff --git a/media-layer/include/media-layer/audio.h b/media-layer/include/media-layer/audio.h new file mode 100644 index 00000000..264437e9 --- /dev/null +++ b/media-layer/include/media-layer/audio.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +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); + +#ifdef __cplusplus +} +#endif diff --git a/media-layer/include/libreborn/media-layer/core.h b/media-layer/include/media-layer/core.h similarity index 100% rename from media-layer/include/libreborn/media-layer/core.h rename to media-layer/include/media-layer/core.h diff --git a/media-layer/include/libreborn/media-layer/internal.h b/media-layer/include/media-layer/internal.h similarity index 100% rename from media-layer/include/libreborn/media-layer/internal.h rename to media-layer/include/media-layer/internal.h diff --git a/media-layer/proxy/src/common/common.c b/media-layer/proxy/src/common/common.c index 28b71760..2aca6911 100644 --- a/media-layer/proxy/src/common/common.c +++ b/media-layer/proxy/src/common/common.c @@ -135,7 +135,7 @@ char *read_string() { return strdup(str); } #define MAX_STRING_SIZE 256 -void write_string(char *str) { +void write_string(const char *str) { unsigned char is_null = str == NULL; write_byte(is_null); if (!is_null) { diff --git a/media-layer/proxy/src/common/common.h b/media-layer/proxy/src/common/common.h index 31ffab01..97a30eda 100644 --- a/media-layer/proxy/src/common/common.h +++ b/media-layer/proxy/src/common/common.h @@ -44,7 +44,7 @@ __attribute__((visibility("internal"))) void write_float(float x); // Read/Write Strings __attribute__((visibility("internal"))) char *read_string(); // Remember To free() -__attribute__((visibility("internal"))) void write_string(char *str); +__attribute__((visibility("internal"))) void write_string(const char *str); // Manipulate Connection __attribute__((visibility("internal"))) void set_connection(int read, int write); diff --git a/media-layer/proxy/src/media-layer-core.c b/media-layer/proxy/src/media-layer-core.c index 73953a99..850466d2 100644 --- a/media-layer/proxy/src/media-layer-core.c +++ b/media-layer/proxy/src/media-layer-core.c @@ -3,8 +3,9 @@ #include #include -#include -#include +#include +#include +#include #include "common/common.h" @@ -356,3 +357,62 @@ CALL(10, media_get_framebuffer_size, void, (int *width, int *height)) { write_int((uint32_t) height); #endif } + +CALL(59, media_audio_update, void, (float volume, float x, float y, float z, float yaw)) { +#if defined(MEDIA_LAYER_PROXY_SERVER) + // Lock Proxy + start_proxy_call(); + + // Arguments + write_float(volume); + write_float(x); + write_float(y); + write_float(z); + write_float(yaw); + + // Release Proxy + end_proxy_call(); +#else + float volume = read_float(); + float x = read_float(); + float y = read_float(); + float z = read_float(); + float yaw = read_float(); + // Run + media_audio_update(volume, x, y, z, yaw); +#endif +} + +CALL(60, media_audio_play, void, (const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui)) { +#if defined(MEDIA_LAYER_PROXY_SERVER) + // Lock Proxy + start_proxy_call(); + + // Arguments + write_string(source); + write_string(name); + write_float(x); + write_float(y); + write_float(z); + write_float(pitch); + write_float(volume); + write_int(is_ui); + + // Release Proxy + end_proxy_call(); +#else + char *source = read_string(); + char *name = read_string(); + float x = read_float(); + float y = read_float(); + float z = read_float(); + float pitch = read_float(); + float volume = read_float(); + int is_ui = read_int(); + // Run + media_audio_play(source, name, x, y, z, pitch, volume, is_ui); + // Free + free(source); + free(name); +#endif +} diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index d193e4cc..7b3e4f26 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -8,7 +8,7 @@ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) ## Mods add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c) -target_link_libraries(compat feature input chat sign media-layer-core home dl) +target_link_libraries(compat reborn media-layer-core) add_library(readdir SHARED src/readdir/readdir.c) @@ -16,73 +16,80 @@ add_library(feature SHARED src/feature/feature.c) target_link_libraries(feature reborn) add_library(version SHARED src/version/version.cpp) -target_link_libraries(version reborn) +target_link_libraries(version reborn symbols) + +add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c) +target_link_libraries(chat reborn symbols feature pthread) if(MCPI_SERVER_MODE) add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp) - target_link_libraries(server reborn feature home compat version dl media-layer-core pthread) + target_link_libraries(server reborn symbols feature home compat version dl media-layer-core pthread) else() + target_link_libraries(compat input sign chat home dl) + + target_link_libraries(chat input) + add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp) - target_link_libraries(multiplayer reborn home feature) + target_link_libraries(multiplayer reborn symbols home feature) + + add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp) + target_link_libraries(sound reborn symbols feature override media-layer-core) + + add_library(camera SHARED src/camera/camera.cpp) + target_link_libraries(camera reborn symbols media-layer-core feature home) + + add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp) + target_link_libraries(input reborn symbols feature media-layer-core) + + add_library(sign SHARED src/sign/sign.cpp) + target_link_libraries(sign reborn symbols feature input) + + add_library(creative SHARED src/creative/creative.cpp) + target_link_libraries(creative reborn symbols feature) + + add_library(touch SHARED src/touch/touch.c) + target_link_libraries(touch reborn symbols feature) + + add_library(override SHARED src/override/override.c) + target_link_libraries(override reborn symbols dl home) + + add_library(textures SHARED src/textures/textures.cpp) + target_link_libraries(textures reborn symbols feature) + + add_library(atlas SHARED src/atlas/atlas.cpp) + target_link_libraries(atlas reborn symbols feature GLESv1_CM) endif() -add_library(camera SHARED src/camera/camera.cpp) -target_link_libraries(camera reborn media-layer-core feature home) - add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/game-mode.cpp) -target_link_libraries(game-mode reborn feature) - -add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp) -target_link_libraries(input reborn feature media-layer-core) - -add_library(sign SHARED src/sign/sign.cpp) -target_link_libraries(sign reborn feature input) +target_link_libraries(game-mode reborn symbols feature) add_library(death SHARED src/death/death.cpp) -target_link_libraries(death reborn feature) +target_link_libraries(death reborn symbols feature) add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp) -target_link_libraries(misc reborn feature) - -add_library(creative SHARED src/creative/creative.cpp) -target_link_libraries(creative reborn feature) +target_link_libraries(misc reborn symbols feature) add_library(options SHARED src/options/options.c) -target_link_libraries(options reborn feature) - -add_library(touch SHARED src/touch/touch.c) -target_link_libraries(touch reborn feature) - -add_library(override SHARED src/override/override.c) -target_link_libraries(override reborn dl home) - -add_library(textures SHARED src/textures/textures.cpp) -target_link_libraries(textures reborn feature) - -add_library(atlas SHARED src/atlas/atlas.cpp) -target_link_libraries(atlas reborn feature GLESv1_CM) - -add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c) -target_link_libraries(chat reborn feature input pthread) +target_link_libraries(options reborn symbols feature) add_library(home SHARED src/home/home.c) -target_link_libraries(home reborn) +target_link_libraries(home reborn symbols) add_library(test SHARED src/test/test.c) target_link_libraries(test reborn home) add_library(init SHARED src/init/init.c) -target_link_libraries(init compat game-mode camera input sign misc creative death options touch textures atlas chat home version test) +target_link_libraries(init compat game-mode misc death options chat home version test) if(MCPI_SERVER_MODE) target_link_libraries(init server) else() - target_link_libraries(init multiplayer) + target_link_libraries(init multiplayer sound camera input sign creative touch textures atlas) endif() ## Install Mods -install(TARGETS init compat readdir feature override game-mode camera input sign misc creative death options touch textures atlas chat home version test DESTINATION "${MCPI_INSTALL_DIR}/mods") +install(TARGETS init compat readdir feature game-mode misc death options chat home version test DESTINATION "${MCPI_INSTALL_DIR}/mods") if(MCPI_SERVER_MODE) install(TARGETS server DESTINATION "${MCPI_INSTALL_DIR}/mods") else() - install(TARGETS multiplayer DESTINATION "${MCPI_INSTALL_DIR}/mods") + install(TARGETS multiplayer sound override camera input sign creative touch textures atlas DESTINATION "${MCPI_INSTALL_DIR}/mods") endif() diff --git a/mods/src/atlas/atlas.cpp b/mods/src/atlas/atlas.cpp index bd0b4c31..a9ffd3de 100644 --- a/mods/src/atlas/atlas.cpp +++ b/mods/src/atlas/atlas.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include "../feature/feature.h" #include "../init/init.h" diff --git a/mods/src/camera/camera.cpp b/mods/src/camera/camera.cpp index f4adb914..ba999524 100644 --- a/mods/src/camera/camera.cpp +++ b/mods/src/camera/camera.cpp @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include "../feature/feature.h" #include "../home/home.h" diff --git a/mods/src/chat/chat.cpp b/mods/src/chat/chat.cpp index f23aacb0..ed17e872 100644 --- a/mods/src/chat/chat.cpp +++ b/mods/src/chat/chat.cpp @@ -5,11 +5,13 @@ #include #include -#include +#include #include "../init/init.h" #include "../feature/feature.h" +#ifndef MCPI_SERVER_MODE #include "../input/input.h" +#endif // #ifndef MCPI_SERVER_MODE #include "chat.h" // Store If Chat is Enabled @@ -19,6 +21,7 @@ int _chat_enabled = 0; #define MAX_CHAT_MESSAGE_LENGTH 512 // Send API Command +#ifndef MCPI_SERVER_MODE static void send_api_command(unsigned char *minecraft, char *str) { struct ConnectedClient client; client.sock = -1; @@ -36,6 +39,7 @@ static void send_api_chat_command(unsigned char *minecraft, char *str) { send_api_command(minecraft, command); free(command); } +#endif // #ifndef MCPI_SERVER_MODE // Send Message To Players static void send_message(unsigned char *server_side_network_handler, char *username, char *message) { @@ -76,6 +80,7 @@ static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char * } } +#ifndef MCPI_SERVER_MODE // Message Queue static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; static std::vector queue; @@ -110,6 +115,7 @@ static void send_queued_messages(unsigned char *minecraft) { // Unlock pthread_mutex_unlock(&queue_mutex); } +#endif // #ifndef MCPI_SERVER_MODE // Init void init_chat() { @@ -123,6 +129,8 @@ void init_chat() { // Re-Broadcast ChatPacket patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, (void *) ServerSideNetworkHandler_handle_ChatPacket_injection); // Send Messages On Input Tick +#ifndef MCPI_SERVER_MODE input_run_on_tick(send_queued_messages); +#endif // #ifndef MCPI_SERVER_MODE } } diff --git a/mods/src/chat/chat.h b/mods/src/chat/chat.h index 0beccbf5..07d4e9b2 100644 --- a/mods/src/chat/chat.h +++ b/mods/src/chat/chat.h @@ -4,11 +4,15 @@ extern "C" { #endif +#ifndef MCPI_SERVER_MODE void chat_open(); unsigned int chat_get_counter(); +#endif // #ifndef MCPI_SERVER_MODE __attribute__((visibility("internal"))) extern int _chat_enabled; +#ifndef MCPI_SERVER_MODE __attribute__((visibility("internal"))) void _chat_queue_message(char *message); +#endif // #ifndef MCPI_SERVER_MODE #ifdef __cplusplus } diff --git a/mods/src/chat/ui.c b/mods/src/chat/ui.c index 6fea1013..06187f76 100644 --- a/mods/src/chat/ui.c +++ b/mods/src/chat/ui.c @@ -1,3 +1,4 @@ +#ifndef MCPI_SERVER_MODE #include #include #include @@ -86,3 +87,4 @@ void chat_open() { pthread_create(&thread, NULL, chat_thread, NULL); } } +#endif // #ifndef MCPI_SERVER_MODE diff --git a/mods/src/compat/compat.c b/mods/src/compat/compat.c index 7d2a842b..5c2e0e81 100644 --- a/mods/src/compat/compat.c +++ b/mods/src/compat/compat.c @@ -1,17 +1,19 @@ #include #include +#include "compat.h" +#include "../init/init.h" + +#ifndef MCPI_SERVER_MODE #include -#include +#include #include #include "../input/input.h" #include "../sign/sign.h" #include "../chat/chat.h" #include "../home/home.h" -#include "../init/init.h" -#include "compat.h" // Custom Title HOOK(SDL_WM_SetCaption, void, (__attribute__((unused)) const char *title, const char *icon)) { @@ -29,7 +31,6 @@ HOOK(SDL_ShowCursor, int, (int toggle)) { // Intercept SDL Events HOOK(SDL_PollEvent, int, (SDL_Event *event)) { // In Server Mode, Exit Requests Are Handled In src/server/server.cpp -#ifndef MCPI_SERVER_MODE // Check If Exit Is Requested if (compat_check_exit_requested()) { // Send SDL_QUIT @@ -37,7 +38,6 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { new_event.type = SDL_QUIT; SDL_PushEvent(&new_event); } -#endif // #ifndef MCPI_SERVER_MODE // Poll Events ensure_SDL_PollEvent(); @@ -106,6 +106,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { return ret; } +#endif // #ifndef MCPI_SERVER_MODE // Exit Handler static void exit_handler(__attribute__((unused)) int data) { diff --git a/mods/src/compat/egl.c b/mods/src/compat/egl.c index 6cb54598..42fbf048 100644 --- a/mods/src/compat/egl.c +++ b/mods/src/compat/egl.c @@ -1,7 +1,7 @@ #include #include -#include +#include // Functions That Have Their Return Values Used static EGLSurface eglCreateWindowSurface_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) { diff --git a/mods/src/compat/x11.c b/mods/src/compat/x11.c index 9beeba40..27dbb73f 100644 --- a/mods/src/compat/x11.c +++ b/mods/src/compat/x11.c @@ -1,7 +1,7 @@ #include #include -#include +#include // Functions That Have Their Return Values Used static int XTranslateCoordinates_injection(__attribute__((unused)) void *display, __attribute__((unused)) XID src_w, __attribute__((unused)) XID dest_w, int src_x, int src_y, int *dest_x_return, int *dest_y_return, __attribute__((unused)) XID *child_return) { diff --git a/mods/src/creative/creative.cpp b/mods/src/creative/creative.cpp index 009f7ee8..8f869ae3 100644 --- a/mods/src/creative/creative.cpp +++ b/mods/src/creative/creative.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "../init/init.h" #include "../feature/feature.h" diff --git a/mods/src/death/death.cpp b/mods/src/death/death.cpp index 70d603e6..5a2e5a45 100644 --- a/mods/src/death/death.cpp +++ b/mods/src/death/death.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include "../init/init.h" #include "../feature/feature.h" diff --git a/mods/src/game-mode/game-mode.c b/mods/src/game-mode/game-mode.c index 833c9adc..9d0b3cec 100644 --- a/mods/src/game-mode/game-mode.c +++ b/mods/src/game-mode/game-mode.c @@ -3,7 +3,7 @@ #include "../feature/feature.h" #include -#include +#include static int is_survival = -1; diff --git a/mods/src/game-mode/game-mode.cpp b/mods/src/game-mode/game-mode.cpp index 1d39e341..0fa98a92 100644 --- a/mods/src/game-mode/game-mode.cpp +++ b/mods/src/game-mode/game-mode.cpp @@ -2,7 +2,7 @@ #include "game-mode.h" -#include +#include // Get Minecraft From Screen static unsigned char *get_minecraft_from_screen(unsigned char *screen) { diff --git a/mods/src/home/home.c b/mods/src/home/home.c index 71052953..5edbafb5 100644 --- a/mods/src/home/home.c +++ b/mods/src/home/home.c @@ -1,5 +1,5 @@ #include -#include +#include #include "home.h" #include "../init/init.h" diff --git a/mods/src/init/init.c b/mods/src/init/init.c index be4e30a7..a3117c33 100644 --- a/mods/src/init/init.c +++ b/mods/src/init/init.c @@ -7,18 +7,19 @@ __attribute__((constructor)) static void init() { init_server(); #else init_multiplayer(); -#endif - init_game_mode(); + init_sound(); init_input(); init_sign(); - init_misc(); init_creative(); - init_death(); init_camera(); - init_options(); init_touch(); init_textures(); init_atlas(); +#endif + init_game_mode(); + init_misc(); + init_death(); + init_options(); init_chat(); init_home(); init_version(); diff --git a/mods/src/init/init.h b/mods/src/init/init.h index 062c80f4..226e1439 100644 --- a/mods/src/init/init.h +++ b/mods/src/init/init.h @@ -10,18 +10,19 @@ void init_compat(); void init_server(); #else void init_multiplayer(); -#endif -void init_game_mode(); +void init_sound(); void init_input(); void init_sign(); -void init_misc(); void init_creative(); -void init_death(); void init_camera(); -void init_options(); void init_touch(); void init_textures(); void init_atlas(); +#endif +void init_game_mode(); +void init_misc(); +void init_death(); +void init_options(); void init_chat(); void init_home(); void init_version(); diff --git a/mods/src/input/attack.c b/mods/src/input/attack.c index 3060ded7..c23c538e 100644 --- a/mods/src/input/attack.c +++ b/mods/src/input/attack.c @@ -1,5 +1,5 @@ #include -#include +#include #include "../feature/feature.h" #include "input.h" diff --git a/mods/src/input/bow.c b/mods/src/input/bow.c index deebbdf5..80a8f2eb 100644 --- a/mods/src/input/bow.c +++ b/mods/src/input/bow.c @@ -1,5 +1,5 @@ #include -#include +#include #include "../feature/feature.h" #include "input.h" diff --git a/mods/src/input/drop.cpp b/mods/src/input/drop.cpp index 411fb42f..68037228 100644 --- a/mods/src/input/drop.cpp +++ b/mods/src/input/drop.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "input.h" #include "../feature/feature.h" diff --git a/mods/src/input/input.cpp b/mods/src/input/input.cpp index 4346ca02..d83b4ca0 100644 --- a/mods/src/input/input.cpp +++ b/mods/src/input/input.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include "../feature/feature.h" #include "../init/init.h" diff --git a/mods/src/input/misc.c b/mods/src/input/misc.c index 50daf8d1..da0a18df 100644 --- a/mods/src/input/misc.c +++ b/mods/src/input/misc.c @@ -1,5 +1,5 @@ #include -#include +#include #include "input.h" #include "../feature/feature.h" diff --git a/mods/src/input/toggle.c b/mods/src/input/toggle.c index 8595a943..2b8f7e69 100644 --- a/mods/src/input/toggle.c +++ b/mods/src/input/toggle.c @@ -1,5 +1,5 @@ #include -#include +#include #include "input.h" #include "../feature/feature.h" diff --git a/mods/src/misc/misc.c b/mods/src/misc/misc.c index 920b311a..3a936cc1 100644 --- a/mods/src/misc/misc.c +++ b/mods/src/misc/misc.c @@ -3,7 +3,7 @@ #include #include -#include +#include #include "../init/init.h" #include "../feature/feature.h" @@ -107,6 +107,16 @@ static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection return result; } +// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened +static unsigned char *RakNetInstance_injection(unsigned char *rak_net_instance) { + // Call Original Method + unsigned char *result = (*RakNetInstance)(rak_net_instance); + // Fix + *(unsigned char *) (rak_net_instance + RakNetInstance_pinging_for_hosts_property_offset) = 0; + // Return + return result; +} + // Init void init_misc() { if (feature_has("Remove Invalid Item Background", 0)) { @@ -131,6 +141,9 @@ void init_misc() { // Print Error Message If RakNet Startup Fails overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection); + // Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened + overwrite_calls((void *) RakNetInstance, (void *) RakNetInstance_injection); + // Init C++ _init_misc_cpp(); } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 3a1daeea..7291a073 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include "../feature/feature.h" #include "misc.h" diff --git a/mods/src/multiplayer/multiplayer.cpp b/mods/src/multiplayer/multiplayer.cpp index 3e6a7482..2f2e5f2d 100644 --- a/mods/src/multiplayer/multiplayer.cpp +++ b/mods/src/multiplayer/multiplayer.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include "../home/home.h" #include "../init/init.h" @@ -110,8 +110,9 @@ static void iterate_servers(std::function c } } +// Ping External Servers static void RakNetInstance_pingForHosts_injection(unsigned char *rak_net_instance, int32_t base_port) { - // Call Original + // Call Original Method (*RakNetInstance_pingForHosts)(rak_net_instance, base_port); // Get RakNet::RakPeer diff --git a/mods/src/options/options.c b/mods/src/options/options.c index 852d96c7..6c108e36 100644 --- a/mods/src/options/options.c +++ b/mods/src/options/options.c @@ -1,7 +1,7 @@ #include #include -#include +#include #include "../feature/feature.h" #include "../init/init.h" diff --git a/mods/src/override/override.c b/mods/src/override/override.c index c1301a7b..f7930d65 100644 --- a/mods/src/override/override.c +++ b/mods/src/override/override.c @@ -14,23 +14,35 @@ static int starts_with(const char *s, const char *t) { return strncmp(s, t, strlen(t)) == 0; } -static char *get_override_path(const char *filename) { +char *override_get_path(const char *filename) { // Get MCPI Home Path char *home_path = home_get(); // Get Asset Override Path char *overrides = NULL; safe_asprintf(&overrides, "%s/overrides", home_path); + // Get Data Path char *data = NULL; - char *cwd = getcwd(NULL, 0); - safe_asprintf(&data, "%s/data", cwd); - free(cwd); + char *binary_directory = get_binary_directory(); + safe_asprintf(&data, "%s/data", binary_directory); + free(binary_directory); + int data_length = strlen(data); + // Get Full Path + char *full_path; + if (strlen(filename) > 0 && filename[0] == '/') { + // Absolute Path + full_path = strdup(filename); + } else { + // Relative Path + full_path = realpath(filename, NULL); + } + + // Check For Override char *new_path = NULL; - char *full_path = realpath(filename, NULL); if (full_path != NULL) { if (starts_with(full_path, data)) { - safe_asprintf(&new_path, "%s%s", overrides, &full_path[strlen(data)]); + safe_asprintf(&new_path, "%s%s", overrides, &full_path[data_length]); if (access(new_path, F_OK) == -1) { free(new_path); new_path = NULL; @@ -38,15 +50,17 @@ static char *get_override_path(const char *filename) { } free(full_path); } + // Free Variables free(overrides); free(data); + // Return return new_path; } HOOK(fopen, FILE *, (const char *filename, const char *mode)) { - char *new_path = get_override_path(filename); + char *new_path = override_get_path(filename); // Open File ensure_fopen(); FILE *file = (*real_fopen)(new_path != NULL ? new_path : filename, mode); @@ -59,7 +73,7 @@ HOOK(fopen, FILE *, (const char *filename, const char *mode)) { } HOOK(fopen64, FILE *, (const char *filename, const char *mode)) { - char *new_path = get_override_path(filename); + char *new_path = override_get_path(filename); // Open File ensure_fopen64(); FILE *file = (*real_fopen64)(new_path != NULL ? new_path : filename, mode); diff --git a/mods/src/override/override.h b/mods/src/override/override.h new file mode 100644 index 00000000..331ec466 --- /dev/null +++ b/mods/src/override/override.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +char *override_get_path(const char *filename); + +#ifdef __cplusplus +} +#endif diff --git a/mods/src/server/server.cpp b/mods/src/server/server.cpp index ae187a4c..a748c575 100644 --- a/mods/src/server/server.cpp +++ b/mods/src/server/server.cpp @@ -25,7 +25,7 @@ #include "../compat/compat.h" #include "../version/version.h" -#include +#include // --only-generate: Ony Generate World And Then Exit static bool only_generate = false; diff --git a/mods/src/sign/sign.cpp b/mods/src/sign/sign.cpp index 7fc5b393..23ce2554 100644 --- a/mods/src/sign/sign.cpp +++ b/mods/src/sign/sign.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include "../init/init.h" #include "../feature/feature.h" diff --git a/mods/src/sound/README.md b/mods/src/sound/README.md new file mode 100644 index 00000000..7c8d082b --- /dev/null +++ b/mods/src/sound/README.md @@ -0,0 +1,2 @@ +# ``sound`` Mod +This mod implements a sound engine. diff --git a/mods/src/sound/repository.cpp b/mods/src/sound/repository.cpp new file mode 100644 index 00000000..55f1c7fe --- /dev/null +++ b/mods/src/sound/repository.cpp @@ -0,0 +1,335 @@ +#include +#include +#include +#include +#include + +#include + +#include "sound.h" + +// Sound Repository Extracted From MCPE 0.6.1 APK +static std::unordered_map> repository = { + { + { + "step.cloth", + { + "PCM_cloth1", + "PCM_cloth2", + "PCM_cloth3", + "PCM_cloth4" + } + }, + { + "step.grass", + { + "PCM_grass1", + "PCM_grass2", + "PCM_grass3", + "PCM_grass4" + } + }, + { + "step.gravel", + { + "PCM_gravel1", + "PCM_gravel2", + "PCM_gravel3", + "PCM_gravel4" + } + }, + { + "step.sand", + { + "PCM_sand1", + "PCM_sand2", + "PCM_sand3", + "PCM_sand4" + } + }, + { + "step.stone", + { + "PCM_stone1", + "PCM_stone2", + "PCM_stone3", + "PCM_stone4" + } + }, + { + "step.wood", + { + "PCM_wood1", + "PCM_wood2", + "PCM_wood3", + "PCM_wood4" + } + }, + { + "random.splash", + { + "PCM_splash" + } + }, + { + "random.explode", + { + "PCM_explode" + } + }, + { + "random.click", + { + "PCM_click" + } + }, + { + "random.door_open", + { + "PCM_door_open" + } + }, + { + "random.door_close", + { + "PCM_door_close" + } + }, + { + "random.pop", + { + "PCM_pop" + } + }, + { + "random.pop2", + { + "PCM_pop2" + } + }, + { + "random.hurt", + { + "PCM_hurt" + } + }, + { + "random.glass", + { + "PCM_glass1", + "PCM_glass2", + "PCM_glass3" + } + }, + { + "mob.sheep", + { + "PCM_sheep1", + "PCM_sheep2", + "PCM_sheep3" + } + }, + { + "mob.pig", + { + "PCM_pig1", + "PCM_pig2", + "PCM_pig3" + } + }, + { + "mob.pigdeath", + { + "PCM_pigdeath" + } + }, + { + "mob.cow", + { + "PCM_cow1", + "PCM_cow2", + "PCM_cow3", + "PCM_cow4" + } + }, + { + "mob.cowhurt", + { + "PCM_cowhurt1", + "PCM_cowhurt2", + "PCM_cowhurt3" + } + }, + { + "mob.chicken", + { + "PCM_chicken2", + "PCM_chicken3" + } + }, + { + "mob.chickenhurt", + { + "PCM_chickenhurt1", + "PCM_chickenhurt2" + } + }, + { + "mob.zombie", + { + "PCM_zombie1", + "PCM_zombie2", + "PCM_zombie3" + } + }, + { + "mob.zombiedeath", + { + "PCM_zombiedeath" + } + }, + { + "mob.zombiehurt", + { + "PCM_zombiehurt1", + "PCM_zombiehurt2" + } + }, + { + "mob.skeleton", + { + "PCM_skeleton1", + "PCM_skeleton2", + "PCM_skeleton3" + } + }, + { + "mob.skeletonhurt", + { + "PCM_skeletonhurt1", + "PCM_skeletonhurt2", + "PCM_skeletonhurt3", + "PCM_skeletonhurt4" + } + }, + { + "mob.spider", + { + "PCM_spider1", + "PCM_spider2", + "PCM_spider3", + "PCM_spider4" + } + }, + { + "mob.spiderdeath", + { + "PCM_spiderdeath" + } + }, + { + "mob.zombiepig.zpig", + { + "PCM_zpig1", + "PCM_zpig2", + "PCM_zpig3", + "PCM_zpig4" + } + }, + { + "mob.zombiepig.zpigangry", + { + "PCM_zpigangry1", + "PCM_zpigangry2", + "PCM_zpigangry3", + "PCM_zpigangry4" + } + }, + { + "mob.zombiepig.zpigdeath", + { + "PCM_zpigdeath" + } + }, + { + "mob.zombiepig.zpighurt", + { + "PCM_zpighurt1", + "PCM_zpighurt2" + } + }, + { + "damage.fallbig", + { + "PCM_fallbig1", + "PCM_fallbig2" + } + }, + { + "damage.fallsmall", + { + "PCM_fallsmall" + } + }, + { + "random.bow", + { + "PCM_bow" + } + }, + { + "random.bowhit", + { + "PCM_bowhit1", + "PCM_bowhit2", + "PCM_bowhit3", + "PCM_bowhit4" + } + }, + { + "mob.creeper", + { + "PCM_creeper1", + "PCM_creeper2", + "PCM_creeper3", + "PCM_creeper4" + } + }, + { + "mob.creeperdeath", + { + "PCM_creeperdeath" + } + }, + { + "random.eat", + { + "PCM_eat1", + "PCM_eat2", + "PCM_eat3" + } + }, + { + "random.fuse", + { + "PCM_fuse" + } + } + } +}; + +// Set rand() Seed +__attribute__((constructor)) static void init_rand_seed() { + srand(time(NULL)); +} +// Pick Sound +std::string _sound_pick(std::string sound) { + if (repository.count(sound) > 0) { + // Sound Exists + std::vector &options = repository[sound]; + return options[rand() % options.size()]; + } else { + // Invalid Sound + ERR("Invalid Sound: %s", sound.c_str()); + } +} diff --git a/mods/src/sound/sound.cpp b/mods/src/sound/sound.cpp new file mode 100644 index 00000000..3060e0b2 --- /dev/null +++ b/mods/src/sound/sound.cpp @@ -0,0 +1,119 @@ +#include + +#include +#include +#include + +#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" +static std::string 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_binary_directory(); + + // Get Full Path + char *full_path = NULL; + safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory); + + // Free Binary Directory + free(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 Exists: " SOURCE_FILE_BASE); + source.assign(""); + } else { + // Set + source.assign(full_path); + } + + // Free + free(full_path); + + // Mark As Loaded + source_loaded = true; + + // Return + return 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(); + 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(); + if (source.size() > 0) { + media_audio_play(source.c_str(), _sound_pick(name).c_str(), x, y, z, 1.0f, volume, 0); + } +} + +// 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); +} + +// 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); + } +} diff --git a/mods/src/sound/sound.h b/mods/src/sound/sound.h new file mode 100644 index 00000000..f20c1bfa --- /dev/null +++ b/mods/src/sound/sound.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +__attribute__((visibility("internal"))) std::string _sound_pick(std::string sound); diff --git a/mods/src/textures/textures.cpp b/mods/src/textures/textures.cpp index 897a7e49..450e2e90 100644 --- a/mods/src/textures/textures.cpp +++ b/mods/src/textures/textures.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "../feature/feature.h" #include "../init/init.h" diff --git a/mods/src/touch/touch.c b/mods/src/touch/touch.c index bc136dfd..dae8d7d7 100644 --- a/mods/src/touch/touch.c +++ b/mods/src/touch/touch.c @@ -3,7 +3,7 @@ #include "../feature/feature.h" #include "../init/init.h" -#include +#include // Enable Touch GUI static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) { diff --git a/mods/src/version/version.cpp b/mods/src/version/version.cpp index ac12b277..4ed14e37 100644 --- a/mods/src/version/version.cpp +++ b/mods/src/version/version.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "version.h" #include "../init/init.h" diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh index 958842ff..003b86f4 100755 --- a/scripts/install-dependencies.sh +++ b/scripts/install-dependencies.sh @@ -31,6 +31,7 @@ sudo apt-get install --no-install-recommends -y \ libfreeimage3 libfreeimage-dev \ crossbuild-essential-armhf \ crossbuild-essential-arm64 \ + libopenal-dev \ qemu-user-static # Install ARM Dependencies @@ -38,7 +39,9 @@ if [ ! -z "${ARM_PACKAGES_SUPPORTED}" ]; then sudo apt-get install --no-install-recommends -y \ libglfw3:armhf libglfw3-dev:armhf \ libfreeimage3:armhf \ + libopenal-dev:armhf \ libglfw3:arm64 libglfw3-dev:arm64 \ - libfreeimage3:arm64 + libfreeimage3:arm64 \ + libopenal-dev:arm64 fi diff --git a/scripts/package.sh b/scripts/package.sh index 556e2d25..8541c0a3 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -15,7 +15,7 @@ package() { cp "debian/$1" "${dir}/DEBIAN/control" # Format DEBIAN/control - sed -i "s/\${VERSION}/${VERSION}~$(lsb_release -cs)/g" "${dir}/DEBIAN/control" + sed -i "s/\${VERSION}/${VERSION}/g" "${dir}/DEBIAN/control" # Fix Permissions On Jenkins chmod -R g-s "${dir}" diff --git a/symbols/CMakeLists.txt b/symbols/CMakeLists.txt new file mode 100644 index 00000000..cfa9dc59 --- /dev/null +++ b/symbols/CMakeLists.txt @@ -0,0 +1,4 @@ +project(symbols) + +add_library(symbols INTERFACE) +target_include_directories(symbols INTERFACE include) diff --git a/libreborn/include/libreborn/minecraft.h b/symbols/include/symbols/minecraft.h similarity index 93% rename from libreborn/include/libreborn/minecraft.h rename to symbols/include/symbols/minecraft.h index 4163a75c..5e27d2d2 100644 --- a/libreborn/include/libreborn/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -7,7 +7,7 @@ // bool In C #ifndef __cplusplus -typedef uint32_t bool; +typedef unsigned char bool; #endif // Globals @@ -182,6 +182,7 @@ static uint32_t Options_ambient_occlusion_property_offset = 0x18; // unsigned ch static uint32_t Options_hide_gui_property_offset = 0xec; // unsigned char / bool static uint32_t Options_third_person_property_offset = 0xed; // unsigned char / bool static uint32_t Options_render_distance_property_offset = 0x10; // int32_t +static uint32_t Options_sound_property_offset = 0x4; // int32_t // MouseBuildInput @@ -221,6 +222,15 @@ static uint32_t Player_inventory_property_offset = 0xbe0; // Inventory * typedef void (*Entity_die_t)(unsigned char *entity, unsigned char *cause); static uint32_t Entity_die_vtable_offset = 0x130; +static uint32_t Entity_x_property_offset = 0x4; // float +static uint32_t Entity_y_property_offset = 0x8; // float +static uint32_t Entity_z_property_offset = 0xc; // float +static uint32_t Entity_yaw_property_offset = 0x40; // float +static uint32_t Entity_old_x_property_offset = 0x28; // float +static uint32_t Entity_old_y_property_offset = 0x2c; // float +static uint32_t Entity_old_z_property_offset = 0x30; // float +static uint32_t Entity_old_yaw_property_offset = 0x48; // float + // Mob typedef void (*Mob_actuallyHurt_t)(unsigned char *entity, int32_t damage); @@ -389,7 +399,11 @@ static RakNetInstance_pingForHosts_t RakNetInstance_pingForHosts = (RakNetInstan static uint32_t RakNetInstance_pingForHosts_vtable_offset = 0x14; static void *RakNetInstance_pingForHosts_vtable_addr = (void *) 0x109afc; +typedef unsigned char *(*RakNetInstance_t)(unsigned char *rak_net_instance); +static RakNetInstance_t RakNetInstance = (RakNetInstance_t) 0x73b20; + static uint32_t RakNetInstance_peer_property_offset = 0x4; // RakNet::RakPeer * +static uint32_t RakNetInstance_pinging_for_hosts_property_offset = 0x24; // unsigned char // RakNet::RakPeer @@ -483,6 +497,17 @@ static Tesselator_colorABGR_t Tesselator_colorABGR = (Tesselator_colorABGR_t) 0x typedef void (*Tesselator_color_t)(unsigned char *tesselator, int32_t r, int32_t g, int32_t b, int32_t a); static Tesselator_color_t Tesselator_color = (Tesselator_color_t) 0x52a48; +// SoundEngine + +typedef void (*SoundEngine_enable_t)(unsigned char *sound_engine, bool state); +static SoundEngine_enable_t SoundEngine_enable = (SoundEngine_enable_t) 0x6776c; + +typedef void (*SoundEngine_update_t)(unsigned char *sound_engine, unsigned char *listener_mob, float listener_angle); +static SoundEngine_update_t SoundEngine_update = (SoundEngine_update_t) 0x67778; + +static uint32_t SoundEngine_minecraft_property_offset = 0xa08; // Minecraft * +static uint32_t SoundEngine_options_property_offset = 0x4; // Options * + // Method That Require C++ Types #ifdef __cplusplus @@ -550,6 +575,14 @@ static SelectWorldScreen_getUniqueLevelName_t SelectWorldScreen_getUniqueLevelNa static SelectWorldScreen_getUniqueLevelName_t Touch_SelectWorldScreen_getUniqueLevelName = (SelectWorldScreen_getUniqueLevelName_t) 0x3d82c; +// SoundEngine + +typedef void (*SoundEngine_playUI_t)(unsigned char *sound_engine, std::string const& name, float pitch, float volume); +static SoundEngine_playUI_t SoundEngine_playUI = (SoundEngine_playUI_t) 0x67864; + +typedef void (*SoundEngine_play_t)(unsigned char *sound_engine, std::string const& name, float x, float y, float z, float pitch, float volume); +static SoundEngine_play_t SoundEngine_play = (SoundEngine_play_t) 0x67860; + // Common typedef std::string (*Common_getGameVersionString_t)(std::string const& version_suffix);