C++-Ification!
This commit is contained in:
parent
7739fb6b9b
commit
b2a7fe3eaf
@ -16,6 +16,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hook Library Function
|
// Hook Library Function
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define hooked_function_setup extern "C"
|
||||||
|
#else
|
||||||
|
#define hooked_function_setup
|
||||||
|
#endif
|
||||||
#define HOOK(name, return_type, args) \
|
#define HOOK(name, return_type, args) \
|
||||||
typedef return_type (*name##_t)args; \
|
typedef return_type (*name##_t)args; \
|
||||||
static name##_t real_##name = NULL; \
|
static name##_t real_##name = NULL; \
|
||||||
@ -30,7 +35,7 @@
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
__attribute__((__used__)) return_type name args
|
hooked_function_setup __attribute__((__used__)) return_type name args
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -3,14 +3,14 @@ project(mods)
|
|||||||
# Common Sources
|
# Common Sources
|
||||||
set(SRC
|
set(SRC
|
||||||
# compat
|
# compat
|
||||||
src/compat/compat.c
|
src/compat/compat.cpp
|
||||||
src/compat/egl.c
|
src/compat/egl.cpp
|
||||||
src/compat/x11.c
|
src/compat/x11.cpp
|
||||||
src/compat/bcm_host.c
|
src/compat/bcm_host.cpp
|
||||||
# readdir
|
# readdir
|
||||||
src/readdir/readdir.c
|
src/readdir/readdir.cpp
|
||||||
# feature
|
# feature
|
||||||
src/feature/feature.c
|
src/feature/feature.cpp
|
||||||
# version
|
# version
|
||||||
src/version/version.cpp
|
src/version/version.cpp
|
||||||
# chat
|
# chat
|
||||||
@ -19,30 +19,28 @@ set(SRC
|
|||||||
# creative
|
# creative
|
||||||
src/creative/creative.cpp
|
src/creative/creative.cpp
|
||||||
# game-mode
|
# game-mode
|
||||||
src/game-mode/game-mode.c
|
src/game-mode/game-mode.cpp
|
||||||
src/game-mode/ui.cpp
|
src/game-mode/ui.cpp
|
||||||
# override
|
# override
|
||||||
src/override/override.c
|
src/override/override.cpp
|
||||||
# death
|
# death
|
||||||
src/death/death.cpp
|
src/death/death.cpp
|
||||||
# misc
|
# misc
|
||||||
src/misc/misc.c
|
|
||||||
src/misc/misc.cpp
|
src/misc/misc.cpp
|
||||||
src/misc/logging.cpp
|
src/misc/logging.cpp
|
||||||
src/misc/api.cpp
|
src/misc/api.cpp
|
||||||
# options
|
# options
|
||||||
src/options/options.c
|
|
||||||
src/options/options.cpp
|
src/options/options.cpp
|
||||||
# bucket
|
# bucket
|
||||||
src/bucket/bucket.cpp
|
src/bucket/bucket.cpp
|
||||||
# cake
|
# cake
|
||||||
src/cake/cake.cpp
|
src/cake/cake.cpp
|
||||||
# home
|
# home
|
||||||
src/home/home.c
|
src/home/home.cpp
|
||||||
# test
|
# test
|
||||||
src/test/test.c
|
src/test/test.cpp
|
||||||
# init
|
# init
|
||||||
src/init/init.c
|
src/init/init.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Server-Only Sources
|
# Server-Only Sources
|
||||||
@ -76,10 +74,10 @@ else()
|
|||||||
src/camera/camera.cpp
|
src/camera/camera.cpp
|
||||||
# input
|
# input
|
||||||
src/input/input.cpp
|
src/input/input.cpp
|
||||||
src/input/bow.c
|
src/input/bow.cpp
|
||||||
src/input/attack.c
|
src/input/attack.cpp
|
||||||
src/input/toggle.c
|
src/input/toggle.cpp
|
||||||
src/input/misc.c
|
src/input/misc.cpp
|
||||||
src/input/drop.cpp
|
src/input/drop.cpp
|
||||||
src/input/crafting.cpp
|
src/input/crafting.cpp
|
||||||
# sign
|
# sign
|
||||||
@ -95,7 +93,7 @@ else()
|
|||||||
src/skin/skin.cpp
|
src/skin/skin.cpp
|
||||||
src/skin/loader.cpp
|
src/skin/loader.cpp
|
||||||
# screenshot
|
# screenshot
|
||||||
src/screenshot/screenshot.c
|
src/screenshot/screenshot.cpp
|
||||||
# textures
|
# textures
|
||||||
src/textures/textures.cpp
|
src/textures/textures.cpp
|
||||||
src/textures/lava.cpp
|
src/textures/lava.cpp
|
||||||
|
@ -2,12 +2,4 @@
|
|||||||
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern bool buckets_enabled;
|
extern bool buckets_enabled;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,22 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#include <string>
|
|
||||||
// Send API Command
|
// Send API Command
|
||||||
std::string chat_send_api_command(Minecraft *minecraft, std::string str);
|
std::string chat_send_api_command(Minecraft *minecraft, std::string str);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Override using the HOOK() macro to provide customized chat behavior.
|
// Override using the HOOK() macro to provide customized chat behavior.
|
||||||
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message);
|
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message);
|
||||||
void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet);
|
void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int compat_check_exit_requested();
|
int compat_check_exit_requested();
|
||||||
void compat_request_exit();
|
void compat_request_exit();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int creative_is_restricted();
|
int creative_is_restricted();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
bool _feature_has(const char *name);
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int _feature_has(const char *name);
|
|
||||||
|
|
||||||
#ifdef MCPI_SERVER_MODE
|
#ifdef MCPI_SERVER_MODE
|
||||||
#define _feature_has__server_defaul_is_server_disabled(name) 0
|
#define _feature_has__server_defaul_is_server_disabled(name) 0
|
||||||
@ -16,7 +12,3 @@ int _feature_has(const char *name);
|
|||||||
#else
|
#else
|
||||||
#define feature_has(name, server_default) _feature_has(name)
|
#define feature_has(name, server_default) _feature_has(name)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern double fps;
|
extern double fps;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *home_get();
|
char *home_get();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void run_tests();
|
void run_tests();
|
||||||
void init_version();
|
void init_version();
|
||||||
void init_compat();
|
void init_compat();
|
||||||
@ -36,7 +32,3 @@ void init_chat();
|
|||||||
void init_bucket();
|
void init_bucket();
|
||||||
void init_cake();
|
void init_cake();
|
||||||
void init_home();
|
void init_home();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*input_tick_function_t)(Minecraft *minecraft);
|
typedef void (*input_tick_function_t)(Minecraft *minecraft);
|
||||||
void input_run_on_tick(input_tick_function_t function);
|
void input_run_on_tick(input_tick_function_t function);
|
||||||
|
|
||||||
@ -17,7 +13,3 @@ void input_open_crafting();
|
|||||||
void input_set_is_left_click(int val);
|
void input_set_is_left_click(int val);
|
||||||
|
|
||||||
void input_set_mouse_grab_state(int state);
|
void input_set_mouse_grab_state(int state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int32_t misc_get_real_selected_slot(Player *player);
|
int32_t misc_get_real_selected_slot(Player *player);
|
||||||
|
|
||||||
typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj);
|
typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj);
|
||||||
@ -32,7 +28,3 @@ void Level_saveLevelData_injection(Level *level);
|
|||||||
void misc_add_message(Gui *gui, const char *text);
|
void misc_add_message(Gui *gui, const char *text);
|
||||||
|
|
||||||
extern bool is_in_chat;
|
extern bool is_in_chat;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *override_get_path(const char *filename);
|
char *override_get_path(const char *filename);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void screenshot_take(char *home);
|
void screenshot_take(char *home);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void sign_key_press(char key);
|
void sign_key_press(char key);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -2,12 +2,4 @@
|
|||||||
|
|
||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels);
|
void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -3,6 +3,4 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void title_screen_load_splashes(std::vector<std::string> &splashes);
|
void title_screen_load_splashes(std::vector<std::string> &splashes);
|
||||||
}
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *version_get();
|
char *version_get();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -13,7 +13,7 @@ static void ItemRenderer_renderGuiItemCorrect_injection(Font *font, Textures *te
|
|||||||
// Replace Rendered Item With Carried Variant
|
// Replace Rendered Item With Carried Variant
|
||||||
ItemInstance carried_item_instance;
|
ItemInstance carried_item_instance;
|
||||||
bool use_carried = false;
|
bool use_carried = false;
|
||||||
if (item_instance != NULL) {
|
if (item_instance != nullptr) {
|
||||||
if (item_instance->id == leaves_id) {
|
if (item_instance->id == leaves_id) {
|
||||||
ItemInstance_constructor_tile_extra(&carried_item_instance, Tile_leaves_carried, item_instance->count, item_instance->auxiliary);
|
ItemInstance_constructor_tile_extra(&carried_item_instance, Tile_leaves_carried, item_instance->count, item_instance->auxiliary);
|
||||||
use_carried = true;
|
use_carried = true;
|
||||||
@ -91,7 +91,7 @@ static void FurnaceScreen_render_ItemRenderer_renderGuiItem_one_injection(Font *
|
|||||||
|
|
||||||
// Init
|
// Init
|
||||||
void init_atlas() {
|
void init_atlas() {
|
||||||
// Add Better NULL-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled)
|
// Add Better nullptr-Check (And More UI Fixes When The gui_blocks Atlas Is Disabled)
|
||||||
overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection);
|
overwrite_calls((void *) ItemRenderer_renderGuiItem_two, (void *) ItemRenderer_renderGuiItem_two_injection);
|
||||||
|
|
||||||
// Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
|
// Disable The gui_blocks Atlas Which Contains Pre-Rendered Textures For Blocks In The Inventory
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include <mods/bucket/bucket.h>
|
#include <mods/bucket/bucket.h>
|
||||||
|
|
||||||
// Items
|
// Items
|
||||||
static FoodItem *bucket = NULL;
|
static FoodItem *bucket = nullptr;
|
||||||
|
|
||||||
// Description And Texture
|
// Description And Texture
|
||||||
static std::string BucketItem_getDescriptionId(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance) {
|
static std::string BucketItem_getDescriptionId(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance) {
|
||||||
@ -111,7 +111,7 @@ static int32_t BucketItem_useOn(__attribute__((unused)) FoodItem *item, ItemInst
|
|||||||
// Get Current Tile
|
// Get Current Tile
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
Material *material = level->vtable->getMaterial(level, x, y, z);
|
Material *material = level->vtable->getMaterial(level, x, y, z);
|
||||||
if (material != NULL) {
|
if (material != nullptr) {
|
||||||
valid = !material->vtable->isSolid(material);
|
valid = !material->vtable->isSolid(material);
|
||||||
}
|
}
|
||||||
if (item_instance->auxiliary != Tile_water->id && item_instance->auxiliary != Tile_lava->id) {
|
if (item_instance->auxiliary != Tile_water->id && item_instance->auxiliary != Tile_lava->id) {
|
||||||
@ -161,7 +161,7 @@ static ItemInstance *BucketItem_use(FoodItem *item, ItemInstance *item_instance,
|
|||||||
|
|
||||||
static ItemInstance *BucketItem_getCraftingRemainingItem(FoodItem *item, ItemInstance *item_instance) {
|
static ItemInstance *BucketItem_getCraftingRemainingItem(FoodItem *item, ItemInstance *item_instance) {
|
||||||
if (item_instance->auxiliary == 0) {
|
if (item_instance->auxiliary == 0) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ItemInstance *ret = alloc_ItemInstance();
|
ItemInstance *ret = alloc_ItemInstance();
|
||||||
ret->id = item->id;
|
ret->id = item->id;
|
||||||
@ -255,7 +255,7 @@ static HitResult Mob_pick_Level_clip_injection(Level *level, unsigned char *para
|
|||||||
}
|
}
|
||||||
static void handle_tick(Minecraft *minecraft) {
|
static void handle_tick(Minecraft *minecraft) {
|
||||||
LocalPlayer *player = minecraft->player;
|
LocalPlayer *player = minecraft->player;
|
||||||
if (player != NULL) {
|
if (player != nullptr) {
|
||||||
// Get Selected Slot
|
// Get Selected Slot
|
||||||
int32_t selected_slot = misc_get_real_selected_slot((Player *) player);
|
int32_t selected_slot = misc_get_real_selected_slot((Player *) player);
|
||||||
Inventory *inventory = player->inventory;
|
Inventory *inventory = player->inventory;
|
||||||
@ -263,7 +263,7 @@ static void handle_tick(Minecraft *minecraft) {
|
|||||||
// Get Item
|
// Get Item
|
||||||
ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot);
|
ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot);
|
||||||
// Check
|
// Check
|
||||||
is_holding_bucket = inventory_item != NULL && inventory_item->id == bucket->id && inventory_item->auxiliary == 0;
|
is_holding_bucket = inventory_item != nullptr && inventory_item->id == bucket->id && inventory_item->auxiliary == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ static bool is_calm_liquid(int32_t id) {
|
|||||||
static void Minecraft_handleMouseDown_injection(Minecraft *minecraft, int param_1, bool can_destroy) {
|
static void Minecraft_handleMouseDown_injection(Minecraft *minecraft, int param_1, bool can_destroy) {
|
||||||
// Check
|
// Check
|
||||||
Level *level = minecraft->level;
|
Level *level = minecraft->level;
|
||||||
if (level != NULL) {
|
if (level != nullptr) {
|
||||||
int32_t x = minecraft->hit_result.x;
|
int32_t x = minecraft->hit_result.x;
|
||||||
int32_t y = minecraft->hit_result.y;
|
int32_t y = minecraft->hit_result.y;
|
||||||
int32_t z = minecraft->hit_result.z;
|
int32_t z = minecraft->hit_result.z;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
#include <mods/bucket/bucket.h>
|
#include <mods/bucket/bucket.h>
|
||||||
|
|
||||||
static Tile *cake = NULL;
|
static Tile *cake = nullptr;
|
||||||
|
|
||||||
#define CAKE_LEN 0.0625F
|
#define CAKE_LEN 0.0625F
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ std::string chat_send_api_command(Minecraft *minecraft, std::string str) {
|
|||||||
client.str = "";
|
client.str = "";
|
||||||
client.time = 0;
|
client.time = 0;
|
||||||
CommandServer *command_server = minecraft->command_server;
|
CommandServer *command_server = minecraft->command_server;
|
||||||
if (command_server != NULL) {
|
if (command_server != nullptr) {
|
||||||
return CommandServer_parse(command_server, &client, &str);
|
return CommandServer_parse(command_server, &client, &str);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
@ -36,7 +36,7 @@ std::string chat_send_api_command(Minecraft *minecraft, std::string str) {
|
|||||||
#ifndef MCPI_HEADLESS_MODE
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
// Send API Chat Command
|
// Send API Chat Command
|
||||||
static void send_api_chat_command(Minecraft *minecraft, char *str) {
|
static void send_api_chat_command(Minecraft *minecraft, char *str) {
|
||||||
char *command = NULL;
|
char *command = nullptr;
|
||||||
safe_asprintf(&command, "chat.post(%s)\n", str);
|
safe_asprintf(&command, "chat.post(%s)\n", str);
|
||||||
chat_send_api_command(minecraft, command);
|
chat_send_api_command(minecraft, command);
|
||||||
free(command);
|
free(command);
|
||||||
@ -48,7 +48,7 @@ std::string _chat_get_prefix(char *username) {
|
|||||||
return std::string("<") + username + "> ";
|
return std::string("<") + username + "> ";
|
||||||
}
|
}
|
||||||
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message) {
|
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, char *username, char *message) {
|
||||||
char *full_message = NULL;
|
char *full_message = nullptr;
|
||||||
safe_asprintf(&full_message, "%s%s", _chat_get_prefix(username).c_str(), message);
|
safe_asprintf(&full_message, "%s%s", _chat_get_prefix(username).c_str(), message);
|
||||||
sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0);
|
sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0);
|
||||||
std::string cpp_string = full_message;
|
std::string cpp_string = full_message;
|
||||||
@ -72,7 +72,7 @@ void chat_handle_packet_send(Minecraft *minecraft, ChatPacket *packet) {
|
|||||||
// Manually Send (And Loopback) ChatPacket
|
// Manually Send (And Loopback) ChatPacket
|
||||||
static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandServer *command_server, Packet *packet) {
|
static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandServer *command_server, Packet *packet) {
|
||||||
Minecraft *minecraft = command_server->minecraft;
|
Minecraft *minecraft = command_server->minecraft;
|
||||||
if (minecraft != NULL) {
|
if (minecraft != nullptr) {
|
||||||
chat_handle_packet_send(minecraft, (ChatPacket *) packet);
|
chat_handle_packet_send(minecraft, (ChatPacket *) packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ static void CommandServer_parse_CommandServer_dispatchPacket_injection(CommandSe
|
|||||||
// Handle ChatPacket Server-Side
|
// Handle ChatPacket Server-Side
|
||||||
static void ServerSideNetworkHandler_handle_ChatPacket_injection(ServerSideNetworkHandler *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, ChatPacket *chat_packet) {
|
static void ServerSideNetworkHandler_handle_ChatPacket_injection(ServerSideNetworkHandler *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, ChatPacket *chat_packet) {
|
||||||
Player *player = ServerSideNetworkHandler_getPlayer(server_side_network_handler, rak_net_guid);
|
Player *player = ServerSideNetworkHandler_getPlayer(server_side_network_handler, rak_net_guid);
|
||||||
if (player != NULL) {
|
if (player != nullptr) {
|
||||||
const char *username = player->username.c_str();
|
const char *username = player->username.c_str();
|
||||||
const char *message = chat_packet->message.c_str();
|
const char *message = chat_packet->message.c_str();
|
||||||
chat_send_message(server_side_network_handler, (char *) username, (char *) message);
|
chat_send_message(server_side_network_handler, (char *) username, (char *) message);
|
||||||
|
@ -95,7 +95,7 @@ CUSTOM_VTABLE(chat_screen, Screen) {
|
|||||||
}
|
}
|
||||||
_chat_queue_message(text.c_str());
|
_chat_queue_message(text.c_str());
|
||||||
}
|
}
|
||||||
Minecraft_setScreen(super->minecraft, NULL);
|
Minecraft_setScreen(super->minecraft, nullptr);
|
||||||
} else if (key == 0x26) {
|
} else if (key == 0x26) {
|
||||||
// Up
|
// Up
|
||||||
local_history.at(self->history_pos) = self->chat->getText();
|
local_history.at(self->history_pos) = self->chat->getText();
|
||||||
@ -147,7 +147,7 @@ static Screen *create_chat_screen() {
|
|||||||
void _init_chat_ui() {
|
void _init_chat_ui() {
|
||||||
misc_run_on_game_key_press([](Minecraft *minecraft, int key) {
|
misc_run_on_game_key_press([](Minecraft *minecraft, int key) {
|
||||||
if (key == 0x54) {
|
if (key == 0x54) {
|
||||||
if (Minecraft_isLevelGenerated(minecraft) && minecraft->screen == NULL) {
|
if (Minecraft_isLevelGenerated(minecraft) && minecraft->screen == nullptr) {
|
||||||
Minecraft_setScreen(minecraft, create_chat_screen());
|
Minecraft_setScreen(minecraft, create_chat_screen());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <csignal>
|
||||||
#include <errno.h>
|
#include <cerrno>
|
||||||
|
|
||||||
#include <mods/compat/compat.h>
|
#include <mods/compat/compat.h>
|
||||||
#include <mods/screenshot/screenshot.h>
|
#include <mods/screenshot/screenshot.h>
|
||||||
@ -51,7 +51,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||||||
int ret = real_SDL_PollEvent(event);
|
int ret = real_SDL_PollEvent(event);
|
||||||
|
|
||||||
// Handle Events
|
// Handle Events
|
||||||
if (ret == 1 && event != NULL) {
|
if (ret == 1 && event != nullptr) {
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
@ -116,11 +116,10 @@ static void exit_handler(__attribute__((unused)) int data) {
|
|||||||
void init_compat() {
|
void init_compat() {
|
||||||
// Install Signal Handlers
|
// Install Signal Handlers
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
struct sigaction act_sigterm;
|
struct sigaction act_sigterm = {};
|
||||||
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
|
|
||||||
act_sigterm.sa_flags = SA_RESTART;
|
act_sigterm.sa_flags = SA_RESTART;
|
||||||
act_sigterm.sa_handler = &exit_handler;
|
act_sigterm.sa_handler = &exit_handler;
|
||||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
sigaction(SIGTERM, &act_sigterm, nullptr);
|
||||||
// Patches
|
// Patches
|
||||||
_patch_egl_calls();
|
_patch_egl_calls();
|
||||||
_patch_x11_calls();
|
_patch_x11_calls();
|
@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
// Functions That Have Their Return Values Used
|
// Functions That Have Their Return Values Used
|
||||||
static EGLSurface eglCreateWindowSurface_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) {
|
static EGLSurface eglCreateWindowSurface_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) {
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static EGLDisplay eglGetDisplay_injection(__attribute__((unused)) NativeDisplayType native_display) {
|
static EGLDisplay eglGetDisplay_injection(__attribute__((unused)) NativeDisplayType native_display) {
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static EGLContext eglCreateContext_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) {
|
static EGLContext eglCreateContext_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) {
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// Call media_swap_buffers()
|
// Call media_swap_buffers()
|
||||||
static EGLBoolean eglSwapBuffers_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
static EGLBoolean eglSwapBuffers_injection(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
@ -13,7 +13,7 @@ static int XTranslateCoordinates_injection(__attribute__((unused)) void *display
|
|||||||
}
|
}
|
||||||
static int XGetWindowAttributes_injection(__attribute__((unused)) void *display, __attribute__((unused)) XID w, XWindowAttributes *window_attributes_return) {
|
static int XGetWindowAttributes_injection(__attribute__((unused)) void *display, __attribute__((unused)) XID w, XWindowAttributes *window_attributes_return) {
|
||||||
// Use MCPI Replacemnt Function
|
// Use MCPI Replacemnt Function
|
||||||
XWindowAttributes attributes;
|
XWindowAttributes attributes = {};
|
||||||
attributes.x = 0;
|
attributes.x = 0;
|
||||||
attributes.y = 0;
|
attributes.y = 0;
|
||||||
media_get_framebuffer_size(&attributes.width, &attributes.height);
|
media_get_framebuffer_size(&attributes.width, &attributes.height);
|
@ -110,7 +110,7 @@ static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) {
|
|||||||
/* Check Health */ \
|
/* Check Health */ \
|
||||||
if (new_health < 1 && old_health >= 1) { \
|
if (new_health < 1 && old_health >= 1) { \
|
||||||
/* Get Death Message */ \
|
/* Get Death Message */ \
|
||||||
std::string message = get_death_message((Player *) player, NULL); \
|
std::string message = get_death_message((Player *) player, nullptr); \
|
||||||
\
|
\
|
||||||
/* Post Death Message */ \
|
/* Post Death Message */ \
|
||||||
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \
|
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \
|
||||||
@ -134,7 +134,7 @@ void init_death() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix TNT
|
// Fix TNT
|
||||||
// This changes PrimedTnt_explode from Level::explode(NULL, x, y, z, 3.1f) to Level::explode(this, x, y, z, 3.1f)
|
// This changes PrimedTnt_explode from Level::explode(nullptr, x, y, z, 3.1f) to Level::explode(this, x, y, z, 3.1f)
|
||||||
unsigned char cpy_r1_r0_patch[4] = {0x00, 0x10, 0xa0, 0xe1}; // "cpy r1, r0"
|
unsigned char cpy_r1_r0_patch[4] = {0x00, 0x10, 0xa0, 0xe1}; // "cpy r1, r0"
|
||||||
patch((void *) 0x87998, cpy_r1_r0_patch);
|
patch((void *) 0x87998, cpy_r1_r0_patch);
|
||||||
unsigned char ldr_r0_24_patch[4] = {0x24, 0x00, 0x90, 0xe5}; // "ldr r0, [r0, #0x24]"
|
unsigned char ldr_r0_24_patch[4] = {0x24, 0x00, 0x90, 0xe5}; // "ldr r0, [r0, #0x24]"
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
#include <mods/feature/feature.h>
|
#include <mods/feature/feature.h>
|
||||||
|
|
||||||
// Check For Feature
|
// Check For Feature
|
||||||
int _feature_has(const char *name) {
|
bool _feature_has(const char *name) {
|
||||||
// Get Value
|
// Get Value
|
||||||
char *env = getenv("MCPI_FEATURE_FLAGS");
|
char *env = getenv("MCPI_FEATURE_FLAGS");
|
||||||
char *features = strdup(env != NULL ? env : "");
|
char *features = strdup(env != nullptr ? env : "");
|
||||||
char *tok = strtok(features, "|");
|
char *tok = strtok(features, "|");
|
||||||
int ret = 0;
|
bool ret = false;
|
||||||
while (tok != NULL) {
|
while (tok != nullptr) {
|
||||||
if (strcmp(tok, name) == 0) {
|
if (strcmp(tok, name) == 0) {
|
||||||
ret = 1;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tok = strtok(NULL, "|");
|
tok = strtok(nullptr, "|");
|
||||||
}
|
}
|
||||||
free(features);
|
free(features);
|
||||||
|
|
@ -8,16 +8,16 @@
|
|||||||
static int is_survival = -1;
|
static int is_survival = -1;
|
||||||
|
|
||||||
// Patch Game Mode
|
// Patch Game Mode
|
||||||
static void set_is_survival(int new_is_survival) {
|
static void set_is_survival(bool new_is_survival) {
|
||||||
if (is_survival != new_is_survival) {
|
if (is_survival != new_is_survival) {
|
||||||
DEBUG("Setting Game Mode: %s", new_is_survival ? "Survival" : "Creative");
|
DEBUG("Setting Game Mode: %s", new_is_survival ? "Survival" : "Creative");
|
||||||
|
|
||||||
// Correct Inventpry UI
|
// Correct Inventpry UI
|
||||||
unsigned char inventory_patch[4] = {new_is_survival ? 0x00 : 0x01, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0" or "mov r3, #0x1"
|
unsigned char inventory_patch[4] = {(unsigned char) (new_is_survival ? 0x00 : 0x01), 0x30, 0xa0, 0xe3}; // "mov r3, #0x0" or "mov r3, #0x1"
|
||||||
patch((void *) 0x16efc, inventory_patch);
|
patch((void *) 0x16efc, inventory_patch);
|
||||||
|
|
||||||
// Use Correct Size For GameMode Object
|
// Use Correct Size For GameMode Object
|
||||||
unsigned char size_patch[4] = {new_is_survival ? SURVIVAL_MODE_SIZE : CREATOR_MODE_SIZE, 0x00, 0xa0, 0xe3}; // "mov r0, #SURVIVAL_MODE_SIZE" or "mov r0, #CREATOR_MODE_SIZE"
|
unsigned char size_patch[4] = {(unsigned char) (new_is_survival ? SURVIVAL_MODE_SIZE : CREATOR_MODE_SIZE), 0x00, 0xa0, 0xe3}; // "mov r0, #SURVIVAL_MODE_SIZE" or "mov r0, #CREATOR_MODE_SIZE"
|
||||||
patch((void *) 0x16ee4, size_patch);
|
patch((void *) 0x16ee4, size_patch);
|
||||||
|
|
||||||
// Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor
|
// Replace Default CreatorMode Constructor With CreatorMode Or SurvivalMode Constructor
|
||||||
@ -28,18 +28,18 @@ static void set_is_survival(int new_is_survival) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle Gamemode Switching
|
// Handle Gamemode Switching
|
||||||
static void Minecraft_setIsCreativeMode_injection(Minecraft *this, int32_t new_game_mode) {
|
static void Minecraft_setIsCreativeMode_injection(Minecraft *self, int32_t new_game_mode) {
|
||||||
set_is_survival(!new_game_mode);
|
set_is_survival(!new_game_mode);
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
Minecraft_setIsCreativeMode(this, new_game_mode);
|
Minecraft_setIsCreativeMode(self, new_game_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing
|
// Disable CreatorMode-Specific API Features (Polling Block Hits) In SurvivalMode, This Is Preferable To Crashing
|
||||||
static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) {
|
static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) {
|
||||||
if (is_survival) {
|
if (is_survival) {
|
||||||
// SurvivalMode, Return NULL
|
// SurvivalMode, Return nullptr
|
||||||
return NULL;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
// CreatorMode, Call Original Method
|
// CreatorMode, Call Original Method
|
||||||
return Minecraft_getCreator(minecraft);
|
return Minecraft_getCreator(minecraft);
|
||||||
@ -50,7 +50,7 @@ static unsigned char *Minecraft_getCreator_injection(Minecraft *minecraft) {
|
|||||||
void init_game_mode() {
|
void init_game_mode() {
|
||||||
// Dynamic Game Mode Switching
|
// Dynamic Game Mode Switching
|
||||||
if (feature_has("Implement Game-Mode Switching", server_enabled)) {
|
if (feature_has("Implement Game-Mode Switching", server_enabled)) {
|
||||||
set_is_survival(1);
|
set_is_survival(true);
|
||||||
overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection);
|
overwrite_calls((void *) Minecraft_setIsCreativeMode, (void *) Minecraft_setIsCreativeMode_injection);
|
||||||
|
|
||||||
// Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning)
|
// Replace CreatorLevel With ServerLevel (This Fixes Beds And Mob Spawning)
|
@ -1,4 +1,4 @@
|
|||||||
#include <errno.h>
|
#include <cerrno>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
// Get MCPI Home Directory
|
// Get MCPI Home Directory
|
||||||
char *home_get() {
|
char *home_get() {
|
||||||
static char *dir = NULL;
|
static char *dir = nullptr;
|
||||||
// Load
|
// Load
|
||||||
if (dir == NULL) {
|
if (dir == nullptr) {
|
||||||
safe_asprintf(&dir, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA, getenv("HOME"));
|
safe_asprintf(&dir, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA, getenv("HOME"));
|
||||||
}
|
}
|
||||||
// Return
|
// Return
|
@ -45,7 +45,7 @@ static bool Player_attack_Entity_hurt_injection(Entity *entity, Entity *attacker
|
|||||||
static ItemInstance *Player_attack_Inventory_getSelected_injection(Inventory *inventory) {
|
static ItemInstance *Player_attack_Inventory_getSelected_injection(Inventory *inventory) {
|
||||||
// Check If Attack Was Successful
|
// Check If Attack Was Successful
|
||||||
if (!last_player_attack_successful) {
|
if (!last_player_attack_successful) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
@ -19,7 +19,7 @@ static void _handle_bow(Minecraft *minecraft) {
|
|||||||
if (fix_bow && !is_right_click) {
|
if (fix_bow && !is_right_click) {
|
||||||
GameMode *game_mode = minecraft->game_mode;
|
GameMode *game_mode = minecraft->game_mode;
|
||||||
LocalPlayer *player = minecraft->player;
|
LocalPlayer *player = minecraft->player;
|
||||||
if (player != NULL && game_mode != NULL && LocalPlayer_isUsingItem(player)) {
|
if (player != nullptr && game_mode != nullptr && LocalPlayer_isUsingItem(player)) {
|
||||||
game_mode->vtable->releaseUsingItem(game_mode, (Player *) player);
|
game_mode->vtable->releaseUsingItem(game_mode, (Player *) player);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,10 +25,10 @@ void input_drop(int drop_slot) {
|
|||||||
|
|
||||||
// Handle Drop Item Presses
|
// Handle Drop Item Presses
|
||||||
static void _handle_drop(Minecraft *minecraft) {
|
static void _handle_drop(Minecraft *minecraft) {
|
||||||
if ((minecraft->screen == NULL) && (!creative_is_restricted() || !Minecraft_isCreativeMode(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) {
|
if ((minecraft->screen == nullptr) && (!creative_is_restricted() || !Minecraft_isCreativeMode(minecraft)) && (drop_item_presses > 0 || drop_slot_pressed)) {
|
||||||
// Get Player
|
// Get Player
|
||||||
LocalPlayer *player = minecraft->player;
|
LocalPlayer *player = minecraft->player;
|
||||||
if (player != NULL) {
|
if (player != nullptr) {
|
||||||
// Get Selected Slot
|
// Get Selected Slot
|
||||||
int32_t selected_slot = misc_get_real_selected_slot((Player *) player);
|
int32_t selected_slot = misc_get_real_selected_slot((Player *) player);
|
||||||
Inventory *inventory = player->inventory;
|
Inventory *inventory = player->inventory;
|
||||||
@ -36,7 +36,7 @@ static void _handle_drop(Minecraft *minecraft) {
|
|||||||
// Get Item
|
// Get Item
|
||||||
ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot);
|
ItemInstance *inventory_item = inventory->vtable->getItem(inventory, selected_slot);
|
||||||
// Check
|
// Check
|
||||||
if (inventory_item != NULL && inventory_item->count > 0) {
|
if (inventory_item != nullptr && inventory_item->count > 0) {
|
||||||
// Copy
|
// Copy
|
||||||
ItemInstance *dropped_item = new ItemInstance;
|
ItemInstance *dropped_item = new ItemInstance;
|
||||||
ALLOC_CHECK(dropped_item);
|
ALLOC_CHECK(dropped_item);
|
||||||
|
@ -22,8 +22,8 @@ int input_back() {
|
|||||||
|
|
||||||
// Handle Back Button Presses
|
// Handle Back Button Presses
|
||||||
static void _handle_back(Minecraft *minecraft) {
|
static void _handle_back(Minecraft *minecraft) {
|
||||||
// If Minecraft's Level property is initialized, but Minecraft's Player property is NULL, then Minecraft::handleBack may crash.
|
// If Minecraft's Level property is initialized, but Minecraft's Player property is nullptr, then Minecraft::handleBack may crash.
|
||||||
if (minecraft->level != NULL && minecraft->player == NULL) {
|
if (minecraft->level != nullptr && minecraft->player == nullptr) {
|
||||||
// Unable to safely run Minecraft::handleBack, deferring until safe.
|
// Unable to safely run Minecraft::handleBack, deferring until safe.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ static void _handle_back(Minecraft *minecraft) {
|
|||||||
static bool OptionsScreen_handleBackEvent_injection(OptionsScreen *screen, bool do_nothing) {
|
static bool OptionsScreen_handleBackEvent_injection(OptionsScreen *screen, bool do_nothing) {
|
||||||
if (!do_nothing) {
|
if (!do_nothing) {
|
||||||
Minecraft *minecraft = screen->minecraft;
|
Minecraft *minecraft = screen->minecraft;
|
||||||
Minecraft_setScreen(minecraft, NULL);
|
Minecraft_setScreen(minecraft, nullptr);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -48,10 +48,10 @@ static int32_t InBedScreen_handleBackEvent_injection(InBedScreen *screen, bool d
|
|||||||
if (!do_nothing) {
|
if (!do_nothing) {
|
||||||
// Close Screen
|
// Close Screen
|
||||||
Minecraft *minecraft = screen->minecraft;
|
Minecraft *minecraft = screen->minecraft;
|
||||||
Minecraft_setScreen(minecraft, NULL);
|
Minecraft_setScreen(minecraft, nullptr);
|
||||||
// Stop Sleeping
|
// Stop Sleeping
|
||||||
LocalPlayer *player = minecraft->player;
|
LocalPlayer *player = minecraft->player;
|
||||||
if (player != NULL) {
|
if (player != nullptr) {
|
||||||
player->vtable->stopSleepInBed(player, 1, 1, 1);
|
player->vtable->stopSleepInBed(player, 1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ static void _handle_mouse_grab(Minecraft *minecraft) {
|
|||||||
|
|
||||||
// Block UI Interaction When Mouse Is Locked
|
// Block UI Interaction When Mouse Is Locked
|
||||||
static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) {
|
static bool Gui_tickItemDrop_Minecraft_isCreativeMode_call_injection(Minecraft *minecraft) {
|
||||||
bool is_in_game = minecraft->screen == NULL || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable_base;
|
bool is_in_game = minecraft->screen == nullptr || minecraft->screen->vtable == (Screen_vtable *) Touch_IngameBlockSelectionScreen_vtable_base;
|
||||||
if (!enable_misc || (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF && is_in_game)) {
|
if (!enable_misc || (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF && is_in_game)) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
return creative_is_restricted() && Minecraft_isCreativeMode(minecraft);
|
return creative_is_restricted() && Minecraft_isCreativeMode(minecraft);
|
@ -32,7 +32,7 @@ static void _fix_third_person(Minecraft *minecraft) {
|
|||||||
|
|
||||||
// Font-Facing View
|
// Font-Facing View
|
||||||
static void invert_rotation(Entity *entity) {
|
static void invert_rotation(Entity *entity) {
|
||||||
if (entity != NULL) {
|
if (entity != nullptr) {
|
||||||
entity->yaw = 180.f + entity->yaw;
|
entity->yaw = 180.f + entity->yaw;
|
||||||
entity->old_yaw = 180.f + entity->old_yaw;
|
entity->old_yaw = 180.f + entity->old_yaw;
|
||||||
entity->pitch = -entity->pitch;
|
entity->pitch = -entity->pitch;
|
||||||
@ -40,7 +40,7 @@ static void invert_rotation(Entity *entity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void revert_rotation(Entity *entity) {
|
static void revert_rotation(Entity *entity) {
|
||||||
if (entity != NULL) {
|
if (entity != nullptr) {
|
||||||
entity->yaw = -180.f + entity->yaw;
|
entity->yaw = -180.f + entity->yaw;
|
||||||
entity->old_yaw = -180.f + entity->old_yaw;
|
entity->old_yaw = -180.f + entity->old_yaw;
|
||||||
entity->pitch = -entity->pitch;
|
entity->pitch = -entity->pitch;
|
||||||
@ -48,7 +48,7 @@ static void revert_rotation(Entity *entity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int is_front_facing = 0;
|
static int is_front_facing = 0;
|
||||||
static LocalPlayer *stored_player = NULL;
|
static LocalPlayer *stored_player = nullptr;
|
||||||
static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, float param_1, int param_2) {
|
static void GameRenderer_setupCamera_injection(GameRenderer *game_renderer, float param_1, int param_2) {
|
||||||
// Get Objects
|
// Get Objects
|
||||||
Minecraft *minecraft = game_renderer->minecraft;
|
Minecraft *minecraft = game_renderer->minecraft;
|
@ -89,7 +89,7 @@ SETUP_CALLBACK(tiles_setup, void);
|
|||||||
// Handle Custom Tiles Setup Behavior
|
// Handle Custom Tiles Setup Behavior
|
||||||
static void Tile_initTiles_injection() {
|
static void Tile_initTiles_injection() {
|
||||||
// Run Functions
|
// Run Functions
|
||||||
handle_misc_tiles_setup(NULL);
|
handle_misc_tiles_setup(nullptr);
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
Tile_initTiles();
|
Tile_initTiles();
|
||||||
@ -103,7 +103,7 @@ static void Item_initItems_injection() {
|
|||||||
Item_initItems();
|
Item_initItems();
|
||||||
|
|
||||||
// Run Functions
|
// Run Functions
|
||||||
handle_misc_items_setup(NULL);
|
handle_misc_items_setup(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run Functions On Language Setup
|
// Run Functions On Language Setup
|
||||||
@ -114,7 +114,7 @@ static void I18n_loadLanguage_injection(AppPlatform *app, std::string language_n
|
|||||||
I18n_loadLanguage(app, language_name);
|
I18n_loadLanguage(app, language_name);
|
||||||
|
|
||||||
// Run Functions
|
// Run Functions
|
||||||
handle_misc_language_setup(NULL);
|
handle_misc_language_setup(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run Functions On GUI Key Press
|
// Run Functions On GUI Key Press
|
||||||
|
@ -45,7 +45,7 @@ void misc_add_message(Gui *gui, const char *text) {
|
|||||||
|
|
||||||
// Print Progress Reports
|
// Print Progress Reports
|
||||||
static int last_progress = -1;
|
static int last_progress = -1;
|
||||||
static const char *last_message = NULL;
|
static const char *last_message = nullptr;
|
||||||
static void print_progress(Minecraft *minecraft) {
|
static void print_progress(Minecraft *minecraft) {
|
||||||
const char *message = Minecraft_getProgressMessage(minecraft);
|
const char *message = Minecraft_getProgressMessage(minecraft);
|
||||||
int32_t progress = minecraft->progress;
|
int32_t progress = minecraft->progress;
|
||||||
@ -53,7 +53,7 @@ static void print_progress(Minecraft *minecraft) {
|
|||||||
message = "Ready";
|
message = "Ready";
|
||||||
progress = -1;
|
progress = -1;
|
||||||
}
|
}
|
||||||
if (message != NULL) {
|
if (message != nullptr) {
|
||||||
bool message_different = message != last_message;
|
bool message_different = message != last_message;
|
||||||
bool progress_significant = is_progress_difference_significant(progress, last_progress);
|
bool progress_significant = is_progress_difference_significant(progress, last_progress);
|
||||||
if (message_different || progress_significant) {
|
if (message_different || progress_significant) {
|
||||||
@ -99,5 +99,5 @@ void _init_misc_logging() {
|
|||||||
overwrite_calls((void *) Level_saveLevelData, (void *) Level_saveLevelData_injection);
|
overwrite_calls((void *) Level_saveLevelData, (void *) Level_saveLevelData_injection);
|
||||||
|
|
||||||
// Disable stdout Buffering
|
// Disable stdout Buffering
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__attribute__((visibility("internal"))) void _init_misc_cpp();
|
|
||||||
__attribute__((visibility("internal"))) void _init_misc_logging();
|
__attribute__((visibility("internal"))) void _init_misc_logging();
|
||||||
__attribute__((visibility("internal"))) void _init_misc_api();
|
__attribute__((visibility("internal"))) void _init_misc_api();
|
||||||
|
|
||||||
|
@ -1,850 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
#include <GLES/gl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
|
||||||
|
|
||||||
#include <SDL/SDL.h>
|
|
||||||
#include <media-layer/core.h>
|
|
||||||
|
|
||||||
#include <mods/init/init.h>
|
|
||||||
#include <mods/feature/feature.h>
|
|
||||||
#include "misc-internal.h"
|
|
||||||
#include <mods/misc/misc.h>
|
|
||||||
|
|
||||||
// Heart food overlay
|
|
||||||
static int heal_amount = 0, heal_amount_drawing = 0;
|
|
||||||
void Gui_renderHearts_injection(Gui *gui) {
|
|
||||||
// Get heal_amount
|
|
||||||
heal_amount = heal_amount_drawing = 0;
|
|
||||||
|
|
||||||
Inventory *inventory = gui->minecraft->player->inventory;
|
|
||||||
ItemInstance *held_ii = Inventory_getSelected(inventory);
|
|
||||||
if (held_ii) {
|
|
||||||
Item *held = Item_items[held_ii->id];
|
|
||||||
if (held->vtable->isFood(held) && held_ii->id) {
|
|
||||||
int nutrition = ((FoodItem *) held)->nutrition;
|
|
||||||
int cur_health = gui->minecraft->player->health;
|
|
||||||
int heal_num = fmin(cur_health + nutrition, 20) - cur_health;
|
|
||||||
heal_amount = heal_amount_drawing = heal_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call original
|
|
||||||
Gui_renderHearts(gui);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PINK_HEART_FULL 70
|
|
||||||
#define PINK_HEART_HALF 79
|
|
||||||
Gui_blit_t Gui_blit_renderHearts_original = NULL;
|
|
||||||
void Gui_renderHearts_GuiComponent_blit_overlay_empty_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) {
|
|
||||||
// Call original
|
|
||||||
Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
|
||||||
// Render the overlay
|
|
||||||
if (heal_amount_drawing == 1) {
|
|
||||||
// Half heart
|
|
||||||
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_HALF, 0, w1, h1, w2, h2);
|
|
||||||
heal_amount_drawing = 0;
|
|
||||||
} else if (heal_amount_drawing > 0) {
|
|
||||||
// Full heart
|
|
||||||
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
|
||||||
heal_amount_drawing -= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) {
|
|
||||||
// Offset the overlay
|
|
||||||
if (x2 == 52) {
|
|
||||||
heal_amount_drawing += 2;
|
|
||||||
} else if (x2 == 61 && heal_amount) {
|
|
||||||
// Half heart, flipped
|
|
||||||
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
|
||||||
heal_amount_drawing += 1;
|
|
||||||
};
|
|
||||||
// Call original
|
|
||||||
Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
|
||||||
heal_amount_drawing = fmin(heal_amount_drawing, heal_amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Classic HUD
|
|
||||||
#define DEFAULT_HUD_PADDING 2
|
|
||||||
#define NEW_HUD_PADDING 1
|
|
||||||
#define HUD_ELEMENT_WIDTH 82
|
|
||||||
#define HUD_ELEMENT_HEIGHT 9
|
|
||||||
#define TOOLBAR_HEIGHT 22
|
|
||||||
#define SLOT_WIDTH 20
|
|
||||||
#define DEFAULT_BUBBLES_PADDING 1
|
|
||||||
#define NUMBER_OF_SLOTS 9
|
|
||||||
static int use_classic_hud = 0;
|
|
||||||
static void Gui_renderHearts_GuiComponent_blit_hearts_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
|
||||||
Minecraft *minecraft = component->minecraft;
|
|
||||||
x_dest -= DEFAULT_HUD_PADDING;
|
|
||||||
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
|
||||||
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
|
||||||
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
|
||||||
y_dest -= DEFAULT_HUD_PADDING;
|
|
||||||
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
|
||||||
// Call Original Method
|
|
||||||
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
|
||||||
}
|
|
||||||
static void Gui_renderHearts_GuiComponent_blit_armor_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
|
||||||
Minecraft *minecraft = component->minecraft;
|
|
||||||
x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH;
|
|
||||||
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
|
||||||
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
|
||||||
x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH;
|
|
||||||
y_dest -= DEFAULT_HUD_PADDING;
|
|
||||||
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
|
||||||
// Call Original Method
|
|
||||||
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
|
||||||
}
|
|
||||||
static void Gui_renderBubbles_GuiComponent_blit_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
|
||||||
Minecraft *minecraft = component->minecraft;
|
|
||||||
x_dest -= DEFAULT_HUD_PADDING;
|
|
||||||
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
|
||||||
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
|
||||||
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
|
||||||
y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT;
|
|
||||||
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING;
|
|
||||||
// Call Original Method
|
|
||||||
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional GUI Rendering
|
|
||||||
static int hide_chat_messages = 0;
|
|
||||||
bool is_in_chat = 0;
|
|
||||||
static int render_selected_item_text = 0;
|
|
||||||
static void Gui_renderChatMessages_injection(Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) {
|
|
||||||
// Handle Classic HUD
|
|
||||||
if (use_classic_hud) {
|
|
||||||
Minecraft *minecraft = gui->minecraft;
|
|
||||||
if (!Minecraft_isCreativeMode(minecraft)) {
|
|
||||||
y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
if (!hide_chat_messages && !is_in_chat) {
|
|
||||||
Gui_renderChatMessages(gui, y_offset, max_messages, disable_fading, font);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render Selected Item Text
|
|
||||||
if (render_selected_item_text) {
|
|
||||||
// Fix GL Mode
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
#endif
|
|
||||||
// Calculate Selected Item Text Scale
|
|
||||||
Minecraft *minecraft = gui->minecraft;
|
|
||||||
int32_t screen_width = minecraft->screen_width;
|
|
||||||
float scale = ((float) screen_width) * Gui_InvGuiScale;
|
|
||||||
// Render Selected Item Text
|
|
||||||
Gui_renderOnSelectItemNameText(gui, (int32_t) scale, font, y_offset - 0x13);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Reset Selected Item Text Timer On Slot Select
|
|
||||||
static uint32_t reset_selected_item_text_timer = 0;
|
|
||||||
static void Gui_tick_injection(Gui *gui) {
|
|
||||||
// Call Original Method
|
|
||||||
Gui_tick(gui);
|
|
||||||
|
|
||||||
// Handle Reset
|
|
||||||
if (render_selected_item_text) {
|
|
||||||
float *selected_item_text_timer = &gui->selected_item_text_timer;
|
|
||||||
if (reset_selected_item_text_timer) {
|
|
||||||
// Reset
|
|
||||||
*selected_item_text_timer = 0;
|
|
||||||
reset_selected_item_text_timer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Trigger Reset Selected Item Text Timer On Slot Select
|
|
||||||
static void Inventory_selectSlot_injection(Inventory *inventory, int32_t slot) {
|
|
||||||
// Call Original Method
|
|
||||||
Inventory_selectSlot(inventory, slot);
|
|
||||||
|
|
||||||
// Trigger Reset Selected Item Text Timer
|
|
||||||
if (render_selected_item_text) {
|
|
||||||
reset_selected_item_text_timer = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translucent Toolbar
|
|
||||||
static void Gui_renderToolBar_injection(Gui *gui, float param_1, int32_t param_2, int32_t param_3) {
|
|
||||||
// Call Original Method
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
int was_blend_enabled = glIsEnabled(GL_BLEND);
|
|
||||||
if (!was_blend_enabled) {
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
}
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
#endif
|
|
||||||
Gui_renderToolBar(gui, param_1, param_2, param_3);
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
if (!was_blend_enabled) {
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GLfloat blue, __attribute__((unused)) GLfloat alpha) {
|
|
||||||
// Fix Alpha
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
glColor4f(red, green, blue, 1.0f);
|
|
||||||
#else
|
|
||||||
(void) red;
|
|
||||||
(void) green;
|
|
||||||
(void) blue;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Screen Rendering When GUI is Hidden
|
|
||||||
static void Screen_render_injection(Screen *screen, int32_t param_1, int32_t param_2, float param_3) {
|
|
||||||
// Fix
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
#endif
|
|
||||||
// Call Original Method
|
|
||||||
Screen_render_non_virtual(screen, param_1, param_2, param_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanitize Username
|
|
||||||
#define MAX_USERNAME_LENGTH 16
|
|
||||||
static void LoginPacket_read_injection(LoginPacket *packet, RakNet_BitStream *bit_stream) {
|
|
||||||
// Call Original Method
|
|
||||||
LoginPacket_read_non_virtual(packet, bit_stream);
|
|
||||||
|
|
||||||
// Prepare
|
|
||||||
RakNet_RakString *rak_string = &packet->username;
|
|
||||||
// Get Original Username
|
|
||||||
RakNet_RakString_SharedString *shared_string = rak_string->sharedString;
|
|
||||||
char *c_str = shared_string->c_str;
|
|
||||||
// Sanitize
|
|
||||||
char *new_username = strdup(c_str);
|
|
||||||
ALLOC_CHECK(new_username);
|
|
||||||
sanitize_string(&new_username, MAX_USERNAME_LENGTH, 0);
|
|
||||||
// Set New Username
|
|
||||||
RakNet_RakString_Assign(rak_string, new_username);
|
|
||||||
// Free
|
|
||||||
free(new_username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix RakNet::RakString Security Bug
|
|
||||||
//
|
|
||||||
// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting,
|
|
||||||
// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the
|
|
||||||
// formatting functionality.
|
|
||||||
static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) {
|
|
||||||
// Call Original Method
|
|
||||||
return RakNet_RakString_constructor(rak_string, "%s", format);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print Error Message If RakNet Startup Fails
|
|
||||||
static char *RAKNET_ERROR_NAMES[] = {
|
|
||||||
"Success",
|
|
||||||
"Already Started",
|
|
||||||
"Invalid Socket Descriptors",
|
|
||||||
"Invalid Max Connections",
|
|
||||||
"Socket Family Not Supported",
|
|
||||||
"Part Already In Use",
|
|
||||||
"Failed To Bind Port",
|
|
||||||
"Failed Test Send",
|
|
||||||
"Port Cannot Be 0",
|
|
||||||
"Failed To Create Network Thread",
|
|
||||||
"Couldn't Generate GUID",
|
|
||||||
"Unknown"
|
|
||||||
};
|
|
||||||
#ifdef MCPI_SERVER_MODE
|
|
||||||
#define PRINT_RAKNET_STARTUP_FAILURE ERR
|
|
||||||
#else
|
|
||||||
#define PRINT_RAKNET_STARTUP_FAILURE WARN
|
|
||||||
#endif
|
|
||||||
static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) {
|
|
||||||
// Call Original Method
|
|
||||||
RakNet_StartupResult result = rak_peer->vtable->Startup(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority);
|
|
||||||
|
|
||||||
// Print Error
|
|
||||||
if (result != RAKNET_STARTED) {
|
|
||||||
PRINT_RAKNET_STARTUP_FAILURE("Failed To Start RakNet: %s", RAKNET_ERROR_NAMES[result]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
|
||||||
static RakNetInstance *RakNetInstance_injection(RakNetInstance *rak_net_instance) {
|
|
||||||
// Call Original Method
|
|
||||||
RakNetInstance *result = RakNetInstance_constructor(rak_net_instance);
|
|
||||||
// Fix
|
|
||||||
rak_net_instance->pinging_for_hosts = 0;
|
|
||||||
// Return
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close Current Screen On Death To Prevent Bugs
|
|
||||||
static void LocalPlayer_die_injection(LocalPlayer *entity, Entity *cause) {
|
|
||||||
// Close Screen
|
|
||||||
Minecraft *minecraft = entity->minecraft;
|
|
||||||
Minecraft_setScreen(minecraft, NULL);
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
LocalPlayer_die_non_virtual(entity, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
|
||||||
static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) {
|
|
||||||
// Get Existing Item
|
|
||||||
FurnaceTileEntity *tile_entity = furnace_screen->tile_entity;
|
|
||||||
ItemInstance *existing_item = tile_entity->vtable->getItem(tile_entity, slot);
|
|
||||||
|
|
||||||
// Check Item
|
|
||||||
int valid;
|
|
||||||
if (item->id == existing_item->id && item->auxiliary == existing_item->auxiliary) {
|
|
||||||
// Item Matches, Is Valid
|
|
||||||
valid = 1;
|
|
||||||
} else {
|
|
||||||
// Item Doesn't Match, Check If Existing Item Is Empty
|
|
||||||
if ((existing_item->id | existing_item->count | existing_item->auxiliary) == 0) {
|
|
||||||
// Existing Item Is Empty, Is Valid
|
|
||||||
valid = 1;
|
|
||||||
} else {
|
|
||||||
// Existing Item Isn't Empty, Isn't Valid
|
|
||||||
valid = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
if (valid) {
|
|
||||||
// Valid
|
|
||||||
return FurnaceScreen_handleAddItem(furnace_screen, slot, item);
|
|
||||||
} else {
|
|
||||||
// Invalid
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Cursor Rendering
|
|
||||||
//
|
|
||||||
// The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that.
|
|
||||||
// This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing.
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
static void GameRenderer_render_injection(GameRenderer *game_renderer, float param_1) {
|
|
||||||
// Call Original Method
|
|
||||||
GameRenderer_render(game_renderer, param_1);
|
|
||||||
|
|
||||||
// Check If Cursor Should Render
|
|
||||||
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {
|
|
||||||
// Fix GL Mode
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
// Get X And Y
|
|
||||||
float x = Mouse_getX() * Gui_InvGuiScale;
|
|
||||||
float y = Mouse_getY() * Gui_InvGuiScale;
|
|
||||||
// Render Cursor
|
|
||||||
Minecraft *minecraft = game_renderer->minecraft;
|
|
||||||
Common_renderCursor(x, y, minecraft);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Get Real Selected Slot
|
|
||||||
int32_t misc_get_real_selected_slot(Player *player) {
|
|
||||||
// Get Selected Slot
|
|
||||||
Inventory *inventory = player->inventory;
|
|
||||||
int32_t selected_slot = inventory->selectedSlot;
|
|
||||||
|
|
||||||
// Linked Slots
|
|
||||||
int32_t linked_slots_length = inventory->linked_slots_length;
|
|
||||||
if (selected_slot < linked_slots_length) {
|
|
||||||
int32_t *linked_slots = inventory->linked_slots;
|
|
||||||
selected_slot = linked_slots[selected_slot];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return selected_slot;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
// Properly Generate Buffers
|
|
||||||
static void anGenBuffers_injection(int32_t count, uint32_t *buffers) {
|
|
||||||
glGenBuffers(count, buffers);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
|
||||||
static void HumanoidMobRenderer_render_injection(HumanoidMobRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) {
|
|
||||||
HumanoidMobRenderer_render_non_virtual(model_renderer, entity, param_2, param_3, param_4, param_5, param_6);
|
|
||||||
HumanoidModel *model = model_renderer->model;
|
|
||||||
model->is_sneaking = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom API Port
|
|
||||||
HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) {
|
|
||||||
const struct sockaddr *new_addr = addr;
|
|
||||||
struct sockaddr_in in_addr;
|
|
||||||
if (addr->sa_family == AF_INET) {
|
|
||||||
in_addr = *(const struct sockaddr_in *) new_addr;
|
|
||||||
if (in_addr.sin_port == ntohs(4711)) {
|
|
||||||
const char *new_port_str = getenv("MCPI_API_PORT");
|
|
||||||
long int new_port;
|
|
||||||
if (new_port_str != NULL && (new_port = strtol(new_port_str, NULL, 0)) != 0L) {
|
|
||||||
in_addr.sin_port = htons(new_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_addr = (const struct sockaddr *) &in_addr;
|
|
||||||
}
|
|
||||||
ensure_bind();
|
|
||||||
return real_bind(sockfd, new_addr, addrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change Grass Color
|
|
||||||
static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) {
|
|
||||||
Biome *biome = level_source->vtable->getBiome(level_source, x, z);
|
|
||||||
if (biome == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return biome->color;
|
|
||||||
}
|
|
||||||
#define BIOME_BLEND_SIZE 7
|
|
||||||
static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) {
|
|
||||||
int r_sum = 0;
|
|
||||||
int g_sum = 0;
|
|
||||||
int b_sum = 0;
|
|
||||||
int color_sum = 0;
|
|
||||||
int x_start = x - (BIOME_BLEND_SIZE / 2);
|
|
||||||
int z_start = z - (BIOME_BLEND_SIZE / 2);
|
|
||||||
for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) {
|
|
||||||
for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) {
|
|
||||||
int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset);
|
|
||||||
r_sum += (color >> 16) & 0xff;
|
|
||||||
g_sum += (color >> 8) & 0xff;
|
|
||||||
b_sum += color & 0xff;
|
|
||||||
color_sum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int r_avg = r_sum / color_sum;
|
|
||||||
int g_avg = g_sum / color_sum;
|
|
||||||
int b_avg = b_sum / color_sum;
|
|
||||||
return (r_avg << 16) | (g_avg << 8) | b_avg;
|
|
||||||
}
|
|
||||||
static int32_t TallGrass_getColor_injection(TallGrass *tile, LevelSource *level_source, int32_t x, int32_t y, int32_t z) {
|
|
||||||
int32_t original_color = TallGrass_getColor_non_virtual(tile, level_source, x, y, z);
|
|
||||||
if (original_color == 0x339933) {
|
|
||||||
return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z);
|
|
||||||
} else {
|
|
||||||
return original_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate Caves
|
|
||||||
static void RandomLevelSource_buildSurface_injection(RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) {
|
|
||||||
// Call Original Method
|
|
||||||
RandomLevelSource_buildSurface(random_level_source, chunk_x, chunk_y, chunk_data, biomes);
|
|
||||||
|
|
||||||
// Get Level
|
|
||||||
Level *level = random_level_source->level;
|
|
||||||
|
|
||||||
// Get Cave Feature
|
|
||||||
LargeCaveFeature *cave_feature = &random_level_source->cave_feature;
|
|
||||||
|
|
||||||
// Generate
|
|
||||||
cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No Block Tinting
|
|
||||||
static int32_t Tile_getColor_injection() {
|
|
||||||
return 0xffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Hostile AI In Creative Mode
|
|
||||||
static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) {
|
|
||||||
// Call Original Method
|
|
||||||
Entity *target = mob->vtable->findAttackTarget(mob);
|
|
||||||
|
|
||||||
// Only modify the AI of monsters
|
|
||||||
if (mob->vtable->getCreatureBaseType(mob) != 1) {
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check If Creative Mode
|
|
||||||
if (target != NULL && target->vtable->isPlayer(target)) {
|
|
||||||
Player *player = (Player *) target;
|
|
||||||
Inventory *inventory = player->inventory;
|
|
||||||
bool is_creative = inventory->is_creative;
|
|
||||||
if (is_creative) {
|
|
||||||
target = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D Chests
|
|
||||||
static int32_t Tile_getRenderShape_injection(Tile *tile) {
|
|
||||||
if (tile == Tile_chest) {
|
|
||||||
// Don't Render "Simple" Chest Model
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
// Call Original Method
|
|
||||||
return tile->vtable->getRenderShape(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity *tile_entity) {
|
|
||||||
// Call Original Method
|
|
||||||
ChestTileEntity_constructor(tile_entity);
|
|
||||||
|
|
||||||
// Enable Renderer
|
|
||||||
tile_entity->renderer_id = 1;
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return tile_entity;
|
|
||||||
}
|
|
||||||
static bool is_rendering_chest = 0;
|
|
||||||
static void ModelPart_render_injection(ModelPart *model_part, float scale) {
|
|
||||||
// Start
|
|
||||||
is_rendering_chest = 1;
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
ModelPart_render(model_part, scale);
|
|
||||||
|
|
||||||
// Stop
|
|
||||||
is_rendering_chest = 0;
|
|
||||||
}
|
|
||||||
static void Tesselator_vertexUV_injection(Tesselator *tesselator, float x, float y, float z, float u, float v) {
|
|
||||||
// Fix Chest Texture
|
|
||||||
if (is_rendering_chest) {
|
|
||||||
v /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
Tesselator_vertexUV(tesselator, x, y, z, u, v);
|
|
||||||
}
|
|
||||||
static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Animated 3D Chest
|
|
||||||
static ContainerMenu *ContainerMenu_injection(ContainerMenu *container_menu, Container *container, int32_t param_1) {
|
|
||||||
// Call Original Method
|
|
||||||
ContainerMenu_constructor(container_menu, container, param_1);
|
|
||||||
|
|
||||||
// Play Animation
|
|
||||||
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
|
||||||
bool is_client = tile_entity->is_client;
|
|
||||||
if (!is_client) {
|
|
||||||
container->vtable->startOpen(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return container_menu;
|
|
||||||
}
|
|
||||||
static ContainerMenu *ContainerMenu_destructor_injection(ContainerMenu *container_menu) {
|
|
||||||
// Play Animation
|
|
||||||
Container *container = container_menu->container;
|
|
||||||
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
|
||||||
bool is_client = tile_entity->is_client;
|
|
||||||
if (!is_client) {
|
|
||||||
container->vtable->stopOpen(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
return ContainerMenu_destructor_complete_non_virtual(container_menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
// Custom Outline Color
|
|
||||||
static void glColor4f_injection(__attribute__((unused)) GLfloat red, __attribute__((unused)) GLfloat green, __attribute__((unused)) GLfloat blue, __attribute__((unused)) GLfloat alpha) {
|
|
||||||
// Set Color
|
|
||||||
glColor4f(0, 0, 0, 0.4);
|
|
||||||
|
|
||||||
// Find Line Width
|
|
||||||
char *custom_line_width = getenv("MCPI_BLOCK_OUTLINE_WIDTH");
|
|
||||||
float line_width;
|
|
||||||
if (custom_line_width != NULL) {
|
|
||||||
// Custom
|
|
||||||
line_width = strtof(custom_line_width, NULL);
|
|
||||||
} else {
|
|
||||||
// Guess
|
|
||||||
line_width = 2 / Gui_InvGuiScale;
|
|
||||||
}
|
|
||||||
// Clamp Line Width
|
|
||||||
float range[2];
|
|
||||||
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
|
|
||||||
if (range[1] < line_width) {
|
|
||||||
line_width = range[1];
|
|
||||||
} else if (range[0] > line_width) {
|
|
||||||
line_width = range[0];
|
|
||||||
}
|
|
||||||
// Set Line Width
|
|
||||||
glLineWidth(line_width);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fix Furnace Visual Bug
|
|
||||||
static int FurnaceTileEntity_getLitProgress_injection(FurnaceTileEntity *furnace, int max) {
|
|
||||||
// Call Original Method
|
|
||||||
int ret = FurnaceTileEntity_getLitProgress(furnace, max);
|
|
||||||
|
|
||||||
// Fix Bug
|
|
||||||
if (ret > max) {
|
|
||||||
ret = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix used items transferring durability
|
|
||||||
static int selected_slot = -1;
|
|
||||||
static void Player_startUsingItem_injection(Player *self, ItemInstance *item_instance, int time) {
|
|
||||||
selected_slot = self->inventory->selectedSlot;
|
|
||||||
Player_startUsingItem(self, item_instance, time);
|
|
||||||
}
|
|
||||||
static void Player_stopUsingItem_injection(Player *self) {
|
|
||||||
if (selected_slot != self->inventory->selectedSlot) {
|
|
||||||
self->itemBeingUsed.id = 0;
|
|
||||||
}
|
|
||||||
Player_stopUsingItem(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Java Light Ramp
|
|
||||||
static void Dimension_updateLightRamp_injection(Dimension *self) {
|
|
||||||
// https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/world/level/Dimension.cpp#L92-L105
|
|
||||||
for (int i = 0; i <= 15; i++) {
|
|
||||||
float f1 = 1.0f - (((float) i) / 15.0f);
|
|
||||||
self->light_ramp[i] = ((1.0f - f1) / (f1 * 3.0f + 1.0f)) * (1.0f - 0.1f) + 0.1f;
|
|
||||||
// Default Light Ramp:
|
|
||||||
// float fVar4 = 1.0 - ((float) i * 0.0625);
|
|
||||||
// self->light_ramp[i] = ((1.0 - fVar4) / (fVar4 * 3.0 + 1.0)) * 0.95 + 0.15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init
|
|
||||||
static void nop() {
|
|
||||||
}
|
|
||||||
void init_misc() {
|
|
||||||
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
|
|
||||||
if (feature_has("Remove Invalid Item Background", server_disabled)) {
|
|
||||||
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x63c98, invalid_item_background_patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Classic HUD
|
|
||||||
Gui_blit_renderHearts_original = Gui_blit;
|
|
||||||
if (feature_has("Classic HUD", server_disabled)) {
|
|
||||||
use_classic_hud = 1;
|
|
||||||
overwrite_call((void *) 0x26758, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
|
||||||
overwrite_call((void *) 0x2656c, (void *) Gui_renderHearts_GuiComponent_blit_armor_injection);
|
|
||||||
overwrite_call((void *) 0x268c4, (void *) Gui_renderBubbles_GuiComponent_blit_injection);
|
|
||||||
overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
|
||||||
overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
|
||||||
Gui_blit_renderHearts_original = Gui_renderHearts_GuiComponent_blit_hearts_injection;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Food overlay
|
|
||||||
if (feature_has("Food Overlay", server_disabled)) {
|
|
||||||
overwrite_calls((void *) Gui_renderHearts, Gui_renderHearts_injection);
|
|
||||||
overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_empty_injection);
|
|
||||||
overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render Selected Item Text + Hide Chat Messages
|
|
||||||
hide_chat_messages = feature_has("Hide Chat Messages", server_disabled);
|
|
||||||
render_selected_item_text = feature_has("Render Selected Item Text", server_disabled);
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Translucent Toolbar
|
|
||||||
if (feature_has("Translucent Toolbar", server_disabled)) {
|
|
||||||
overwrite_calls((void *) Gui_renderToolBar, (void *) Gui_renderToolBar_injection);
|
|
||||||
overwrite_call((void *) 0x26c5c, (void *) Gui_renderToolBar_glColor4f_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Screen Rendering When GUI is Hidden
|
|
||||||
overwrite_calls((void *) Screen_render_non_virtual, (void *) Screen_render_injection);
|
|
||||||
|
|
||||||
// Sanitize Username
|
|
||||||
patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection);
|
|
||||||
|
|
||||||
// Fix RakNet::RakString Security Bug
|
|
||||||
overwrite_calls((void *) RakNet_RakString_constructor, (void *) RakNet_RakString_injection);
|
|
||||||
|
|
||||||
// Print Error Message If RakNet Startup Fails
|
|
||||||
overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection);
|
|
||||||
|
|
||||||
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
|
||||||
overwrite_calls((void *) RakNetInstance_constructor, (void *) RakNetInstance_injection);
|
|
||||||
|
|
||||||
// Close Current Screen On Death To Prevent Bugs
|
|
||||||
if (feature_has("Close Current Screen On Death", server_disabled)) {
|
|
||||||
patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
|
||||||
if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) {
|
|
||||||
overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MCPI_HEADLESS_MODE
|
|
||||||
// Don't Render Game In Headless Mode
|
|
||||||
overwrite_calls((void *) GameRenderer_render, (void *) nop);
|
|
||||||
overwrite_calls((void *) NinecraftApp_initGLStates, (void *) nop);
|
|
||||||
overwrite_calls((void *) Gui_onConfigChanged, (void *) nop);
|
|
||||||
overwrite_calls((void *) LevelRenderer_generateSky, (void *) nop);
|
|
||||||
#else
|
|
||||||
// Improved Cursor Rendering
|
|
||||||
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
|
||||||
// Disable Normal Cursor Rendering
|
|
||||||
unsigned char disable_cursor_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x4a6c0, disable_cursor_patch);
|
|
||||||
// Add Custom Cursor Rendering
|
|
||||||
overwrite_calls((void *) GameRenderer_render, (void *) GameRenderer_render_injection);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Disable V-Sync
|
|
||||||
if (feature_has("Disable V-Sync", server_enabled)) {
|
|
||||||
media_disable_vsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force EGL
|
|
||||||
if (feature_has("Force EGL", server_disabled)) {
|
|
||||||
media_force_egl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove Forced GUI Lag
|
|
||||||
if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) {
|
|
||||||
overwrite_calls((void *) Common_sleepMs, (void *) nop);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
// Properly Generate Buffers
|
|
||||||
overwrite((void *) Common_anGenBuffers, (void *) anGenBuffers_injection);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
|
||||||
patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection);
|
|
||||||
|
|
||||||
// Disable Speed Bridging
|
|
||||||
if (feature_has("Disable Speed Bridging", server_disabled)) {
|
|
||||||
unsigned char disable_speed_bridging_patch[4] = {0x03, 0x00, 0x53, 0xe1}; // "cmp r3, r3"
|
|
||||||
patch((void *) 0x494b4, disable_speed_bridging_patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Creative Mode Mining Delay
|
|
||||||
if (feature_has("Disable Creative Mode Mining Delay", server_disabled)) {
|
|
||||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x19fa0, nop_patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change Grass Color
|
|
||||||
if (feature_has("Add Biome Colors To Grass", server_disabled)) {
|
|
||||||
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) GrassTile_getColor_injection);
|
|
||||||
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) TallGrass_getColor_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate Caves
|
|
||||||
if (feature_has("Generate Caves", server_auto)) {
|
|
||||||
overwrite_calls((void *) RandomLevelSource_buildSurface, (void *) RandomLevelSource_buildSurface_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Block Tinting
|
|
||||||
if (feature_has("Disable Block Tinting", server_disabled)) {
|
|
||||||
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
|
||||||
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
|
||||||
patch_address((void *) StemTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
|
||||||
patch_address((void *) LeafTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
|
||||||
overwrite((void *) LiquidTile_getColor_non_virtual, (void *) Tile_getColor_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom GUI Scale
|
|
||||||
const char *gui_scale_str = getenv("MCPI_GUI_SCALE");
|
|
||||||
if (gui_scale_str != NULL) {
|
|
||||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x173e8, nop_patch);
|
|
||||||
patch((void *) 0x173f0, nop_patch);
|
|
||||||
float gui_scale = strtof(gui_scale_str, NULL);
|
|
||||||
uint32_t gui_scale_raw;
|
|
||||||
memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw));
|
|
||||||
patch_address((void *) 0x17520, (void *) gui_scale_raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Hostile AI In Creative Mode
|
|
||||||
if (feature_has("Disable Hostile AI In Creative Mode", server_enabled)) {
|
|
||||||
overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D Chests
|
|
||||||
if (feature_has("3D Chest Model", server_disabled)) {
|
|
||||||
overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection);
|
|
||||||
overwrite_calls((void *) ChestTileEntity_constructor, (void *) ChestTileEntity_injection);
|
|
||||||
overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection);
|
|
||||||
overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection);
|
|
||||||
overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection);
|
|
||||||
overwrite_calls((void *) Tesselator_vertexUV, (void *) Tesselator_vertexUV_injection);
|
|
||||||
unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13"
|
|
||||||
patch((void *) 0x66fc8, chest_model_patch);
|
|
||||||
unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x66404, chest_color_patch);
|
|
||||||
|
|
||||||
// Animation
|
|
||||||
overwrite_calls((void *) ContainerMenu_constructor, (void *) ContainerMenu_injection);
|
|
||||||
overwrite_calls((void *) ContainerMenu_destructor_complete_non_virtual, (void *) ContainerMenu_destructor_injection);
|
|
||||||
}
|
|
||||||
patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection);
|
|
||||||
|
|
||||||
#ifndef MCPI_HEADLESS_MODE
|
|
||||||
// Replace Block Highlight With Outline
|
|
||||||
if (feature_has("Replace Block Highlight With Outline", server_disabled)) {
|
|
||||||
overwrite((void *) LevelRenderer_renderHitSelect, (void *) LevelRenderer_renderHitOutline);
|
|
||||||
unsigned char fix_outline_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x4d830, fix_outline_patch);
|
|
||||||
overwrite_call((void *) 0x4d764, (void *) glColor4f_injection);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fix Furnace Visual Bug
|
|
||||||
overwrite_calls((void *) FurnaceTileEntity_getLitProgress, (void *) FurnaceTileEntity_getLitProgress_injection);
|
|
||||||
|
|
||||||
// Send the full level, not only changed chunks
|
|
||||||
if (feature_has("Send Full Level When Hosting Game", server_enabled)) {
|
|
||||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
||||||
patch((void *) 0x717c4, nop_patch);
|
|
||||||
unsigned char mov_r3_ff[4] = {0xff, 0x30, 0xa0, 0xe3}; // "mov r3, #0xff"
|
|
||||||
patch((void *) 0x7178c, mov_r3_ff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Java Light Ramp
|
|
||||||
if (feature_has("Use Java Beta 1.3 Light Ramp", server_disabled)) {
|
|
||||||
overwrite((void *) Dimension_updateLightRamp_non_virtual, (void *) Dimension_updateLightRamp_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix used items transferring durability
|
|
||||||
overwrite_calls((void *) Player_startUsingItem, (void *) Player_startUsingItem_injection);
|
|
||||||
overwrite_calls((void *) Player_stopUsingItem, (void *) Player_stopUsingItem_injection);
|
|
||||||
|
|
||||||
// Fix invalid ItemInHandRenderer texture cache
|
|
||||||
if (feature_has("Disable Buggy Held Item Caching", server_disabled)) {
|
|
||||||
// This works by forcing MCPI to always use the branch that enables using the
|
|
||||||
// cache, but then patches that as well to do the opposite
|
|
||||||
uchar ensure_equal_patch[] = {0x07, 0x00, 0x57, 0xe1}; // "cmp r7, r7"
|
|
||||||
patch((void *) 0x4b938, ensure_equal_patch);
|
|
||||||
uchar set_true_patch[] = {0x01, 0x30, 0xa0, 0x03}; // "moveq r3, #0x1"
|
|
||||||
patch((void *) 0x4b93c, set_true_patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init C++ And Logging
|
|
||||||
_init_misc_cpp();
|
|
||||||
_init_misc_logging();
|
|
||||||
_init_misc_api();
|
|
||||||
}
|
|
@ -1,17 +1,636 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <cstring>
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
#include <symbols/minecraft.h>
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
#include <media-layer/core.h>
|
||||||
|
|
||||||
|
#include <mods/init/init.h>
|
||||||
#include <mods/feature/feature.h>
|
#include <mods/feature/feature.h>
|
||||||
#include "misc-internal.h"
|
#include "misc-internal.h"
|
||||||
#include <mods/misc/misc.h>
|
#include <mods/misc/misc.h>
|
||||||
|
|
||||||
|
// Heart food overlay
|
||||||
|
static int heal_amount = 0, heal_amount_drawing = 0;
|
||||||
|
void Gui_renderHearts_injection(Gui *gui) {
|
||||||
|
// Get heal_amount
|
||||||
|
heal_amount = heal_amount_drawing = 0;
|
||||||
|
|
||||||
|
Inventory *inventory = gui->minecraft->player->inventory;
|
||||||
|
ItemInstance *held_ii = Inventory_getSelected(inventory);
|
||||||
|
if (held_ii) {
|
||||||
|
Item *held = Item_items[held_ii->id];
|
||||||
|
if (held->vtable->isFood(held) && held_ii->id) {
|
||||||
|
int nutrition = ((FoodItem *) held)->nutrition;
|
||||||
|
int cur_health = gui->minecraft->player->health;
|
||||||
|
int heal_num = fmin(cur_health + nutrition, 20) - cur_health;
|
||||||
|
heal_amount = heal_amount_drawing = heal_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call original
|
||||||
|
Gui_renderHearts(gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PINK_HEART_FULL 70
|
||||||
|
#define PINK_HEART_HALF 79
|
||||||
|
Gui_blit_t Gui_blit_renderHearts_original = nullptr;
|
||||||
|
void Gui_renderHearts_GuiComponent_blit_overlay_empty_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) {
|
||||||
|
// Call original
|
||||||
|
Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
||||||
|
// Render the overlay
|
||||||
|
if (heal_amount_drawing == 1) {
|
||||||
|
// Half heart
|
||||||
|
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_HALF, 0, w1, h1, w2, h2);
|
||||||
|
heal_amount_drawing = 0;
|
||||||
|
} else if (heal_amount_drawing > 0) {
|
||||||
|
// Full heart
|
||||||
|
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
||||||
|
heal_amount_drawing -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection(Gui *gui, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t w1, int32_t h1, int32_t w2, int32_t h2) {
|
||||||
|
// Offset the overlay
|
||||||
|
if (x2 == 52) {
|
||||||
|
heal_amount_drawing += 2;
|
||||||
|
} else if (x2 == 61 && heal_amount) {
|
||||||
|
// Half heart, flipped
|
||||||
|
Gui_blit_renderHearts_original(gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
||||||
|
heal_amount_drawing += 1;
|
||||||
|
};
|
||||||
|
// Call original
|
||||||
|
Gui_blit_renderHearts_original(gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
||||||
|
heal_amount_drawing = fmin(heal_amount_drawing, heal_amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classic HUD
|
||||||
|
#define DEFAULT_HUD_PADDING 2
|
||||||
|
#define NEW_HUD_PADDING 1
|
||||||
|
#define HUD_ELEMENT_WIDTH 82
|
||||||
|
#define HUD_ELEMENT_HEIGHT 9
|
||||||
|
#define TOOLBAR_HEIGHT 22
|
||||||
|
#define SLOT_WIDTH 20
|
||||||
|
#define DEFAULT_BUBBLES_PADDING 1
|
||||||
|
#define NUMBER_OF_SLOTS 9
|
||||||
|
static int use_classic_hud = 0;
|
||||||
|
static void Gui_renderHearts_GuiComponent_blit_hearts_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
||||||
|
Minecraft *minecraft = component->minecraft;
|
||||||
|
x_dest -= DEFAULT_HUD_PADDING;
|
||||||
|
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
||||||
|
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
||||||
|
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
||||||
|
y_dest -= DEFAULT_HUD_PADDING;
|
||||||
|
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
||||||
|
// Call Original Method
|
||||||
|
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
||||||
|
}
|
||||||
|
static void Gui_renderHearts_GuiComponent_blit_armor_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
||||||
|
Minecraft *minecraft = component->minecraft;
|
||||||
|
x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH;
|
||||||
|
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
||||||
|
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
||||||
|
x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH;
|
||||||
|
y_dest -= DEFAULT_HUD_PADDING;
|
||||||
|
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
||||||
|
// Call Original Method
|
||||||
|
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
||||||
|
}
|
||||||
|
static void Gui_renderBubbles_GuiComponent_blit_injection(Gui *component, int32_t x_dest, int32_t y_dest, int32_t x_src, int32_t y_src, int32_t width_dest, int32_t height_dest, int32_t width_src, int32_t height_src) {
|
||||||
|
Minecraft *minecraft = component->minecraft;
|
||||||
|
x_dest -= DEFAULT_HUD_PADDING;
|
||||||
|
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
|
||||||
|
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
|
||||||
|
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
||||||
|
y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT;
|
||||||
|
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING;
|
||||||
|
// Call Original Method
|
||||||
|
Gui_blit(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional GUI Rendering
|
||||||
|
static int hide_chat_messages = 0;
|
||||||
|
bool is_in_chat = 0;
|
||||||
|
static int render_selected_item_text = 0;
|
||||||
|
static void Gui_renderChatMessages_injection(Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) {
|
||||||
|
// Handle Classic HUD
|
||||||
|
if (use_classic_hud) {
|
||||||
|
Minecraft *minecraft = gui->minecraft;
|
||||||
|
if (!Minecraft_isCreativeMode(minecraft)) {
|
||||||
|
y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
if (!hide_chat_messages && !is_in_chat) {
|
||||||
|
Gui_renderChatMessages(gui, y_offset, max_messages, disable_fading, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Selected Item Text
|
||||||
|
if (render_selected_item_text) {
|
||||||
|
// Fix GL Mode
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
#endif
|
||||||
|
// Calculate Selected Item Text Scale
|
||||||
|
Minecraft *minecraft = gui->minecraft;
|
||||||
|
int32_t screen_width = minecraft->screen_width;
|
||||||
|
float scale = ((float) screen_width) * Gui_InvGuiScale;
|
||||||
|
// Render Selected Item Text
|
||||||
|
Gui_renderOnSelectItemNameText(gui, (int32_t) scale, font, y_offset - 0x13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reset Selected Item Text Timer On Slot Select
|
||||||
|
static uint32_t reset_selected_item_text_timer = 0;
|
||||||
|
static void Gui_tick_injection(Gui *gui) {
|
||||||
|
// Call Original Method
|
||||||
|
Gui_tick(gui);
|
||||||
|
|
||||||
|
// Handle Reset
|
||||||
|
if (render_selected_item_text) {
|
||||||
|
float *selected_item_text_timer = &gui->selected_item_text_timer;
|
||||||
|
if (reset_selected_item_text_timer) {
|
||||||
|
// Reset
|
||||||
|
*selected_item_text_timer = 0;
|
||||||
|
reset_selected_item_text_timer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Trigger Reset Selected Item Text Timer On Slot Select
|
||||||
|
static void Inventory_selectSlot_injection(Inventory *inventory, int32_t slot) {
|
||||||
|
// Call Original Method
|
||||||
|
Inventory_selectSlot(inventory, slot);
|
||||||
|
|
||||||
|
// Trigger Reset Selected Item Text Timer
|
||||||
|
if (render_selected_item_text) {
|
||||||
|
reset_selected_item_text_timer = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translucent Toolbar
|
||||||
|
static void Gui_renderToolBar_injection(Gui *gui, float param_1, int32_t param_2, int32_t param_3) {
|
||||||
|
// Call Original Method
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
int was_blend_enabled = glIsEnabled(GL_BLEND);
|
||||||
|
if (!was_blend_enabled) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
}
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
#endif
|
||||||
|
Gui_renderToolBar(gui, param_1, param_2, param_3);
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
if (!was_blend_enabled) {
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GLfloat blue, __attribute__((unused)) GLfloat alpha) {
|
||||||
|
// Fix Alpha
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
glColor4f(red, green, blue, 1.0f);
|
||||||
|
#else
|
||||||
|
(void) red;
|
||||||
|
(void) green;
|
||||||
|
(void) blue;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Screen Rendering When GUI is Hidden
|
||||||
|
static void Screen_render_injection(Screen *screen, int32_t param_1, int32_t param_2, float param_3) {
|
||||||
|
// Fix
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
#endif
|
||||||
|
// Call Original Method
|
||||||
|
Screen_render_non_virtual(screen, param_1, param_2, param_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize Username
|
||||||
|
#define MAX_USERNAME_LENGTH 16
|
||||||
|
static void LoginPacket_read_injection(LoginPacket *packet, RakNet_BitStream *bit_stream) {
|
||||||
|
// Call Original Method
|
||||||
|
LoginPacket_read_non_virtual(packet, bit_stream);
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
RakNet_RakString *rak_string = &packet->username;
|
||||||
|
// Get Original Username
|
||||||
|
RakNet_RakString_SharedString *shared_string = rak_string->sharedString;
|
||||||
|
char *c_str = shared_string->c_str;
|
||||||
|
// Sanitize
|
||||||
|
char *new_username = strdup(c_str);
|
||||||
|
ALLOC_CHECK(new_username);
|
||||||
|
sanitize_string(&new_username, MAX_USERNAME_LENGTH, 0);
|
||||||
|
// Set New Username
|
||||||
|
RakNet_RakString_Assign(rak_string, new_username);
|
||||||
|
// Free
|
||||||
|
free(new_username);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix RakNet::RakString Security Bug
|
||||||
|
//
|
||||||
|
// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting,
|
||||||
|
// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the
|
||||||
|
// formatting functionality.
|
||||||
|
static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) {
|
||||||
|
// Call Original Method
|
||||||
|
return RakNet_RakString_constructor(rak_string, "%s", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print Error Message If RakNet Startup Fails
|
||||||
|
static const char *RAKNET_ERROR_NAMES[] = {
|
||||||
|
"Success",
|
||||||
|
"Already Started",
|
||||||
|
"Invalid Socket Descriptors",
|
||||||
|
"Invalid Max Connections",
|
||||||
|
"Socket Family Not Supported",
|
||||||
|
"Part Already In Use",
|
||||||
|
"Failed To Bind Port",
|
||||||
|
"Failed Test Send",
|
||||||
|
"Port Cannot Be 0",
|
||||||
|
"Failed To Create Network Thread",
|
||||||
|
"Couldn't Generate GUID",
|
||||||
|
"Unknown"
|
||||||
|
};
|
||||||
|
#ifdef MCPI_SERVER_MODE
|
||||||
|
#define PRINT_RAKNET_STARTUP_FAILURE ERR
|
||||||
|
#else
|
||||||
|
#define PRINT_RAKNET_STARTUP_FAILURE WARN
|
||||||
|
#endif
|
||||||
|
static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) {
|
||||||
|
// Call Original Method
|
||||||
|
RakNet_StartupResult result = rak_peer->vtable->Startup(rak_peer, maxConnections, socketDescriptors, socketDescriptorCount, threadPriority);
|
||||||
|
|
||||||
|
// Print Error
|
||||||
|
if (result != RAKNET_STARTED) {
|
||||||
|
PRINT_RAKNET_STARTUP_FAILURE("Failed To Start RakNet: %s", RAKNET_ERROR_NAMES[result]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||||
|
static RakNetInstance *RakNetInstance_injection(RakNetInstance *rak_net_instance) {
|
||||||
|
// Call Original Method
|
||||||
|
RakNetInstance *result = RakNetInstance_constructor(rak_net_instance);
|
||||||
|
// Fix
|
||||||
|
rak_net_instance->pinging_for_hosts = 0;
|
||||||
|
// Return
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close Current Screen On Death To Prevent Bugs
|
||||||
|
static void LocalPlayer_die_injection(LocalPlayer *entity, Entity *cause) {
|
||||||
|
// Close Screen
|
||||||
|
Minecraft *minecraft = entity->minecraft;
|
||||||
|
Minecraft_setScreen(minecraft, nullptr);
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
LocalPlayer_die_non_virtual(entity, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
||||||
|
static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) {
|
||||||
|
// Get Existing Item
|
||||||
|
FurnaceTileEntity *tile_entity = furnace_screen->tile_entity;
|
||||||
|
ItemInstance *existing_item = tile_entity->vtable->getItem(tile_entity, slot);
|
||||||
|
|
||||||
|
// Check Item
|
||||||
|
int valid;
|
||||||
|
if (item->id == existing_item->id && item->auxiliary == existing_item->auxiliary) {
|
||||||
|
// Item Matches, Is Valid
|
||||||
|
valid = 1;
|
||||||
|
} else {
|
||||||
|
// Item Doesn't Match, Check If Existing Item Is Empty
|
||||||
|
if ((existing_item->id | existing_item->count | existing_item->auxiliary) == 0) {
|
||||||
|
// Existing Item Is Empty, Is Valid
|
||||||
|
valid = 1;
|
||||||
|
} else {
|
||||||
|
// Existing Item Isn't Empty, Isn't Valid
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
if (valid) {
|
||||||
|
// Valid
|
||||||
|
return FurnaceScreen_handleAddItem(furnace_screen, slot, item);
|
||||||
|
} else {
|
||||||
|
// Invalid
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom Cursor Rendering
|
||||||
|
//
|
||||||
|
// The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that.
|
||||||
|
// This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing.
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
static void GameRenderer_render_injection(GameRenderer *game_renderer, float param_1) {
|
||||||
|
// Call Original Method
|
||||||
|
GameRenderer_render(game_renderer, param_1);
|
||||||
|
|
||||||
|
// Check If Cursor Should Render
|
||||||
|
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {
|
||||||
|
// Fix GL Mode
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
// Get X And Y
|
||||||
|
float x = Mouse_getX() * Gui_InvGuiScale;
|
||||||
|
float y = Mouse_getY() * Gui_InvGuiScale;
|
||||||
|
// Render Cursor
|
||||||
|
Minecraft *minecraft = game_renderer->minecraft;
|
||||||
|
Common_renderCursor(x, y, minecraft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get Real Selected Slot
|
||||||
|
int32_t misc_get_real_selected_slot(Player *player) {
|
||||||
|
// Get Selected Slot
|
||||||
|
Inventory *inventory = player->inventory;
|
||||||
|
int32_t selected_slot = inventory->selectedSlot;
|
||||||
|
|
||||||
|
// Linked Slots
|
||||||
|
int32_t linked_slots_length = inventory->linked_slots_length;
|
||||||
|
if (selected_slot < linked_slots_length) {
|
||||||
|
int32_t *linked_slots = inventory->linked_slots;
|
||||||
|
selected_slot = linked_slots[selected_slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return selected_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
// Properly Generate Buffers
|
||||||
|
static void anGenBuffers_injection(int32_t count, uint32_t *buffers) {
|
||||||
|
glGenBuffers(count, buffers);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||||
|
static void HumanoidMobRenderer_render_injection(HumanoidMobRenderer *model_renderer, Entity *entity, float param_2, float param_3, float param_4, float param_5, float param_6) {
|
||||||
|
HumanoidMobRenderer_render_non_virtual(model_renderer, entity, param_2, param_3, param_4, param_5, param_6);
|
||||||
|
HumanoidModel *model = model_renderer->model;
|
||||||
|
model->is_sneaking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom API Port
|
||||||
|
HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) {
|
||||||
|
const sockaddr *new_addr = addr;
|
||||||
|
sockaddr_in in_addr = {};
|
||||||
|
if (addr->sa_family == AF_INET) {
|
||||||
|
in_addr = *(const struct sockaddr_in *) new_addr;
|
||||||
|
if (in_addr.sin_port == ntohs(4711)) {
|
||||||
|
const char *new_port_str = getenv("MCPI_API_PORT");
|
||||||
|
long int new_port;
|
||||||
|
if (new_port_str != nullptr && (new_port = strtol(new_port_str, nullptr, 0)) != 0L) {
|
||||||
|
in_addr.sin_port = htons(new_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_addr = (const struct sockaddr *) &in_addr;
|
||||||
|
}
|
||||||
|
ensure_bind();
|
||||||
|
return real_bind(sockfd, new_addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change Grass Color
|
||||||
|
static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) {
|
||||||
|
Biome *biome = level_source->vtable->getBiome(level_source, x, z);
|
||||||
|
if (biome == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return biome->color;
|
||||||
|
}
|
||||||
|
#define BIOME_BLEND_SIZE 7
|
||||||
|
static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) {
|
||||||
|
int r_sum = 0;
|
||||||
|
int g_sum = 0;
|
||||||
|
int b_sum = 0;
|
||||||
|
int color_sum = 0;
|
||||||
|
int x_start = x - (BIOME_BLEND_SIZE / 2);
|
||||||
|
int z_start = z - (BIOME_BLEND_SIZE / 2);
|
||||||
|
for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) {
|
||||||
|
for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) {
|
||||||
|
int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset);
|
||||||
|
r_sum += (color >> 16) & 0xff;
|
||||||
|
g_sum += (color >> 8) & 0xff;
|
||||||
|
b_sum += color & 0xff;
|
||||||
|
color_sum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int r_avg = r_sum / color_sum;
|
||||||
|
int g_avg = g_sum / color_sum;
|
||||||
|
int b_avg = b_sum / color_sum;
|
||||||
|
return (r_avg << 16) | (g_avg << 8) | b_avg;
|
||||||
|
}
|
||||||
|
static int32_t TallGrass_getColor_injection(TallGrass *tile, LevelSource *level_source, int32_t x, int32_t y, int32_t z) {
|
||||||
|
int32_t original_color = TallGrass_getColor_non_virtual(tile, level_source, x, y, z);
|
||||||
|
if (original_color == 0x339933) {
|
||||||
|
return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z);
|
||||||
|
} else {
|
||||||
|
return original_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Caves
|
||||||
|
static void RandomLevelSource_buildSurface_injection(RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) {
|
||||||
|
// Call Original Method
|
||||||
|
RandomLevelSource_buildSurface(random_level_source, chunk_x, chunk_y, chunk_data, biomes);
|
||||||
|
|
||||||
|
// Get Level
|
||||||
|
Level *level = random_level_source->level;
|
||||||
|
|
||||||
|
// Get Cave Feature
|
||||||
|
LargeCaveFeature *cave_feature = &random_level_source->cave_feature;
|
||||||
|
|
||||||
|
// Generate
|
||||||
|
cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No Block Tinting
|
||||||
|
static int32_t Tile_getColor_injection() {
|
||||||
|
return 0xffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable Hostile AI In Creative Mode
|
||||||
|
static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) {
|
||||||
|
// Call Original Method
|
||||||
|
Entity *target = mob->vtable->findAttackTarget(mob);
|
||||||
|
|
||||||
|
// Only modify the AI of monsters
|
||||||
|
if (mob->vtable->getCreatureBaseType(mob) != 1) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check If Creative Mode
|
||||||
|
if (target != nullptr && target->vtable->isPlayer(target)) {
|
||||||
|
Player *player = (Player *) target;
|
||||||
|
Inventory *inventory = player->inventory;
|
||||||
|
bool is_creative = inventory->is_creative;
|
||||||
|
if (is_creative) {
|
||||||
|
target = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D Chests
|
||||||
|
static int32_t Tile_getRenderShape_injection(Tile *tile) {
|
||||||
|
if (tile == Tile_chest) {
|
||||||
|
// Don't Render "Simple" Chest Model
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
// Call Original Method
|
||||||
|
return tile->vtable->getRenderShape(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity *tile_entity) {
|
||||||
|
// Call Original Method
|
||||||
|
ChestTileEntity_constructor(tile_entity);
|
||||||
|
|
||||||
|
// Enable Renderer
|
||||||
|
tile_entity->renderer_id = 1;
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return tile_entity;
|
||||||
|
}
|
||||||
|
static bool is_rendering_chest = false;
|
||||||
|
static void ModelPart_render_injection(ModelPart *model_part, float scale) {
|
||||||
|
// Start
|
||||||
|
is_rendering_chest = true;
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
ModelPart_render(model_part, scale);
|
||||||
|
|
||||||
|
// Stop
|
||||||
|
is_rendering_chest = false;
|
||||||
|
}
|
||||||
|
static void Tesselator_vertexUV_injection(Tesselator *tesselator, float x, float y, float z, float u, float v) {
|
||||||
|
// Fix Chest Texture
|
||||||
|
if (is_rendering_chest) {
|
||||||
|
v /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
Tesselator_vertexUV(tesselator, x, y, z, u, v);
|
||||||
|
}
|
||||||
|
static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animated 3D Chest
|
||||||
|
static ContainerMenu *ContainerMenu_injection(ContainerMenu *container_menu, Container *container, int32_t param_1) {
|
||||||
|
// Call Original Method
|
||||||
|
ContainerMenu_constructor(container_menu, container, param_1);
|
||||||
|
|
||||||
|
// Play Animation
|
||||||
|
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
||||||
|
bool is_client = tile_entity->is_client;
|
||||||
|
if (!is_client) {
|
||||||
|
container->vtable->startOpen(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return container_menu;
|
||||||
|
}
|
||||||
|
static ContainerMenu *ContainerMenu_destructor_injection(ContainerMenu *container_menu) {
|
||||||
|
// Play Animation
|
||||||
|
Container *container = container_menu->container;
|
||||||
|
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
||||||
|
bool is_client = tile_entity->is_client;
|
||||||
|
if (!is_client) {
|
||||||
|
container->vtable->stopOpen(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
return ContainerMenu_destructor_complete_non_virtual(container_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
// Custom Outline Color
|
||||||
|
static void glColor4f_injection(__attribute__((unused)) GLfloat red, __attribute__((unused)) GLfloat green, __attribute__((unused)) GLfloat blue, __attribute__((unused)) GLfloat alpha) {
|
||||||
|
// Set Color
|
||||||
|
glColor4f(0, 0, 0, 0.4);
|
||||||
|
|
||||||
|
// Find Line Width
|
||||||
|
char *custom_line_width = getenv("MCPI_BLOCK_OUTLINE_WIDTH");
|
||||||
|
float line_width;
|
||||||
|
if (custom_line_width != nullptr) {
|
||||||
|
// Custom
|
||||||
|
line_width = strtof(custom_line_width, nullptr);
|
||||||
|
} else {
|
||||||
|
// Guess
|
||||||
|
line_width = 2 / Gui_InvGuiScale;
|
||||||
|
}
|
||||||
|
// Clamp Line Width
|
||||||
|
float range[2];
|
||||||
|
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
|
||||||
|
if (range[1] < line_width) {
|
||||||
|
line_width = range[1];
|
||||||
|
} else if (range[0] > line_width) {
|
||||||
|
line_width = range[0];
|
||||||
|
}
|
||||||
|
// Set Line Width
|
||||||
|
glLineWidth(line_width);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fix Furnace Visual Bug
|
||||||
|
static int FurnaceTileEntity_getLitProgress_injection(FurnaceTileEntity *furnace, int max) {
|
||||||
|
// Call Original Method
|
||||||
|
int ret = FurnaceTileEntity_getLitProgress(furnace, max);
|
||||||
|
|
||||||
|
// Fix Bug
|
||||||
|
if (ret > max) {
|
||||||
|
ret = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix used items transferring durability
|
||||||
|
static int selected_slot = -1;
|
||||||
|
static void Player_startUsingItem_injection(Player *self, ItemInstance *item_instance, int time) {
|
||||||
|
selected_slot = self->inventory->selectedSlot;
|
||||||
|
Player_startUsingItem(self, item_instance, time);
|
||||||
|
}
|
||||||
|
static void Player_stopUsingItem_injection(Player *self) {
|
||||||
|
if (selected_slot != self->inventory->selectedSlot) {
|
||||||
|
self->itemBeingUsed.id = 0;
|
||||||
|
}
|
||||||
|
Player_stopUsingItem(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Java Light Ramp
|
||||||
|
static void Dimension_updateLightRamp_injection(Dimension *self) {
|
||||||
|
// https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/world/level/Dimension.cpp#L92-L105
|
||||||
|
for (int i = 0; i <= 15; i++) {
|
||||||
|
float f1 = 1.0f - (((float) i) / 15.0f);
|
||||||
|
self->light_ramp[i] = ((1.0f - f1) / (f1 * 3.0f + 1.0f)) * (1.0f - 0.1f) + 0.1f;
|
||||||
|
// Default Light Ramp:
|
||||||
|
// float fVar4 = 1.0 - ((float) i * 0.0625);
|
||||||
|
// self->light_ramp[i] = ((1.0 - fVar4) / (fVar4 * 3.0 + 1.0)) * 0.95 + 0.15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Read Asset File
|
// Read Asset File
|
||||||
static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) AppPlatform *app_platform, std::string const& path) {
|
static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) AppPlatform *app_platform, std::string const& path) {
|
||||||
// Open File
|
// Open File
|
||||||
@ -20,13 +639,14 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio
|
|||||||
// Does Not Exist
|
// Does Not Exist
|
||||||
AppPlatform_readAssetFile_return_value ret;
|
AppPlatform_readAssetFile_return_value ret;
|
||||||
ret.length = -1;
|
ret.length = -1;
|
||||||
ret.data = NULL;
|
ret.data = nullptr;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// Read File
|
// Read File
|
||||||
long len = stream.tellg();
|
std::streamoff len = stream.tellg();
|
||||||
char *buf = new char[len];
|
char *buf = new char[len];
|
||||||
stream.seekg(0, stream.beg);
|
ALLOC_CHECK(buf);
|
||||||
|
stream.seekg(0, std::ifstream::beg);
|
||||||
stream.read(buf, len);
|
stream.read(buf, len);
|
||||||
stream.close();
|
stream.close();
|
||||||
// Return String
|
// Return String
|
||||||
@ -44,7 +664,7 @@ static void PauseScreen_init_injection(PauseScreen *screen) {
|
|||||||
// Check If Server
|
// Check If Server
|
||||||
Minecraft *minecraft = screen->minecraft;
|
Minecraft *minecraft = screen->minecraft;
|
||||||
RakNetInstance *rak_net_instance = minecraft->rak_net_instance;
|
RakNetInstance *rak_net_instance = minecraft->rak_net_instance;
|
||||||
if (rak_net_instance != NULL) {
|
if (rak_net_instance != nullptr) {
|
||||||
if (rak_net_instance->vtable->isServer(rak_net_instance)) {
|
if (rak_net_instance->vtable->isServer(rak_net_instance)) {
|
||||||
// Add Button
|
// Add Button
|
||||||
std::vector<Button *> *rendered_buttons = &screen->rendered_buttons;
|
std::vector<Button *> *rendered_buttons = &screen->rendered_buttons;
|
||||||
@ -67,7 +687,7 @@ void PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_inje
|
|||||||
ItemInstance requested_item_instance = item->ingredients[i].requested_item;
|
ItemInstance requested_item_instance = item->ingredients[i].requested_item;
|
||||||
Item *requested_item = Item_items[requested_item_instance.id];
|
Item *requested_item = Item_items[requested_item_instance.id];
|
||||||
ItemInstance *craftingRemainingItem = requested_item->vtable->getCraftingRemainingItem(requested_item, &requested_item_instance);
|
ItemInstance *craftingRemainingItem = requested_item->vtable->getCraftingRemainingItem(requested_item, &requested_item_instance);
|
||||||
if (craftingRemainingItem != NULL) {
|
if (craftingRemainingItem != nullptr) {
|
||||||
// Add or drop remainder
|
// Add or drop remainder
|
||||||
LocalPlayer *player = self->minecraft->player;
|
LocalPlayer *player = self->minecraft->player;
|
||||||
if (!player->inventory->vtable->add(player->inventory, craftingRemainingItem)) {
|
if (!player->inventory->vtable->add(player->inventory, craftingRemainingItem)) {
|
||||||
@ -81,14 +701,14 @@ void PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_inje
|
|||||||
}
|
}
|
||||||
|
|
||||||
ItemInstance *Item_getCraftingRemainingItem_injection(Item *self, ItemInstance *item_instance) {
|
ItemInstance *Item_getCraftingRemainingItem_injection(Item *self, ItemInstance *item_instance) {
|
||||||
if (self->craftingRemainingItem != NULL) {
|
if (self->craftingRemainingItem != nullptr) {
|
||||||
ItemInstance *ret = alloc_ItemInstance();
|
ItemInstance *ret = alloc_ItemInstance();
|
||||||
ret->id = self->craftingRemainingItem->id;
|
ret->id = self->craftingRemainingItem->id;
|
||||||
ret->count = item_instance->count;
|
ret->count = item_instance->count;
|
||||||
ret->auxiliary = 0;
|
ret->auxiliary = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort Chunks
|
// Sort Chunks
|
||||||
@ -108,7 +728,7 @@ static void sort_chunks(Chunk **chunks_begin, Chunk **chunks_end, DistanceChunkS
|
|||||||
Chunk *chunk = chunks_begin[i];
|
Chunk *chunk = chunks_begin[i];
|
||||||
float distance = Chunk_distanceToSqr(chunk, (Entity *) sorter.mob);
|
float distance = Chunk_distanceToSqr(chunk, (Entity *) sorter.mob);
|
||||||
if ((1024.0 <= distance) && chunk->y < 0x40) {
|
if ((1024.0 <= distance) && chunk->y < 0x40) {
|
||||||
distance = distance * 10.0;
|
distance *= 10.0;
|
||||||
}
|
}
|
||||||
data[i].chunk = chunk;
|
data[i].chunk = chunk;
|
||||||
data[i].distance = distance;
|
data[i].distance = distance;
|
||||||
@ -127,7 +747,7 @@ static void sort_chunks(Chunk **chunks_begin, Chunk **chunks_end, DistanceChunkS
|
|||||||
static std::string AppPlatform_linux_getDateString_injection(__attribute__((unused)) AppPlatform_linux *app_platform, int time) {
|
static std::string AppPlatform_linux_getDateString_injection(__attribute__((unused)) AppPlatform_linux *app_platform, int time) {
|
||||||
// From https://github.com/ReMinecraftPE/mcpe/blob/56e51027b1c2e67fe5a0e8a091cefe51d4d11926/platforms/sdl/base/AppPlatform_sdl_base.cpp#L68-L84
|
// From https://github.com/ReMinecraftPE/mcpe/blob/56e51027b1c2e67fe5a0e8a091cefe51d4d11926/platforms/sdl/base/AppPlatform_sdl_base.cpp#L68-L84
|
||||||
time_t tt = time;
|
time_t tt = time;
|
||||||
struct tm t;
|
tm t = {};
|
||||||
gmtime_r(&tt, &t);
|
gmtime_r(&tt, &t);
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
strftime(buf, sizeof buf, "%b %d %Y %H:%M:%S", &t);
|
strftime(buf, sizeof buf, "%b %d %Y %H:%M:%S", &t);
|
||||||
@ -135,7 +755,220 @@ static std::string AppPlatform_linux_getDateString_injection(__attribute__((unus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
void _init_misc_cpp() {
|
static void nop() {
|
||||||
|
}
|
||||||
|
void init_misc() {
|
||||||
|
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
|
||||||
|
if (feature_has("Remove Invalid Item Background", server_disabled)) {
|
||||||
|
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x63c98, invalid_item_background_patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classic HUD
|
||||||
|
Gui_blit_renderHearts_original = Gui_blit;
|
||||||
|
if (feature_has("Classic HUD", server_disabled)) {
|
||||||
|
use_classic_hud = 1;
|
||||||
|
overwrite_call((void *) 0x26758, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
||||||
|
overwrite_call((void *) 0x2656c, (void *) Gui_renderHearts_GuiComponent_blit_armor_injection);
|
||||||
|
overwrite_call((void *) 0x268c4, (void *) Gui_renderBubbles_GuiComponent_blit_injection);
|
||||||
|
overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
||||||
|
overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
|
||||||
|
Gui_blit_renderHearts_original = Gui_renderHearts_GuiComponent_blit_hearts_injection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Food overlay
|
||||||
|
if (feature_has("Food Overlay", server_disabled)) {
|
||||||
|
overwrite_calls((void *) Gui_renderHearts, (void *) Gui_renderHearts_injection);
|
||||||
|
overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_empty_injection);
|
||||||
|
overwrite_call((void *) 0x267c8, (void *) Gui_renderHearts_GuiComponent_blit_overlay_hearts_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Selected Item Text + Hide Chat Messages
|
||||||
|
hide_chat_messages = feature_has("Hide Chat Messages", server_disabled);
|
||||||
|
render_selected_item_text = feature_has("Render Selected Item Text", server_disabled);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Translucent Toolbar
|
||||||
|
if (feature_has("Translucent Toolbar", server_disabled)) {
|
||||||
|
overwrite_calls((void *) Gui_renderToolBar, (void *) Gui_renderToolBar_injection);
|
||||||
|
overwrite_call((void *) 0x26c5c, (void *) Gui_renderToolBar_glColor4f_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Screen Rendering When GUI is Hidden
|
||||||
|
overwrite_calls((void *) Screen_render_non_virtual, (void *) Screen_render_injection);
|
||||||
|
|
||||||
|
// Sanitize Username
|
||||||
|
patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection);
|
||||||
|
|
||||||
|
// Fix RakNet::RakString Security Bug
|
||||||
|
overwrite_calls((void *) RakNet_RakString_constructor, (void *) RakNet_RakString_injection);
|
||||||
|
|
||||||
|
// Print Error Message If RakNet Startup Fails
|
||||||
|
overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection);
|
||||||
|
|
||||||
|
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||||
|
overwrite_calls((void *) RakNetInstance_constructor, (void *) RakNetInstance_injection);
|
||||||
|
|
||||||
|
// Close Current Screen On Death To Prevent Bugs
|
||||||
|
if (feature_has("Close Current Screen On Death", server_disabled)) {
|
||||||
|
patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
||||||
|
if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) {
|
||||||
|
overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MCPI_HEADLESS_MODE
|
||||||
|
// Don't Render Game In Headless Mode
|
||||||
|
overwrite_calls((void *) GameRenderer_render, (void *) nop);
|
||||||
|
overwrite_calls((void *) NinecraftApp_initGLStates, (void *) nop);
|
||||||
|
overwrite_calls((void *) Gui_onConfigChanged, (void *) nop);
|
||||||
|
overwrite_calls((void *) LevelRenderer_generateSky, (void *) nop);
|
||||||
|
#else
|
||||||
|
// Improved Cursor Rendering
|
||||||
|
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
||||||
|
// Disable Normal Cursor Rendering
|
||||||
|
unsigned char disable_cursor_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x4a6c0, disable_cursor_patch);
|
||||||
|
// Add Custom Cursor Rendering
|
||||||
|
overwrite_calls((void *) GameRenderer_render, (void *) GameRenderer_render_injection);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Disable V-Sync
|
||||||
|
if (feature_has("Disable V-Sync", server_enabled)) {
|
||||||
|
media_disable_vsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force EGL
|
||||||
|
if (feature_has("Force EGL", server_disabled)) {
|
||||||
|
media_force_egl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove Forced GUI Lag
|
||||||
|
if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) {
|
||||||
|
overwrite_calls((void *) Common_sleepMs, (void *) nop);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
// Properly Generate Buffers
|
||||||
|
overwrite((void *) Common_anGenBuffers, (void *) anGenBuffers_injection);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||||
|
patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection);
|
||||||
|
|
||||||
|
// Disable Speed Bridging
|
||||||
|
if (feature_has("Disable Speed Bridging", server_disabled)) {
|
||||||
|
unsigned char disable_speed_bridging_patch[4] = {0x03, 0x00, 0x53, 0xe1}; // "cmp r3, r3"
|
||||||
|
patch((void *) 0x494b4, disable_speed_bridging_patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable Creative Mode Mining Delay
|
||||||
|
if (feature_has("Disable Creative Mode Mining Delay", server_disabled)) {
|
||||||
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x19fa0, nop_patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change Grass Color
|
||||||
|
if (feature_has("Add Biome Colors To Grass", server_disabled)) {
|
||||||
|
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) GrassTile_getColor_injection);
|
||||||
|
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) TallGrass_getColor_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Caves
|
||||||
|
if (feature_has("Generate Caves", server_auto)) {
|
||||||
|
overwrite_calls((void *) RandomLevelSource_buildSurface, (void *) RandomLevelSource_buildSurface_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable Block Tinting
|
||||||
|
if (feature_has("Disable Block Tinting", server_disabled)) {
|
||||||
|
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||||
|
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||||
|
patch_address((void *) StemTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||||
|
patch_address((void *) LeafTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||||
|
overwrite((void *) LiquidTile_getColor_non_virtual, (void *) Tile_getColor_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom GUI Scale
|
||||||
|
const char *gui_scale_str = getenv("MCPI_GUI_SCALE");
|
||||||
|
if (gui_scale_str != nullptr) {
|
||||||
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x173e8, nop_patch);
|
||||||
|
patch((void *) 0x173f0, nop_patch);
|
||||||
|
float gui_scale = strtof(gui_scale_str, nullptr);
|
||||||
|
uint32_t gui_scale_raw;
|
||||||
|
memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw));
|
||||||
|
patch_address((void *) 0x17520, (void *) gui_scale_raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable Hostile AI In Creative Mode
|
||||||
|
if (feature_has("Disable Hostile AI In Creative Mode", server_enabled)) {
|
||||||
|
overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D Chests
|
||||||
|
if (feature_has("3D Chest Model", server_disabled)) {
|
||||||
|
overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection);
|
||||||
|
overwrite_calls((void *) ChestTileEntity_constructor, (void *) ChestTileEntity_injection);
|
||||||
|
overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection);
|
||||||
|
overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection);
|
||||||
|
overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection);
|
||||||
|
overwrite_calls((void *) Tesselator_vertexUV, (void *) Tesselator_vertexUV_injection);
|
||||||
|
unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13"
|
||||||
|
patch((void *) 0x66fc8, chest_model_patch);
|
||||||
|
unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x66404, chest_color_patch);
|
||||||
|
|
||||||
|
// Animation
|
||||||
|
overwrite_calls((void *) ContainerMenu_constructor, (void *) ContainerMenu_injection);
|
||||||
|
overwrite_calls((void *) ContainerMenu_destructor_complete_non_virtual, (void *) ContainerMenu_destructor_injection);
|
||||||
|
}
|
||||||
|
patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection);
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
|
// Replace Block Highlight With Outline
|
||||||
|
if (feature_has("Replace Block Highlight With Outline", server_disabled)) {
|
||||||
|
overwrite((void *) LevelRenderer_renderHitSelect, (void *) LevelRenderer_renderHitOutline);
|
||||||
|
unsigned char fix_outline_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x4d830, fix_outline_patch);
|
||||||
|
overwrite_call((void *) 0x4d764, (void *) glColor4f_injection);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fix Furnace Visual Bug
|
||||||
|
overwrite_calls((void *) FurnaceTileEntity_getLitProgress, (void *) FurnaceTileEntity_getLitProgress_injection);
|
||||||
|
|
||||||
|
// Send the full level, not only changed chunks
|
||||||
|
if (feature_has("Send Full Level When Hosting Game", server_enabled)) {
|
||||||
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
patch((void *) 0x717c4, nop_patch);
|
||||||
|
unsigned char mov_r3_ff[4] = {0xff, 0x30, 0xa0, 0xe3}; // "mov r3, #0xff"
|
||||||
|
patch((void *) 0x7178c, mov_r3_ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Java Light Ramp
|
||||||
|
if (feature_has("Use Java Beta 1.3 Light Ramp", server_disabled)) {
|
||||||
|
overwrite((void *) Dimension_updateLightRamp_non_virtual, (void *) Dimension_updateLightRamp_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix used items transferring durability
|
||||||
|
overwrite_calls((void *) Player_startUsingItem, (void *) Player_startUsingItem_injection);
|
||||||
|
overwrite_calls((void *) Player_stopUsingItem, (void *) Player_stopUsingItem_injection);
|
||||||
|
|
||||||
|
// Fix invalid ItemInHandRenderer texture cache
|
||||||
|
if (feature_has("Disable Buggy Held Item Caching", server_disabled)) {
|
||||||
|
// This works by forcing MCPI to always use the branch that enables using the
|
||||||
|
// cache, but then patches that as well to do the opposite
|
||||||
|
uchar ensure_equal_patch[] = {0x07, 0x00, 0x57, 0xe1}; // "cmp r7, r7"
|
||||||
|
patch((void *) 0x4b938, ensure_equal_patch);
|
||||||
|
uchar set_true_patch[] = {0x01, 0x30, 0xa0, 0x03}; // "moveq r3, #0x1"
|
||||||
|
patch((void *) 0x4b93c, set_true_patch);
|
||||||
|
}
|
||||||
|
|
||||||
// Implement AppPlatform::readAssetFile So Translations Work
|
// Implement AppPlatform::readAssetFile So Translations Work
|
||||||
if (feature_has("Load Language Files", server_enabled)) {
|
if (feature_has("Load Language Files", server_enabled)) {
|
||||||
overwrite((void *) *AppPlatform_readAssetFile_vtable_addr, (void *) AppPlatform_readAssetFile_injection);
|
overwrite((void *) *AppPlatform_readAssetFile_vtable_addr, (void *) AppPlatform_readAssetFile_injection);
|
||||||
@ -160,4 +993,8 @@ void _init_misc_cpp() {
|
|||||||
if (feature_has("Display Date In Select World Screen", server_disabled)) {
|
if (feature_has("Display Date In Select World Screen", server_disabled)) {
|
||||||
patch_address(AppPlatform_linux_getDateString_vtable_addr, (void *) AppPlatform_linux_getDateString_injection);
|
patch_address(AppPlatform_linux_getDateString_vtable_addr, (void *) AppPlatform_linux_getDateString_injection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init Logging
|
||||||
|
_init_misc_logging();
|
||||||
|
_init_misc_api();
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <symbols/minecraft.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__attribute__((visibility("internal"))) void _init_options_cpp();
|
|
||||||
__attribute__((visibility("internal"))) extern Options *stored_options;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
#include <symbols/minecraft.h>
|
|
||||||
|
|
||||||
#include <mods/feature/feature.h>
|
|
||||||
#include <mods/init/init.h>
|
|
||||||
#include "options-internal.h"
|
|
||||||
|
|
||||||
// Force Mob Spawning
|
|
||||||
static bool LevelData_getSpawnMobs_injection(__attribute__((unused)) unsigned char *level_data) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Custom Render Distance
|
|
||||||
static int get_render_distance() {
|
|
||||||
char *distance_str = getenv("MCPI_RENDER_DISTANCE");
|
|
||||||
if (distance_str == NULL) {
|
|
||||||
distance_str = "Short";
|
|
||||||
}
|
|
||||||
if (strcmp("Far", distance_str) == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp("Normal", distance_str) == 0) {
|
|
||||||
return 1;
|
|
||||||
} else if (strcmp("Short", distance_str) == 0) {
|
|
||||||
return 2;
|
|
||||||
} else if (strcmp("Tiny", distance_str) == 0) {
|
|
||||||
return 3;
|
|
||||||
} else {
|
|
||||||
ERR("Invalid Render Distance: %s", distance_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Custom Username
|
|
||||||
static char *get_username() {
|
|
||||||
char *username = getenv("MCPI_USERNAME");
|
|
||||||
if (username == NULL) {
|
|
||||||
username = "StevePi";
|
|
||||||
}
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
static char *safe_username = NULL;
|
|
||||||
__attribute__((destructor)) static void _free_safe_username() {
|
|
||||||
free(safe_username);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int render_distance;
|
|
||||||
// Configure Options
|
|
||||||
Options *stored_options = NULL;
|
|
||||||
static void Options_initDefaultValue_injection(Options *options) {
|
|
||||||
// Call Original Method
|
|
||||||
Options_initDefaultValue(options);
|
|
||||||
|
|
||||||
// Default Graphics Settings
|
|
||||||
#ifndef MCPI_SERVER_MODE
|
|
||||||
options->fancy_graphics = 1;
|
|
||||||
options->ambient_occlusion = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Store
|
|
||||||
stored_options = options;
|
|
||||||
}
|
|
||||||
static void Minecraft_init_injection(Minecraft *minecraft) {
|
|
||||||
// Call Original Method
|
|
||||||
Minecraft_init_non_virtual(minecraft);
|
|
||||||
|
|
||||||
Options *options = &minecraft->options;
|
|
||||||
// Enable Crosshair In Touch GUI
|
|
||||||
options->split_controls = 1;
|
|
||||||
// Render Distance
|
|
||||||
options->render_distance = render_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth Lighting
|
|
||||||
static void TileRenderer_tesselateBlockInWorld_injection(TileRenderer *tile_renderer, Tile *tile, int32_t x, int32_t y, int32_t z) {
|
|
||||||
// Set Variable
|
|
||||||
Minecraft_useAmbientOcclusion = stored_options->ambient_occlusion;
|
|
||||||
|
|
||||||
// Call Original Method
|
|
||||||
TileRenderer_tesselateBlockInWorld(tile_renderer, tile, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init
|
|
||||||
void init_options() {
|
|
||||||
// Force Mob Spawning
|
|
||||||
if (feature_has("Force Mob Spawning", server_auto)) {
|
|
||||||
overwrite((void *) LevelData_getSpawnMobs, (void *) LevelData_getSpawnMobs_injection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render Distance
|
|
||||||
render_distance = get_render_distance();
|
|
||||||
DEBUG("Setting Render Distance: %i", render_distance);
|
|
||||||
|
|
||||||
// Set Options
|
|
||||||
overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection);
|
|
||||||
overwrite_calls((void *) Minecraft_init_non_virtual, (void *) Minecraft_init_injection);
|
|
||||||
|
|
||||||
// Change Username
|
|
||||||
const char *username = get_username();
|
|
||||||
DEBUG("Setting Username: %s", username);
|
|
||||||
if (strcmp(Strings_default_username, "StevePi") != 0) {
|
|
||||||
ERR("Default Username Is Invalid");
|
|
||||||
}
|
|
||||||
safe_username = to_cp437(username);
|
|
||||||
patch_address((void *) Strings_default_username_pointer, (void *) safe_username);
|
|
||||||
|
|
||||||
// Disable Autojump By Default
|
|
||||||
if (feature_has("Disable Autojump By Default", server_disabled)) {
|
|
||||||
unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0"
|
|
||||||
patch((void *) 0x44b90, autojump_patch);
|
|
||||||
}
|
|
||||||
// Display Nametags By Default
|
|
||||||
if (feature_has("Display Nametags By Default", server_disabled)) {
|
|
||||||
// r6 = 0x1
|
|
||||||
// r5 = 0x0
|
|
||||||
unsigned char display_nametags_patch[4] = {0x1d, 0x60, 0xc0, 0xe5}; // "strb r6, [r0, #0x1d]"
|
|
||||||
patch((void *) 0xa6628, display_nametags_patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth Lighting
|
|
||||||
overwrite_calls((void *) TileRenderer_tesselateBlockInWorld, (void *) TileRenderer_tesselateBlockInWorld_injection);
|
|
||||||
|
|
||||||
// Init C++
|
|
||||||
_init_options_cpp();
|
|
||||||
}
|
|
@ -1,15 +1,87 @@
|
|||||||
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
#include <symbols/minecraft.h>
|
||||||
|
|
||||||
#include <mods/feature/feature.h>
|
#include <mods/feature/feature.h>
|
||||||
|
#include <mods/init/init.h>
|
||||||
#include <mods/home/home.h>
|
#include <mods/home/home.h>
|
||||||
#include "options-internal.h"
|
|
||||||
|
|
||||||
#include <symbols/minecraft.h>
|
// Force Mob Spawning
|
||||||
|
static bool LevelData_getSpawnMobs_injection(__attribute__((unused)) unsigned char *level_data) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Custom Render Distance
|
||||||
|
static int get_render_distance() {
|
||||||
|
const char *distance_str = getenv("MCPI_RENDER_DISTANCE");
|
||||||
|
if (distance_str == nullptr) {
|
||||||
|
distance_str = "Short";
|
||||||
|
}
|
||||||
|
if (strcmp("Far", distance_str) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (strcmp("Normal", distance_str) == 0) {
|
||||||
|
return 1;
|
||||||
|
} else if (strcmp("Short", distance_str) == 0) {
|
||||||
|
return 2;
|
||||||
|
} else if (strcmp("Tiny", distance_str) == 0) {
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
ERR("Invalid Render Distance: %s", distance_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Custom Username
|
||||||
|
static const char *get_username() {
|
||||||
|
const char *username = getenv("MCPI_USERNAME");
|
||||||
|
if (username == nullptr) {
|
||||||
|
username = "StevePi";
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
static char *safe_username = nullptr;
|
||||||
|
__attribute__((destructor)) static void _free_safe_username() {
|
||||||
|
free(safe_username);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int render_distance;
|
||||||
|
// Configure Options
|
||||||
|
Options *stored_options = nullptr;
|
||||||
|
static void Options_initDefaultValue_injection(Options *options) {
|
||||||
|
// Call Original Method
|
||||||
|
Options_initDefaultValue(options);
|
||||||
|
|
||||||
|
// Default Graphics Settings
|
||||||
|
#ifndef MCPI_SERVER_MODE
|
||||||
|
options->fancy_graphics = true;
|
||||||
|
options->ambient_occlusion = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Store
|
||||||
|
stored_options = options;
|
||||||
|
}
|
||||||
|
static void Minecraft_init_injection(Minecraft *minecraft) {
|
||||||
|
// Call Original Method
|
||||||
|
Minecraft_init_non_virtual(minecraft);
|
||||||
|
|
||||||
|
Options *options = &minecraft->options;
|
||||||
|
// Enable Crosshair In Touch GUI
|
||||||
|
options->split_controls = true;
|
||||||
|
// Render Distance
|
||||||
|
options->render_distance = render_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth Lighting
|
||||||
|
static void TileRenderer_tesselateBlockInWorld_injection(TileRenderer *tile_renderer, Tile *tile, int32_t x, int32_t y, int32_t z) {
|
||||||
|
// Set Variable
|
||||||
|
Minecraft_useAmbientOcclusion = stored_options->ambient_occlusion;
|
||||||
|
|
||||||
|
// Call Original Method
|
||||||
|
TileRenderer_tesselateBlockInWorld(tile_renderer, tile, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
// Fix Initial Option Button Rendering
|
// Fix Initial Option Button Rendering
|
||||||
// The calling function doesn't exist in MCPE v0.6.1, so its name is unknown.
|
// The calling function doesn't exist in MCPE v0.6.1, so its name is unknown.
|
||||||
@ -49,8 +121,8 @@ static std::vector<std::string> OptionsFile_getOptionStrings_injection(OptionsFi
|
|||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
FILE *stream = fopen(path.c_str(), "r");
|
FILE *stream = fopen(path.c_str(), "r");
|
||||||
char line[128];
|
char line[128];
|
||||||
if (stream != NULL) {
|
if (stream != nullptr) {
|
||||||
while (fgets(line, 0x80, stream) != NULL) {
|
while (fgets(line, 0x80, stream) != nullptr) {
|
||||||
size_t sVar1 = strlen(line);
|
size_t sVar1 = strlen(line);
|
||||||
if (2 < sVar1) {
|
if (2 < sVar1) {
|
||||||
std::stringstream string_stream(line);
|
std::stringstream string_stream(line);
|
||||||
@ -74,9 +146,9 @@ static std::vector<std::string> OptionsFile_getOptionStrings_injection(OptionsFi
|
|||||||
// Get New options.txt Path
|
// Get New options.txt Path
|
||||||
#ifndef MCPI_SERVER_MODE
|
#ifndef MCPI_SERVER_MODE
|
||||||
static char *get_new_options_txt_path() {
|
static char *get_new_options_txt_path() {
|
||||||
static char *path = NULL;
|
static char *path = nullptr;
|
||||||
// Path
|
// Path
|
||||||
if (path == NULL) {
|
if (path == nullptr) {
|
||||||
safe_asprintf(&path, "%s/options.txt", home_get());
|
safe_asprintf(&path, "%s/options.txt", home_get());
|
||||||
}
|
}
|
||||||
// Return
|
// Return
|
||||||
@ -162,8 +234,46 @@ static void OptionButton_toggle_Options_save_injection(Options *self) {
|
|||||||
Options_save(self);
|
Options_save(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init C++
|
// Init
|
||||||
void _init_options_cpp() {
|
void init_options() {
|
||||||
|
// Force Mob Spawning
|
||||||
|
if (feature_has("Force Mob Spawning", server_auto)) {
|
||||||
|
overwrite((void *) LevelData_getSpawnMobs, (void *) LevelData_getSpawnMobs_injection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Distance
|
||||||
|
render_distance = get_render_distance();
|
||||||
|
DEBUG("Setting Render Distance: %i", render_distance);
|
||||||
|
|
||||||
|
// Set Options
|
||||||
|
overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection);
|
||||||
|
overwrite_calls((void *) Minecraft_init_non_virtual, (void *) Minecraft_init_injection);
|
||||||
|
|
||||||
|
// Change Username
|
||||||
|
const char *username = get_username();
|
||||||
|
DEBUG("Setting Username: %s", username);
|
||||||
|
if (strcmp(Strings_default_username, "StevePi") != 0) {
|
||||||
|
ERR("Default Username Is Invalid");
|
||||||
|
}
|
||||||
|
safe_username = to_cp437(username);
|
||||||
|
patch_address((void *) Strings_default_username_pointer, (void *) safe_username);
|
||||||
|
|
||||||
|
// Disable Autojump By Default
|
||||||
|
if (feature_has("Disable Autojump By Default", server_disabled)) {
|
||||||
|
unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3}; // "mov r3, #0x0"
|
||||||
|
patch((void *) 0x44b90, autojump_patch);
|
||||||
|
}
|
||||||
|
// Display Nametags By Default
|
||||||
|
if (feature_has("Display Nametags By Default", server_disabled)) {
|
||||||
|
// r6 = 0x1
|
||||||
|
// r5 = 0x0
|
||||||
|
unsigned char display_nametags_patch[4] = {0x1d, 0x60, 0xc0, 0xe5}; // "strb r6, [r0, #0x1d]"
|
||||||
|
patch((void *) 0xa6628, display_nametags_patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth Lighting
|
||||||
|
overwrite_calls((void *) TileRenderer_tesselateBlockInWorld, (void *) TileRenderer_tesselateBlockInWorld_injection);
|
||||||
|
|
||||||
// NOP
|
// NOP
|
||||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -16,9 +16,9 @@ HOOK(access, int, (const char *pathname, int mode)) {
|
|||||||
char *new_path = override_get_path(pathname);
|
char *new_path = override_get_path(pathname);
|
||||||
// Open File
|
// Open File
|
||||||
ensure_access();
|
ensure_access();
|
||||||
int ret = real_access(new_path != NULL ? new_path : pathname, mode);
|
int ret = real_access(new_path != nullptr ? new_path : pathname, mode);
|
||||||
// Free Data
|
// Free Data
|
||||||
if (new_path != NULL) {
|
if (new_path != nullptr) {
|
||||||
free(new_path);
|
free(new_path);
|
||||||
}
|
}
|
||||||
// Return
|
// Return
|
||||||
@ -36,11 +36,11 @@ char *override_get_path(const char *filename) {
|
|||||||
// Get MCPI Home Path
|
// Get MCPI Home Path
|
||||||
char *home_path = home_get();
|
char *home_path = home_get();
|
||||||
// Get Asset Override Path
|
// Get Asset Override Path
|
||||||
char *overrides = NULL;
|
char *overrides = nullptr;
|
||||||
safe_asprintf(&overrides, "%s/overrides", home_path);
|
safe_asprintf(&overrides, "%s/overrides", home_path);
|
||||||
|
|
||||||
// Data Prefiix
|
// Data Prefiix
|
||||||
char *data_prefix = "data/";
|
const char *data_prefix = "data/";
|
||||||
int data_prefix_length = strlen(data_prefix);
|
int data_prefix_length = strlen(data_prefix);
|
||||||
|
|
||||||
// Folders To Check
|
// Folders To Check
|
||||||
@ -48,20 +48,20 @@ char *override_get_path(const char *filename) {
|
|||||||
overrides,
|
overrides,
|
||||||
getenv("MCPI_REBORN_ASSETS_PATH"),
|
getenv("MCPI_REBORN_ASSETS_PATH"),
|
||||||
getenv("MCPI_VANILLA_ASSETS_PATH"),
|
getenv("MCPI_VANILLA_ASSETS_PATH"),
|
||||||
NULL
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check For Override
|
// Check For Override
|
||||||
char *new_path = NULL;
|
char *new_path = nullptr;
|
||||||
if (starts_with(filename, data_prefix)) {
|
if (starts_with(filename, data_prefix)) {
|
||||||
// Test Asset Folders
|
// Test Asset Folders
|
||||||
for (int i = 0; asset_folders[i] != NULL; i++) {
|
for (int i = 0; asset_folders[i] != nullptr; i++) {
|
||||||
safe_asprintf(&new_path, "%s/%s", asset_folders[i], &filename[data_prefix_length]);
|
safe_asprintf(&new_path, "%s/%s", asset_folders[i], &filename[data_prefix_length]);
|
||||||
ensure_access();
|
ensure_access();
|
||||||
if (real_access(new_path, F_OK) == -1) {
|
if (real_access(new_path, F_OK) == -1) {
|
||||||
// Not Found In Asset Folder
|
// Not Found In Asset Folder
|
||||||
free(new_path);
|
free(new_path);
|
||||||
new_path = NULL;
|
new_path = nullptr;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// Found
|
// Found
|
||||||
@ -82,9 +82,9 @@ HOOK(fopen, FILE *, (const char *filename, const char *mode)) {
|
|||||||
char *new_path = override_get_path(filename);
|
char *new_path = override_get_path(filename);
|
||||||
// Open File
|
// Open File
|
||||||
ensure_fopen();
|
ensure_fopen();
|
||||||
FILE *file = real_fopen(new_path != NULL ? new_path : filename, mode);
|
FILE *file = real_fopen(new_path != nullptr ? new_path : filename, mode);
|
||||||
// Free Data
|
// Free Data
|
||||||
if (new_path != NULL) {
|
if (new_path != nullptr) {
|
||||||
free(new_path);
|
free(new_path);
|
||||||
}
|
}
|
||||||
// Return File
|
// Return File
|
||||||
@ -96,9 +96,9 @@ HOOK(fopen64, FILE *, (const char *filename, const char *mode)) {
|
|||||||
char *new_path = override_get_path(filename);
|
char *new_path = override_get_path(filename);
|
||||||
// Open File
|
// Open File
|
||||||
ensure_fopen64();
|
ensure_fopen64();
|
||||||
FILE *file = real_fopen64(new_path != NULL ? new_path : filename, mode);
|
FILE *file = real_fopen64(new_path != nullptr ? new_path : filename, mode);
|
||||||
// Free Data
|
// Free Data
|
||||||
if (new_path != NULL) {
|
if (new_path != nullptr) {
|
||||||
free(new_path);
|
free(new_path);
|
||||||
}
|
}
|
||||||
// Return File
|
// Return File
|
@ -1,22 +0,0 @@
|
|||||||
#define __USE_LARGEFILE64
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
// Minecraft: Pi Edition Was Not Compiled With 64-Bit Filesystem Support, So This Shims readdir() To Read Directories Properly
|
|
||||||
|
|
||||||
#define FILENAME_SIZE 256
|
|
||||||
|
|
||||||
struct dirent *readdir(DIR *dirp) {
|
|
||||||
struct dirent64 *original = readdir64(dirp);
|
|
||||||
if (original == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
static struct dirent new;
|
|
||||||
for (int i = 0; i < FILENAME_SIZE; i++) {
|
|
||||||
new.d_name[i] = original->d_name[i];
|
|
||||||
}
|
|
||||||
new.d_type = original->d_type;
|
|
||||||
return &new;
|
|
||||||
}
|
|
22
mods/src/readdir/readdir.cpp
Normal file
22
mods/src/readdir/readdir.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#define __USE_LARGEFILE64
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
// Minecraft: Pi Edition Was Not Compiled With 64-Bit Filesystem Support, So This Shims readdir() To Read Directories Properly
|
||||||
|
|
||||||
|
#define FILENAME_SIZE 256
|
||||||
|
|
||||||
|
dirent *readdir(DIR *dirp) {
|
||||||
|
dirent64 *original = readdir64(dirp);
|
||||||
|
if (original == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
static dirent new_dirent;
|
||||||
|
for (int i = 0; i < FILENAME_SIZE; i++) {
|
||||||
|
new_dirent.d_name[i] = original->d_name[i];
|
||||||
|
}
|
||||||
|
new_dirent.d_type = original->d_type;
|
||||||
|
return &new_dirent;
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <ctime>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <errno.h>
|
#include <cerrno>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
@ -16,7 +16,7 @@
|
|||||||
// Ensure Screenshots Folder Exists
|
// Ensure Screenshots Folder Exists
|
||||||
static void ensure_screenshots_folder(char *screenshots) {
|
static void ensure_screenshots_folder(char *screenshots) {
|
||||||
// Check Screenshots Folder
|
// Check Screenshots Folder
|
||||||
struct stat obj;
|
struct stat obj = {};
|
||||||
if (stat(screenshots, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
|
if (stat(screenshots, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
|
||||||
// Create Screenshots Folder
|
// Create Screenshots Folder
|
||||||
int ret = mkdir(screenshots, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
int ret = mkdir(screenshots, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||||
@ -40,12 +40,12 @@ static int save_png(const char *filename, unsigned char *pixels, int line_size,
|
|||||||
}
|
}
|
||||||
void screenshot_take(char *home) {
|
void screenshot_take(char *home) {
|
||||||
// Get Directory
|
// Get Directory
|
||||||
char *screenshots = NULL;
|
char *screenshots = nullptr;
|
||||||
safe_asprintf(&screenshots, "%s/screenshots", home);
|
safe_asprintf(&screenshots, "%s/screenshots", home);
|
||||||
|
|
||||||
// Get Timestamp
|
// Get Timestamp
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
struct tm *timeinfo;
|
tm *timeinfo = {};
|
||||||
time(&rawtime);
|
time(&rawtime);
|
||||||
timeinfo = localtime(&rawtime);
|
timeinfo = localtime(&rawtime);
|
||||||
char time[TIME_SIZE];
|
char time[TIME_SIZE];
|
||||||
@ -56,11 +56,11 @@ void screenshot_take(char *home) {
|
|||||||
|
|
||||||
// Prevent Overwriting Screenshots
|
// Prevent Overwriting Screenshots
|
||||||
int num = 1;
|
int num = 1;
|
||||||
char *file = NULL;
|
char *file = nullptr;
|
||||||
safe_asprintf(&file, "%s/%s.png", screenshots, time);
|
safe_asprintf(&file, "%s/%s.png", screenshots, time);
|
||||||
while (access(file, F_OK) != -1) {
|
while (access(file, F_OK) != -1) {
|
||||||
free(file);
|
free(file);
|
||||||
file = NULL;
|
file = nullptr;
|
||||||
safe_asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
|
safe_asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
@ -88,7 +88,7 @@ static void start_world(Minecraft *minecraft) {
|
|||||||
LevelSettings settings;
|
LevelSettings settings;
|
||||||
settings.game_type = get_server_properties().get_int("game-mode", DEFAULT_GAME_MODE);
|
settings.game_type = get_server_properties().get_int("game-mode", DEFAULT_GAME_MODE);
|
||||||
std::string seed_str = get_server_properties().get_string("seed", DEFAULT_SEED);
|
std::string seed_str = get_server_properties().get_string("seed", DEFAULT_SEED);
|
||||||
int32_t seed = seed_str.length() > 0 ? std::stoi(seed_str) : time(NULL);
|
int32_t seed = seed_str.length() > 0 ? std::stoi(seed_str) : time(nullptr);
|
||||||
settings.seed = seed;
|
settings.seed = seed;
|
||||||
|
|
||||||
// Select Level
|
// Select Level
|
||||||
@ -202,12 +202,12 @@ static void ban_callback(Minecraft *minecraft, std::string username, Player *pla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reload
|
// Reload
|
||||||
is_ip_in_blacklist(NULL);
|
is_ip_in_blacklist(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill Player
|
// Kill Player
|
||||||
static void kill_callback(__attribute__((unused)) Minecraft *minecraft, __attribute__((unused)) std::string username, Player *player) {
|
static void kill_callback(__attribute__((unused)) Minecraft *minecraft, __attribute__((unused)) std::string username, Player *player) {
|
||||||
player->vtable->hurt(player, NULL, INT32_MAX);
|
player->vtable->hurt(player, nullptr, INT32_MAX);
|
||||||
INFO("Killed: %s", username.c_str());
|
INFO("Killed: %s", username.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ static void handle_server_stop(Minecraft *minecraft) {
|
|||||||
INFO("Stopping Server");
|
INFO("Stopping Server");
|
||||||
// Save And Exit
|
// Save And Exit
|
||||||
Level *level = get_level(minecraft);
|
Level *level = get_level(minecraft);
|
||||||
if (level != NULL) {
|
if (level != nullptr) {
|
||||||
Level_saveLevelData_injection(level);
|
Level_saveLevelData_injection(level);
|
||||||
}
|
}
|
||||||
Minecraft_leaveGame(minecraft, false);
|
Minecraft_leaveGame(minecraft, false);
|
||||||
@ -263,7 +263,7 @@ static ServerSideNetworkHandler *get_server_side_network_handler(Minecraft *mine
|
|||||||
|
|
||||||
// Read STDIN Thread
|
// Read STDIN Thread
|
||||||
static volatile bool stdin_buffer_complete = false;
|
static volatile bool stdin_buffer_complete = false;
|
||||||
static volatile char *stdin_buffer = NULL;
|
static volatile char *stdin_buffer = nullptr;
|
||||||
static void *read_stdin_thread(__attribute__((unused)) void *data) {
|
static void *read_stdin_thread(__attribute__((unused)) void *data) {
|
||||||
// Loop
|
// Loop
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -278,7 +278,7 @@ static void *read_stdin_thread(__attribute__((unused)) void *data) {
|
|||||||
// Read Data
|
// Read Data
|
||||||
char x = buffer[i];
|
char x = buffer[i];
|
||||||
if (x == '\n') {
|
if (x == '\n') {
|
||||||
if (stdin_buffer == NULL) {
|
if (stdin_buffer == nullptr) {
|
||||||
stdin_buffer = (volatile char *) malloc(1);
|
stdin_buffer = (volatile char *) malloc(1);
|
||||||
stdin_buffer[0] = '\0';
|
stdin_buffer[0] = '\0';
|
||||||
}
|
}
|
||||||
@ -289,12 +289,12 @@ static void *read_stdin_thread(__attribute__((unused)) void *data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
__attribute__((destructor)) static void _free_stdin_buffer() {
|
__attribute__((destructor)) static void _free_stdin_buffer() {
|
||||||
if (stdin_buffer != NULL) {
|
if (stdin_buffer != nullptr) {
|
||||||
free((void *) stdin_buffer);
|
free((void *) stdin_buffer);
|
||||||
stdin_buffer = NULL;
|
stdin_buffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,9 +303,9 @@ static void handle_commands(Minecraft *minecraft) {
|
|||||||
// Check If Level Is Generated
|
// Check If Level Is Generated
|
||||||
if (Minecraft_isLevelGenerated(minecraft) && stdin_buffer_complete) {
|
if (Minecraft_isLevelGenerated(minecraft) && stdin_buffer_complete) {
|
||||||
// Command Ready; Run It
|
// Command Ready; Run It
|
||||||
if (stdin_buffer != NULL) {
|
if (stdin_buffer != nullptr) {
|
||||||
ServerSideNetworkHandler *server_side_network_handler = get_server_side_network_handler(minecraft);
|
ServerSideNetworkHandler *server_side_network_handler = get_server_side_network_handler(minecraft);
|
||||||
if (server_side_network_handler != NULL) {
|
if (server_side_network_handler != nullptr) {
|
||||||
std::string data((char *) stdin_buffer);
|
std::string data((char *) stdin_buffer);
|
||||||
|
|
||||||
static std::string ban_command("ban ");
|
static std::string ban_command("ban ");
|
||||||
@ -322,7 +322,7 @@ static void handle_commands(Minecraft *minecraft) {
|
|||||||
find_players(minecraft, ban_username, ban_callback, false);
|
find_players(minecraft, ban_username, ban_callback, false);
|
||||||
} else if (data == reload_command) {
|
} else if (data == reload_command) {
|
||||||
INFO("Reloading %s", is_whitelist() ? "Whitelist" : "Blacklist");
|
INFO("Reloading %s", is_whitelist() ? "Whitelist" : "Blacklist");
|
||||||
is_ip_in_blacklist(NULL);
|
is_ip_in_blacklist(nullptr);
|
||||||
} else if (data.rfind(kill_command, 0) == 0) {
|
} else if (data.rfind(kill_command, 0) == 0) {
|
||||||
// Kill Target Username
|
// Kill Target Username
|
||||||
std::string kill_username = data.substr(kill_command.length());
|
std::string kill_username = data.substr(kill_command.length());
|
||||||
@ -365,7 +365,7 @@ static void handle_commands(Minecraft *minecraft) {
|
|||||||
|
|
||||||
// Free
|
// Free
|
||||||
free((void *) stdin_buffer);
|
free((void *) stdin_buffer);
|
||||||
stdin_buffer = NULL;
|
stdin_buffer = nullptr;
|
||||||
}
|
}
|
||||||
stdin_buffer_complete = false;
|
stdin_buffer_complete = false;
|
||||||
}
|
}
|
||||||
@ -398,7 +398,7 @@ static void Minecraft_update_injection(Minecraft *minecraft) {
|
|||||||
// Check Blacklist/Whitelist
|
// Check Blacklist/Whitelist
|
||||||
static bool is_ip_in_blacklist(const char *ip) {
|
static bool is_ip_in_blacklist(const char *ip) {
|
||||||
static std::vector<std::string> ips;
|
static std::vector<std::string> ips;
|
||||||
if (ip == NULL) {
|
if (ip == nullptr) {
|
||||||
// Reload
|
// Reload
|
||||||
ips.clear();
|
ips.clear();
|
||||||
// Check banned-ips.txt
|
// Check banned-ips.txt
|
||||||
@ -449,7 +449,7 @@ static Player *ServerSideNetworkHandler_onReady_ClientGeneration_ServerSideNetwo
|
|||||||
Player *player = ServerSideNetworkHandler_popPendingPlayer(server_side_network_handler, guid);
|
Player *player = ServerSideNetworkHandler_popPendingPlayer(server_side_network_handler, guid);
|
||||||
|
|
||||||
// Check If Player Is Null
|
// Check If Player Is Null
|
||||||
if (player != NULL) {
|
if (player != nullptr) {
|
||||||
// Get Data
|
// Get Data
|
||||||
std::string *username = &player->username;
|
std::string *username = &player->username;
|
||||||
Minecraft *minecraft = server_side_network_handler->minecraft;
|
Minecraft *minecraft = server_side_network_handler->minecraft;
|
||||||
@ -565,7 +565,7 @@ static void server_init() {
|
|||||||
blacklist_file.close();
|
blacklist_file.close();
|
||||||
}
|
}
|
||||||
// Load Blacklist/Whitelist
|
// Load Blacklist/Whitelist
|
||||||
is_ip_in_blacklist(NULL);
|
is_ip_in_blacklist(nullptr);
|
||||||
|
|
||||||
// Prevent Main Player From Loading
|
// Prevent Main Player From Loading
|
||||||
unsigned char player_patch[4] = {0x00, 0x20, 0xa0, 0xe3}; // "mov r2, #0x0"
|
unsigned char player_patch[4] = {0x00, 0x20, 0xa0, 0xe3}; // "mov r2, #0x0"
|
||||||
@ -592,7 +592,7 @@ static void server_init() {
|
|||||||
|
|
||||||
// Start Reading STDIN
|
// Start Reading STDIN
|
||||||
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, nullptr, read_stdin_thread, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init Server
|
// Init Server
|
||||||
|
@ -66,7 +66,7 @@ static void load_pending_skins(__attribute__((unused)) Minecraft *minecraft) {
|
|||||||
// Skin Server
|
// Skin Server
|
||||||
static std::string get_skin_server() {
|
static std::string get_skin_server() {
|
||||||
const char *custom_server = getenv("MCPI_SKIN_SERVER");
|
const char *custom_server = getenv("MCPI_SKIN_SERVER");
|
||||||
if (custom_server != NULL) {
|
if (custom_server != nullptr) {
|
||||||
return custom_server;
|
return custom_server;
|
||||||
} else {
|
} else {
|
||||||
return MCPI_SKIN_SERVER;
|
return MCPI_SKIN_SERVER;
|
||||||
@ -85,12 +85,12 @@ static void *loader_thread(void *user_data) {
|
|||||||
// Download
|
// Download
|
||||||
std::string url = get_skin_server() + '/' + data->name + ".png";
|
std::string url = get_skin_server() + '/' + data->name + ".png";
|
||||||
int return_code;
|
int return_code;
|
||||||
const char *command[] = {"wget", "-O", "-", url.c_str(), NULL};
|
const char *command[] = {"wget", "-O", "-", url.c_str(), nullptr};
|
||||||
size_t output_size = 0;
|
size_t output_size = 0;
|
||||||
char *output = run_command(command, &return_code, &output_size);
|
char *output = run_command(command, &return_code, &output_size);
|
||||||
|
|
||||||
// Check Success
|
// Check Success
|
||||||
if (output != NULL && is_exit_status_success(return_code)) {
|
if (output != nullptr && is_exit_status_success(return_code)) {
|
||||||
// Success
|
// Success
|
||||||
DEBUG("Downloaded Skin: %s", data->name.c_str());
|
DEBUG("Downloaded Skin: %s", data->name.c_str());
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ static void *loader_thread(void *user_data) {
|
|||||||
|
|
||||||
// Free
|
// Free
|
||||||
delete data;
|
delete data;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intercept Texture Creation
|
// Intercept Texture Creation
|
||||||
@ -126,7 +126,7 @@ static int32_t Textures_assignTexture_injection(Textures *textures, std::string
|
|||||||
user_data->texture_id = id;
|
user_data->texture_id = id;
|
||||||
// Start Thread
|
// Start Thread
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_create(&thread, NULL, loader_thread, (void *) user_data);
|
pthread_create(&thread, nullptr, loader_thread, (void *) user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
|
@ -350,7 +350,7 @@ std::unordered_map<std::string, std::vector<std::string>> sound_repository = {
|
|||||||
|
|
||||||
// Set rand() Seed
|
// Set rand() Seed
|
||||||
__attribute__((constructor)) static void init_rand_seed() {
|
__attribute__((constructor)) static void init_rand_seed() {
|
||||||
srand(time(NULL));
|
srand(time(nullptr));
|
||||||
}
|
}
|
||||||
// Pick Sound
|
// Pick Sound
|
||||||
std::string _sound_pick(std::string sound) {
|
std::string _sound_pick(std::string sound) {
|
||||||
|
@ -28,7 +28,7 @@ std::string _sound_get_source_file() {
|
|||||||
|
|
||||||
// Handle Overrides
|
// Handle Overrides
|
||||||
char *overridden_full_path = override_get_path(path);
|
char *overridden_full_path = override_get_path(path);
|
||||||
if (overridden_full_path != NULL) {
|
if (overridden_full_path != nullptr) {
|
||||||
free(path);
|
free(path);
|
||||||
path = overridden_full_path;
|
path = overridden_full_path;
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ static void SoundEngine_update_injection(SoundEngine *sound_engine, Mob *listene
|
|||||||
volume = sound_enabled ? 1 : 0;
|
volume = sound_enabled ? 1 : 0;
|
||||||
|
|
||||||
// Position And Rotation
|
// Position And Rotation
|
||||||
if (listener_mob != NULL) {
|
if (listener_mob != nullptr) {
|
||||||
// Values
|
// Values
|
||||||
x = listener_mob->x;
|
x = listener_mob->x;
|
||||||
y = listener_mob->y;
|
y = listener_mob->y;
|
||||||
|
@ -7,7 +7,7 @@ static Texture AppPlatform_linux_loadTexture_injection(__attribute__((unused)) A
|
|||||||
Texture out;
|
Texture out;
|
||||||
out.width = 0;
|
out.width = 0;
|
||||||
out.height = 0;
|
out.height = 0;
|
||||||
out.data = NULL;
|
out.data = nullptr;
|
||||||
out.field3_0xc = 0;
|
out.field3_0xc = 0;
|
||||||
out.field4_0x10 = true;
|
out.field4_0x10 = true;
|
||||||
out.field5_0x11 = false;
|
out.field5_0x11 = false;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
static void Minecraft_tick_injection(Minecraft *minecraft) {
|
static void Minecraft_tick_injection(Minecraft *minecraft) {
|
||||||
// Tick Dynamic Textures
|
// Tick Dynamic Textures
|
||||||
Textures *textures = minecraft->textures;
|
Textures *textures = minecraft->textures;
|
||||||
if (textures != NULL) {
|
if (textures != nullptr) {
|
||||||
Textures_tick(textures, true);
|
Textures_tick(textures, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ static Texture AppPlatform_linux_loadTexture_injection(__attribute__((unused)) A
|
|||||||
// Empty Texture
|
// Empty Texture
|
||||||
out.width = 0;
|
out.width = 0;
|
||||||
out.height = 0;
|
out.height = 0;
|
||||||
out.data = NULL;
|
out.data = nullptr;
|
||||||
out.field3_0xc = 0;
|
out.field3_0xc = 0;
|
||||||
out.field4_0x10 = true;
|
out.field4_0x10 = true;
|
||||||
out.field5_0x11 = false;
|
out.field5_0x11 = false;
|
||||||
|
@ -162,6 +162,6 @@ void init_title_screen() {
|
|||||||
overwrite_call((void *) 0x39764, (void *) StartMenuScreen_render_Screen_render_injection);
|
overwrite_call((void *) 0x39764, (void *) StartMenuScreen_render_Screen_render_injection);
|
||||||
overwrite_call((void *) 0x3e0c4, (void *) StartMenuScreen_render_Screen_render_injection);
|
overwrite_call((void *) 0x3e0c4, (void *) StartMenuScreen_render_Screen_render_injection);
|
||||||
// Init Random
|
// Init Random
|
||||||
srand(time(NULL));
|
srand(time(nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ static int32_t Button_hovered_injection(__attribute__((unused)) Button *button,
|
|||||||
}
|
}
|
||||||
static void LargeImageButton_render_GuiComponent_drawCenteredString_injection(GuiComponent *component, Font *font, std::string *text, int32_t x, int32_t y, int32_t color) {
|
static void LargeImageButton_render_GuiComponent_drawCenteredString_injection(GuiComponent *component, Font *font, std::string *text, int32_t x, int32_t y, int32_t color) {
|
||||||
// Change Color On Hover
|
// Change Color On Hover
|
||||||
if (color == 0xe0e0e0 && Button_hovered_injection((Button *) component, NULL, 0, 0)) {
|
if (color == 0xe0e0e0 && Button_hovered_injection((Button *) component, nullptr, 0, 0)) {
|
||||||
color = 0xffffa0;
|
color = 0xffffa0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
// Get New Version
|
// Get New Version
|
||||||
char *version_get() {
|
char *version_get() {
|
||||||
static char *version = NULL;
|
static char *version = nullptr;
|
||||||
// Load
|
// Load
|
||||||
if (version == NULL) {
|
if (version == nullptr) {
|
||||||
safe_asprintf(&version, "%s / Reborn v%s", Strings_minecraft_pi_version, reborn_get_version());
|
safe_asprintf(&version, "%s / Reborn v%s", Strings_minecraft_pi_version, reborn_get_version());
|
||||||
}
|
}
|
||||||
// Return
|
// Return
|
||||||
|
@ -12,7 +12,7 @@ property int game_difficulty = 0xe8;
|
|||||||
property bool anaglyph_3d = 0x15;
|
property bool anaglyph_3d = 0x15;
|
||||||
property bool ambient_occlusion = 0x18;
|
property bool ambient_occlusion = 0x18;
|
||||||
property bool hide_gui = 0xec;
|
property bool hide_gui = 0xec;
|
||||||
property bool third_person = 0xed;
|
property uchar third_person = 0xed; // Technically This Is A Boolean
|
||||||
property int render_distance = 0x10;
|
property int render_distance = 0x10;
|
||||||
property int sound = 0x4;
|
property int sound = 0x4;
|
||||||
property bool debug = 0xee;
|
property bool debug = 0xee;
|
||||||
|
Loading…
Reference in New Issue
Block a user