Compare commits

...

5 Commits

Author SHA1 Message Date
16f919d147 2.3.5
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
2022-04-23 21:19:53 -04:00
e18fc9fc63 Simplify 2022-04-23 21:10:44 -04:00
3ebdffd396 Fixes 2022-04-23 18:49:08 -04:00
82b6252927 Classic UI By Default! 2022-04-23 16:46:40 -04:00
4a35935daf Add Improved Title Background 2022-04-22 19:38:15 -04:00
20 changed files with 230 additions and 76 deletions

View File

@ -123,3 +123,8 @@ endif()
if(BUILD_ARM_COMPONENTS)
add_subdirectory(mods)
endif()
# Include Images
if(BUILD_NATIVE_COMPONENTS)
add_subdirectory(images)
endif()

View File

@ -1 +1 @@
2.3.4
2.3.5

View File

@ -1,5 +1,13 @@
# Changelog
**2.3.5**
* Rename Some Feature Flags
* Add `Improved Title Background` Feature Flag (Enabled By Default)
* Non-Touch GUI Rework
* Make `Full Touch GUI` Feature Flag Disabled By Default
* Add `Force Touch GUI Button Behavior` Feature Flag (Enabled By Default)
* Add `Improved Button Hover Behavior` Feature Flag (Enabled By Default)
**2.3.4**
* AppImage Fixes
* Make Death Messages Customizable Server-Side

10
images/CMakeLists.txt Normal file
View File

@ -0,0 +1,10 @@
project(images)
# Title Background
if(NOT MCPI_SERVER_MODE)
install(
FILES "background.png"
DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui"
RENAME "titleBG.png"
)
endif()

BIN
images/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 153 KiB

View File

@ -1,4 +1,4 @@
TRUE Touch GUI
FALSE Full Touch GUI
TRUE Fix Bow & Arrow
TRUE Fix Attacking
FALSE Force Mob Spawning
@ -31,5 +31,8 @@ TRUE Fix Furnace Not Checking Item Auxiliary
TRUE Improved Cursor Rendering
FALSE Disable V-Sync
TRUE Fix Options Screen
FALSE Force Touch Inventory
TRUE Force Touch GUI Inventory
TRUE Fix Pause Menu
TRUE Improved Title Background
TRUE Force Touch GUI Button Behavior
TRUE Improved Button Hover Behavior

View File

@ -209,10 +209,23 @@ void bootstrap(int argc, char *argv[]) {
// Set MCPI_EXECUTABLE_PATH
set_and_print_env("MCPI_EXECUTABLE_PATH", resolved_path);
// Set MCPI_DIRECTORY
chop_last_component(&resolved_path);
set_and_print_env("MCPI_DIRECTORY", resolved_path);
free(resolved_path);
// Set MCPI_VANILLA_ASSETS_PATH
{
chop_last_component(&resolved_path);
string_append(&resolved_path, "/data");
set_and_print_env("MCPI_VANILLA_ASSETS_PATH", resolved_path);
free(resolved_path);
}
}
// Set MCPI_REBORN_ASSETS_PATH
{
char *assets_path = realpath("/proc/self/exe", NULL);
ALLOC_CHECK(assets_path);
chop_last_component(&assets_path);
string_append(&assets_path, "/data");
set_and_print_env("MCPI_REBORN_ASSETS_PATH", assets_path);
free(assets_path);
}
// Fix MCPI Dependencies
@ -241,12 +254,6 @@ 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

View File

@ -8,12 +8,26 @@
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
#define TMP_DIR "/tmp/.minecraft-pi-tmp"
static void duplicate_mcpi_executable() {
// Get Original Path
const char *original_path = getenv("MCPI_EXECUTABLE_PATH");
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(TMP_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(TMP_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Generate New File
char new_path[] = "/tmp/.minecraft-pi-XXXXXX";
char new_path[] = TMP_DIR "/XXXXXX";
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));

View File

@ -26,9 +26,6 @@ char *get_binary_directory();
// Safe execvpe() Relative To Binary
__attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const argv[], const char *const envp[]);
// Get MCPI Directory
char *get_mcpi_directory();
// Run Command And Get Output
char *run_command(const char *const command[], int *return_code);

View File

@ -19,7 +19,7 @@
#define string_append(str, format, ...) \
{ \
char *old = *str; \
safe_asprintf(str, "%s" format, *str == NULL ? "" : *str, __VA_ARGS__); \
safe_asprintf(str, "%s" format, *str == NULL ? "" : *str, ##__VA_ARGS__); \
ALLOC_CHECK(*str); \
if (old != NULL && old != *str) { \
free(old); \

View File

@ -57,11 +57,6 @@ __attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const
safe_execvpe(new_argv, envp);
}
// Get MCPI Directory
char *get_mcpi_directory() {
return getenv("MCPI_DIRECTORY");
}
// Run Command And Get Output
char *run_command(const char *const command[], int *return_code) {
// Store Output

View File

@ -26,11 +26,8 @@ void init_home() {
// Store Data In ~/.minecraft-pi Instead Of ~/.minecraft
patch_address((void *) default_path, (void *) HOME_SUBDIRECTORY_FOR_GAME_DATA);
// Change Directory To Binary Directory Manually
// The override code resolves assets manually,
// making changing directory redundant.
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
patch((void *) 0xe0ac, nop_patch);
char *binary_directory = get_mcpi_directory();
if (chdir(binary_directory) != 0) {
ERR("Unable To Change Directory: %s", strerror(errno));
}
}

View File

@ -14,7 +14,7 @@
// Read Asset File
static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path) {
// Read File
std::string full_path("./data/");
std::string full_path("data/");
full_path.append(path);
std::ifstream stream(full_path);
std::string str((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
@ -70,6 +70,15 @@ static void PauseScreen_init_injection(unsigned char *screen) {
}
}
// Improved Title Background
static void StartMenuScreen_render_Screen_renderBackground_injection(unsigned char *screen) {
// Draw
unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset);
unsigned char *textures = *(unsigned char **) (minecraft + Minecraft_textures_property_offset);
(*Textures_loadAndBindTexture)(textures, "gui/titleBG.png");
(*GuiComponent_blit)(screen, 0, 0, 0, 0, *(int32_t *) (screen + Screen_width_property_offset), *(int32_t *) (screen + Screen_height_property_offset), 0x100, 0x100);
}
// Init
void _init_misc_cpp() {
// Implement AppPlatform::readAssetFile So Translations Work
@ -85,4 +94,14 @@ void _init_misc_cpp() {
// Add Missing Buttons To Pause Menu
patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection);
}
// Improved Title Background
if (feature_has("Improved Title Background", server_disabled)) {
// Switch Background
overwrite_call((void *) 0x39528, (void *) StartMenuScreen_render_Screen_renderBackground_injection);
overwrite_call((void *) 0x3dee0, (void *) StartMenuScreen_render_Screen_renderBackground_injection);
// Text Color
patch_address((void *) 0x397ac, (void *) 0xffffffff);
patch_address((void *) 0x3e10c, (void *) 0xffffffff);
}
}

View File

@ -50,13 +50,6 @@ static void Options_initDefaultValue_injection(unsigned char *options) {
// Call Original Method
(*Options_initDefaultValue)(options);
// Enable Crosshair In Touch GUI
*(options + Options_split_controls_property_offset) = 1;
// 3D Anaglyph
*(options + Options_3d_anaglyph_property_offset) = anaglyph;
// Render Distance
*(int32_t *) (options + Options_render_distance_property_offset) = render_distance;
// Default Graphics Settings
*(options + Options_fancy_graphics_property_offset) = 1;
*(options + Options_ambient_occlusion_property_offset) = 1;
@ -64,6 +57,18 @@ static void Options_initDefaultValue_injection(unsigned char *options) {
// Store
stored_options = options;
}
static void Minecraft_init_injection(unsigned char *minecraft) {
// Call Original Method
(*Minecraft_init)(minecraft);
unsigned char *options = minecraft + Minecraft_options_property_offset;
// Enable Crosshair In Touch GUI
*(options + Options_split_controls_property_offset) = 1;
// 3D Anaglyph
*(options + Options_3d_anaglyph_property_offset) = anaglyph;
// Render Distance
*(int32_t *) (options + Options_render_distance_property_offset) = render_distance;
}
// Smooth Lighting
static void TileRenderer_tesselateBlockInWorld_injection(unsigned char *tile_renderer, unsigned char *tile, int32_t x, int32_t y, int32_t z) {
@ -93,6 +98,7 @@ void init_options() {
// Set Options
overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection);
overwrite_calls((void *) Minecraft_init, (void *) Minecraft_init_injection);
// Change Username
const char *username = get_username();

View File

@ -8,8 +8,23 @@
#include <libreborn/libreborn.h>
#include "override.h"
#include "../home/home.h"
// Hook access
HOOK(access, int, (const char *pathname, int mode)) {
char *new_path = override_get_path(pathname);
// Open File
ensure_access();
int ret = (*real_access)(new_path != NULL ? new_path : pathname, mode);
// Free Data
if (new_path != NULL) {
free(new_path);
}
// Return
return ret;
}
// Get Override Path For File (If It Exists)
char *override_get_path(const char *filename) {
// Get MCPI Home Path
@ -18,43 +33,45 @@ char *override_get_path(const char *filename) {
char *overrides = NULL;
safe_asprintf(&overrides, "%s/overrides", home_path);
// Get Data Path
char *data = NULL;
char *binary_directory = get_mcpi_directory();
safe_asprintf(&data, "%s/data", binary_directory);
int data_length = strlen(data);
// Data Prefiix
char *data_prefix = "data/";
int data_prefix_length = strlen(data_prefix);
// Get Full Path
char *full_path;
if (strlen(filename) > 0 && filename[0] == '/') {
// Absolute Path
full_path = strdup(filename);
} else {
// Relative Path
full_path = realpath(filename, NULL);
}
// Folders To Check
char *asset_folders[] = {
overrides,
getenv("MCPI_REBORN_ASSETS_PATH"),
getenv("MCPI_VANILLA_ASSETS_PATH"),
NULL
};
// Check For Override
char *new_path = NULL;
if (full_path != NULL) {
if (starts_with(full_path, data)) {
safe_asprintf(&new_path, "%s%s", overrides, &full_path[data_length]);
if (access(new_path, F_OK) == -1) {
if (starts_with(filename, data_prefix)) {
// Test Asset Folders
for (int i = 0; asset_folders[i] != NULL; i++) {
safe_asprintf(&new_path, "%s/%s", asset_folders[i], &filename[data_prefix_length]);
ensure_access();
if ((*real_access)(new_path, F_OK) == -1) {
// Not Found In Asset Folder
free(new_path);
new_path = NULL;
continue;
} else {
// Found
break;
}
}
free(full_path);
}
// Free Variables
// Free
free(overrides);
free(data);
// Return
return new_path;
}
// Hook fopen
HOOK(fopen, FILE *, (const char *filename, const char *mode)) {
char *new_path = override_get_path(filename);
// Open File
@ -68,6 +85,7 @@ HOOK(fopen, FILE *, (const char *filename, const char *mode)) {
return file;
}
// Hook fopen64
HOOK(fopen64, FILE *, (const char *filename, const char *mode)) {
char *new_path = override_get_path(filename);
// Open File

View File

@ -22,31 +22,29 @@ std::string _sound_get_source_file() {
} else {
// Resolve
// Get Binary Directory
char *binary_directory = get_mcpi_directory();
// Get Full Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory);
// Get Path
char *path = strdup(SOURCE_FILE_BASE);
ALLOC_CHECK(path);
// Handle Overrides
char *overridden_full_path = override_get_path(full_path);
char *overridden_full_path = override_get_path(path);
if (overridden_full_path != NULL) {
free(full_path);
full_path = overridden_full_path;
free(path);
path = overridden_full_path;
}
// Check If Sound Exists
if (access(full_path, F_OK) == -1) {
if (access(path, F_OK) == -1) {
// Fail
WARN("Audio Source File Doesn't Exist: " SOURCE_FILE_BASE);
source.assign("");
} else {
// Set
source.assign(full_path);
source.assign(path);
}
// Free
free(full_path);
free(path);
// Mark As Loaded
source_loaded = true;

View File

@ -15,9 +15,35 @@ static unsigned char *operator_new_IngameBlockSelectionScreen_injection(__attrib
return (unsigned char *) ::operator new(TOUCH_INGAME_BLOCK_SELECTION_SCREEN_SIZE);
}
// Improved Button Hover Behavior
static int32_t Button_hovered_injection(__attribute__((unused)) unsigned char *button, __attribute__((unused)) unsigned char *minecraft, __attribute__((unused)) int32_t click_x, __attribute__((unused)) int32_t click_y) {
// Get Mouse Position
int32_t x = (*Mouse_getX)() * (*InvGuiScale);
int32_t y = (*Mouse_getY)() * (*InvGuiScale);
// Get Button Position
int32_t button_x1 = *(int32_t *) (button + Button_x_property_offset);
int32_t button_y1 = *(int32_t *) (button + Button_y_property_offset);
int32_t button_x2 = button_x1 + (*(int32_t *) (button + Button_width_property_offset));
int32_t button_y2 = button_y1 + (*(int32_t *) (button + Button_height_property_offset));
// Check
return x >= button_x1 && x <= button_x2 && y >= button_y1 && y <= button_y2;
}
static void LargeImageButton_render_GuiComponent_drawCenteredString_injection(unsigned char *component, unsigned char *font, std::string const& text, int32_t x, int32_t y, int32_t color) {
// Change Color On Hover
if (color == 0xe0e0e0 && Button_hovered_injection(component, NULL, 0, 0)) {
color = 0xffffa0;
}
// Call Original Method
(*GuiComponent_drawCenteredString)(component, font, text, x, y, color);
}
// Init
void init_touch() {
int touch_gui = feature_has("Touch GUI", server_disabled);
int touch_gui = feature_has("Full Touch GUI", server_disabled);
int touch_buttons = touch_gui;
if (touch_gui) {
// Main UI
overwrite((void *) Minecraft_isTouchscreen, (void *) Minecraft_isTouchscreen_injection);
@ -25,16 +51,37 @@ void init_touch() {
// Force Correct Toolbar Size
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3}; // "cmp r0, #0x1"
patch((void *) 0x257b0, toolbar_patch);
} else {
// Force Touch Inventory
if (feature_has("Force Touch GUI Inventory", server_disabled)) {
overwrite_call((void *) 0x2943c, (void *) operator_new_IngameBlockSelectionScreen_injection);
overwrite_call((void *) 0x29444, (void *) Touch_IngameBlockSelectionScreen);
}
// Force Touch Button Behavior
if (feature_has("Force Touch GUI Button Behavior", server_disabled)) {
touch_buttons = 1;
overwrite_call((void *) 0x1baf4, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x1be40, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x1c470, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x1e868, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x290b8, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x29168, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x3e314, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x2cbc0, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x2ea7c, (void *) Minecraft_isTouchscreen_injection);
overwrite_call((void *) 0x4a438, (void *) Minecraft_isTouchscreen_injection);
}
}
// Improved Button Hover Behavior
if (touch_buttons && feature_has("Improved Button Hover Behavior", server_disabled)) {
overwrite((void *) Button_hovered, (void *) Button_hovered_injection);
overwrite_call((void *) 0x1ebd4, (void *) LargeImageButton_render_GuiComponent_drawCenteredString_injection);
}
// 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

@ -122,7 +122,8 @@ const runtime = {
GTK_DATA_PREFIX: '${APPDIR}',
GTK_THEME: 'Default',
XDG_DATA_DIRS: '${APPDIR}/share:${APPDIR}/usr/share',
APPDIR_LIBRARY_PATH: `\${APPDIR}/usr/lib/${triplet}:\${APPDIR}/usr/${triplet}/lib:\${APPDIR}/lib/${triplet}:\${APPDIR}/usr/lib:\${APPDIR}/usr/lib/${triplet}/gdk-pixbuf-2.0/2.10.0/loaders`
APPDIR_LIBRARY_PATH: `\${APPDIR}/usr/lib/${triplet}:\${APPDIR}/usr/${triplet}/lib:\${APPDIR}/lib/${triplet}:\${APPDIR}/usr/lib:\${APPDIR}/usr/lib/${triplet}/gdk-pixbuf-2.0/2.10.0/loaders`,
APPDIR_MODULE_DIR: '/tmp/.minecraft-pi-tmp'
} : undefined,
preserve: arch !== 'armhf' ? [
// On non-ARM32 systems, an ARM32 linker is embedded, this

View File

@ -467,6 +467,11 @@ static uint32_t FurnaceScreen_tile_entity_property_offset = 0x1d0; // FurnaceTil
typedef ItemInstance *(*FurnaceTileEntity_getItem_t)(unsigned char *furnace_tile_entity, int32_t slot);
static uint32_t FurnaceTileEntity_getItem_vtable_offset = 0x2c;
// GuiComponent
typedef void (*GuiComponent_blit_t)(unsigned char *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src);
static GuiComponent_blit_t GuiComponent_blit = (GuiComponent_blit_t) 0x282a4;
// Screen
typedef void (*Screen_updateEvents_t)(unsigned char *screen);
@ -482,11 +487,25 @@ typedef void (*Screen_init_t)(unsigned char *screen);
typedef void (*Screen_tick_t)(unsigned char *screen);
typedef void (*Screen_render_t)(unsigned char *screen, int32_t param_1, int32_t param_2, float param_3);
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 *>
static uint32_t Screen_width_property_offset = 0x8; // int32_t
static uint32_t Screen_height_property_offset = 0xc; // int32_t
// Button
typedef int32_t (*Button_hovered_t)(unsigned char *button, unsigned char *minecraft, int32_t click_x, int32_t click_y);
static Button_hovered_t Button_hovered = (Button_hovered_t) 0x1be2c;
static uint32_t Button_width_property_offset = 0x14; // int32_t
static uint32_t Button_height_property_offset = 0x18; // int32_t
static uint32_t Button_x_property_offset = 0xc; // int32_t
static uint32_t Button_y_property_offset = 0x10; // int32_t
// StartMenuScreen
@ -755,6 +774,11 @@ static Level_addParticle_t Level_addParticle = (Level_addParticle_t) 0xa449c;
typedef void (*Gui_addMessage_t)(unsigned char *gui, std::string const& text);
static Gui_addMessage_t Gui_addMessage = (Gui_addMessage_t) 0x27820;
// GuiComponent
typedef void (*GuiComponent_drawCenteredString_t)(unsigned char *component, unsigned char *font, std::string const& text, int32_t x, int32_t y, int32_t color);
static GuiComponent_drawCenteredString_t GuiComponent_drawCenteredString = (GuiComponent_drawCenteredString_t) 0x2821c;
// ServerSideNetworkHandler
typedef void (*ServerSideNetworkHandler_displayGameMessage_t)(unsigned char *server_side_network_handler, std::string const& message);
@ -809,6 +833,11 @@ static uint32_t OptionsFile_options_txt_path_property_offset = 0x0; // std::stri
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;
// Textures
typedef void (*Textures_loadAndBindTexture_t)(unsigned char *textures, std::string const& name);
static Textures_loadAndBindTexture_t Textures_loadAndBindTexture = (Textures_loadAndBindTexture_t) 0x539cc;
#endif
#pragma GCC diagnostic pop