Fix Options Screen

This commit is contained in:
TheBrokenRail 2022-04-10 22:41:47 -04:00
parent 0b1849a9ad
commit 623cf06516
8 changed files with 276 additions and 81 deletions

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

View File

@ -216,17 +216,6 @@ int main(int argc, char *argv[]) {
// Run
run_zenity_and_set_env("MCPI_RENDER_DISTANCE", command);
}
// Setup MCPI_USERNAME
{
std::vector<std::string> command;
command.push_back("--entry");
command.push_back("--text");
command.push_back("Minecraft Username:");
command.push_back("--entry-text");
command.push_back("StevePi");
// Run
run_zenity_and_set_env("MCPI_USERNAME", command);
}
// Bootstrap
bootstrap(argc, argv);

View File

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

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) {
@ -32,41 +33,32 @@ static int get_render_distance() {
}
#endif
// Get Custom Username
static char *get_username() {
char *username = getenv("MCPI_USERNAME");
if (username == NULL) {
username = "StevePi";
}
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;
// 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
@ -76,10 +68,6 @@ void init_options() {
overwrite((void *) LevelData_getSpawnMobs, (void *) LevelData_getSpawnMobs_injection);
}
// Enable Fancy Graphics
fancy_graphics = feature_has("Fancy Graphics", server_disabled);
// Peaceful Mode
peaceful_mode = feature_has("Peaceful Mode", server_auto);
// 3D Anaglyph
anaglyph = feature_has("3D Anaglyph", server_disabled);
// Render Distance
@ -89,21 +77,9 @@ void init_options() {
#else
render_distance = 3;
#endif
// Server Visible
server_visible = !feature_has("Disable Hosting LAN Worlds", server_disabled);
// Set Options
overwrite_calls((void *) Minecraft_init, (void *) Minecraft_init_injection);
// Change Username
const char *username = get_username();
#ifndef MCPI_SERVER_MODE
INFO("Setting Username: %s", username);
#endif
if (strcmp(*default_username, "StevePi") != 0) {
ERR("%s", "Default Username Is Invalid");
}
patch_address((void *) default_username, (void *) username);
overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection);
// Disable Autojump By Default
if (feature_has("Disable Autojump By Default", server_disabled)) {
@ -118,10 +94,9 @@ void init_options() {
patch((void *) 0xa6628, display_nametags_patch);
}
// Enable Smooth Lighting
smooth_lighting = feature_has("Smooth Lighting", server_disabled);
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,187 @@
#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 Username
{
std::string entry = "mp_username:";
std::string username = *(std::string *) (options + Options_username_property_offset);
entry += username;
data.push_back(entry);
}
// 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
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());
}
// 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);
}
}
// 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);
}
// 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);
// Replace "feedback_vibration" Loading/Saving With "gfx_ao"
{
// Replace String
static const char *new_feedback_vibration_options_txt_nam = "gfx_ao";
static const char **new_feedback_vibration_options_txt_nam_ptr = &new_feedback_vibration_options_txt_nam;
patch_address((void *) feedback_vibration_options_txt_name_1, (void *) new_feedback_vibration_options_txt_nam_ptr);
patch_address((void *) feedback_vibration_options_txt_name_2, (void *) new_feedback_vibration_options_txt_nam_ptr);
// 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

@ -48,13 +48,11 @@ static ServerProperties &get_server_properties() {
}
// Default Server Properties
#define DEFAULT_MOTD "Minecraft Server"
#define DEFAULT_SHOW_MINECON_BADGE "false"
#define DEFAULT_GAME_MODE "0"
#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"
@ -404,12 +402,6 @@ static unsigned char *ServerSideNetworkHandler_onReady_ClientGeneration_ServerSi
return player;
}
// Get MOTD
static std::string get_motd() {
std::string motd(get_server_properties().get_string("motd", DEFAULT_MOTD));
return motd;
}
// Get Feature Flags
static bool loaded_features = false;
static const char *get_features() {
@ -418,9 +410,6 @@ 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|";
}
@ -453,8 +442,6 @@ static void server_init() {
if (!properties_file.good()) {
// Write Defaults
std::ofstream properties_file_output(file);
properties_file_output << "# Message Of The Day\n";
properties_file_output << "motd=" DEFAULT_MOTD "\n";
properties_file_output << "# Show The MineCon Badge Next To MOTD In Server List\n";
properties_file_output << "show-minecon-badge=" DEFAULT_SHOW_MINECON_BADGE "\n";
properties_file_output << "# Game Mode (0 = Survival, 1 = Creative)\n";
@ -465,8 +452,6 @@ 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";
@ -531,5 +516,4 @@ static void server_init() {
void init_server() {
server_init();
setenv("MCPI_FEATURE_FLAGS", get_features(), 1);
setenv("MCPI_USERNAME", get_motd().c_str(), 1);
}

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
@ -644,6 +674,7 @@ static uint32_t SoundEngine_options_property_offset = 0x4; // Options *
#ifdef __cplusplus
#include <string>
#include <vector>
// Structures
@ -730,6 +761,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