Refactor
This commit is contained in:
parent
43b1231153
commit
f9e893d1c3
@ -10,26 +10,48 @@ add_subdirectory(../core core)
|
|||||||
|
|
||||||
include_directories(include)
|
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)
|
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)
|
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)
|
add_library(screenshot SHARED src/screenshot/screenshot.c)
|
||||||
target_link_libraries(screenshot GLESv1_CM freeimage)
|
target_link_libraries(screenshot GLESv1_CM freeimage)
|
||||||
|
|
||||||
add_library(extra SHARED src/extra.c src/extra.cpp src/cxx11_util.cpp)
|
add_library(camera SHARED src/camera/camera.cpp)
|
||||||
target_link_libraries(extra core dl server screenshot GLESv1_CM)
|
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)
|
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)
|
add_library(init SHARED src/init/init.c)
|
||||||
target_link_libraries(compat core extra screenshot SDL GLESv1_CM GLESv2 X11 dl glfw Xfixes)
|
target_link_libraries(init compat server game_mode camera input misc options textures)
|
||||||
# Force GLESv1 Link
|
|
||||||
target_link_options(compat PRIVATE "-Wl,--no-as-needed")
|
|
||||||
|
|
||||||
add_library(readdir SHARED src/readdir.c)
|
|
||||||
|
40
mods/src/camera/camera.cpp
Normal file
40
mods/src/camera/camera.cpp
Normal 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);
|
||||||
|
}
|
@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
#include <libcore/libcore.h>
|
#include <libcore/libcore.h>
|
||||||
|
|
||||||
#include "extra.h"
|
#include "../feature/feature.h"
|
||||||
#include "screenshot/screenshot.h"
|
#include "../input/input.h"
|
||||||
|
#include "../screenshot/screenshot.h"
|
||||||
|
#include "../init/init.h"
|
||||||
|
|
||||||
static GLFWwindow *glfw_window;
|
static GLFWwindow *glfw_window;
|
||||||
static Display *x11_display;
|
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);
|
event.key.keysym.sym = glfw_key_to_sdl_key(key);
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
if (key == GLFW_KEY_BACKSPACE && !up) {
|
if (key == GLFW_KEY_BACKSPACE && !up) {
|
||||||
extra_key_press((char) '\b');
|
input_key_press((char) '\b');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass Text To Minecraft
|
// Pass Text To Minecraft
|
||||||
static void glfw_char(__attribute__((unused)) GLFWwindow *window, unsigned int codepoint) {
|
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;
|
static double last_mouse_x = 0;
|
||||||
@ -281,17 +283,17 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||||||
take_screenshot();
|
take_screenshot();
|
||||||
handled = 1;
|
handled = 1;
|
||||||
} else if (event->key.keysym.sym == SDLK_F1) {
|
} else if (event->key.keysym.sym == SDLK_F1) {
|
||||||
extra_hide_gui();
|
input_hide_gui();
|
||||||
handled = 1;
|
handled = 1;
|
||||||
} else if (event->key.keysym.sym == SDLK_F5) {
|
} else if (event->key.keysym.sym == SDLK_F5) {
|
||||||
extra_third_person();
|
input_third_person();
|
||||||
handled = 1;
|
handled = 1;
|
||||||
}
|
}
|
||||||
} else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) {
|
} else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) {
|
||||||
if (event->button.button == SDL_BUTTON_RIGHT) {
|
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) {
|
} 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>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Use VirGL
|
// Use VirGL
|
||||||
__attribute__((constructor)) static void init() {
|
void init_compat() {
|
||||||
int mode = extra_get_mode();
|
int mode = feature_get_mode();
|
||||||
if (mode != 1) {
|
if (mode != 1) {
|
||||||
// Force Software Rendering When Not In Native Mode
|
// Force Software Rendering When Not In Native Mode
|
||||||
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
|
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
|
325
mods/src/extra.c
325
mods/src/extra.c
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
42
mods/src/feature/feature.c
Normal file
42
mods/src/feature/feature.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
16
mods/src/feature/feature.h
Normal file
16
mods/src/feature/feature.h
Normal 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
|
57
mods/src/game_mode/game_mode.c
Normal file
57
mods/src/game_mode/game_mode.c
Normal 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();
|
||||||
|
}
|
59
mods/src/game_mode/game_mode.cpp
Normal file
59
mods/src/game_mode/game_mode.cpp
Normal 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);
|
||||||
|
}
|
15
mods/src/game_mode/game_mode.h
Normal file
15
mods/src/game_mode/game_mode.h
Normal 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
12
mods/src/init/init.c
Normal 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
22
mods/src/init/init.h
Normal 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
133
mods/src/input/input.c
Normal 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
63
mods/src/input/input.cpp
Normal 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
24
mods/src/input/input.h
Normal 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
|
@ -183,6 +183,8 @@ static void *Touch_SelectWorldScreen_tick_vtable_addr = (void *) 0x105780;
|
|||||||
|
|
||||||
// ItemInstance
|
// ItemInstance
|
||||||
|
|
||||||
|
#define ITEM_INSTANCE_SIZE 0xc
|
||||||
|
|
||||||
typedef unsigned char *(*ItemInstance_constructor_t)(unsigned char *item_instance, unsigned char *item);
|
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_item = (ItemInstance_constructor_t) 0x9992c;
|
||||||
static ItemInstance_constructor_t ItemInstance_constructor_tile = (ItemInstance_constructor_t) 0x998e4;
|
static ItemInstance_constructor_t ItemInstance_constructor_tile = (ItemInstance_constructor_t) 0x998e4;
|
||||||
@ -289,7 +291,7 @@ static ItemRenderer_renderGuiItemCorrect_t ItemRenderer_renderGuiItemCorrect = (
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "cxx11_util.h"
|
#include "util/cxx11_util.h"
|
||||||
|
|
||||||
// AppPlatform
|
// AppPlatform
|
||||||
|
|
||||||
|
18
mods/src/misc/misc.c
Normal file
18
mods/src/misc/misc.c
Normal 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
103
mods/src/misc/misc.cpp
Normal 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
15
mods/src/misc/misc.h
Normal 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
105
mods/src/options/options.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,9 @@
|
|||||||
#include "server_properties.h"
|
#include "server_properties.h"
|
||||||
#include "playerdata.h"
|
#include "playerdata.h"
|
||||||
|
|
||||||
|
#include "../feature/feature.h"
|
||||||
|
#include "../init/init.h"
|
||||||
|
|
||||||
#include "../minecraft.h"
|
#include "../minecraft.h"
|
||||||
|
|
||||||
// Server Properties
|
// Server Properties
|
||||||
@ -387,13 +390,13 @@ static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *server_get_motd() {
|
static std::string get_motd() {
|
||||||
std::string *motd = new std::string(get_server_properties().get_string("motd", DEFAULT_MOTD));
|
std::string motd(get_server_properties().get_string("motd", DEFAULT_MOTD));
|
||||||
return motd->c_str();
|
return motd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool loaded_features = false;
|
static bool loaded_features = false;
|
||||||
const char *server_get_features() {
|
static const char *get_features() {
|
||||||
static std::string features;
|
static std::string features;
|
||||||
if (!loaded_features) {
|
if (!loaded_features) {
|
||||||
loaded_features = true;
|
loaded_features = true;
|
||||||
@ -420,7 +423,7 @@ static unsigned char get_max_players() {
|
|||||||
return (unsigned char) val;
|
return (unsigned char) val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_init() {
|
static void server_init() {
|
||||||
// Open Properties File
|
// Open Properties File
|
||||||
std::string file(getenv("HOME"));
|
std::string file(getenv("HOME"));
|
||||||
file.append("/.minecraft/server.properties");
|
file.append("/.minecraft/server.properties");
|
||||||
@ -508,3 +511,11 @@ void server_init() {
|
|||||||
pthread_t read_stdin_thread_obj;
|
pthread_t read_stdin_thread_obj;
|
||||||
pthread_create(&read_stdin_thread_obj, NULL, read_stdin_thread, NULL);
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -4,14 +4,10 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif\
|
||||||
|
|
||||||
void server_init();
|
|
||||||
|
|
||||||
const char *server_get_motd();
|
const char *server_get_motd();
|
||||||
|
|
||||||
const char *server_get_features();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
69
mods/src/textures/textures.cpp
Normal file
69
mods/src/textures/textures.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user