Refactor
This commit is contained in:
parent
43b1231153
commit
f9e893d1c3
@ -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)
|
||||
|
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 "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);
|
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
|
||||
|
||||
#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
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 "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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
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