Compare commits
13 Commits
fae728061a
...
89c29f14b1
Author | SHA1 | Date | |
---|---|---|---|
89c29f14b1 | |||
4edfaeead4 | |||
bfcdd3c7e9 | |||
5467b5178f | |||
8f49c550ba | |||
50eb4801a0 | |||
a3eef9fc3b | |||
f455780833 | |||
0150879d2b | |||
623cf06516 | |||
0b1849a9ad | |||
157d51e6b6 | |||
ed58356dd8 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,5 +6,6 @@ CMakeLists.txt.user
|
||||
*.autosave
|
||||
AppImageBuilder.yml
|
||||
appimage-builder-cache
|
||||
appimage-build
|
||||
AppDir
|
||||
*.zsync
|
||||
|
2
dependencies/glfw/src
vendored
2
dependencies/glfw/src
vendored
@ -1 +1 @@
|
||||
Subproject commit 955fbd9d265fa95adf9cb94896eb9a516aa50420
|
||||
Subproject commit 4cb36872a5fe448c205d0b46f0e8c8b57530cfe0
|
2
dependencies/zlib/src
vendored
2
dependencies/zlib/src
vendored
@ -1 +1 @@
|
||||
Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f
|
||||
Subproject commit 21767c654d31d2dccdde4330529775c6c5fd5389
|
@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
**2.3.4**
|
||||
* AppImage Fixes
|
||||
* Make Death Messages Customizable Server-Side
|
||||
* Fix Q-Key Behavior Behavior When Editing Signs
|
||||
* Add ``Force Touch Inventory`` Feature Flag (Disabled By Default)
|
||||
* Add ``Fix Pause Menu`` Feature Flag (Enabled By Default)
|
||||
* Enables Server Visibility Toggle Button
|
||||
* Options Changes (Not Supported On Legacy)
|
||||
* Add ``Fix Options Screen`` Feature Flag (Enabled By Default)
|
||||
* Adds Options Button To Classic UI Start Screen
|
||||
* Removes Useless Options Toggles
|
||||
* Fixes Options Toggles' Default Position
|
||||
* Store Multiple Settings In `options.txt`
|
||||
* ``Peaceful Mode`` Feature Flag Moved To ``game_difficulty``
|
||||
* ``Smooth Lighting`` Feature Flag Moved To ``gfx_ao``
|
||||
* ``Fancy Graphics`` Feature Flag Moved To ``gfx_fancygraphics``
|
||||
* ``Disable Hosting LAN Worlds`` Feature Flag Moved To ``mp_server_visible_default``
|
||||
|
||||
**2.3.3**
|
||||
* Add More Blocks To Expanded Creative Inventory
|
||||
* Add AppStream Metadata
|
||||
|
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -2,18 +2,15 @@ TRUE Touch GUI
|
||||
TRUE Fix Bow & Arrow
|
||||
TRUE Fix Attacking
|
||||
FALSE Force Mob Spawning
|
||||
TRUE Fancy Graphics
|
||||
TRUE Disable Autojump By Default
|
||||
TRUE Display Nametags By Default
|
||||
TRUE Fix Sign Placement
|
||||
TRUE Show Block Outlines
|
||||
FALSE Expand Creative Inventory
|
||||
FALSE Remove Creative Mode Restrictions
|
||||
FALSE Peaceful Mode
|
||||
TRUE Animated Water
|
||||
TRUE Remove Invalid Item Background
|
||||
TRUE Disable "gui_blocks" Atlas
|
||||
TRUE Smooth Lighting
|
||||
FALSE 3D Anaglyph
|
||||
TRUE Fix Camera Rendering
|
||||
TRUE Implement Chat
|
||||
@ -31,6 +28,8 @@ TRUE Implement Sound Engine
|
||||
TRUE Close Current Screen On Death
|
||||
FALSE Disable Raw Mouse Motion (Not Recommended)
|
||||
TRUE Fix Furnace Not Checking Item Auxiliary
|
||||
FALSE Disable Hosting LAN Worlds
|
||||
TRUE Improved Cursor Rendering
|
||||
FALSE Disable V-Sync
|
||||
TRUE Fix Options Screen
|
||||
FALSE Force Touch Inventory
|
||||
TRUE Fix Pause Menu
|
||||
|
@ -180,7 +180,7 @@ void pre_bootstrap() {
|
||||
|
||||
// Bootstrap
|
||||
void bootstrap(int argc, char *argv[]) {
|
||||
INFO("%s", "Configuring Game...");
|
||||
INFO("Configuring Game...");
|
||||
|
||||
// Get Binary Directory
|
||||
char *binary_directory = get_binary_directory();
|
||||
@ -197,7 +197,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
// Resolve Binary Path & Set MCPI_DIRECTORY
|
||||
{
|
||||
// Log
|
||||
DEBUG("%s", "Resolving File Paths...");
|
||||
DEBUG("Resolving File Paths...");
|
||||
|
||||
// Resolve Full Binary Path
|
||||
char *full_path = NULL;
|
||||
@ -218,21 +218,22 @@ void bootstrap(int argc, char *argv[]) {
|
||||
// Fix MCPI Dependencies
|
||||
{
|
||||
// Log
|
||||
DEBUG("%s", "Patching ELF Dependencies...");
|
||||
DEBUG("Patching ELF Dependencies...");
|
||||
|
||||
// Find Linker
|
||||
char *linker = NULL;
|
||||
// Preserve Existing Linker On ARM
|
||||
#ifndef __arm__
|
||||
safe_asprintf(&linker, "%s/usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3", usr_prefix);
|
||||
#else
|
||||
safe_asprintf(&linker, "/lib/ld-linux-armhf.so.3");
|
||||
#endif
|
||||
|
||||
// Patch
|
||||
patch_mcpi_elf_dependencies(linker);
|
||||
|
||||
// Free Linker Path
|
||||
free(linker);
|
||||
if (linker != NULL) {
|
||||
free(linker);
|
||||
}
|
||||
|
||||
// Verify
|
||||
if (!starts_with(getenv("MCPI_EXECUTABLE_PATH"), "/tmp")) {
|
||||
@ -240,10 +241,16 @@ void bootstrap(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// AppImage
|
||||
#ifdef MCPI_IS_APPIMAGE_BUILD
|
||||
// Mark Patched MCPI As Part Of AppImage
|
||||
set_and_print_env("APPDIR_MODULE_DIR", getenv("MCPI_EXECUTABLE_PATH"));
|
||||
#endif
|
||||
|
||||
// Configure LD_LIBRARY_PATH
|
||||
{
|
||||
// Log
|
||||
DEBUG("%s", "Setting Linker Search Paths...");
|
||||
DEBUG("Setting Linker Search Paths...");
|
||||
|
||||
// Preserve
|
||||
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH");
|
||||
@ -255,7 +262,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
// Load ARM Libraries (Ensure Priority)
|
||||
string_append(&new_ld_path, ":%s/usr/lib/arm-linux-gnueabihf:%s/usr/arm-linux-gnueabihf/lib", usr_prefix, usr_prefix);
|
||||
|
||||
// Add LD_LIBRARY_PATH (ARM32 Only)
|
||||
// Add LD_LIBRARY_PATH
|
||||
{
|
||||
char *value = get_env_safe("LD_LIBRARY_PATH");
|
||||
if (strlen(value) > 0) {
|
||||
@ -271,23 +278,12 @@ void bootstrap(int argc, char *argv[]) {
|
||||
// Configure LD_PRELOAD
|
||||
{
|
||||
// Log
|
||||
DEBUG("%s", "Locating Mods...");
|
||||
DEBUG("Locating Mods...");
|
||||
|
||||
// Preserve
|
||||
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_PRELOAD");
|
||||
char *new_ld_preload = NULL;
|
||||
|
||||
// ~/.minecraft-pi/mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
|
||||
// Load Mods From ./mods
|
||||
load(&new_ld_preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Built-In Mods
|
||||
{
|
||||
// Get Mods Folder
|
||||
@ -299,23 +295,24 @@ void bootstrap(int argc, char *argv[]) {
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Add MCPI_LD_PRELOAD
|
||||
// ~/.minecraft-pi/mods
|
||||
{
|
||||
char *value = get_env_safe("MCPI_LD_PRELOAD");
|
||||
if (strlen(value) > 0) {
|
||||
string_append(&new_ld_preload, ":%s", value);
|
||||
}
|
||||
// Get Mods Folder
|
||||
char *mods_folder = NULL;
|
||||
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
|
||||
// Load Mods From ./mods
|
||||
load(&new_ld_preload, mods_folder);
|
||||
// Free Mods Folder
|
||||
free(mods_folder);
|
||||
}
|
||||
|
||||
// Add LD_PRELOAD (ARM32 Only)
|
||||
#ifdef __arm__
|
||||
// Add LD_PRELOAD
|
||||
{
|
||||
char *value = get_env_safe("MCPI_LD_PRELOAD");
|
||||
char *value = get_env_safe("LD_PRELOAD");
|
||||
if (strlen(value) > 0) {
|
||||
string_append(&new_ld_preload, ":%s", value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set LD_PRELOAD
|
||||
set_and_print_env("LD_PRELOAD", new_ld_preload);
|
||||
@ -326,7 +323,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
free(binary_directory);
|
||||
|
||||
// Start Game
|
||||
INFO("%s", "Starting Game...");
|
||||
INFO("Starting Game...");
|
||||
|
||||
// Arguments
|
||||
int argv_start = 1; // argv = &new_args[argv_start]
|
||||
|
@ -31,7 +31,7 @@ static std::string strip_feature_flag_default(std::string flag, bool *default_re
|
||||
return flag.substr(false_str.length(), std::string::npos);
|
||||
} else {
|
||||
// Invalid
|
||||
ERR("%s", "Invalid Feature Flag Default");
|
||||
ERR("Invalid Feature Flag Default");
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ static void load_available_feature_flags(std::function<void(std::string)> callba
|
||||
lines.push_back(line);
|
||||
} else {
|
||||
// Invalid Line
|
||||
ERR("%s", "Feature Flag Contains Invalid '|'");
|
||||
ERR("Feature Flag Contains Invalid '|'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ static void load_available_feature_flags(std::function<void(std::string)> callba
|
||||
// Close File
|
||||
stream.close();
|
||||
} else {
|
||||
ERR("%s", "Unable To Load Available Feature Flags");
|
||||
ERR("Unable To Load Available Feature Flags");
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ static void run_command_and_set_env(const char *env_name, const char *command[])
|
||||
}
|
||||
// Check Return Code
|
||||
if (return_code != 0) {
|
||||
ERR("%s", "Launch Interrupted");
|
||||
ERR("Launch Interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,25 @@ static void duplicate_mcpi_executable() {
|
||||
}
|
||||
|
||||
// Fix MCPI Dependencies
|
||||
#define patch_mcpi_elf_dependencies_with_extra_patchelf_args(...) \
|
||||
({ \
|
||||
const char *const _macro_command[] = { \
|
||||
"patchelf", \
|
||||
##__VA_ARGS__, \
|
||||
"--remove-needed", "libbcm_host.so", \
|
||||
"--remove-needed", "libX11.so.6", \
|
||||
"--remove-needed", "libEGL.so", \
|
||||
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1", \
|
||||
exe, \
|
||||
NULL \
|
||||
}; \
|
||||
int _macro_return_code = 0; \
|
||||
char *_macro_output = run_command(_macro_command, &_macro_return_code); \
|
||||
if (_macro_output != NULL) { \
|
||||
free(_macro_output); \
|
||||
} \
|
||||
_macro_return_code; \
|
||||
})
|
||||
void patch_mcpi_elf_dependencies(const char *linker) {
|
||||
// Duplicate MCPI executable into /tmp so it can be modified.
|
||||
duplicate_mcpi_executable();
|
||||
@ -64,20 +83,11 @@ void patch_mcpi_elf_dependencies(const char *linker) {
|
||||
char *exe = getenv("MCPI_EXECUTABLE_PATH");
|
||||
|
||||
// Run patchelf
|
||||
const char *const command[] = {
|
||||
"patchelf",
|
||||
"--set-interpreter", linker,
|
||||
"--remove-needed", "libbcm_host.so",
|
||||
"--remove-needed", "libX11.so.6",
|
||||
"--remove-needed", "libEGL.so",
|
||||
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1",
|
||||
exe,
|
||||
NULL
|
||||
};
|
||||
int return_code = 0;
|
||||
char *output = run_command(command, &return_code);
|
||||
if (output != NULL) {
|
||||
free(output);
|
||||
int return_code;
|
||||
if (linker == NULL) {
|
||||
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args();
|
||||
} else {
|
||||
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args("--set-interpreter", linker);
|
||||
}
|
||||
if (return_code != 0) {
|
||||
ERR("patchelf Failed: Exit Code: %i", return_code);
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
// Logging
|
||||
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", __VA_ARGS__); }
|
||||
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", __VA_ARGS__); }
|
||||
#define DEBUG(format, ...) { const char *debug = getenv("MCPI_DEBUG"); if (debug != NULL && strlen(debug) > 0) { fprintf(stderr, "[DEBUG]: " format "\n", __VA_ARGS__); } }
|
||||
#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")
|
||||
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__); }
|
||||
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", ##__VA_ARGS__); }
|
||||
#define DEBUG(format, ...) { const char *debug = getenv("MCPI_DEBUG"); if (debug != NULL && strlen(debug) > 0) { fprintf(stderr, "[DEBUG]: " format "\n", ##__VA_ARGS__); } }
|
||||
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
#define IMPOSSIBLE() ERR("This Should Never Be Called")
|
||||
|
@ -11,7 +11,7 @@
|
||||
#define ALLOC_CHECK(obj) \
|
||||
{ \
|
||||
if (obj == NULL) { \
|
||||
ERR("%s", "Memory Allocation Failed"); \
|
||||
ERR("Memory Allocation Failed"); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ static void update_code_block(void *target) {
|
||||
DEBUG("Code Block Allocated At: 0x%08x", (uint32_t) code_block);
|
||||
}
|
||||
if (code_block_remaining < CODE_SIZE) {
|
||||
ERR("%s", "Maximum Amount Of overwrite_calls() Uses Reached");
|
||||
ERR("Maximum Amount Of overwrite_calls() Uses Reached");
|
||||
}
|
||||
_overwrite(NULL, -1, code_block, target);
|
||||
}
|
||||
@ -115,7 +115,7 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
||||
data.replacement = code_block;
|
||||
data.found = 0;
|
||||
|
||||
iterate_text_sections("/proc/self/exe", overwrite_calls_callback, &data);
|
||||
iterate_text_sections(getenv("MCPI_EXECUTABLE_PATH"), overwrite_calls_callback, &data);
|
||||
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
@ -141,7 +141,7 @@ void _overwrite(const char *file, int line, void *start, void *target) {
|
||||
// Patch Instruction
|
||||
void _patch(const char *file, int line, void *start, unsigned char patch[4]) {
|
||||
if (((uint32_t) start) % 4 != 0) {
|
||||
ERR("%s", "Invalid Address");
|
||||
ERR("Invalid Address");
|
||||
}
|
||||
|
||||
size_t page_size = sysconf(_SC_PAGESIZE);
|
||||
|
@ -7,7 +7,7 @@ void iterate_text_sections(const char *exe, text_section_callback_t callback, vo
|
||||
|
||||
// Verify Binary
|
||||
if (!file_obj) {
|
||||
ERR("%s", "Unable To Open Binary");
|
||||
ERR("Unable To Open Binary");
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
@ -44,7 +44,7 @@ void iterate_text_sections(const char *exe, text_section_callback_t callback, vo
|
||||
|
||||
// Ensure At Least .text Section Was Scanned
|
||||
if (text_sections < 1) {
|
||||
ERR("%s", "Unable To Find .text Sectons");
|
||||
ERR("Unable To Find .text Sectons");
|
||||
}
|
||||
|
||||
// Unmap And Close File
|
||||
|
@ -22,7 +22,7 @@ void _media_audio_init() {
|
||||
// Open Device
|
||||
device = alcOpenDevice(NULL);
|
||||
if (!device) {
|
||||
WARN("%s", "Unable To Load Audio Engine");
|
||||
WARN("Unable To Load Audio Engine");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ void _media_audio_init() {
|
||||
}
|
||||
|
||||
// Log
|
||||
INFO("%s", "Loaded Audio Engine");
|
||||
INFO("Loaded Audio Engine");
|
||||
is_loaded = 1;
|
||||
}
|
||||
|
||||
@ -80,6 +80,6 @@ void _media_audio_cleanup() {
|
||||
}
|
||||
|
||||
// Log
|
||||
INFO("%s", "Unloaded Audio Engine");
|
||||
INFO("Unloaded Audio Engine");
|
||||
}
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ ALuint _media_audio_get_buffer(const char *source, const char *name) {
|
||||
return _media_audio_get_buffer(source, name);
|
||||
}
|
||||
} else {
|
||||
ERR("%s", "Audio Engine Isn't Loaded");
|
||||
ERR("Audio Engine Isn't Loaded");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ void media_set_raw_mouse_motion_enabled(int enabled) {
|
||||
}
|
||||
#endif
|
||||
if (!raw_mouse_motion_enabled) {
|
||||
WARN("%s", "Raw mouse motion has been DISABLED, this IS NOT recommended, and should only ever be used on systems that don't support or have broken raw mouse motion.");
|
||||
WARN("Raw mouse motion has been DISABLED, this IS NOT recommended, and should only ever be used on systems that don't support or have broken raw mouse motion.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
glfwSetErrorCallback(glfw_error);
|
||||
|
||||
if (!glfwInit()) {
|
||||
ERR("%s", "Unable To Initialize GLFW");
|
||||
ERR("Unable To Initialize GLFW");
|
||||
}
|
||||
|
||||
// Create OpenGL ES 1.1 Context
|
||||
@ -275,7 +275,7 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
|
||||
glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, NULL, NULL);
|
||||
if (!glfw_window) {
|
||||
ERR("%s", "Unable To Create GLFW Window");
|
||||
ERR("Unable To Create GLFW Window");
|
||||
}
|
||||
|
||||
// Don't Process Events In Headless Mode
|
||||
|
@ -36,6 +36,6 @@ __attribute__ ((noreturn)) void SDL_Quit() {
|
||||
while (wait(NULL) > 0) {}
|
||||
|
||||
// Exit
|
||||
INFO("%s", "Stopped");
|
||||
INFO("Stopped");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) {
|
||||
GLint current_buffer = 0; \
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer); \
|
||||
if (current_buffer == 0) { \
|
||||
PROXY_ERR("%s", "gl*Pointer() Functions Are Only Supported When A Buffer Is Bound To GL_ARRAY_BUFFER"); \
|
||||
PROXY_ERR("gl*Pointer() Functions Are Only Supported When A Buffer Is Bound To GL_ARRAY_BUFFER"); \
|
||||
} \
|
||||
GLint size = (GLint) read_int(); \
|
||||
GLenum type = (GLenum) read_int(); \
|
||||
|
@ -33,7 +33,7 @@ void _check_proxy_state() {
|
||||
// Check Server State
|
||||
if (!parent_is_alive) {
|
||||
void_write_cache(); // Parent Is Dead, No Reason To Send A Dead Process Data
|
||||
PROXY_ERR("%s", "Server Terminated");
|
||||
PROXY_ERR("Server Terminated");
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,12 +54,12 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Get Connection
|
||||
if (argc != 3) {
|
||||
PROXY_ERR("%s", "Invalid Arguments");
|
||||
PROXY_ERR("Invalid Arguments");
|
||||
}
|
||||
char *read_str = argv[1];
|
||||
char *write_str = argv[2];
|
||||
set_connection(atoi(read_str), atoi(write_str));
|
||||
PROXY_INFO("%s", "Connected");
|
||||
PROXY_INFO("Connected");
|
||||
|
||||
// Send Connection Message
|
||||
write_string((char *) CONNECTED_MSG);
|
||||
@ -86,6 +86,6 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Exit
|
||||
PROXY_INFO("%s", "Stopped");
|
||||
PROXY_INFO("Stopped");
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,13 +9,13 @@
|
||||
{ \
|
||||
_check_proxy_state(); \
|
||||
if (!is_connection_open()) { \
|
||||
PROXY_ERR("%s", "Attempting To Access Closed Connection"); \
|
||||
PROXY_ERR("Attempting To Access Closed Connection"); \
|
||||
} \
|
||||
}
|
||||
void safe_read(void *buf, size_t len) {
|
||||
// Check Data
|
||||
if (buf == NULL) {
|
||||
PROXY_ERR("%s", "Attempting To Read Into NULL Buffer");
|
||||
PROXY_ERR("Attempting To Read Into NULL Buffer");
|
||||
}
|
||||
// Flush Write Cache
|
||||
flush_write_cache();
|
||||
@ -42,7 +42,7 @@ static size_t _write_cache_position = 0;
|
||||
void safe_write(void *buf, size_t len) {
|
||||
// Check Data
|
||||
if (buf == NULL) {
|
||||
PROXY_ERR("%s", "Attempting To Send NULL Data");
|
||||
PROXY_ERR("Attempting To Send NULL Data");
|
||||
}
|
||||
// Expand Write Cache If Needed
|
||||
size_t needed_size = _write_cache_position + len;
|
||||
@ -165,7 +165,7 @@ void close_connection() {
|
||||
}
|
||||
set_connection(-1, -1);
|
||||
if (state_changed) {
|
||||
PROXY_INFO("%s", "Connection Closed");
|
||||
PROXY_INFO("Connection Closed");
|
||||
}
|
||||
}
|
||||
// Check If Connection Is Open
|
||||
|
@ -22,8 +22,8 @@ extern "C" {
|
||||
|
||||
#define CONNECTED_MSG "Connected"
|
||||
|
||||
#define PROXY_INFO(format, ...) INFO(PROXY_LOG_TAG format, __VA_ARGS__);
|
||||
#define PROXY_ERR(format, ...) { close_connection(); ERR(PROXY_LOG_TAG format, __VA_ARGS__); }
|
||||
#define PROXY_INFO(format, ...) INFO(PROXY_LOG_TAG format, ##__VA_ARGS__);
|
||||
#define PROXY_ERR(format, ...) { close_connection(); ERR(PROXY_LOG_TAG format, ##__VA_ARGS__); }
|
||||
|
||||
// Safely Send/Receive Data From The Connection
|
||||
__attribute__((visibility("internal"))) void safe_read(void *buf, size_t len);
|
||||
|
@ -31,7 +31,7 @@ void _check_proxy_state() {
|
||||
} else if (WIFSIGNALED(_client_status)) {
|
||||
PROXY_ERR("Client Terminated: Signal: %i%s", WTERMSIG(_client_status), WCOREDUMP(_client_status) ? " (Core Dumped)" : "");
|
||||
} else {
|
||||
PROXY_ERR("%s", "Client Terminated");
|
||||
PROXY_ERR("Client Terminated");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,7 +95,7 @@ __attribute__((constructor)) void media_ensure_loaded() {
|
||||
loaded = 1;
|
||||
|
||||
// Log
|
||||
PROXY_INFO("%s", "Starting...");
|
||||
PROXY_INFO("Starting...");
|
||||
|
||||
// Create Connection
|
||||
int server_to_client_pipe[2];
|
||||
@ -111,9 +111,9 @@ __attribute__((constructor)) void media_ensure_loaded() {
|
||||
// Wait For Connection Message
|
||||
char *str = read_string();
|
||||
if (strcmp(str, CONNECTED_MSG) == 0) {
|
||||
PROXY_INFO("%s", "Connected");
|
||||
PROXY_INFO("Connected");
|
||||
} else {
|
||||
PROXY_ERR("%s", "Unable To Connect");
|
||||
PROXY_ERR("Unable To Connect");
|
||||
}
|
||||
// Free
|
||||
free(str);
|
||||
|
@ -21,6 +21,9 @@ target_link_libraries(version reborn-patch symbols)
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat reborn-patch symbols feature pthread)
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative reborn-patch symbols feature)
|
||||
|
||||
if(MCPI_SERVER_MODE)
|
||||
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
|
||||
target_link_libraries(server reborn-patch symbols feature home misc compat dl media-layer-core pthread)
|
||||
@ -44,10 +47,7 @@ else()
|
||||
add_library(sign SHARED src/sign/sign.cpp)
|
||||
target_link_libraries(sign reborn-patch symbols feature input)
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative reborn-patch symbols feature)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.c)
|
||||
add_library(touch SHARED src/touch/touch.cpp)
|
||||
target_link_libraries(touch reborn-patch symbols feature)
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
@ -74,8 +74,8 @@ target_link_libraries(death reborn-patch symbols feature)
|
||||
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp)
|
||||
target_link_libraries(misc reborn-patch symbols media-layer-core feature GLESv1_CM)
|
||||
|
||||
add_library(options SHARED src/options/options.c)
|
||||
target_link_libraries(options reborn-patch symbols feature)
|
||||
add_library(options SHARED src/options/options.c src/options/options.cpp)
|
||||
target_link_libraries(options reborn-patch symbols feature home)
|
||||
|
||||
add_library(home SHARED src/home/home.c)
|
||||
target_link_libraries(home reborn-patch symbols)
|
||||
@ -84,22 +84,22 @@ add_library(test SHARED src/test/test.c)
|
||||
target_link_libraries(test reborn-patch home)
|
||||
|
||||
add_library(init SHARED src/init/init.c)
|
||||
target_link_libraries(init compat game-mode misc death options chat home version test media-layer-core)
|
||||
target_link_libraries(init compat game-mode misc death options chat creative home version test media-layer-core)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_link_libraries(init server)
|
||||
else()
|
||||
target_link_libraries(init multiplayer sound camera input sign creative touch textures atlas)
|
||||
target_link_libraries(init multiplayer sound camera input sign touch textures atlas)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(init benchmark)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
## Install Mods
|
||||
install(TARGETS init compat readdir feature game-mode misc death options chat home version test DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
install(TARGETS init compat readdir feature game-mode misc death options chat creative home version test DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
if(MCPI_SERVER_MODE)
|
||||
install(TARGETS server DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
else()
|
||||
install(TARGETS multiplayer sound override camera input sign creative touch textures atlas DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
install(TARGETS multiplayer sound override camera input sign touch textures atlas DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
install(TARGETS benchmark DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
endif()
|
||||
|
@ -123,7 +123,7 @@ void init_atlas() {
|
||||
overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection);
|
||||
|
||||
// Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
|
||||
if (feature_has("Disable \"gui_blocks\" Atlas", 0)) {
|
||||
if (feature_has("Disable \"gui_blocks\" Atlas", server_disabled)) {
|
||||
unsigned char disable_gui_blocks_atlas_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x63c2c, disable_gui_blocks_atlas_patch);
|
||||
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
|
||||
|
@ -38,7 +38,7 @@ __attribute__((constructor)) static void _init_active(int argc, char *argv[]) {
|
||||
// Create/Start World
|
||||
static void start_world(unsigned char *minecraft) {
|
||||
// Log
|
||||
INFO("%s", "Loading Benchmark");
|
||||
INFO("Loading Benchmark");
|
||||
|
||||
// Specify Level Settings
|
||||
LevelSettings settings;
|
||||
|
@ -37,7 +37,7 @@ void init_camera() {
|
||||
patch_address(AppPlatform_linux_saveScreenshot_vtable_addr, (void *) AppPlatform_linux_saveScreenshot_injection);
|
||||
|
||||
// Fix Camera Rendering
|
||||
if (feature_has("Fix Camera Rendering", 0)) {
|
||||
if (feature_has("Fix Camera Rendering", server_disabled)) {
|
||||
// Enable TripodCameraRenderer
|
||||
overwrite_calls((void *) EntityRenderDispatcher, (void *) EntityRenderDispatcher_injection);
|
||||
// Display Smoke From TripodCamera Higher
|
||||
|
@ -119,7 +119,7 @@ static void send_queued_messages(unsigned char *minecraft) {
|
||||
|
||||
// Init
|
||||
void init_chat() {
|
||||
_chat_enabled = feature_has("Implement Chat", 1);
|
||||
_chat_enabled = feature_has("Implement Chat", server_enabled);
|
||||
if (_chat_enabled) {
|
||||
// Disable Original ChatPacket Loopback
|
||||
unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "../feature/feature.h"
|
||||
#include "creative.h"
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
// Add Item To Inventory
|
||||
static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) {
|
||||
ItemInstance *item_instance = new ItemInstance;
|
||||
@ -80,6 +81,7 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Hook Specific TileItem Constructor
|
||||
static unsigned char *Tile_initTiles_TileItem_injection(unsigned char *tile_item, int32_t id) {
|
||||
@ -106,8 +108,10 @@ int creative_is_restricted() {
|
||||
// Init
|
||||
void init_creative() {
|
||||
// Add Extra Items To Creative Inventory (Only Replace Specific Function Call)
|
||||
if (feature_has("Expand Creative Inventory", 0)) {
|
||||
if (feature_has("Expand Creative Inventory", server_enabled)) {
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
|
||||
#endif
|
||||
|
||||
// Use AuxDataTileItem by default instead of TileItem, so tiles in the Creative
|
||||
// Inventory can have arbitrary auxiliary values.
|
||||
@ -121,7 +125,7 @@ void init_creative() {
|
||||
}
|
||||
|
||||
// Remove Creative Restrictions (Opening Chests, Crafting, Etc)
|
||||
if (feature_has("Remove Creative Mode Restrictions", 0)) {
|
||||
if (feature_has("Remove Creative Mode Restrictions", server_disabled)) {
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
// Remove Restrictions
|
||||
patch((void *) 0x43ee8, nop_patch);
|
||||
|
@ -62,7 +62,7 @@ static void LocalPlayer_actuallyHurt_injection(unsigned char *player, int32_t da
|
||||
// Init
|
||||
void init_death() {
|
||||
// Death Messages
|
||||
if (feature_has("Implement Death Messages", 1)) {
|
||||
if (feature_has("Implement Death Messages", server_auto)) {
|
||||
patch_address(ServerPlayer_actuallyHurt_vtable_addr, (void *) ServerPlayer_actuallyHurt_injection);
|
||||
patch_address(LocalPlayer_actuallyHurt_vtable_addr, (void *) LocalPlayer_actuallyHurt_injection);
|
||||
}
|
||||
|
@ -6,16 +6,7 @@
|
||||
#include "feature.h"
|
||||
|
||||
// Check For Feature
|
||||
int feature_has(const char *name, int server_default) {
|
||||
// Default Value For Server Mode
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
if (server_default != -1) {
|
||||
return server_default;
|
||||
}
|
||||
#else
|
||||
(void) server_default;
|
||||
#endif
|
||||
|
||||
int _feature_has(const char *name) {
|
||||
// Get Value
|
||||
char *env = getenv("MCPI_FEATURE_FLAGS");
|
||||
char *features = strdup(env != NULL ? env : "");
|
||||
|
@ -4,7 +4,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int feature_has(const char *name, int server_default);
|
||||
int _feature_has(const char *name);
|
||||
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
#define _feature_has__server_defaul_is_server_disabled(name) 0
|
||||
#define _feature_has__server_defaul_is_server_auto(name) _feature_has(name)
|
||||
#define _feature_has__server_defaul_is_server_enabled(name) 1
|
||||
#define feature_has(name, server_default) _feature_has__server_defaul_is_##server_default(name)
|
||||
#else
|
||||
#define feature_has(name, server_default) _feature_has(name)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ static unsigned char *Minecraft_getCreator_injection(unsigned char *minecraft) {
|
||||
// Init
|
||||
void init_game_mode() {
|
||||
// Dynamic Game Mode Switching
|
||||
if (feature_has("Implement Game-Mode Switching", 1)) {
|
||||
if (feature_has("Implement Game-Mode Switching", server_enabled)) {
|
||||
set_is_survival(1);
|
||||
overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection);
|
||||
|
||||
@ -68,7 +68,7 @@ void init_game_mode() {
|
||||
}
|
||||
|
||||
// Allow Joining Survival Servers
|
||||
if (feature_has("Allow Joining Survival Servers", 1)) {
|
||||
if (feature_has("Allow Joining Survival Servers", server_enabled)) {
|
||||
unsigned char server_patch[4] = {0x0f, 0x00, 0x00, 0xea}; // "b 0x6dcb4"
|
||||
patch((void *) 0x6dc70, server_patch);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ static int32_t MouseBuildInput_tickBuild_injection(unsigned char *mouse_build_in
|
||||
// Init
|
||||
void _init_attack() {
|
||||
// Allow Attacking Mobs
|
||||
if (feature_has("Fix Attacking", 0)) {
|
||||
if (feature_has("Fix Attacking", server_disabled)) {
|
||||
patch_address(MouseBuildInput_tickBuild_vtable_addr, (void *) MouseBuildInput_tickBuild_injection);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,6 @@ static void _handle_bow(unsigned char *minecraft) {
|
||||
// Init
|
||||
void _init_bow() {
|
||||
// Enable Bow & Arrow Fix
|
||||
fix_bow = feature_has("Fix Bow & Arrow", 0);
|
||||
fix_bow = feature_has("Fix Bow & Arrow", server_disabled);
|
||||
input_run_on_tick(_handle_bow);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ void input_drop(int drop_slot) {
|
||||
|
||||
// Handle Drop Item Presses
|
||||
static void _handle_drop(unsigned char *minecraft) {
|
||||
if ((!creative_is_restricted() || !(*Minecraft_isCreativeMode)(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) {
|
||||
if (((*(unsigned char **) (minecraft + Minecraft_screen_property_offset)) == NULL) && (!creative_is_restricted() || !(*Minecraft_isCreativeMode)(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) {
|
||||
// Get Player
|
||||
unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset);
|
||||
if (player != NULL) {
|
||||
@ -86,6 +86,6 @@ static void _handle_drop(unsigned char *minecraft) {
|
||||
|
||||
// Init
|
||||
void _init_drop() {
|
||||
enable_drop = feature_has("Bind \"Q\" Key To Item Dropping", 0);
|
||||
enable_drop = feature_has("Bind \"Q\" Key To Item Dropping", server_disabled);
|
||||
input_run_on_tick(_handle_drop);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ void init_input() {
|
||||
_init_attack();
|
||||
|
||||
// Disable Raw Mouse Motion
|
||||
if (feature_has("Disable Raw Mouse Motion (Not Recommended)", 9)) {
|
||||
if (feature_has("Disable Raw Mouse Motion (Not Recommended)", server_disabled)) {
|
||||
media_set_raw_mouse_motion_enabled(0);
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ static void Gui_handleClick_injection(unsigned char *gui, int32_t param_2, int32
|
||||
|
||||
// Init
|
||||
void _init_misc() {
|
||||
enable_misc = feature_has("Miscellaneous Input Fixes", 0);
|
||||
enable_misc = feature_has("Miscellaneous Input Fixes", server_disabled);
|
||||
if (enable_misc) {
|
||||
// Fix OptionsScreen Ignoring The Back Button
|
||||
patch_address(OptionsScreen_handleBackEvent_vtable_addr, (void *) OptionsScreen_handleBackEvent_injection);
|
||||
|
@ -37,6 +37,6 @@ static void _handle_toggle_options(unsigned char *minecraft) {
|
||||
|
||||
// Init
|
||||
void _init_toggle() {
|
||||
enable_toggles = feature_has("Bind Common Toggleable Options To Function Keys", 0);
|
||||
enable_toggles = feature_has("Bind Common Toggleable Options To Function Keys", server_disabled);
|
||||
input_run_on_tick(_handle_toggle_options);
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
|
||||
// Log When Game Is Saved
|
||||
void Level_saveLevelData_injection(unsigned char *level) {
|
||||
// Print Log Message
|
||||
INFO("%s", "Saving Game");
|
||||
INFO("Saving Game");
|
||||
|
||||
// Call Original Method
|
||||
(*Level_saveLevelData)(level);
|
||||
|
@ -204,14 +204,14 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa
|
||||
// Init
|
||||
void init_misc() {
|
||||
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
|
||||
if (feature_has("Remove Invalid Item Background", 0)) {
|
||||
if (feature_has("Remove Invalid Item Background", server_disabled)) {
|
||||
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x63c98, invalid_item_background_patch);
|
||||
}
|
||||
|
||||
// Render Selected Item Text + Hide Chat Messages
|
||||
hide_chat_messages = feature_has("Hide Chat Messages", 0);
|
||||
render_selected_item_text = feature_has("Render Selected Item Text", 0);
|
||||
hide_chat_messages = feature_has("Hide Chat Messages", server_disabled);
|
||||
render_selected_item_text = feature_has("Render Selected Item Text", server_disabled);
|
||||
overwrite_calls((void *) Gui_renderChatMessages, (void *) Gui_renderChatMessages_injection);
|
||||
overwrite_calls((void *) Gui_tick, (void *) Gui_tick_injection);
|
||||
overwrite_calls((void *) Inventory_selectSlot, (void *) Inventory_selectSlot_injection);
|
||||
@ -229,17 +229,17 @@ void init_misc() {
|
||||
overwrite_calls((void *) RakNetInstance, (void *) RakNetInstance_injection);
|
||||
|
||||
// Close Current Screen On Death To Prevent Bugs
|
||||
if (feature_has("Close Current Screen On Death", 0)) {
|
||||
if (feature_has("Close Current Screen On Death", server_disabled)) {
|
||||
patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection);
|
||||
}
|
||||
|
||||
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
||||
if (feature_has("Fix Furnace Not Checking Item Auxiliary", 0)) {
|
||||
if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) {
|
||||
overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection);
|
||||
}
|
||||
|
||||
// Improved Cursor Rendering
|
||||
if (feature_has("Improved Cursor Rendering", 0)) {
|
||||
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
||||
// Disable Normal Cursor Rendering
|
||||
unsigned char disable_cursor_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x4a6c0, disable_cursor_patch);
|
||||
@ -248,7 +248,7 @@ void init_misc() {
|
||||
}
|
||||
|
||||
// Disable V-Sync
|
||||
if (feature_has("Disable V-Sync", 0)) {
|
||||
if (feature_has("Disable V-Sync", server_disabled)) {
|
||||
media_disable_vsync();
|
||||
}
|
||||
|
||||
|
@ -45,13 +45,44 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
|
||||
}
|
||||
}
|
||||
|
||||
// Add Missing Buttons To Pause Menu
|
||||
static void PauseScreen_init_injection(unsigned char *screen) {
|
||||
// Call Original Method
|
||||
(*PauseScreen_init)(screen);
|
||||
|
||||
// Check If Server
|
||||
unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset);
|
||||
unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset);
|
||||
if (rak_net_instance != NULL) {
|
||||
unsigned char *rak_net_instance_vtable = *(unsigned char**) rak_net_instance;
|
||||
RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset);
|
||||
if ((*RakNetInstance_isServer)(rak_net_instance)) {
|
||||
// Add Button
|
||||
std::vector<unsigned char *> *rendered_buttons = (std::vector<unsigned char *> *) (screen + Screen_rendered_buttons_property_offset);
|
||||
std::vector<unsigned char *> *selectable_buttons = (std::vector<unsigned char *> *) (screen + Screen_selectable_buttons_property_offset);
|
||||
unsigned char *button = *(unsigned char **) (screen + PauseScreen_server_visibility_button_property_offset);
|
||||
rendered_buttons->push_back(button);
|
||||
selectable_buttons->push_back(button);
|
||||
|
||||
// Update Button Text
|
||||
(*PauseScreen_updateServerVisibilityText)(screen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_misc_cpp() {
|
||||
// Implement AppPlatform::readAssetFile So Translations Work
|
||||
if (feature_has("Load Language Files", 1)) {
|
||||
if (feature_has("Load Language Files", server_enabled)) {
|
||||
overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection);
|
||||
}
|
||||
|
||||
// Handle Custom Update Behavior
|
||||
overwrite_calls((void *) Minecraft_update, (void *) Minecraft_update_injection);
|
||||
|
||||
// Fix Pause Menu
|
||||
if (feature_has("Fix Pause Menu", server_disabled)) {
|
||||
// Add Missing Buttons To Pause Menu
|
||||
patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ static void RakNetInstance_pingForHosts_injection(unsigned char *rak_net_instanc
|
||||
// Init
|
||||
void init_multiplayer() {
|
||||
// Inject Code
|
||||
if (feature_has("External Server Support", 0)) {
|
||||
if (feature_has("External Server Support", server_disabled)) {
|
||||
patch_address(RakNetInstance_pingForHosts_vtable_addr, (void *) RakNetInstance_pingForHosts_injection);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
#include "options.h"
|
||||
|
||||
// Force Mob Spawning
|
||||
static bool LevelData_getSpawnMobs_injection(__attribute__((unused)) unsigned char *level_data) {
|
||||
@ -41,47 +42,47 @@ static char *get_username() {
|
||||
return username;
|
||||
}
|
||||
|
||||
static int fancy_graphics;
|
||||
static int peaceful_mode;
|
||||
static int anaglyph;
|
||||
static int smooth_lighting;
|
||||
static int render_distance;
|
||||
static int server_visible;
|
||||
// Configure Options
|
||||
static void Minecraft_init_injection(unsigned char *this) {
|
||||
unsigned char *stored_options = NULL;
|
||||
static void Options_initDefaultValue_injection(unsigned char *options) {
|
||||
// Call Original Method
|
||||
(*Minecraft_init)(this);
|
||||
(*Options_initDefaultValue)(options);
|
||||
|
||||
unsigned char *options = this + Minecraft_options_property_offset;
|
||||
// Enable Fancy Graphics
|
||||
*(options + Options_fancy_graphics_property_offset) = fancy_graphics;
|
||||
// Enable Crosshair In Touch GUI
|
||||
*(options + Options_split_controls_property_offset) = 1;
|
||||
// Peaceful Mode
|
||||
*(int32_t *) (options + Options_peaceful_mode_property_offset) = peaceful_mode ? 0 : 2;
|
||||
// 3D Anaglyph
|
||||
*(options + Options_3d_anaglyph_property_offset) = anaglyph;
|
||||
// Smooth Lighting
|
||||
*(options + Options_ambient_occlusion_property_offset) = smooth_lighting;
|
||||
// Render Distance
|
||||
*(int32_t *) (options + Options_render_distance_property_offset) = render_distance;
|
||||
// Server Visible
|
||||
*(options + Options_server_visible_property_offset) = server_visible;
|
||||
|
||||
// Default Graphics Settings
|
||||
*(options + Options_fancy_graphics_property_offset) = 1;
|
||||
*(options + Options_ambient_occlusion_property_offset) = 1;
|
||||
|
||||
// Store
|
||||
stored_options = options;
|
||||
}
|
||||
|
||||
// Smooth Lighting
|
||||
static void TileRenderer_tesselateBlockInWorld_injection(unsigned char *tile_renderer, unsigned char *tile, int32_t x, int32_t y, int32_t z) {
|
||||
// Set Variable
|
||||
*Minecraft_useAmbientOcclusion = *(stored_options + Options_ambient_occlusion_property_offset);
|
||||
|
||||
// Call Original Method
|
||||
(*TileRenderer_tesselateBlockInWorld)(tile_renderer, tile, x, y, z);
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_options() {
|
||||
// Force Mob Spawning
|
||||
if (feature_has("Force Mob Spawning", -1)) {
|
||||
if (feature_has("Force Mob Spawning", server_auto)) {
|
||||
overwrite((void *) LevelData_getSpawnMobs, (void *) LevelData_getSpawnMobs_injection);
|
||||
}
|
||||
|
||||
// Enable Fancy Graphics
|
||||
fancy_graphics = feature_has("Fancy Graphics", 0);
|
||||
// Peaceful Mode
|
||||
peaceful_mode = feature_has("Peaceful Mode", -1);
|
||||
// 3D Anaglyph
|
||||
anaglyph = feature_has("3D Anaglyph", 0);
|
||||
anaglyph = feature_has("3D Anaglyph", server_disabled);
|
||||
// Render Distance
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
render_distance = get_render_distance();
|
||||
@ -89,11 +90,9 @@ void init_options() {
|
||||
#else
|
||||
render_distance = 3;
|
||||
#endif
|
||||
// Server Visible
|
||||
server_visible = !feature_has("Disable Hosting LAN Worlds", 0);
|
||||
|
||||
// Set Options
|
||||
overwrite_calls((void *) Minecraft_init, (void *) Minecraft_init_injection);
|
||||
overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection);
|
||||
|
||||
// Change Username
|
||||
const char *username = get_username();
|
||||
@ -101,27 +100,26 @@ void init_options() {
|
||||
INFO("Setting Username: %s", username);
|
||||
#endif
|
||||
if (strcmp(*default_username, "StevePi") != 0) {
|
||||
ERR("%s", "Default Username Is Invalid");
|
||||
ERR("Default Username Is Invalid");
|
||||
}
|
||||
patch_address((void *) default_username, (void *) username);
|
||||
|
||||
// Disable Autojump By Default
|
||||
if (feature_has("Disable Autojump By Default", 0)) {
|
||||
if (feature_has("Disable Autojump By Default", server_disabled)) {
|
||||
unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0"
|
||||
patch((void *) 0x44b90, autojump_patch);
|
||||
}
|
||||
// Display Nametags By Default
|
||||
if (feature_has("Display Nametags By Default", 0)) {
|
||||
if (feature_has("Display Nametags By Default", server_disabled)) {
|
||||
// r6 = 0x1
|
||||
// r5 = 0x0
|
||||
unsigned char display_nametags_patch[4] = {0x1d, 0x60, 0xc0, 0xe5}; // "strb r6, [r0, #0x1d]"
|
||||
patch((void *) 0xa6628, display_nametags_patch);
|
||||
}
|
||||
|
||||
// Enable Smooth Lighting
|
||||
smooth_lighting = feature_has("Smooth Lighting", 0);
|
||||
if (smooth_lighting) {
|
||||
unsigned char smooth_lighting_patch[4] = {0x01, 0x00, 0x53, 0xe3}; // "cmp r3, #0x1"
|
||||
patch((void *) 0x59ea4, smooth_lighting_patch);
|
||||
}
|
||||
// Smooth Lighting
|
||||
overwrite_calls((void *) TileRenderer_tesselateBlockInWorld, (void *) TileRenderer_tesselateBlockInWorld_injection);
|
||||
|
||||
// Init C++
|
||||
_init_options_cpp();
|
||||
}
|
||||
|
226
mods/src/options/options.cpp
Normal file
226
mods/src/options/options.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../home/home.h"
|
||||
#include "options.h"
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Fix Initial Option Button Rendering
|
||||
// The calling function doesn't exist in MCPE v0.6.1, so its name is unknown.
|
||||
static unsigned char *OptionsPane_unknown_toggle_creating_function_OptionButton_injection(unsigned char *option_button, unsigned char *option) {
|
||||
// Call Original Method
|
||||
unsigned char *ret = (*OptionButton)(option_button, option);
|
||||
|
||||
// Setup Image
|
||||
(*OptionButton_updateImage)(option_button, stored_options);
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Actually Save options.txt
|
||||
// Hook Last Options::addOptionToSaveOutput Call
|
||||
static void Options_save_Options_addOptionToSaveOutput_injection(unsigned char *options, std::vector<std::string> &data, std::string option, int32_t value) {
|
||||
// Call Original Method
|
||||
(*Options_addOptionToSaveOutput)(options, data, option, value);
|
||||
|
||||
// Save Fancy Graphics
|
||||
(*Options_addOptionToSaveOutput)(options, data, "gfx_fancygraphics", *(options + Options_fancy_graphics_property_offset));
|
||||
|
||||
// Save File
|
||||
unsigned char *options_file = options + Options_options_file_property_offset;
|
||||
(*OptionsFile_save)(options_file, data);
|
||||
}
|
||||
|
||||
// MCPI's OptionsFile::getOptionStrings is broken, this is the version in v0.7.0
|
||||
static std::vector<std::string> OptionsFile_getOptionStrings_injection(unsigned char *options_file) {
|
||||
// Get options.txt Path
|
||||
std::string path = *(std::string *) (options_file + OptionsFile_options_txt_path_property_offset);
|
||||
// Parse
|
||||
std::vector<std::string> ret;
|
||||
FILE *stream = fopen(path.c_str(), "r");
|
||||
char line[128];
|
||||
if (stream != NULL) {
|
||||
while (fgets(line, 0x80, stream) != NULL) {
|
||||
size_t sVar1 = strlen(line);
|
||||
if (2 < sVar1) {
|
||||
std::stringstream string_stream(line);
|
||||
while (true) {
|
||||
std::string data;
|
||||
std::getline(string_stream, data, ':');
|
||||
int iVar2 = data.find_last_not_of(" \n\r\t");
|
||||
data.erase(iVar2 + 1);
|
||||
if (data.length() == 0) {
|
||||
break;
|
||||
}
|
||||
ret.push_back(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(stream);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get New options.txt Path
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
static char *get_new_options_txt_path() {
|
||||
static char *path = NULL;
|
||||
// Path
|
||||
if (path == NULL) {
|
||||
safe_asprintf(&path, "%s/options.txt", home_get());
|
||||
}
|
||||
// Return
|
||||
return path;
|
||||
}
|
||||
// Free
|
||||
__attribute__((destructor)) static void _free_new_options_txt_path() {
|
||||
free(get_new_options_txt_path());
|
||||
}
|
||||
#else
|
||||
static char *get_new_options_txt_path() {
|
||||
// Block options.txt On Servers
|
||||
return (char *) "/dev/null";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Modify Option Toggles
|
||||
static void OptionsPane_unknown_toggle_creating_function_injection(unsigned char *options_pane, unsigned char *unknown_object, std::string const& name, unsigned char *option) {
|
||||
// Modify
|
||||
if (name == "Fancy Graphics") {
|
||||
option = Options_Option_GRAPHICS;
|
||||
} else if (name == "Soft shadows") {
|
||||
option = Options_Option_AMBIENT_OCCLUSION;
|
||||
} else if (name == "Fancy Skies" || name == "Animated water") {
|
||||
// These have no corresponding option, so disable the toggle.
|
||||
return;
|
||||
} else if (name == "Third person camera") {
|
||||
// This isn't saved/loaded, so disable the toggle.
|
||||
return;
|
||||
} else if (name == "Lefty" || name == "Use touch screen" || name == "Split touch controls") {
|
||||
// These toggles require touch support, so disable them.
|
||||
return;
|
||||
} else if (name == "Vibrate on destroy") {
|
||||
// This toggle requires vibration support, so disable it.
|
||||
return;
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
(*OptionsPane_unknown_toggle_creating_function)(options_pane, unknown_object, name, option);
|
||||
}
|
||||
|
||||
// Add Missing Options To Options::getBooleanValue
|
||||
static bool Options_getBooleanValue_injection(unsigned char *options, unsigned char *option) {
|
||||
// Check
|
||||
if (option == Options_Option_GRAPHICS) {
|
||||
return *(options + Options_fancy_graphics_property_offset);
|
||||
} else {
|
||||
// Call Original Method
|
||||
return (*Options_getBooleanValue)(options, option);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Options Button Back To Classic Start Screen
|
||||
static void StartMenuScreen_init_injection(unsigned char *screen) {
|
||||
// Call Original Method
|
||||
(*StartMenuScreen_init)(screen);
|
||||
|
||||
// Add Button
|
||||
std::vector<unsigned char *> *rendered_buttons = (std::vector<unsigned char *> *) (screen + Screen_rendered_buttons_property_offset);
|
||||
std::vector<unsigned char *> *selectable_buttons = (std::vector<unsigned char *> *) (screen + Screen_selectable_buttons_property_offset);
|
||||
unsigned char *options_button = screen + StartMenuScreen_options_button_property_offset;
|
||||
rendered_buttons->push_back(options_button);
|
||||
selectable_buttons->push_back(options_button);
|
||||
}
|
||||
|
||||
// Init C++
|
||||
void _init_options_cpp() {
|
||||
// NOP
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
|
||||
// Fix Options Screen
|
||||
if (feature_has("Fix Options Screen", server_disabled)) {
|
||||
// Fix Initial Option Button Rendering
|
||||
overwrite_call((void *) 0x24510, (void *) OptionsPane_unknown_toggle_creating_function_OptionButton_injection);
|
||||
|
||||
// "Gui Scale" slider is broken, so disable it.
|
||||
patch((void *) 0x35a10, nop_patch);
|
||||
// "Vibrate on destroy" is disabled, so "Feedback" is empty, so disable it.
|
||||
patch((void *) 0x35960, nop_patch);
|
||||
|
||||
// Disconnect "This works?" Slider From Difficulty
|
||||
unsigned char this_works_slider_patch[4] = {0x00, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0"
|
||||
patch((void *) 0x3577c, this_works_slider_patch);
|
||||
|
||||
// Modify Option Toggles
|
||||
overwrite_calls((void *) OptionsPane_unknown_toggle_creating_function, (void *) OptionsPane_unknown_toggle_creating_function_injection);
|
||||
|
||||
// Add Missing Options To Options::getBooleanValue
|
||||
overwrite_calls((void *) Options_getBooleanValue, (void *) Options_getBooleanValue_injection);
|
||||
|
||||
// Add Options Button Back To Classic Start Screen
|
||||
patch_address(StartMenuScreen_init_vtable_addr, (void *) StartMenuScreen_init_injection);
|
||||
// Fix Classic UI Options Button Size
|
||||
unsigned char classic_options_button_width_patch[4] = {0xa0, 0x00, 0xa0, 0xe3}; // "mov r0, #0xa0"
|
||||
patch((void *) 0x39a98, classic_options_button_width_patch);
|
||||
unsigned char classic_options_button_height_patch[4] = {0x18, 0x30, 0xa0, 0xe3}; // "mov r3, #0x18"
|
||||
patch((void *) 0x39a9c, classic_options_button_height_patch);
|
||||
// Fix Classic UI Buttons Spacing
|
||||
{
|
||||
// Join Button
|
||||
unsigned char classic_join_button_spacing_patch[4] = {0x12, 0x20, 0x83, 0xe2}; // "add r2, r3, #0x12"
|
||||
patch((void *) 0x39894, classic_join_button_spacing_patch);
|
||||
// Start Button
|
||||
unsigned char classic_start_button_spacing_patch[4] = {0x08, 0x20, 0x43, 0xe2}; // "sub r2, r3, #0x08"
|
||||
patch((void *) 0x3988c, classic_start_button_spacing_patch);
|
||||
// Options Button
|
||||
unsigned char classic_options_button_spacing_patch[4] = {0x2c, 0x30, 0x83, 0xe2}; // "add r3, r3, #0x2c"
|
||||
patch((void *) 0x39898, classic_options_button_spacing_patch);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually Save options.txt
|
||||
overwrite_call((void *) 0x197fc, (void *) Options_save_Options_addOptionToSaveOutput_injection);
|
||||
// Fix options.txt Path
|
||||
patch_address((void *) options_txt_path, (void *) get_new_options_txt_path());
|
||||
// When Loading, options.txt Should Be Opened In Read Mode
|
||||
patch_address((void *) options_txt_fopen_mode_when_loading, (void *) "r");
|
||||
// Fix OptionsFile::getOptionStrings
|
||||
overwrite_calls((void *) OptionsFile_getOptionStrings, (void *) OptionsFile_getOptionStrings_injection);
|
||||
|
||||
// Sensitivity Loading/Saving Is Broken, Disable It
|
||||
patch((void *) 0x1931c, nop_patch);
|
||||
patch((void *) 0x1973c, nop_patch);
|
||||
|
||||
// Unsplit Touch Controls Breaks Things, Never Load/Save It
|
||||
unsigned char cmp_r0_r0_patch[4] = {0x00, 0x00, 0x50, 0xe1}; // "cmp r0, r0"
|
||||
patch((void *) 0x19378, cmp_r0_r0_patch);
|
||||
patch((void *) 0x197cc, nop_patch);
|
||||
|
||||
// Custom Username Is Loaded Manually, Disable Loading From options.txt
|
||||
patch((void *) 0x192ac, nop_patch);
|
||||
|
||||
// Replace "feedback_vibration" Loading/Saving With "gfx_ao"
|
||||
{
|
||||
// Replace String
|
||||
static const char *new_feedback_vibration_options_txt_nam = "gfx_ao";
|
||||
patch_address((void *) feedback_vibration_options_txt_name_1, (void *) &new_feedback_vibration_options_txt_nam);
|
||||
patch_address((void *) feedback_vibration_options_txt_name_2, (void *) &new_feedback_vibration_options_txt_nam);
|
||||
// Loading
|
||||
unsigned char gfx_ao_loading_patch[4] = {(unsigned char) Options_ambient_occlusion_property_offset, 0x10, 0x84, 0xe2}; // "add param_2, r4, #OFFSET"
|
||||
patch((void *) 0x193b8, gfx_ao_loading_patch);
|
||||
// Saving
|
||||
unsigned char gfx_ao_saving_patch[4] = {(unsigned char) Options_ambient_occlusion_property_offset, 0x30, 0xd4, 0xe5}; // "ldrb r3, [r4, #OFFSET]"
|
||||
patch((void *) 0x197f8, gfx_ao_saving_patch);
|
||||
}
|
||||
|
||||
// Disable "gfx_lowquality" Loading
|
||||
patch((void *) 0x19414, nop_patch);
|
||||
patch((void *) 0x1941c, nop_patch);
|
||||
}
|
12
mods/src/options/options.h
Normal file
12
mods/src/options/options.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_options_cpp();
|
||||
__attribute__((visibility("internal"))) extern unsigned char *stored_options;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -54,10 +54,10 @@ static ServerProperties &get_server_properties() {
|
||||
#define DEFAULT_PORT "19132"
|
||||
#define DEFAULT_SEED ""
|
||||
#define DEFAULT_FORCE_MOB_SPAWNING "false"
|
||||
#define DEFAULT_PEACEFUL_MODE "false"
|
||||
#define DEFAULT_WORLD_NAME "world"
|
||||
#define DEFAULT_MAX_PLAYERS "4"
|
||||
#define DEFAULT_WHITELIST "false"
|
||||
#define DEFAULT_DEATH_MESSAGES "false"
|
||||
|
||||
// Get World Name
|
||||
static std::string get_world_name() {
|
||||
@ -205,7 +205,7 @@ static void list_callback(unsigned char *minecraft, std::string username, unsign
|
||||
// Handle Server Stop
|
||||
static void handle_server_stop(unsigned char *minecraft) {
|
||||
if (compat_check_exit_requested()) {
|
||||
INFO("%s", "Stopping Server");
|
||||
INFO("Stopping Server");
|
||||
// Save And Exit
|
||||
unsigned char *level = get_level(minecraft);
|
||||
if (level != NULL) {
|
||||
@ -294,21 +294,21 @@ static void handle_commands(unsigned char *minecraft) {
|
||||
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, message);
|
||||
} else if (data == list_command) {
|
||||
// List Players
|
||||
INFO("%s", "All Players:");
|
||||
INFO("All Players:");
|
||||
find_players(minecraft, "", list_callback, true);
|
||||
} else if (data == stop_command) {
|
||||
// Stop Server
|
||||
compat_request_exit();
|
||||
} else if (data == help_command) {
|
||||
INFO("%s", "All Commands:");
|
||||
INFO("All Commands:");
|
||||
if (!is_whitelist()) {
|
||||
INFO("%s", " ban <Username> - IP-Ban All Players With Specifed Username");
|
||||
INFO(" ban <Username> - IP-Ban All Players With Specifed Username");
|
||||
}
|
||||
INFO("%s", " kill <Username> - Kill All Players With Specifed Username");
|
||||
INFO("%s", " say <Message> - Print Specified Message To Chat");
|
||||
INFO("%s", " list - List All Players");
|
||||
INFO("%s", " stop - Stop Server");
|
||||
INFO("%s", " help - Print This Message");
|
||||
INFO(" kill <Username> - Kill All Players With Specifed Username");
|
||||
INFO(" say <Message> - Print Specified Message To Chat");
|
||||
INFO(" list - List All Players");
|
||||
INFO(" stop - Stop Server");
|
||||
INFO(" help - Print This Message");
|
||||
} else {
|
||||
INFO("Invalid Command: %s", data.c_str());
|
||||
}
|
||||
@ -378,7 +378,7 @@ static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned c
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ERR("%s", "Unable To Read Blacklist/Whitelist");
|
||||
ERR("Unable To Read Blacklist/Whitelist");
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,12 +417,12 @@ static const char *get_features() {
|
||||
loaded_features = true;
|
||||
|
||||
features.clear();
|
||||
if (get_server_properties().get_bool("peaceful-mode", DEFAULT_PEACEFUL_MODE)) {
|
||||
features += "Peaceful Mode|";
|
||||
}
|
||||
if (get_server_properties().get_bool("force-mob-spawning", DEFAULT_FORCE_MOB_SPAWNING)) {
|
||||
features += "Force Mob Spawning|";
|
||||
}
|
||||
if (get_server_properties().get_bool("death-messages", DEFAULT_DEATH_MESSAGES)) {
|
||||
features += "Implement Death Messages|";
|
||||
}
|
||||
}
|
||||
return features.c_str();
|
||||
}
|
||||
@ -461,14 +461,14 @@ static void server_init() {
|
||||
properties_file_output << "seed=" DEFAULT_SEED "\n";
|
||||
properties_file_output << "# Force Mob Spawning (false = Disabled, true = Enabled)\n";
|
||||
properties_file_output << "force-mob-spawning=" DEFAULT_FORCE_MOB_SPAWNING "\n";
|
||||
properties_file_output << "# Peaceful Mode (false = Disabled, true = Enabled)\n";
|
||||
properties_file_output << "peaceful-mode=" DEFAULT_PEACEFUL_MODE "\n";
|
||||
properties_file_output << "# World To Select\n";
|
||||
properties_file_output << "world-name=" DEFAULT_WORLD_NAME "\n";
|
||||
properties_file_output << "# Maximum Player Count\n";
|
||||
properties_file_output << "max-players=" DEFAULT_MAX_PLAYERS "\n";
|
||||
properties_file_output << "# Enable Whitelist\n";
|
||||
properties_file_output << "whitelist=" DEFAULT_WHITELIST "\n";
|
||||
properties_file_output << "# Enable Death Messages\n";
|
||||
properties_file_output << "death-messages=" DEFAULT_DEATH_MESSAGES "\n";
|
||||
properties_file_output.close();
|
||||
// Re-Open File
|
||||
properties_file = std::ifstream(file);
|
||||
|
@ -58,7 +58,7 @@ static void TextEditScreen_updateEvents_injection(unsigned char *screen) {
|
||||
|
||||
// Init
|
||||
void init_sign() {
|
||||
if (feature_has("Fix Sign Placement", 0)) {
|
||||
if (feature_has("Fix Sign Placement", server_disabled)) {
|
||||
// Fix Signs
|
||||
patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection);
|
||||
patch_address(TextEditScreen_updateEvents_vtable_addr, (void *) TextEditScreen_updateEvents_injection);
|
||||
|
@ -38,7 +38,7 @@ std::string _sound_get_source_file() {
|
||||
// Check If Sound Exists
|
||||
if (access(full_path, F_OK) == -1) {
|
||||
// Fail
|
||||
WARN("%s", "Audio Source File Doesn't Exist: " SOURCE_FILE_BASE);
|
||||
WARN("Audio Source File Doesn't Exist: " SOURCE_FILE_BASE);
|
||||
source.assign("");
|
||||
} else {
|
||||
// Set
|
||||
@ -114,7 +114,7 @@ static void SoundEngine_init_injection(unsigned char *sound_engine, unsigned cha
|
||||
// Init
|
||||
void init_sound() {
|
||||
// Implement Sound Engine
|
||||
if (feature_has("Implement Sound Engine", 0)) {
|
||||
if (feature_has("Implement Sound Engine", server_disabled)) {
|
||||
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);
|
||||
|
@ -16,7 +16,7 @@ void run_tests() {
|
||||
|
||||
if (!can_write) {
|
||||
// Failure
|
||||
ERR("%s", "Invalid Data Directory Permissions");
|
||||
ERR("Invalid Data Directory Permissions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level,
|
||||
// Check
|
||||
if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) {
|
||||
// Pixels Must Be 4 Bytes
|
||||
ERR("%s", "Unsupported Texture Format For Scaling");
|
||||
ERR("Unsupported Texture Format For Scaling");
|
||||
}
|
||||
|
||||
// Scale
|
||||
@ -166,7 +166,7 @@ static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level,
|
||||
// Init
|
||||
void init_textures() {
|
||||
// Tick Dynamic Textures (Animated Water)
|
||||
if (feature_has("Animated Water", 0)) {
|
||||
if (feature_has("Animated Water", server_disabled)) {
|
||||
overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection);
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Enable Touch GUI
|
||||
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_touch() {
|
||||
int touch_gui = feature_has("Touch GUI", 0);
|
||||
if (touch_gui) {
|
||||
// Main UI
|
||||
overwrite((void *) Minecraft_isTouchscreen, (void *) Minecraft_isTouchscreen_injection);
|
||||
|
||||
// Force Correct Toolbar Size
|
||||
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1"
|
||||
patch((void *) 0x257b0, toolbar_patch);
|
||||
}
|
||||
|
||||
// Show Block Outlines
|
||||
int block_outlines = feature_has("Show Block Outlines", 0);
|
||||
unsigned char outline_patch[4] = {block_outlines ? !touch_gui : touch_gui, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1" or "cmp r0, #0x0"
|
||||
patch((void *) 0x4a210, outline_patch);
|
||||
}
|
40
mods/src/touch/touch.cpp
Normal file
40
mods/src/touch/touch.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "../feature/feature.h"
|
||||
#include "../init/init.h"
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
// Enable Touch GUI
|
||||
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IngameBlockSelectionScreen Memory Allocation Override
|
||||
static unsigned char *operator_new_IngameBlockSelectionScreen_injection(__attribute__((unused)) uint32_t size) {
|
||||
return (unsigned char *) ::operator new(TOUCH_INGAME_BLOCK_SELECTION_SCREEN_SIZE);
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_touch() {
|
||||
int touch_gui = feature_has("Touch GUI", server_disabled);
|
||||
if (touch_gui) {
|
||||
// Main UI
|
||||
overwrite((void *) Minecraft_isTouchscreen, (void *) Minecraft_isTouchscreen_injection);
|
||||
|
||||
// Force Correct Toolbar Size
|
||||
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1"
|
||||
patch((void *) 0x257b0, toolbar_patch);
|
||||
}
|
||||
|
||||
// Show Block Outlines
|
||||
int block_outlines = feature_has("Show Block Outlines", 0);
|
||||
unsigned char outline_patch[4] = {(unsigned char) (block_outlines ? !touch_gui : touch_gui), 0x00, 0x50, 0xe3}; // "cmp r0, #0x1" or "cmp r0, #0x0"
|
||||
patch((void *) 0x4a210, outline_patch);
|
||||
|
||||
// Force Touch Inventory
|
||||
if (feature_has("Force Touch Inventory", server_disabled)) {
|
||||
overwrite_call((void *) 0x2943c, (void *) operator_new_IngameBlockSelectionScreen_injection);
|
||||
overwrite_call((void *) 0x29444, (void *) Touch_IngameBlockSelectionScreen);
|
||||
}
|
||||
}
|
@ -131,9 +131,7 @@ const runtime = {
|
||||
`usr/lib/${name}/minecraft-pi`,
|
||||
`usr/lib/${name}/**/*.so`,
|
||||
'usr/arm-linux-gnueabihf/lib'
|
||||
] : undefined,
|
||||
// libapprun_hooks.so Is Buggy And Unneeded
|
||||
no_hooks: true
|
||||
] : undefined
|
||||
};
|
||||
|
||||
// AppDir
|
||||
|
@ -118,4 +118,4 @@ sudo rm -f /usr/local/bin/appimagetool
|
||||
sudo ln -s /opt/appimagetool.AppDir/AppRun /usr/local/bin/appimagetool
|
||||
|
||||
# Install appimage-builder
|
||||
sudo pip3 install 'git+https://github.com/TheBrokenRail/appimage-builder.git@combined'
|
||||
sudo pip3 install 'git+https://github.com/AppImageCrafters/appimage-builder.git'
|
||||
|
@ -18,6 +18,10 @@ static renderCursor_t renderCursor = (renderCursor_t) 0x480c4;
|
||||
static char **default_path = (char **) 0xe264; // /.minecraft/
|
||||
static char **default_username = (char **) 0x18fd4; // StevePi
|
||||
static char **minecraft_pi_version = (char **) 0x39d94; // v0.1.1 alpha
|
||||
static char **options_txt_path = (char **) 0x19bc8; // options.txt
|
||||
static char **options_txt_fopen_mode_when_loading = (char **) 0x19d24; // w
|
||||
static char ***feedback_vibration_options_txt_name_1 = (char ***) 0x198a0; // feedback_vibration
|
||||
static char ***feedback_vibration_options_txt_name_2 = (char ***) 0x194bc; // feedback_vibration
|
||||
|
||||
static unsigned char **Material_stone = (unsigned char **) 0x180a9c; // Material
|
||||
|
||||
@ -53,6 +57,11 @@ static unsigned char **Tile_grass_carried = (unsigned char **) 0x181dd4; // Tile
|
||||
|
||||
static float *InvGuiScale = (float *) 0x135d98;
|
||||
|
||||
static unsigned char *Options_Option_GRAPHICS = (unsigned char *) 0x136c2c; // Option
|
||||
static unsigned char *Options_Option_AMBIENT_OCCLUSION = (unsigned char *) 0x136c38; // Option
|
||||
|
||||
static bool *Minecraft_useAmbientOcclusion = (bool *) 0x136b90;
|
||||
|
||||
// Structures
|
||||
|
||||
struct AABB {
|
||||
@ -109,6 +118,11 @@ static uint32_t Tile_use_vtable_offset = 0x98;
|
||||
static uint32_t Tile_id_property_offset = 0x8; // int32_t
|
||||
static uint32_t Tile_category_property_offset = 0x3c; // int32_t
|
||||
|
||||
// TileRenderer
|
||||
|
||||
typedef void (*TileRenderer_tesselateBlockInWorld_t)(unsigned char *tile_renderer, unsigned char *tile, int32_t x, int32_t y, int32_t z);
|
||||
static TileRenderer_tesselateBlockInWorld_t TileRenderer_tesselateBlockInWorld = (TileRenderer_tesselateBlockInWorld_t) 0x59e30;
|
||||
|
||||
// GameMode
|
||||
|
||||
typedef void (*GameMode_releaseUsingItem_t)(unsigned char *game_mode, unsigned char *player);
|
||||
@ -237,9 +251,16 @@ static uint32_t HitResult_type_property_offset = 0x0;
|
||||
|
||||
// Options
|
||||
|
||||
typedef void (*Options_initDefaultValue_t)(unsigned char *options);
|
||||
static Options_initDefaultValue_t Options_initDefaultValue = (Options_initDefaultValue_t) 0x18a54;
|
||||
|
||||
typedef bool (*Options_getBooleanValue_t)(unsigned char *options, unsigned char *option);
|
||||
static Options_getBooleanValue_t Options_getBooleanValue = (Options_getBooleanValue_t) 0x1cd74;
|
||||
|
||||
static uint32_t Options_options_file_property_offset = 0x10c; // OptionsFile
|
||||
static uint32_t Options_fancy_graphics_property_offset = 0x17; // unsigned char / bool
|
||||
static uint32_t Options_split_controls_property_offset = 0x105; // int32_t
|
||||
static uint32_t Options_peaceful_mode_property_offset = 0xe8; // unsigned char / bool
|
||||
static uint32_t Options_game_difficulty_property_offset = 0xe8; // int32_t
|
||||
static uint32_t Options_3d_anaglyph_property_offset = 0x15; // unsigned char / bool
|
||||
static uint32_t Options_ambient_occlusion_property_offset = 0x18; // unsigned char / bool
|
||||
static uint32_t Options_hide_gui_property_offset = 0xec; // unsigned char / bool
|
||||
@ -248,6 +269,15 @@ static uint32_t Options_render_distance_property_offset = 0x10; // int32_t
|
||||
static uint32_t Options_sound_property_offset = 0x4; // int32_t
|
||||
static uint32_t Options_debug_property_offset = 0xee; // unsigned char / bool
|
||||
static uint32_t Options_server_visible_property_offset = 0x104; // unsigned char / bool
|
||||
static uint32_t Options_username_property_offset = 0x100; // std::string
|
||||
|
||||
// OptionButton
|
||||
|
||||
typedef unsigned char *(*OptionButton_t)(unsigned char *option_button, unsigned char *option);
|
||||
static OptionButton_t OptionButton = (OptionButton_t) 0x1c968;
|
||||
|
||||
typedef void (*OptionButton_updateImage_t)(unsigned char *option_button, unsigned char *options);
|
||||
static OptionButton_updateImage_t OptionButton_updateImage = (OptionButton_updateImage_t) 0x1ca58;
|
||||
|
||||
// MouseBuildInput
|
||||
|
||||
@ -407,7 +437,7 @@ static PerfRenderer_debugFpsMeterKeyPress_t PerfRenderer_debugFpsMeterKeyPress =
|
||||
|
||||
// TextEditScreen
|
||||
|
||||
#define TEXT_EDIT_SCREEN_SIZE 0xd0
|
||||
#define TEXT_EDIT_SCREEN_SIZE 0xa9
|
||||
|
||||
typedef unsigned char *(*TextEditScreen_t)(unsigned char *text_edit_screen, unsigned char *sign);
|
||||
static TextEditScreen_t TextEditScreen = (TextEditScreen_t) 0x3a840;
|
||||
@ -448,11 +478,39 @@ static uint32_t Screen_keyboardNewChar_vtable_offset = 0x70;
|
||||
typedef void (*Screen_keyPressed_t)(unsigned char *screen, int32_t key);
|
||||
static uint32_t Screen_keyPressed_vtable_offset = 0x6c;
|
||||
|
||||
typedef void (*Screen_init_t)(unsigned char *screen);
|
||||
|
||||
typedef void (*Screen_tick_t)(unsigned char *screen);
|
||||
|
||||
typedef int32_t (*Screen_handleBackEvent_t)(unsigned char *screen, bool param_1);
|
||||
|
||||
static uint32_t Screen_minecraft_property_offset = 0x14; // Minecraft *
|
||||
static uint32_t Screen_rendered_buttons_property_offset = 0x18; // std::vector<Button *>
|
||||
static uint32_t Screen_selectable_buttons_property_offset = 0x30; // std::vector<Button *>
|
||||
|
||||
// StartMenuScreen
|
||||
|
||||
static Screen_init_t StartMenuScreen_init = (Screen_init_t) 0x39cc0;
|
||||
static void *StartMenuScreen_init_vtable_addr = (void *) 0x105194;
|
||||
|
||||
static uint32_t StartMenuScreen_options_button_property_offset = 0x98; // Button
|
||||
|
||||
// PauseScreen
|
||||
|
||||
static Screen_init_t PauseScreen_init = (Screen_init_t) 0x36810;
|
||||
static void *PauseScreen_init_vtable_addr = (void *) 0x104b2c;
|
||||
|
||||
typedef void (*PauseScreen_updateServerVisibilityText_t)(unsigned char *screen);
|
||||
static PauseScreen_updateServerVisibilityText_t PauseScreen_updateServerVisibilityText = (PauseScreen_updateServerVisibilityText_t) 0x366b8;
|
||||
|
||||
static uint32_t PauseScreen_server_visibility_button_property_offset = 0x60; // Button *
|
||||
|
||||
// Touch::IngameBlockSelectionScreen
|
||||
|
||||
#define TOUCH_INGAME_BLOCK_SELECTION_SCREEN_SIZE 0x16c
|
||||
|
||||
typedef unsigned char *(*Touch_IngameBlockSelectionScreen_t)(unsigned char *screen);
|
||||
static Touch_IngameBlockSelectionScreen_t Touch_IngameBlockSelectionScreen = (Touch_IngameBlockSelectionScreen_t) 0x3afbc;
|
||||
|
||||
// SelectWorldScreen
|
||||
|
||||
@ -644,6 +702,7 @@ static uint32_t SoundEngine_options_property_offset = 0x4; // Options *
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Structures
|
||||
|
||||
@ -730,6 +789,26 @@ static SoundEngine_play_t SoundEngine_play = (SoundEngine_play_t) 0x67860;
|
||||
typedef std::string (*Common_getGameVersionString_t)(std::string const& version_suffix);
|
||||
static Common_getGameVersionString_t Common_getGameVersionString = (Common_getGameVersionString_t) 0x15068;
|
||||
|
||||
// Options
|
||||
|
||||
typedef void (*Options_addOptionToSaveOutput_t)(unsigned char *options, std::vector<std::string> &data, std::string option, int32_t value);
|
||||
static Options_addOptionToSaveOutput_t Options_addOptionToSaveOutput = (Options_addOptionToSaveOutput_t) 0x195e4;
|
||||
|
||||
// OptionsFile
|
||||
|
||||
typedef std::vector<std::string> (*OptionsFile_getOptionStrings_t)(unsigned char *options_file);
|
||||
static OptionsFile_getOptionStrings_t OptionsFile_getOptionStrings = (OptionsFile_getOptionStrings_t) 0x19c1c;
|
||||
|
||||
typedef void (*OptionsFile_save_t)(unsigned char *options_file, std::vector<std::string> const& data);
|
||||
static OptionsFile_save_t OptionsFile_save = (OptionsFile_save_t) 0x19bcc;
|
||||
|
||||
static uint32_t OptionsFile_options_txt_path_property_offset = 0x0; // std::string
|
||||
|
||||
// OptionsPane
|
||||
|
||||
typedef void (*OptionsPane_unknown_toggle_creating_function_t)(unsigned char *options_pane, unsigned char *unknown_object, std::string const& name, unsigned char *option);
|
||||
static OptionsPane_unknown_toggle_creating_function_t OptionsPane_unknown_toggle_creating_function = (OptionsPane_unknown_toggle_creating_function_t) 0x24470;
|
||||
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
Loading…
Reference in New Issue
Block a user