Compare commits

...

13 Commits

Author SHA1 Message Date
89c29f14b1 More AppImage Fixes
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
2022-04-20 18:21:29 -04:00
4edfaeead4 More Fixes 2022-04-16 16:38:09 -04:00
bfcdd3c7e9 AppImage Fixes 2022-04-14 21:12:42 -04:00
5467b5178f Fix LD_PRELOAD 2022-04-13 20:59:47 -04:00
8f49c550ba 2.3.4 2022-04-12 22:08:27 -04:00
50eb4801a0 Revert Earlier Username Decision 2022-04-12 20:38:44 -04:00
a3eef9fc3b Add "Fix Pause Menu" 2022-04-11 22:52:38 -04:00
f455780833 Add "Force Touch Inventory" 2022-04-11 19:59:21 -04:00
0150879d2b Fix Options Button On Classic UI 2022-04-11 18:48:43 -04:00
623cf06516 Fix Options Screen 2022-04-10 22:41:47 -04:00
0b1849a9ad Make Death Messages Customizable Server-Side 2022-04-09 20:06:44 -04:00
157d51e6b6 Improve feature_has 2022-04-09 20:01:16 -04:00
ed58356dd8 Fix Q Behavior 2022-04-02 19:25:03 -04:00
56 changed files with 610 additions and 226 deletions

1
.gitignore vendored
View File

@ -6,5 +6,6 @@ CMakeLists.txt.user
*.autosave
AppImageBuilder.yml
appimage-builder-cache
appimage-build
AppDir
*.zsync

View File

@ -1 +1 @@
2.3.3
2.3.4

@ -1 +1 @@
Subproject commit 955fbd9d265fa95adf9cb94896eb9a516aa50420
Subproject commit 4cb36872a5fe448c205d0b46f0e8c8b57530cfe0

@ -1 +1 @@
Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f
Subproject commit 21767c654d31d2dccdde4330529775c6c5fd5389

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -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

View File

@ -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]

View File

@ -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");
}
}
}

View File

@ -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);

View File

@ -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")

View File

@ -11,7 +11,7 @@
#define ALLOC_CHECK(obj) \
{ \
if (obj == NULL) { \
ERR("%s", "Memory Allocation Failed"); \
ERR("Memory Allocation Failed"); \
} \
}

View File

@ -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);

View File

@ -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

View 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");
}
}

View File

@ -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");
}
}

View File

@ -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

View File

@ -36,6 +36,6 @@ __attribute__ ((noreturn)) void SDL_Quit() {
while (wait(NULL) > 0) {}
// Exit
INFO("%s", "Stopped");
INFO("Stopped");
exit(EXIT_SUCCESS);
}

View File

@ -58,7 +58,7 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) {
GLint current_buffer = 0; \
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &current_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(); \

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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);
}

View File

@ -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 : "");

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View 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);
}

View 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

View File

@ -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);

View 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);

View File

@ -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);

View File

@ -16,7 +16,7 @@ void run_tests() {
if (!can_write) {
// Failure
ERR("%s", "Invalid Data Directory Permissions");
ERR("Invalid Data Directory Permissions");
}
}
}

View File

@ -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);
}

View File

@ -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
View 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);
}
}

View File

@ -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

View File

@ -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'

View File

@ -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