This commit is contained in:
parent
a762654e35
commit
d851a8f3e1
@ -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)
|
||||
|
@ -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 \
|
||||
|
2
debian/client-arm
vendored
2
debian/client-arm
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
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
|
||||
|
2
debian/client-arm64
vendored
2
debian/client-arm64
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
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
|
||||
|
2
debian/client-x86_64
vendored
2
debian/client-x86_64
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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-<Variant>_X.Y.Z~<Distribution>_<Architecture>
|
||||
minecraft-pi-reborn-<Variant>_X.Y.Z_<Architecture>
|
||||
```
|
||||
|
||||
### 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)
|
||||
|
@ -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)
|
||||
|
7
docs/SOUND.md
Normal file
7
docs/SOUND.md
Normal file
@ -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.
|
@ -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 |
|
||||
|
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -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
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define FORCE_PROC_FOR_ROOT_PATH
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -4,53 +4,46 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ extern "C" {
|
||||
#include "exec.h"
|
||||
#include "elf.h"
|
||||
|
||||
#ifdef __arm__
|
||||
#ifdef REBORN_HAS_COMPILED_CODE
|
||||
|
||||
// Patching Functions
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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]"
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
104
media-layer/core/src/audio/api.cpp
Normal file
104
media-layer/core/src/audio/api.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include <media-layer/audio.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "engine.h"
|
||||
|
||||
// Store Audio Sources
|
||||
static std::vector<ALuint> &get_sources() {
|
||||
static std::vector<ALuint> 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<ALuint>::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);
|
||||
}
|
||||
}
|
85
media-layer/core/src/audio/engine.c
Normal file
85
media-layer/core/src/audio/engine.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alext.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
15
media-layer/core/src/audio/engine.h
Normal file
15
media-layer/core/src/audio/engine.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#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
|
241
media-layer/core/src/audio/file.cpp
Normal file
241
media-layer/core/src/audio/file.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <elf.h>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "engine.h"
|
||||
|
||||
// Load Symbol From ELF File
|
||||
static void load_symbol(const char *source, const char *name, std::function<void(unsigned char *, uint32_t)> 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<std::string, ALuint> &get_buffers() {
|
||||
static std::unordered_map<std::string, ALuint> 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();
|
||||
}
|
14
media-layer/core/src/audio/file.h
Normal file
14
media-layer/core/src/audio/file.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#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
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
// SDL Is Replaced With GLFW
|
||||
|
||||
|
@ -9,10 +9,12 @@
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
// 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
|
||||
// Terminate GLFW
|
||||
glfwDestroyWindow(glfw_window);
|
||||
glfwTerminate();
|
||||
|
||||
// Cleanup OpenAL
|
||||
_media_audio_cleanup();
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
// Update State
|
||||
is_running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Store Cursor State
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Screenshot Code Is Useless In Server Mode
|
||||
// Screenshot Code Is Useless In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -14,7 +14,7 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// Ensure Screenshots Folder Exists
|
||||
static void ensure_screenshots_folder(char *screenshots) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// SDL Stub
|
||||
void *SDL_SetVideoMode(__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags) {
|
||||
|
12
media-layer/include/media-layer/audio.h
Normal file
12
media-layer/include/media-layer/audio.h
Normal file
@ -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
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -3,8 +3,9 @@
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <media-layer/audio.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
@ -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)
|
||||
endif()
|
||||
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 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)
|
||||
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 feature media-layer-core)
|
||||
target_link_libraries(input reborn symbols feature media-layer-core)
|
||||
|
||||
add_library(sign SHARED src/sign/sign.cpp)
|
||||
target_link_libraries(sign reborn feature input)
|
||||
|
||||
add_library(death SHARED src/death/death.cpp)
|
||||
target_link_libraries(death reborn feature)
|
||||
|
||||
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp)
|
||||
target_link_libraries(misc reborn feature)
|
||||
target_link_libraries(sign reborn symbols feature input)
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative reborn feature)
|
||||
|
||||
add_library(options SHARED src/options/options.c)
|
||||
target_link_libraries(options reborn feature)
|
||||
target_link_libraries(creative reborn symbols feature)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.c)
|
||||
target_link_libraries(touch reborn feature)
|
||||
target_link_libraries(touch reborn symbols feature)
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
target_link_libraries(override reborn dl home)
|
||||
target_link_libraries(override reborn symbols dl home)
|
||||
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
target_link_libraries(textures reborn feature)
|
||||
target_link_libraries(textures reborn symbols feature)
|
||||
|
||||
add_library(atlas SHARED src/atlas/atlas.cpp)
|
||||
target_link_libraries(atlas reborn feature GLESv1_CM)
|
||||
target_link_libraries(atlas reborn symbols feature GLESv1_CM)
|
||||
endif()
|
||||
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat reborn feature input pthread)
|
||||
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/game-mode.cpp)
|
||||
target_link_libraries(game-mode reborn symbols feature)
|
||||
|
||||
add_library(death SHARED src/death/death.cpp)
|
||||
target_link_libraries(death reborn symbols feature)
|
||||
|
||||
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp)
|
||||
target_link_libraries(misc reborn symbols feature)
|
||||
|
||||
add_library(options SHARED src/options/options.c)
|
||||
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()
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../home/home.h"
|
||||
|
@ -5,11 +5,13 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#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<std::string> 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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
@ -86,3 +87,4 @@ void chat_open() {
|
||||
pthread_create(&thread, NULL, chat_thread, NULL);
|
||||
}
|
||||
}
|
||||
#endif // #ifndef MCPI_SERVER_MODE
|
||||
|
@ -1,17 +1,19 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "../init/init.h"
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#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) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// 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) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// 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) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../init/init.h"
|
||||
#include "../feature/feature.h"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../init/init.h"
|
||||
#include "../feature/feature.h"
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "../feature/feature.h"
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
static int is_survival = -1;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "game-mode.h"
|
||||
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Get Minecraft From Screen
|
||||
static unsigned char *get_minecraft_from_screen(unsigned char *screen) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "home.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "input.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "input.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "../feature/feature.h"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "../feature/feature.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "../feature/feature.h"
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "misc.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../home/home.h"
|
||||
#include "../init/init.h"
|
||||
@ -110,8 +110,9 @@ static void iterate_servers(std::function<void(const char *address, int port)> 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -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);
|
||||
|
11
mods/src/override/override.h
Normal file
11
mods/src/override/override.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *override_get_path(const char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -25,7 +25,7 @@
|
||||
#include "../compat/compat.h"
|
||||
#include "../version/version.h"
|
||||
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// --only-generate: Ony Generate World And Then Exit
|
||||
static bool only_generate = false;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../init/init.h"
|
||||
#include "../feature/feature.h"
|
||||
|
2
mods/src/sound/README.md
Normal file
2
mods/src/sound/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# ``sound`` Mod
|
||||
This mod implements a sound engine.
|
335
mods/src/sound/repository.cpp
Normal file
335
mods/src/sound/repository.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
// Sound Repository Extracted From MCPE 0.6.1 APK
|
||||
static std::unordered_map<std::string, std::vector<std::string>> 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<std::string> &options = repository[sound];
|
||||
return options[rand() % options.size()];
|
||||
} else {
|
||||
// Invalid Sound
|
||||
ERR("Invalid Sound: %s", sound.c_str());
|
||||
}
|
||||
}
|
119
mods/src/sound/sound.cpp
Normal file
119
mods/src/sound/sound.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#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"
|
||||
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);
|
||||
}
|
||||
}
|
5
mods/src/sound/sound.h
Normal file
5
mods/src/sound/sound.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
__attribute__((visibility("internal"))) std::string _sound_pick(std::string sound);
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Enable Touch GUI
|
||||
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/minecraft.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "../init/init.h"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}"
|
||||
|
4
symbols/CMakeLists.txt
Normal file
4
symbols/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
project(symbols)
|
||||
|
||||
add_library(symbols INTERFACE)
|
||||
target_include_directories(symbols INTERFACE include)
|
@ -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);
|
Loading…
Reference in New Issue
Block a user