minecraft-pi-reborn/mods/src/options/options.cpp

237 lines
8.3 KiB
C++
Raw Normal View History

2024-04-02 23:22:01 +00:00
#include <cstring>
2022-04-11 02:41:47 +00:00
#include <string>
#include <vector>
#include <sstream>
#include <libreborn/libreborn.h>
2024-04-02 23:22:01 +00:00
#include <symbols/minecraft.h>
2022-04-11 02:41:47 +00:00
2022-06-25 21:30:08 +00:00
#include <mods/feature/feature.h>
2024-04-02 23:22:01 +00:00
#include <mods/init/init.h>
2022-06-25 21:30:08 +00:00
#include <mods/home/home.h>
2022-04-11 02:41:47 +00:00
2024-05-09 00:18:50 +00:00
#include "options-internal.h"
2024-04-02 23:22:01 +00:00
// Force Mob Spawning
2024-06-21 05:19:37 +00:00
static bool LevelData_getSpawnMobs_injection(__attribute__((unused)) LevelData_getSpawnMobs_t original, __attribute__((unused)) LevelData *level_data) {
2024-04-02 23:22:01 +00:00
return true;
}
// Get Custom Render Distance
static int get_render_distance() {
const char *distance_str = getenv(MCPI_RENDER_DISTANCE_ENV);
2024-04-02 23:22:01 +00:00
if (distance_str == nullptr) {
distance_str = "Short";
}
if (strcmp("Far", distance_str) == 0) {
return 0;
} else if (strcmp("Normal", distance_str) == 0) {
return 1;
} else if (strcmp("Short", distance_str) == 0) {
return 2;
} else if (strcmp("Tiny", distance_str) == 0) {
return 3;
} else {
ERR("Invalid Render Distance: %s", distance_str);
}
}
// Get Custom Username
static const char *get_username() {
const char *username = getenv(MCPI_USERNAME_ENV);
2024-04-02 23:22:01 +00:00
if (username == nullptr) {
username = "StevePi";
}
return username;
}
static char *safe_username = nullptr;
__attribute__((destructor)) static void _free_safe_username() {
free(safe_username);
}
static int render_distance;
// Configure Options
2024-05-09 00:18:50 +00:00
Options *stored_options = nullptr;
2024-04-03 07:19:12 +00:00
static void Options_initDefaultValue_injection(Options_initDefaultValue_t original, Options *options) {
2024-04-02 23:22:01 +00:00
// Call Original Method
2024-04-03 07:19:12 +00:00
original(options);
2024-04-02 23:22:01 +00:00
// Default Graphics Settings
options->fancy_graphics = true;
options->ambient_occlusion = true;
// Store
stored_options = options;
}
2024-04-03 07:19:12 +00:00
static void Minecraft_init_injection(Minecraft_init_t original, Minecraft *minecraft) {
2024-04-02 23:22:01 +00:00
// Call Original Method
2024-04-03 07:19:12 +00:00
original(minecraft);
2024-04-02 23:22:01 +00:00
Options *options = &minecraft->options;
// Enable Crosshair In Touch GUI
options->split_controls = true;
// Render Distance
options->render_distance = render_distance;
}
// Smooth Lighting
2024-09-21 01:30:47 +00:00
static bool TileRenderer_tesselateBlockInWorld_injection(TileRenderer_tesselateBlockInWorld_t original, TileRenderer *tile_renderer, Tile *tile, const int32_t x, const int32_t y, const int32_t z) {
2024-04-02 23:22:01 +00:00
// Set Variable
2024-05-17 06:52:55 +00:00
Minecraft::useAmbientOcclusion = stored_options->ambient_occlusion;
2024-04-02 23:22:01 +00:00
// Call Original Method
2024-04-03 07:19:12 +00:00
return original(tile_renderer, tile, x, y, z);
2024-04-02 23:22:01 +00:00
}
2022-04-11 02:41:47 +00:00
// Actually Save options.txt
// Hook Last Options::addOptionToSaveOutput Call
2024-01-06 11:30:23 +00:00
static void Options_save_Options_addOptionToSaveOutput_injection(Options *options, std::vector<std::string> *data, std::string option, int32_t value) {
2022-04-11 02:41:47 +00:00
// Call Original Method
2024-05-15 09:02:19 +00:00
options->addOptionToSaveOutput(data, option, value);
2022-04-11 02:41:47 +00:00
// Save Fancy Graphics
2024-05-15 09:02:19 +00:00
options->addOptionToSaveOutput(data, "gfx_fancygraphics", options->fancy_graphics);
2022-04-11 02:41:47 +00:00
2022-09-21 22:40:09 +00:00
// Save 3D Anaglyph
2024-05-15 09:02:19 +00:00
options->addOptionToSaveOutput(data, "gfx_anaglyph", options->anaglyph_3d);
2022-09-21 22:40:09 +00:00
2022-04-11 02:41:47 +00:00
// Save File
2024-01-06 11:30:23 +00:00
OptionsFile *options_file = &options->options_file;
2024-05-15 09:02:19 +00:00
options_file->save(data);
2022-04-11 02:41:47 +00:00
}
// MCPI's OptionsFile::getOptionStrings is broken, this is the version in v0.7.0
2024-06-21 05:19:37 +00:00
static std::vector<std::string> OptionsFile_getOptionStrings_injection(__attribute__((unused)) OptionsFile_getOptionStrings_t original, OptionsFile *options_file) {
2022-04-11 02:41:47 +00:00
// Get options.txt Path
2024-09-21 01:30:47 +00:00
const std::string path = options_file->options_txt_path;
2022-04-11 02:41:47 +00:00
// Parse
std::vector<std::string> ret;
FILE *stream = fopen(path.c_str(), "r");
2024-04-02 23:22:01 +00:00
if (stream != nullptr) {
2024-09-21 01:30:47 +00:00
char line[128];
2024-04-02 23:22:01 +00:00
while (fgets(line, 0x80, stream) != nullptr) {
2024-09-21 01:30:47 +00:00
const size_t sVar1 = strlen(line);
2022-04-11 02:41:47 +00:00
if (2 < sVar1) {
std::stringstream string_stream(line);
while (true) {
std::string data;
std::getline(string_stream, data, ':');
2024-09-21 01:30:47 +00:00
const int iVar2 = data.find_last_not_of(" \n\r\t");
2022-04-11 02:41:47 +00:00
data.erase(iVar2 + 1);
if (data.length() == 0) {
break;
}
ret.push_back(data);
}
}
}
fclose(stream);
}
return ret;
}
// Get New options.txt Path
2024-06-15 12:52:15 +00:00
static const char *get_new_options_txt_path() {
static std::string path = "";
2022-04-11 02:41:47 +00:00
// Path
2024-06-15 12:52:15 +00:00
if (path.empty()) {
path = !reborn_is_server() ? (std::string(home_get()) + "/options.txt") : "/dev/null";
2022-04-11 02:41:47 +00:00
}
// Return
2024-06-15 12:52:15 +00:00
return path.c_str();
2022-04-11 02:41:47 +00:00
}
2024-04-02 23:22:01 +00:00
// Init
void init_options() {
// Force Mob Spawning
if (feature_has("Force Mob Spawning", server_auto)) {
2024-06-21 05:19:37 +00:00
overwrite_calls(LevelData_getSpawnMobs, LevelData_getSpawnMobs_injection);
2024-04-02 23:22:01 +00:00
}
// Render Distance
render_distance = get_render_distance();
DEBUG("Setting Render Distance: %i", render_distance);
// Set Options
2024-04-03 07:19:12 +00:00
overwrite_calls(Options_initDefaultValue, Options_initDefaultValue_injection);
2024-05-24 08:44:53 +00:00
overwrite_calls(Minecraft_init, Minecraft_init_injection);
2024-04-02 23:22:01 +00:00
// Change Username
const char *username = get_username();
DEBUG("Setting Username: %s", username);
2024-05-17 06:52:55 +00:00
if (strcmp(Strings::default_username, "StevePi") != 0) {
2024-04-02 23:22:01 +00:00
ERR("Default Username Is Invalid");
}
safe_username = to_cp437(username);
2024-05-17 06:52:55 +00:00
patch_address((void *) &Strings::default_username, (void *) safe_username);
2024-04-02 23:22:01 +00:00
// Disable Autojump By Default
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", 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);
}
// Smooth Lighting
2024-04-03 07:19:12 +00:00
overwrite_calls(TileRenderer_tesselateBlockInWorld, TileRenderer_tesselateBlockInWorld_injection);
2024-04-02 23:22:01 +00:00
2022-04-11 02:41:47 +00:00
// NOP
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
// Actually Save options.txt
overwrite_call((void *) 0x197fc, (void *) Options_save_Options_addOptionToSaveOutput_injection);
// Fix options.txt Path
2024-05-17 06:52:55 +00:00
patch_address((void *) &Strings::options_txt_path, (void *) get_new_options_txt_path());
2022-04-11 02:41:47 +00:00
// When Loading, options.txt Should Be Opened In Read Mode
2024-05-17 06:52:55 +00:00
patch_address((void *) &Strings::options_txt_fopen_mode_when_loading, (void *) "r");
2022-04-11 02:41:47 +00:00
// Fix OptionsFile::getOptionStrings
2024-06-21 05:19:37 +00:00
overwrite_calls(OptionsFile_getOptionStrings, OptionsFile_getOptionStrings_injection);
2022-04-11 02:41:47 +00:00
// Sensitivity Loading/Saving Is Broken, Disable It
patch((void *) 0x1931c, nop_patch);
patch((void *) 0x1973c, nop_patch);
2022-04-12 02:52:38 +00:00
// 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);
2022-04-13 00:38:44 +00:00
// Custom Username Is Loaded Manually, Disable Loading From options.txt
patch((void *) 0x192ac, nop_patch);
2022-04-11 02:41:47 +00:00
// Replace "feedback_vibration" Loading/Saving With "gfx_ao"
{
// Replace String
2024-05-17 06:52:55 +00:00
patch_address((void *) &Strings::feedback_vibration_options_txt_name, (void *) "gfx_ao");
2022-04-11 02:41:47 +00:00
// Loading
2024-09-21 01:30:47 +00:00
const unsigned char offset = (unsigned char) offsetof(Options, ambient_occlusion);
2024-01-06 11:30:23 +00:00
unsigned char gfx_ao_loading_patch[4] = {offset, 0x10, 0x84, 0xe2}; // "add r1, r4, #OFFSET"
2022-04-11 02:41:47 +00:00
patch((void *) 0x193b8, gfx_ao_loading_patch);
// Saving
2024-01-06 11:30:23 +00:00
unsigned char gfx_ao_saving_patch[4] = {offset, 0x30, 0xd4, 0xe5}; // "ldrb r3, [r4, #OFFSET]"
2022-04-11 02:41:47 +00:00
patch((void *) 0x197f8, gfx_ao_saving_patch);
}
2022-09-21 22:40:09 +00:00
// Replace "gfx_lowquality" Loading With "gfx_anaglyph"
{
// Replace String
2024-05-17 06:52:55 +00:00
patch_address((void *) &Strings::gfx_lowquality_options_txt_name, (void *) "gfx_anaglyph");
2022-09-21 22:40:09 +00:00
// Loading
2024-09-21 01:30:47 +00:00
const unsigned char offset = (unsigned char) offsetof(Options, anaglyph_3d);
2024-01-06 11:30:23 +00:00
unsigned char gfx_anaglyph_loading_patch[4] = {offset, 0x10, 0x84, 0xe2}; // "add r1, r4, #OFFSET"
2022-09-21 22:40:09 +00:00
patch((void *) 0x19400, gfx_anaglyph_loading_patch);
// Disable Loading Side Effects
patch((void *) 0x19414, nop_patch);
patch((void *) 0x1941c, nop_patch);
}
2024-05-09 00:18:50 +00:00
// UI
_init_options_ui();
2022-04-11 02:41:47 +00:00
}