Refactor
minecraft-pi-docker/pipeline/head This commit looks good Details

This commit is contained in:
TheBrokenRail 2020-12-02 18:18:49 -05:00
parent 43b1231153
commit f9e893d1c3
29 changed files with 859 additions and 690 deletions

View File

@ -10,26 +10,48 @@ add_subdirectory(../core core)
include_directories(include)
add_library(core SHARED src/core.c)
find_package(glfw3 3.3 REQUIRED)
add_library(compat SHARED src/compat/compat.c)
target_link_libraries(compat feature input screenshot SDL GLESv1_CM GLESv2 X11 dl glfw Xfixes)
# Force GLESv1 Link
target_link_options(compat PRIVATE "-Wl,--no-as-needed")
add_library(readdir SHARED src/compat/readdir.c)
add_library(core SHARED src/core/core.c)
target_link_libraries(core dl)
add_library(feature SHARED src/feature/feature.c)
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp src/server/playerdata.cpp)
target_link_libraries(server core dl SDL pthread)
target_link_libraries(server core feature dl SDL pthread)
add_library(screenshot SHARED src/screenshot/screenshot.c)
target_link_libraries(screenshot GLESv1_CM freeimage)
add_library(extra SHARED src/extra.c src/extra.cpp src/cxx11_util.cpp)
target_link_libraries(extra core dl server screenshot GLESv1_CM)
add_library(camera SHARED src/camera/camera.cpp)
target_link_libraries(camera core screenshot)
add_library(override SHARED src/override.c)
add_library(game_mode SHARED src/game_mode/game_mode.c src/game_mode/game_mode.cpp)
target_link_libraries(game_mode core)
add_library(input SHARED src/input/input.c src/input/input.cpp)
target_link_libraries(input core feature SDL)
add_library(util SHARED src/util/cxx11_util.cpp)
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp)
target_link_libraries(misc core feature util)
add_library(options SHARED src/options/options.c)
target_link_libraries(options core feature)
add_library(override SHARED src/override/override.c)
target_link_libraries(override dl)
find_package(glfw3 3.3 REQUIRED)
add_library(textures SHARED src/textures/textures.cpp)
target_link_libraries(textures core feature GLESv1_CM)
add_library(compat SHARED src/compat.c)
target_link_libraries(compat core extra screenshot SDL GLESv1_CM GLESv2 X11 dl glfw Xfixes)
# Force GLESv1 Link
target_link_options(compat PRIVATE "-Wl,--no-as-needed")
add_library(readdir SHARED src/readdir.c)
add_library(init SHARED src/init/init.c)
target_link_libraries(init compat server game_mode camera input misc options textures)

View File

@ -0,0 +1,40 @@
#include <libcore/libcore.h>
#include "../screenshot/screenshot.h"
#include "../init/init.h"
#include "../minecraft.h"
// Take Screenshot Using TripodCamera
static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) unsigned char *app_platform, __attribute__((unused)) std::string const& param1, __attribute__((unused)) std::string const& param_2) {
take_screenshot();
}
// Enable TripodCameraRenderer
static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher) {
// Call Original Method
(*EntityRenderDispatcher)(dispatcher);
// Register TripodCameraRenderer
unsigned char *renderer = (unsigned char *) ::operator new(0x193);
(*TripodCameraRenderer)(renderer);
(*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer);
return dispatcher;
}
// Display Smoke From TripodCamera Higher
static void TripodCamera_tick_Level_addParticle_call_injection(unsigned char *level, std::string const& particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count) {
// Call Original Method
(*Level_addParticle)(level, particle, x, y + 0.5, z, deltaX, deltaY, deltaZ, count);
}
void init_camera() {
// Implement AppPlatform_linux::saveScreenshot So Cameras Work
patch_address(AppPlatform_linux_saveScreenshot_vtable_addr, (void *) AppPlatform_linux_saveScreenshot_injection);
// Enable TripodCameraRenderer
overwrite_calls((void *) EntityRenderDispatcher, (void *) EntityRenderDispatcher_injection);
// Display Smoke From TripodCamera Higher
overwrite_call((void *) 0x87dc4, (void *) TripodCamera_tick_Level_addParticle_call_injection);
}

View File

@ -16,8 +16,10 @@
#include <libcore/libcore.h>
#include "extra.h"
#include "screenshot/screenshot.h"
#include "../feature/feature.h"
#include "../input/input.h"
#include "../screenshot/screenshot.h"
#include "../init/init.h"
static GLFWwindow *glfw_window;
static Display *x11_display;
@ -125,13 +127,13 @@ static void glfw_key(__attribute__((unused)) GLFWwindow *window, int key, int sc
event.key.keysym.sym = glfw_key_to_sdl_key(key);
SDL_PushEvent(&event);
if (key == GLFW_KEY_BACKSPACE && !up) {
extra_key_press((char) '\b');
input_key_press((char) '\b');
}
}
// Pass Text To Minecraft
static void glfw_char(__attribute__((unused)) GLFWwindow *window, unsigned int codepoint) {
extra_key_press((char) codepoint);
input_key_press((char) codepoint);
}
static double last_mouse_x = 0;
@ -281,17 +283,17 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
take_screenshot();
handled = 1;
} else if (event->key.keysym.sym == SDLK_F1) {
extra_hide_gui();
input_hide_gui();
handled = 1;
} else if (event->key.keysym.sym == SDLK_F5) {
extra_third_person();
input_third_person();
handled = 1;
}
} else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) {
if (event->button.button == SDL_BUTTON_RIGHT) {
extra_set_is_right_click(event->button.state != SDL_RELEASED);
input_set_is_right_click(event->button.state != SDL_RELEASED);
} else if (event->button.button == SDL_BUTTON_LEFT) {
extra_set_is_left_click(event->button.state != SDL_RELEASED);
input_set_is_left_click(event->button.state != SDL_RELEASED);
}
}
@ -411,8 +413,8 @@ HOOK(SDL_GetWMInfo, int, (SDL_SysWMinfo *info)) {
#include <stdlib.h>
// Use VirGL
__attribute__((constructor)) static void init() {
int mode = extra_get_mode();
void init_compat() {
int mode = feature_get_mode();
if (mode != 1) {
// Force Software Rendering When Not In Native Mode
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);

View File

@ -1,325 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <libcore/libcore.h>
#include "extra.h"
#include "server/server.h"
#include "minecraft.h"
static int mob_spawning = 0;
// Override Mob Spawning
static uint32_t LevelData_getSpawnMobs_injection(__attribute__((unused)) unsigned char *level_data) {
return mob_spawning;
}
// Store Right-Click Status
static int is_right_click = 0;
void extra_set_is_right_click(int val) {
is_right_click = val;
}
// Enable Bow & Arrow Fix
static int fix_bow = 0;
// Store Function Input
static int hide_gui_toggle = 0;
void extra_hide_gui() {
hide_gui_toggle++;
}
static int third_person_toggle = 0;
void extra_third_person() {
third_person_toggle++;
}
// Handle Input Fixes
static void Minecraft_tickInput_injection(unsigned char *minecraft) {
// Call Original Method
(*Minecraft_tickInput)(minecraft);
if (fix_bow && !is_right_click) {
// GameMode Is Offset From minecraft By 0x160
// Player Is Offset From minecraft By 0x18c
unsigned char *game_mode = *(unsigned char **) (minecraft + 0x160);
unsigned char *player = *(unsigned char **) (minecraft + 0x18c);
if (player != NULL && game_mode != NULL && (*Player_isUsingItem)(player)) {
unsigned char *game_mode_vtable = *(unsigned char **) game_mode;
GameMode_releaseUsingItem_t GameMode_releaseUsingItem = *(GameMode_releaseUsingItem_t *) (game_mode_vtable + 0x5c);
(*GameMode_releaseUsingItem)(game_mode, player);
}
}
// Clear Unused Sign Input
extra_clear_input();
// Handle Functions
unsigned char *options = minecraft + 0x3c;
if (hide_gui_toggle % 2 != 0) {
// Toggle Hide GUI
*(options + 0xec) = *(options + 0xec) ^ 1;
}
hide_gui_toggle = 0;
if (third_person_toggle % 2 != 0) {
// Toggle Third Person
*(options + 0xed) = *(options + 0xed) ^ 1;
}
third_person_toggle = 0;
}
#include <SDL/SDL_events.h>
// Block UI Interaction When Mouse Is Locked
static int32_t Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(unsigned char *minecraft) {
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
// Call Original Method
return (*Minecraft_isCreativeMode)(minecraft);
} else {
// Disable Item Drop Ticking
return 1;
}
}
// Block UI Interaction When Mouse Is Locked
static void Gui_handleClick_injection(unsigned char *this, int32_t param_2, int32_t param_3, int32_t param_4) {
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
// Call Original Method
(*Gui_handleClick)(this, param_2, param_3, param_4);
}
}
static int is_survival = -1;
// Patch Game Mode
static void set_is_survival(int new_is_survival) {
if (is_survival != new_is_survival) {
INFO("Setting Game Mode: %s", new_is_survival ? "Survival" : "Creative");
// Correct Inventpry UI
unsigned char inventory_patch[4] = {new_is_survival ? 0x00 : 0x01, 0x30, 0xa0, 0xe3};
patch((void *) 0x16efc, inventory_patch);
// Use Correct Size For GameMode Object
unsigned char size_patch[4] = {new_is_survival ? 0x24 : 0x18, 0x00, 0xa0, 0xe3};
patch((void *) 0x16ee4, size_patch);
// Replace Creator Constructor With CreativeMode Or SurvivalMode Constructor
overwrite(Creator, new_is_survival ? SurvivalMode : CreativeMode);
is_survival = new_is_survival;
}
}
// Handle Gamemode Switching
static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t new_game_mode) {
set_is_survival(!new_game_mode);
// Call Original Method
(*Minecraft_setIsCreativeMode)(this, new_game_mode);
}
// 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;
// Configure Options
static void Minecraft_init_injection(unsigned char *this) {
// Call Original Method
(*Minecraft_init)(this);
unsigned char *options = this + 0x3c;
// Enable Fancy Graphics
*(options + 0x17) = fancy_graphics;
// Enable Crosshair In Touch GUI
*(options + 0x105) = 1;
// Peaceful Mode
*(int32_t *) (options + 0xe8) = peaceful_mode ? 0 : 2;
// 3D Anaglyph
*(options + 0x15) = anaglyph;
// Smooth Lighting
*(options + 0x18) = smooth_lighting;
}
// Is Dedicated Server
static int is_server = 0;
// Check For Feature
int extra_has_feature(const char *name) {
char *env = is_server ? (char *) server_get_features() : getenv("MCPI_FEATURES");
char *features = strdup(env != NULL ? env : "");
char *tok = strtok(features, "|");
int ret = 0;
while (tok != NULL) {
if (strcmp(tok, name) == 0) {
ret = 1;
break;
}
tok = strtok(NULL, "|");
}
free(features);
if (!is_server) {
INFO("Feature: %s: %s", name, ret ? "Enabled" : "Disabled");
}
return ret;
}
// Get Graphics Mode
int extra_get_mode() {
char *mode = getenv("MCPI_MODE");
if (mode == NULL) {
ERR("%s", "MCPI Mode Not Specified");
} else if (strcmp("virgl", mode) == 0) {
return 0;
} else if (strcmp("native", mode) == 0) {
return 1;
} else if (strcmp("server", mode) == 0) {
return 2;
} else {
ERR("Inavlid MCPI_MODE: %s", mode);
}
}
// Enable Touch GUI
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
return 1;
}
// Store Left Click (0 = Not Pressed, 1 = Pressed, 2 = Repeat)
// This Is Set To Repeat After First Attempted Left-Click Build Interaction
static int is_left_click = 0;
void extra_set_is_left_click(int val) {
if ((is_left_click == 0 && val == 1) || (is_left_click != 0 && val == 0) || (is_left_click == 1 && val == 2)) {
is_left_click = val;
}
}
// Add Attacking To MouseBuildInput
static int32_t MouseBuildInput_tickBuild_injection(unsigned char *mouse_build_input, unsigned char *local_player, uint32_t *build_action_intention_return) {
// Call Original Method
int32_t ret = (*MouseBuildInput_tickBuild)(mouse_build_input, local_player, build_action_intention_return);
// Use Attack/Place BuildActionIntention If No Other Valid BuildActionIntention Was Selected And This Was Not A Repeated Left Click
if (ret != 0 && is_left_click == 1 && *build_action_intention_return == 0xa) {
// Get Target HitResult
unsigned char *minecraft = *(unsigned char **) (local_player + 0xc90);
unsigned char *hit_result = minecraft + 0xc38;
int32_t hit_result_type = *(int32_t *) hit_result;
// Check if The Target Is An Entity Using HitResult
if (hit_result_type == 1) {
// Change BuildActionIntention To Attack/Place Mode (Place Will Not Happen Because The HitResult Is An Entity)
*build_action_intention_return = 0x8;
}
// Block Repeat Changes Without Releasing Left Click
is_left_click = 2;
}
return ret;
}
__attribute__((constructor)) static void init() {
is_server = extra_get_mode() == 2;
if (is_server) {
server_init();
}
int touch_gui = !is_server && extra_has_feature("Touch GUI");
if (touch_gui) {
// Main UI
overwrite((void *) Minecraft_isTouchscreen, Minecraft_isTouchscreen_injection);
// Force Correct Toolbar Size
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3};
patch((void *) 0x257b0, toolbar_patch);
}
// Dynamic Game Mode Switching
set_is_survival(1);
overwrite_calls((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection);
// Disable Item Dropping Using The Cursor When Cursor Is Hidden
overwrite_call((void *) 0x27800, Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection);
// Disable Opening Inventory Using The Cursor When Cursor Is Hidden
overwrite_calls((void *) Gui_handleClick, Gui_handleClick_injection);
// Enable Bow & Arrow Fix
fix_bow = extra_has_feature("Fix Bow & Arrow");
// Fix Bow & Arrow + Clear Unused Sign Input
overwrite_calls((void *) Minecraft_tickInput, Minecraft_tickInput_injection);
if (extra_has_feature("Fix Attacking")) {
// Allow Attacking Mobs
patch_address(MouseBuildInput_tickBuild_vtable_addr, (void *) MouseBuildInput_tickBuild_injection);
}
mob_spawning = extra_has_feature("Mob Spawning");
// Set Mob Spawning
overwrite((void *) LevelData_getSpawnMobs, LevelData_getSpawnMobs_injection);
// Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning)
unsigned char level_patch[4] = {0x68, 0x7e, 0x01, 0xeb};
patch((void *) 0x16f84, level_patch);
// Allocate Correct Size For ServerLevel
unsigned char level_size_patch[4] = {0x94, 0x0b, 0x00, 0x00};
patch((void *) 0x17004, level_size_patch);
// Enable Fancy Graphics
fancy_graphics = extra_has_feature("Fancy Graphics");
// Peaceful Mode
peaceful_mode = extra_has_feature("Peaceful Mode");
// 3D Anaglyph
anaglyph = extra_has_feature("3D Anaglyph");
// Set Options
overwrite_calls((void *) Minecraft_init, Minecraft_init_injection);
// Allow Connecting To Non-Pi Servers
unsigned char server_patch[4] = {0x0f, 0x00, 0x00, 0xea};
patch((void *) 0x6dc70, server_patch);
// Change Username
const char *username;
if (is_server) {
// MOTD is Username
username = server_get_motd();
} else {
username = get_username();
INFO("Setting Username: %s", username);
}
if (strcmp(*default_username, "StevePi") != 0) {
ERR("%s", "Default Username Is Invalid");
}
patch_address((void *) default_username, (void *) username);
if (extra_has_feature("Disable Autojump By Default")) {
// Disable Autojump By Default
unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3};
patch((void *) 0x44b90, autojump_patch);
}
// Show Block Outlines
int block_outlines = extra_has_feature("Show Block Outlines");
unsigned char outline_patch[4] = {block_outlines ? !touch_gui : touch_gui, 0x00, 0x50, 0xe3};
patch((void *) 0x4a210, outline_patch);
if (extra_has_feature("Remove Invalid Item Background")) {
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Obtainable Without Modding/Inventory Editing)
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
patch((void *) 0x63c98, invalid_item_background_patch);
}
smooth_lighting = extra_has_feature("Smooth Lighting");
if (smooth_lighting) {
// Enable Smooth Lighting
unsigned char smooth_lighting_patch[4] = {0x01, 0x00, 0x53, 0xe3};
patch((void *) 0x59ea4, smooth_lighting_patch);
}
}

View File

@ -1,307 +0,0 @@
#include <string>
#include <fstream>
#include <streambuf>
#include <vector>
#include <unistd.h>
#include <GLES/gl.h>
#include <libcore/libcore.h>
#include "extra.h"
#include "cxx11_util.h"
#include "screenshot/screenshot.h"
#include "minecraft.h"
#include <cstdio>
extern "C" {
// Read Asset File
static cxx11_string AppPlatform_readAssetFile_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path) {
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>());
return create_cxx11_string(str.c_str());
}
// Take Screenshot Using TripodCamera
static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) unsigned char *app_platform, __attribute__((unused)) std::string const& param1, __attribute__((unused)) std::string const& param_2) {
take_screenshot();
}
// Open Sign Screen
static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) {
if (*(int *)(sign + 0x18) == 4) {
unsigned char *minecraft = *(unsigned char **) (local_player + 0xc90);
unsigned char *screen = (unsigned char *) ::operator new(0xd0);
screen = (*TextEditScreen)(screen, sign);
(*Minecraft_setScreen)(minecraft, screen);
}
}
#define BACKSPACE_KEY 8
static int is_valid_key(char key) {
return (key >= 32 && key <= 126) || key == BACKSPACE_KEY;
}
// Store Text Input
std::vector<char> input;
void extra_key_press(char key) {
if (is_valid_key(key)) {
input.push_back(key);
}
}
void extra_clear_input() {
input.clear();
}
// Handle Text Input
static void TextEditScreen_updateEvents_injection(unsigned char *screen) {
// Call Original Method
(*Screen_updateEvents)(screen);
if (*(char *)(screen + 4) == '\0') {
uint32_t vtable = *((uint32_t *) screen);
for (char key : input) {
if (key == BACKSPACE_KEY) {
// Handle Backspace
(*(Screen_keyPressed_t *) (vtable + 0x6c))(screen, BACKSPACE_KEY);
} else {
// Handle Nrmal Key
(*(Screen_keyboardNewChar_t *) (vtable + 0x70))(screen, key);
}
}
}
extra_clear_input();
}
#define ITEM_INSTANCE_SIZE 0xc
static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) {
unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
item_instance = (*(is_tile ? ItemInstance_constructor_tile : ItemInstance_constructor_item))(item_instance, item);
(*FillingContainer_addItem)(inventory, item_instance);
}
static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, unsigned char *item_instance) {
// Call Original
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
// Add Items
inventory_add_item(filling_container, *Item_flintAndSteel, false);
inventory_add_item(filling_container, *Item_snowball, false);
inventory_add_item(filling_container, *Item_egg, false);
inventory_add_item(filling_container, *Item_shears, false);
for (int i = 0; i < 15; i++) {
unsigned char *item_instance = (unsigned char *) ::operator new(0xc);
item_instance = (*ItemInstance_constructor_item_extra)(item_instance, *Item_dye_powder, 1, i);
(*FillingContainer_addItem)(filling_container, item_instance);
}
inventory_add_item(filling_container, *Item_camera, false);
// Add Tiles
inventory_add_item(filling_container, *Tile_water, true);
inventory_add_item(filling_container, *Tile_lava, true);
inventory_add_item(filling_container, *Tile_calmWater, true);
inventory_add_item(filling_container, *Tile_calmLava, true);
inventory_add_item(filling_container, *Tile_glowingObsidian, true);
inventory_add_item(filling_container, *Tile_web, true);
inventory_add_item(filling_container, *Tile_topSnow, true);
inventory_add_item(filling_container, *Tile_ice, true);
inventory_add_item(filling_container, *Tile_invisible_bedrock, true);
return ret;
}
static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) {
// Call Original Method
(*Minecraft_tick)(minecraft, param_1, param_2);
// Tick Dynamic Textures
unsigned char *textures = *(unsigned char **) (minecraft + 0x164);
if (textures != NULL) {
(*Textures_tick)(textures, true);
}
}
// Get Minecraft From Screen
static unsigned char *get_minecraft_from_screen(unsigned char *screen) {
return *(unsigned char **) (screen + 0x14);
}
// Redirect Create World Button To SimpleLevelChooseScreen
#define WORLD_NAME "world"
#define SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE 0x68
static void SelectWorldScreen_tick_injection(unsigned char *screen) {
bool create_world = *(bool *) (screen + 0xfc);
if (create_world) {
// Get New World Name
std::string new_name;
(*SelectWorldScreen_getUniqueLevelName)(new_name, screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);
(*Minecraft_setScreen)(minecraft, new_screen);
// Finish
*(bool *) (screen + 0xf9) = true;
} else {
(*SelectWorldScreen_tick)(screen);
}
}
static void Touch_SelectWorldScreen_tick_injection(unsigned char *screen) {
bool create_world = *(bool *) (screen + 0x154);
if (create_world) {
// Get New World Name
std::string new_name;
(*Touch_SelectWorldScreen_getUniqueLevelName)(new_name, screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);
(*Minecraft_setScreen)(minecraft, new_screen);
// Finish
*(bool *) (screen + 0x151) = true;
} else {
(*Touch_SelectWorldScreen_tick)(screen);
}
}
// Enable TripodCameraRenderer
static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher) {
// Call Original Method
(*EntityRenderDispatcher)(dispatcher);
// Register TripodCameraRenderer
unsigned char *renderer = (unsigned char *) ::operator new(0x193);
(*TripodCameraRenderer)(renderer);
(*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer);
return dispatcher;
}
// Display Smoke From TripodCamera Higher
static void Level_addParticle_injection(unsigned char *level, std::string const& particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count) {
// Call Original Method
(*Level_addParticle)(level, particle, x, y + 0.5, z, deltaX, deltaY, deltaZ, count);
}
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
static float ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, unsigned char *textures, unsigned char *item_instance, int32_t param_1, int32_t param_2) {
int32_t leaves_id = *(int32_t *) (*Tile_leaves + 0x8);
int32_t grass_id = *(int32_t *) (*Tile_grass + 0x8);
// Replace Rendered Item With Carried Variant
unsigned char *carried_item_instance = NULL;
if (item_instance != NULL) {
int32_t id = *(int32_t *) (item_instance + 0x4);
int32_t count = *(int32_t *) item_instance;
int32_t auxilary = *(int32_t *) (item_instance + 0x8);
if (id == leaves_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
(*ItemInstance_constructor_title_extra)(carried_item_instance, *Tile_leaves_carried, count, auxilary);
} else if (id == grass_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
(*ItemInstance_constructor_title_extra)(carried_item_instance, *Tile_grass_carried, count, auxilary);
}
}
// Fix Toolbar Rendering
GLboolean depth_test_was_enabled = glIsEnabled(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
// Call Original Method
float ret = (*ItemRenderer_renderGuiItemCorrect)(font, textures, carried_item_instance != NULL ? carried_item_instance : item_instance, param_1, param_2);
// Revert GL State Changes
if (depth_test_was_enabled) {
glEnable(GL_DEPTH_TEST);
}
// Free Carried Item Instance Variant
if (carried_item_instance != NULL) {
::operator delete(carried_item_instance);
}
// Return
return ret;
}
// Render Selected Item Text
static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t param_1, uint32_t param_2, bool param_3, unsigned char *font) {
// Call Original Method
(*Gui_renderChatMessages)(gui, param_1, param_2, param_3, font);
// Calculate Selected Item Text Scale
unsigned char *minecraft = *(unsigned char **) (gui + 0x9f4);
int32_t screen_width = *(int32_t *) (minecraft + 0x20);
float scale = ((float) screen_width) * *InvGuiScale;
// Render Selected Item Text
(*Gui_renderOnSelectItemNameText)(gui, (int32_t) scale, font, param_1 - 0x13);
}
// Reset Selected Item Text Timer On Slot Select
static bool reset_selected_item_text_timer = false;
static void Gui_tick_injection(unsigned char *gui) {
// Call Original Method
(*Gui_tick)(gui);
// Handle Reset
float *selected_item_text_timer = (float *) (gui + 0x9fc);
if (reset_selected_item_text_timer) {
// Reset
*selected_item_text_timer = 0;
reset_selected_item_text_timer = false;
}
}
// Trigger Reset Selected Item Text Timer On Slot Select
static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slot) {
// Call Original Method
(*Inventory_selectSlot)(inventory, slot);
// Trigger Reset Selected Item Text Timer
reset_selected_item_text_timer = true;
}
__attribute((constructor)) static void init() {
// Implement AppPlatform::readAssetFile So Translations Work
overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection);
// Implement AppPlatform_linux::saveScreenshot So Cameras Work
patch_address(AppPlatform_linux_saveScreenshot_vtable_addr, (void *) AppPlatform_linux_saveScreenshot_injection);
// Enable TripodCameraRenderer
overwrite_calls((void *) EntityRenderDispatcher, (void *) EntityRenderDispatcher_injection);
// Display Smoke From TripodCamera Higher
overwrite_call((void *) 0x87dc4, (void *) Level_addParticle_injection);
if (extra_has_feature("Fix Sign Placement")) {
// Fix Signs
patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection);
patch_address(TextEditScreen_updateEvents_vtable_addr, (void *) TextEditScreen_updateEvents_injection);
}
if (extra_has_feature("Expand Creative Inventory")) {
// Add Extra Items To Creative Inventory (Only Replace Specific Function Call)
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
}
if (extra_has_feature("Animated Water")) {
// Tick Dynamic Textures (Animated Water)
overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection);
}
// Hijack Create World Button
patch_address(SelectWorldScreen_tick_vtable_addr, (void *) SelectWorldScreen_tick_injection);
patch_address(Touch_SelectWorldScreen_tick_vtable_addr, (void *) Touch_SelectWorldScreen_tick_injection);
// Make The SimpleChooseLevelScreen Back Button Go To SelectWorldScreen Instead Of StartMenuScreen
unsigned char simple_choose_level_screen_back_button_patch[4] = {0x05, 0x10, 0xa0, 0xe3};
patch((void *) 0x31144, simple_choose_level_screen_back_button_patch);
if (extra_has_feature("Disable gui_blocks Atlas")) {
// Disable gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
unsigned char disable_gui_blocks_atlas_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
patch((void *) 0x63c2c, disable_gui_blocks_atlas_patch);
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
overwrite_calls((void *) ItemRenderer_renderGuiItemCorrect, (void *) ItemRenderer_renderGuiItemCorrect_injection);
}
// Fix Selected Item Text
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);
}
}

View File

@ -1,25 +0,0 @@
#ifndef EXTRA_H
#define EXTRA_H
#ifdef __cplusplus
extern "C" {
#endif
int extra_has_feature(const char *name);
int extra_get_mode();
void extra_key_press(char key);
void extra_clear_input();
void extra_set_is_right_click(int val);
void extra_hide_gui();
void extra_third_person();
void extra_set_is_left_click(int val);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,42 @@
#include <stdlib.h>
#include <string.h>
#include <libcore/libcore.h>
#include "feature.h"
// Check For Feature
int feature_has(const char *name) {
char *env = getenv("MCPI_FEATURES");
char *features = strdup(env != NULL ? env : "");
char *tok = strtok(features, "|");
int ret = 0;
while (tok != NULL) {
if (strcmp(tok, name) == 0) {
ret = 1;
break;
}
tok = strtok(NULL, "|");
}
free(features);
if (feature_get_mode() != 2) {
INFO("Feature: %s: %s", name, ret ? "Enabled" : "Disabled");
}
return ret;
}
// Get Graphics Mode
int feature_get_mode() {
char *mode = getenv("MCPI_MODE");
if (mode == NULL) {
ERR("%s", "MCPI Mode Not Specified");
} else if (strcmp("virgl", mode) == 0) {
return 0;
} else if (strcmp("native", mode) == 0) {
return 1;
} else if (strcmp("server", mode) == 0) {
return 2;
} else {
ERR("Inavlid MCPI_MODE: %s", mode);
}
}

View File

@ -0,0 +1,16 @@
#ifndef FEATURE_H
#define FEATURE_H
#ifdef __cplusplus
extern "C" {
#endif
int feature_has(const char *name);
int feature_get_mode();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
#include <libcore/libcore.h>
#include "game_mode.h"
#include "../init/init.h"
#include "../minecraft.h"
static int is_survival = -1;
// Patch Game Mode
static void set_is_survival(int new_is_survival) {
if (is_survival != new_is_survival) {
INFO("Setting Game Mode: %s", new_is_survival ? "Survival" : "Creative");
// Correct Inventpry UI
unsigned char inventory_patch[4] = {new_is_survival ? 0x00 : 0x01, 0x30, 0xa0, 0xe3};
patch((void *) 0x16efc, inventory_patch);
// Use Correct Size For GameMode Object
unsigned char size_patch[4] = {new_is_survival ? 0x24 : 0x18, 0x00, 0xa0, 0xe3};
patch((void *) 0x16ee4, size_patch);
// Replace Creator Constructor With CreativeMode Or SurvivalMode Constructor
overwrite(Creator, new_is_survival ? SurvivalMode : CreativeMode);
is_survival = new_is_survival;
}
}
// Handle Gamemode Switching
static void Minecraft_setIsCreativeMode_injection(unsigned char *this, int32_t new_game_mode) {
set_is_survival(!new_game_mode);
// Call Original Method
(*Minecraft_setIsCreativeMode)(this, new_game_mode);
}
void init_game_mode() {
// Dynamic Game Mode Switching
set_is_survival(1);
overwrite_calls((void *) Minecraft_setIsCreativeMode, Minecraft_setIsCreativeMode_injection);
// Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning)
unsigned char level_patch[4] = {0x68, 0x7e, 0x01, 0xeb};
patch((void *) 0x16f84, level_patch);
// Allocate Correct Size For ServerLevel
unsigned char level_size_patch[4] = {0x94, 0x0b, 0x00, 0x00};
patch((void *) 0x17004, level_size_patch);
// Allow Connecting To Survival Servers
unsigned char server_patch[4] = {0x0f, 0x00, 0x00, 0xea};
patch((void *) 0x6dc70, server_patch);
// Init C++
init_game_mode_cpp();
}

View File

@ -0,0 +1,59 @@
#include <libcore/libcore.h>
#include "game_mode.h"
#include "../minecraft.h"
// Get Minecraft From Screen
static unsigned char *get_minecraft_from_screen(unsigned char *screen) {
return *(unsigned char **) (screen + 0x14);
}
// Redirect Create World Button To SimpleLevelChooseScreen
#define WORLD_NAME "world"
#define SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE 0x68
static void SelectWorldScreen_tick_injection(unsigned char *screen) {
bool create_world = *(bool *) (screen + 0xfc);
if (create_world) {
// Get New World Name
std::string new_name;
(*SelectWorldScreen_getUniqueLevelName)(new_name, screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);
(*Minecraft_setScreen)(minecraft, new_screen);
// Finish
*(bool *) (screen + 0xf9) = true;
} else {
(*SelectWorldScreen_tick)(screen);
}
}
static void Touch_SelectWorldScreen_tick_injection(unsigned char *screen) {
bool create_world = *(bool *) (screen + 0x154);
if (create_world) {
// Get New World Name
std::string new_name;
(*Touch_SelectWorldScreen_getUniqueLevelName)(new_name, screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);
(*Minecraft_setScreen)(minecraft, new_screen);
// Finish
*(bool *) (screen + 0x151) = true;
} else {
(*Touch_SelectWorldScreen_tick)(screen);
}
}
void init_game_mode_cpp() {
// Hijack Create World Button
patch_address(SelectWorldScreen_tick_vtable_addr, (void *) SelectWorldScreen_tick_injection);
patch_address(Touch_SelectWorldScreen_tick_vtable_addr, (void *) Touch_SelectWorldScreen_tick_injection);
// Make The SimpleChooseLevelScreen Back Button Go To SelectWorldScreen Instead Of StartMenuScreen
unsigned char simple_choose_level_screen_back_button_patch[4] = {0x05, 0x10, 0xa0, 0xe3};
patch((void *) 0x31144, simple_choose_level_screen_back_button_patch);
}

View File

@ -0,0 +1,15 @@
#ifndef GAME_MODE_H
#define GAME_MODE_H
#ifdef __cplusplus
extern "C" {
#endif
void init_game_mode_cpp();
#ifdef __cplusplus
}
#endif
#endif

12
mods/src/init/init.c Normal file
View File

@ -0,0 +1,12 @@
#include "init.h"
__attribute__((constructor)) static void init() {
init_compat();
init_server();
init_game_mode();
init_input();
init_misc();
init_camera();
init_options();
init_textures();
}

22
mods/src/init/init.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef INIT_H
#define INIT_H
#ifdef __cplusplus
extern "C" {
#endif
void init_compat();
void init_server();
void init_game_mode();
void init_input();
void init_misc();
void init_camera();
void init_options();
void init_textures();
#ifdef __cplusplus
}
#endif
#endif

133
mods/src/input/input.c Normal file
View File

@ -0,0 +1,133 @@
#include <libcore/libcore.h>
#include "../feature/feature.h"
#include "input.h"
#include "../init/init.h"
#include "../minecraft.h"
// Store Right-Click Status
static int is_right_click = 0;
void input_set_is_right_click(int val) {
is_right_click = val;
}
// Enable Bow & Arrow Fix
static int fix_bow = 0;
// Store Function Input
static int hide_gui_toggle = 0;
void input_hide_gui() {
hide_gui_toggle++;
}
static int third_person_toggle = 0;
void input_third_person() {
third_person_toggle++;
}
// Handle Input Fixes
static void Minecraft_tickInput_injection(unsigned char *minecraft) {
// Call Original Method
(*Minecraft_tickInput)(minecraft);
if (fix_bow && !is_right_click) {
// GameMode Is Offset From minecraft By 0x160
// Player Is Offset From minecraft By 0x18c
unsigned char *game_mode = *(unsigned char **) (minecraft + 0x160);
unsigned char *player = *(unsigned char **) (minecraft + 0x18c);
if (player != NULL && game_mode != NULL && (*Player_isUsingItem)(player)) {
unsigned char *game_mode_vtable = *(unsigned char **) game_mode;
GameMode_releaseUsingItem_t GameMode_releaseUsingItem = *(GameMode_releaseUsingItem_t *) (game_mode_vtable + 0x5c);
(*GameMode_releaseUsingItem)(game_mode, player);
}
}
// Clear Unused Sign Input
input_clear_input();
// Handle Functions
unsigned char *options = minecraft + 0x3c;
if (hide_gui_toggle % 2 != 0) {
// Toggle Hide GUI
*(options + 0xec) = *(options + 0xec) ^ 1;
}
hide_gui_toggle = 0;
if (third_person_toggle % 2 != 0) {
// Toggle Third Person
*(options + 0xed) = *(options + 0xed) ^ 1;
}
third_person_toggle = 0;
}
#include <SDL/SDL_events.h>
// Block UI Interaction When Mouse Is Locked
static int32_t Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(unsigned char *minecraft) {
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
// Call Original Method
return (*Minecraft_isCreativeMode)(minecraft);
} else {
// Disable Item Drop Ticking
return 1;
}
}
// Block UI Interaction When Mouse Is Locked
static void Gui_handleClick_injection(unsigned char *this, int32_t param_2, int32_t param_3, int32_t param_4) {
if (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) {
// Call Original Method
(*Gui_handleClick)(this, param_2, param_3, param_4);
}
}
// Store Left Click (0 = Not Pressed, 1 = Pressed, 2 = Repeat)
// This Is Set To Repeat After First Attempted Left-Click Build Interaction
static int is_left_click = 0;
void input_set_is_left_click(int val) {
if ((is_left_click == 0 && val == 1) || (is_left_click != 0 && val == 0) || (is_left_click == 1 && val == 2)) {
is_left_click = val;
}
}
// Add Attacking To MouseBuildInput
static int32_t MouseBuildInput_tickBuild_injection(unsigned char *mouse_build_input, unsigned char *local_player, uint32_t *build_action_intention_return) {
// Call Original Method
int32_t ret = (*MouseBuildInput_tickBuild)(mouse_build_input, local_player, build_action_intention_return);
// Use Attack/Place BuildActionIntention If No Other Valid BuildActionIntention Was Selected And This Was Not A Repeated Left Click
if (ret != 0 && is_left_click == 1 && *build_action_intention_return == 0xa) {
// Get Target HitResult
unsigned char *minecraft = *(unsigned char **) (local_player + 0xc90);
unsigned char *hit_result = minecraft + 0xc38;
int32_t hit_result_type = *(int32_t *) hit_result;
// Check if The Target Is An Entity Using HitResult
if (hit_result_type == 1) {
// Change BuildActionIntention To Attack/Place Mode (Place Will Not Happen Because The HitResult Is An Entity)
*build_action_intention_return = 0x8;
}
// Block Repeat Changes Without Releasing Left Click
is_left_click = 2;
}
return ret;
}
void init_input() {
// Disable Item Dropping Using The Cursor When Cursor Is Hidden
overwrite_call((void *) 0x27800, Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection);
// Disable Opening Inventory Using The Cursor When Cursor Is Hidden
overwrite_calls((void *) Gui_handleClick, Gui_handleClick_injection);
// Enable Bow & Arrow Fix
fix_bow = feature_has("Fix Bow & Arrow");
// Fix Bow & Arrow + Clear Unused Sign Input
overwrite_calls((void *) Minecraft_tickInput, Minecraft_tickInput_injection);
if (feature_has("Fix Attacking")) {
// Allow Attacking Mobs
patch_address(MouseBuildInput_tickBuild_vtable_addr, (void *) MouseBuildInput_tickBuild_injection);
}
// Init C++
init_input_cpp();
}

63
mods/src/input/input.cpp Normal file
View File

@ -0,0 +1,63 @@
#include <vector>
#include <libcore/libcore.h>
#include "../feature/feature.h"
#include "input.h"
#include "../minecraft.h"
// Open Sign Screen
static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) {
if (*(int *)(sign + 0x18) == 4) {
unsigned char *minecraft = *(unsigned char **) (local_player + 0xc90);
unsigned char *screen = (unsigned char *) ::operator new(0xd0);
screen = (*TextEditScreen)(screen, sign);
(*Minecraft_setScreen)(minecraft, screen);
}
}
#define BACKSPACE_KEY 8
static int is_valid_key(char key) {
return (key >= 32 && key <= 126) || key == BACKSPACE_KEY;
}
// Store Text Input
std::vector<char> input;
void input_key_press(char key) {
if (is_valid_key(key)) {
input.push_back(key);
}
}
void input_clear_input() {
input.clear();
}
// Handle Text Input
static void TextEditScreen_updateEvents_injection(unsigned char *screen) {
// Call Original Method
(*Screen_updateEvents)(screen);
if (*(char *)(screen + 4) == '\0') {
uint32_t vtable = *((uint32_t *) screen);
for (char key : input) {
if (key == BACKSPACE_KEY) {
// Handle Backspace
(*(Screen_keyPressed_t *) (vtable + 0x6c))(screen, BACKSPACE_KEY);
} else {
// Handle Nrmal Key
(*(Screen_keyboardNewChar_t *) (vtable + 0x70))(screen, key);
}
}
}
input_clear_input();
}
void init_input_cpp() {
if (feature_has("Fix Sign Placement")) {
// Fix Signs
patch_address(LocalPlayer_openTextEdit_vtable_addr, (void *) LocalPlayer_openTextEdit_injection);
patch_address(TextEditScreen_updateEvents_vtable_addr, (void *) TextEditScreen_updateEvents_injection);
}
}

24
mods/src/input/input.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef INPUT_H
#define INPUT_H
#ifdef __cplusplus
extern "C" {
#endif
void input_key_press(char key);
void input_clear_input();
void input_set_is_right_click(int val);
void input_hide_gui();
void input_third_person();
void input_set_is_left_click(int val);
void init_input_cpp();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -183,6 +183,8 @@ static void *Touch_SelectWorldScreen_tick_vtable_addr = (void *) 0x105780;
// ItemInstance
#define ITEM_INSTANCE_SIZE 0xc
typedef unsigned char *(*ItemInstance_constructor_t)(unsigned char *item_instance, unsigned char *item);
static ItemInstance_constructor_t ItemInstance_constructor_item = (ItemInstance_constructor_t) 0x9992c;
static ItemInstance_constructor_t ItemInstance_constructor_tile = (ItemInstance_constructor_t) 0x998e4;
@ -289,7 +291,7 @@ static ItemRenderer_renderGuiItemCorrect_t ItemRenderer_renderGuiItemCorrect = (
#include <string>
#include "cxx11_util.h"
#include "util/cxx11_util.h"
// AppPlatform

18
mods/src/misc/misc.c Normal file
View File

@ -0,0 +1,18 @@
#include <libcore/libcore.h>
#include "../feature/feature.h"
#include "misc.h"
#include "../init/init.h"
#include "../minecraft.h"
void init_misc() {
if (feature_has("Remove Invalid Item Background")) {
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
patch((void *) 0x63c98, invalid_item_background_patch);
}
// Init C++
init_misc_cpp();
}

103
mods/src/misc/misc.cpp Normal file
View File

@ -0,0 +1,103 @@
#include <string>
#include <fstream>
#include <streambuf>
#include <libcore/libcore.h>
#include "../util/cxx11_util.h"
#include "../feature/feature.h"
#include "misc.h"
#include "../minecraft.h"
// Read Asset File
static cxx11_string AppPlatform_readAssetFile_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path) {
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>());
return create_cxx11_string(str.c_str());
}
static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) {
unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
item_instance = (*(is_tile ? ItemInstance_constructor_tile : ItemInstance_constructor_item))(item_instance, item);
(*FillingContainer_addItem)(inventory, item_instance);
}
static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, unsigned char *item_instance) {
// Call Original
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
// Add Items
inventory_add_item(filling_container, *Item_flintAndSteel, false);
inventory_add_item(filling_container, *Item_snowball, false);
inventory_add_item(filling_container, *Item_egg, false);
inventory_add_item(filling_container, *Item_shears, false);
for (int i = 0; i < 15; i++) {
unsigned char *item_instance = (unsigned char *) ::operator new(0xc);
item_instance = (*ItemInstance_constructor_item_extra)(item_instance, *Item_dye_powder, 1, i);
(*FillingContainer_addItem)(filling_container, item_instance);
}
inventory_add_item(filling_container, *Item_camera, false);
// Add Tiles
inventory_add_item(filling_container, *Tile_water, true);
inventory_add_item(filling_container, *Tile_lava, true);
inventory_add_item(filling_container, *Tile_calmWater, true);
inventory_add_item(filling_container, *Tile_calmLava, true);
inventory_add_item(filling_container, *Tile_glowingObsidian, true);
inventory_add_item(filling_container, *Tile_web, true);
inventory_add_item(filling_container, *Tile_topSnow, true);
inventory_add_item(filling_container, *Tile_ice, true);
inventory_add_item(filling_container, *Tile_invisible_bedrock, true);
return ret;
}
// Render Selected Item Text
static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t param_1, uint32_t param_2, bool param_3, unsigned char *font) {
// Call Original Method
(*Gui_renderChatMessages)(gui, param_1, param_2, param_3, font);
// Calculate Selected Item Text Scale
unsigned char *minecraft = *(unsigned char **) (gui + 0x9f4);
int32_t screen_width = *(int32_t *) (minecraft + 0x20);
float scale = ((float) screen_width) * *InvGuiScale;
// Render Selected Item Text
(*Gui_renderOnSelectItemNameText)(gui, (int32_t) scale, font, param_1 - 0x13);
}
// Reset Selected Item Text Timer On Slot Select
static bool reset_selected_item_text_timer = false;
static void Gui_tick_injection(unsigned char *gui) {
// Call Original Method
(*Gui_tick)(gui);
// Handle Reset
float *selected_item_text_timer = (float *) (gui + 0x9fc);
if (reset_selected_item_text_timer) {
// Reset
*selected_item_text_timer = 0;
reset_selected_item_text_timer = false;
}
}
// Trigger Reset Selected Item Text Timer On Slot Select
static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slot) {
// Call Original Method
(*Inventory_selectSlot)(inventory, slot);
// Trigger Reset Selected Item Text Timer
reset_selected_item_text_timer = true;
}
void init_misc_cpp() {
// Implement AppPlatform::readAssetFile So Translations Work
overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection);
if (feature_has("Expand Creative Inventory")) {
// Add Extra Items To Creative Inventory (Only Replace Specific Function Call)
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
}
// Fix Selected Item Text
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);
}

15
mods/src/misc/misc.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef MISC_H
#define MISC_H
#ifdef __cplusplus
extern "C" {
#endif
void init_misc_cpp();
#ifdef __cplusplus
}
#endif
#endif

105
mods/src/options/options.c Normal file
View File

@ -0,0 +1,105 @@
#include <string.h>
#include <libcore/libcore.h>
#include "../feature/feature.h"
#include "../init/init.h"
#include "../minecraft.h"
static int mob_spawning = 0;
// Override Mob Spawning
static uint32_t LevelData_getSpawnMobs_injection(__attribute__((unused)) unsigned char *level_data) {
return mob_spawning;
}
// 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;
// Configure Options
static void Minecraft_init_injection(unsigned char *this) {
// Call Original Method
(*Minecraft_init)(this);
unsigned char *options = this + 0x3c;
// Enable Fancy Graphics
*(options + 0x17) = fancy_graphics;
// Enable Crosshair In Touch GUI
*(options + 0x105) = 1;
// Peaceful Mode
*(int32_t *) (options + 0xe8) = peaceful_mode ? 0 : 2;
// 3D Anaglyph
*(options + 0x15) = anaglyph;
// Smooth Lighting
*(options + 0x18) = smooth_lighting;
}
// Enable Touch GUI
static int32_t Minecraft_isTouchscreen_injection(__attribute__((unused)) unsigned char *minecraft) {
return 1;
}
void init_options() {
int is_server = feature_get_mode() == 2;
int touch_gui = feature_has("Touch GUI");
if (touch_gui) {
// Main UI
overwrite((void *) Minecraft_isTouchscreen, Minecraft_isTouchscreen_injection);
// Force Correct Toolbar Size
unsigned char toolbar_patch[4] = {0x01, 0x00, 0x50, 0xe3};
patch((void *) 0x257b0, toolbar_patch);
}
mob_spawning = feature_has("Mob Spawning");
// Set Mob Spawning
overwrite((void *) LevelData_getSpawnMobs, LevelData_getSpawnMobs_injection);
// Enable Fancy Graphics
fancy_graphics = feature_has("Fancy Graphics");
// Peaceful Mode
peaceful_mode = feature_has("Peaceful Mode");
// 3D Anaglyph
anaglyph = feature_has("3D Anaglyph");
// Set Options
overwrite_calls((void *) Minecraft_init, Minecraft_init_injection);
// Change Username
const char *username = get_username();
if (!is_server) {
INFO("Setting Username: %s", username);
}
if (strcmp(*default_username, "StevePi") != 0) {
ERR("%s", "Default Username Is Invalid");
}
patch_address((void *) default_username, (void *) username);
if (feature_has("Disable Autojump By Default")) {
// Disable Autojump By Default
unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3};
patch((void *) 0x44b90, autojump_patch);
}
// Show Block Outlines
int block_outlines = feature_has("Show Block Outlines");
unsigned char outline_patch[4] = {block_outlines ? !touch_gui : touch_gui, 0x00, 0x50, 0xe3};
patch((void *) 0x4a210, outline_patch);
smooth_lighting = feature_has("Smooth Lighting");
if (smooth_lighting) {
// Enable Smooth Lighting
unsigned char smooth_lighting_patch[4] = {0x01, 0x00, 0x53, 0xe3};
patch((void *) 0x59ea4, smooth_lighting_patch);
}
}

View File

@ -19,6 +19,9 @@
#include "server_properties.h"
#include "playerdata.h"
#include "../feature/feature.h"
#include "../init/init.h"
#include "../minecraft.h"
// Server Properties
@ -387,13 +390,13 @@ static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned c
}
}
const char *server_get_motd() {
std::string *motd = new std::string(get_server_properties().get_string("motd", DEFAULT_MOTD));
return motd->c_str();
static std::string get_motd() {
std::string motd(get_server_properties().get_string("motd", DEFAULT_MOTD));
return motd;
}
static bool loaded_features = false;
const char *server_get_features() {
static const char *get_features() {
static std::string features;
if (!loaded_features) {
loaded_features = true;
@ -420,7 +423,7 @@ static unsigned char get_max_players() {
return (unsigned char) val;
}
void server_init() {
static void server_init() {
// Open Properties File
std::string file(getenv("HOME"));
file.append("/.minecraft/server.properties");
@ -508,3 +511,11 @@ void server_init() {
pthread_t read_stdin_thread_obj;
pthread_create(&read_stdin_thread_obj, NULL, read_stdin_thread, NULL);
}
void init_server() {
if (feature_get_mode() == 2) {
server_init();
setenv("MCPI_FEATURES", get_features(), 1);
setenv("MCPI_USERNAME", get_motd().c_str(), 1);
}
}

View File

@ -4,14 +4,10 @@
#ifdef __cplusplus
extern "C" {
#endif
void server_init();
#endif\
const char *server_get_motd();
const char *server_get_features();
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,69 @@
#include <GLES/gl.h>
#include <libcore/libcore.h>
#include "../feature/feature.h"
#include "../init/init.h"
#include "../minecraft.h"
static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) {
// Call Original Method
(*Minecraft_tick)(minecraft, param_1, param_2);
// Tick Dynamic Textures
unsigned char *textures = *(unsigned char **) (minecraft + 0x164);
if (textures != NULL) {
(*Textures_tick)(textures, true);
}
}
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
static float ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, unsigned char *textures, unsigned char *item_instance, int32_t param_1, int32_t param_2) {
int32_t leaves_id = *(int32_t *) (*Tile_leaves + 0x8);
int32_t grass_id = *(int32_t *) (*Tile_grass + 0x8);
// Replace Rendered Item With Carried Variant
unsigned char *carried_item_instance = NULL;
if (item_instance != NULL) {
int32_t id = *(int32_t *) (item_instance + 0x4);
int32_t count = *(int32_t *) item_instance;
int32_t auxilary = *(int32_t *) (item_instance + 0x8);
if (id == leaves_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
(*ItemInstance_constructor_title_extra)(carried_item_instance, *Tile_leaves_carried, count, auxilary);
} else if (id == grass_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
(*ItemInstance_constructor_title_extra)(carried_item_instance, *Tile_grass_carried, count, auxilary);
}
}
// Fix Toolbar Rendering
GLboolean depth_test_was_enabled = glIsEnabled(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
// Call Original Method
float ret = (*ItemRenderer_renderGuiItemCorrect)(font, textures, carried_item_instance != NULL ? carried_item_instance : item_instance, param_1, param_2);
// Revert GL State Changes
if (depth_test_was_enabled) {
glEnable(GL_DEPTH_TEST);
}
// Free Carried Item Instance Variant
if (carried_item_instance != NULL) {
::operator delete(carried_item_instance);
}
// Return
return ret;
}
void init_textures() {
if (feature_has("Animated Water")) {
// Tick Dynamic Textures (Animated Water)
overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection);
}
if (feature_has("Disable gui_blocks Atlas")) {
// Disable gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
unsigned char disable_gui_blocks_atlas_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
patch((void *) 0x63c2c, disable_gui_blocks_atlas_patch);
// Fix Grass And Leaves Inventory Rendering When The gui_blocks Atlas Is Disabled
overwrite_calls((void *) ItemRenderer_renderGuiItemCorrect, (void *) ItemRenderer_renderGuiItemCorrect_injection);
}
}