minecraft-pi-reborn/mods/src/misc/misc.c

702 lines
27 KiB
C
Raw Normal View History

#include <stdlib.h>
#include <string.h>
2021-06-17 21:32:24 +00:00
#include <unistd.h>
2022-09-21 21:54:40 +00:00
#include <sys/socket.h>
#include <netinet/in.h>
2023-12-26 07:31:22 +00:00
#ifndef MCPI_HEADLESS_MODE
2021-11-14 04:29:48 +00:00
#include <GLES/gl.h>
2023-12-26 07:31:22 +00:00
#endif
2021-11-14 04:29:48 +00:00
2021-01-27 21:26:19 +00:00
#include <libreborn/libreborn.h>
2021-09-12 03:18:12 +00:00
#include <symbols/minecraft.h>
2022-03-16 23:49:13 +00:00
2022-03-15 01:51:38 +00:00
#include <SDL/SDL.h>
2022-03-16 23:49:13 +00:00
#include <media-layer/core.h>
2020-12-02 23:18:49 +00:00
2022-06-25 21:30:08 +00:00
#include <mods/init/init.h>
#include <mods/feature/feature.h>
#include "misc-internal.h"
#include <mods/misc/misc.h>
2020-12-02 23:18:49 +00:00
2022-07-14 02:11:46 +00:00
// Classic HUD
#define DEFAULT_HUD_PADDING 2
2022-07-14 23:52:51 +00:00
#define NEW_HUD_PADDING 1
2022-07-14 02:11:46 +00:00
#define HUD_ELEMENT_WIDTH 82
#define HUD_ELEMENT_HEIGHT 9
2022-07-14 23:52:51 +00:00
#define TOOLBAR_HEIGHT 22
#define SLOT_WIDTH 20
2022-07-14 02:11:46 +00:00
#define DEFAULT_BUBBLES_PADDING 1
#define NUMBER_OF_SLOTS 9
static int use_classic_hud = 0;
2024-01-06 11:30:23 +00:00
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;
2022-07-14 02:11:46 +00:00
x_dest -= DEFAULT_HUD_PADDING;
2024-01-07 07:59:04 +00:00
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
2022-07-15 05:37:12 +00:00
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
2022-07-14 02:11:46 +00:00
y_dest -= DEFAULT_HUD_PADDING;
2022-07-14 23:52:51 +00:00
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
2022-07-14 02:11:46 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
(*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
2022-07-14 02:11:46 +00:00
}
2024-01-06 11:30:23 +00:00
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;
2022-07-14 02:11:46 +00:00
x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH;
2024-01-07 07:59:04 +00:00
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
2022-07-15 05:37:12 +00:00
x_dest += width - ((width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH;
2022-07-14 02:11:46 +00:00
y_dest -= DEFAULT_HUD_PADDING;
2022-07-14 23:52:51 +00:00
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
2022-07-14 02:11:46 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
(*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
2022-07-14 02:11:46 +00:00
}
2024-01-06 11:30:23 +00:00
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;
2022-07-14 02:11:46 +00:00
x_dest -= DEFAULT_HUD_PADDING;
2024-01-07 07:59:04 +00:00
float width = ((float) minecraft->screen_width) * Gui_InvGuiScale;
float height = ((float) minecraft->screen_height) * Gui_InvGuiScale;
2022-07-15 05:37:12 +00:00
x_dest += (width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
2022-07-14 02:11:46 +00:00
y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT;
2022-07-14 23:52:51 +00:00
y_dest += height - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING;
2022-07-14 02:11:46 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
(*Gui_blit)(component, x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
2022-07-14 02:11:46 +00:00
}
2021-11-14 04:29:48 +00:00
// Additional GUI Rendering
static int hide_chat_messages = 0;
static int render_selected_item_text = 0;
2024-01-06 11:30:23 +00:00
static void Gui_renderChatMessages_injection(Gui *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, Font *font) {
2022-07-14 02:11:46 +00:00
// Handle Classic HUD
if (use_classic_hud) {
2024-01-06 11:30:23 +00:00
Minecraft *minecraft = gui->minecraft;
2022-07-14 02:11:46 +00:00
if (!(*Minecraft_isCreativeMode)(minecraft)) {
2022-07-14 23:52:51 +00:00
y_offset -= (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING;
2022-07-14 02:11:46 +00:00
}
}
2021-02-17 16:31:01 +00:00
// Call Original Method
2021-11-14 04:29:48 +00:00
if (!hide_chat_messages) {
(*Gui_renderChatMessages)(gui, y_offset, max_messages, disable_fading, font);
}
2021-02-17 16:31:01 +00:00
// Render Selected Item Text
2021-11-14 04:29:48 +00:00
if (render_selected_item_text) {
// Fix GL Mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Calculate Selected Item Text Scale
2024-01-06 11:30:23 +00:00
Minecraft *minecraft = gui->minecraft;
int32_t screen_width = minecraft->screen_width;
2024-01-07 07:59:04 +00:00
float scale = ((float) screen_width) * Gui_InvGuiScale;
2021-11-14 04:29:48 +00:00
// Render Selected Item Text
(*Gui_renderOnSelectItemNameText)(gui, (int32_t) scale, font, y_offset - 0x13);
}
2021-02-17 16:31:01 +00:00
}
// Reset Selected Item Text Timer On Slot Select
static uint32_t reset_selected_item_text_timer = 0;
2024-01-06 11:30:23 +00:00
static void Gui_tick_injection(Gui *gui) {
2021-02-17 16:31:01 +00:00
// Call Original Method
(*Gui_tick)(gui);
2021-11-14 04:29:48 +00:00
2021-02-17 16:31:01 +00:00
// Handle Reset
2021-11-14 04:29:48 +00:00
if (render_selected_item_text) {
2024-01-06 11:30:23 +00:00
float *selected_item_text_timer = &gui->selected_item_text_timer;
2021-11-14 04:29:48 +00:00
if (reset_selected_item_text_timer) {
// Reset
*selected_item_text_timer = 0;
reset_selected_item_text_timer = 0;
}
2021-02-17 16:31:01 +00:00
}
}
// Trigger Reset Selected Item Text Timer On Slot Select
2024-01-06 11:30:23 +00:00
static void Inventory_selectSlot_injection(Inventory *inventory, int32_t slot) {
2021-02-17 16:31:01 +00:00
// Call Original Method
(*Inventory_selectSlot)(inventory, slot);
2021-11-14 04:29:48 +00:00
2021-02-17 16:31:01 +00:00
// Trigger Reset Selected Item Text Timer
2021-11-14 04:29:48 +00:00
if (render_selected_item_text) {
reset_selected_item_text_timer = 1;
}
2021-02-17 16:31:01 +00:00
}
2022-07-14 23:52:51 +00:00
// Translucent Toolbar
2024-01-06 11:30:23 +00:00
static void Gui_renderToolBar_injection(Gui *gui, float param_1, int32_t param_2, int32_t param_3) {
2022-07-14 23:52:51 +00:00
// Call Original Method
2022-07-16 02:08:12 +00:00
int was_blend_enabled = glIsEnabled(GL_BLEND);
if (!was_blend_enabled) {
glEnable(GL_BLEND);
}
2022-07-14 23:52:51 +00:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
(*Gui_renderToolBar)(gui, param_1, param_2, param_3);
2022-07-16 02:08:12 +00:00
if (!was_blend_enabled) {
glDisable(GL_BLEND);
}
2022-07-14 23:52:51 +00:00
}
static void Gui_renderToolBar_glColor4f_injection(GLfloat red, GLfloat green, GLfloat blue, __attribute__((unused)) GLfloat alpha) {
2022-07-14 23:52:51 +00:00
// Fix Alpha
glColor4f(red, green, blue, 1.0f);
}
// Fix Screen Rendering When GUI is Hidden
2024-01-06 11:30:23 +00:00
static void Screen_render_injection(Screen *screen, int32_t param_1, int32_t param_2, float param_3) {
// Fix
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Call Original Method
2024-01-06 11:30:23 +00:00
(*Screen_render_non_virtual)(screen, param_1, param_2, param_3);
2022-07-14 23:52:51 +00:00
}
// Sanitize Username
2022-07-14 02:11:46 +00:00
#define MAX_USERNAME_LENGTH 16
2024-01-06 11:30:23 +00:00
static void LoginPacket_read_injection(LoginPacket *packet, unsigned char *bit_stream) {
// Call Original Method
2024-01-06 11:30:23 +00:00
(*LoginPacket_read_non_virtual)(packet, bit_stream);
// Prepare
2024-01-06 11:30:23 +00:00
RakNet_RakString *rak_string = &packet->username;
// Get Original Username
2024-01-06 11:30:23 +00:00
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);
}
2021-07-16 22:17:49 +00:00
// 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.
2024-01-06 11:30:23 +00:00
static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) {
2021-07-16 22:17:49 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
return (*RakNet_RakString_constructor)(rak_string, "%s", format);
2021-07-16 22:17:49 +00:00
}
// 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
2024-01-06 11:30:23 +00:00
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
2024-01-06 11:30:23 +00:00
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;
}
2021-09-12 03:18:12 +00:00
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
2024-01-06 11:30:23 +00:00
static RakNetInstance *RakNetInstance_injection(RakNetInstance *rak_net_instance) {
2021-09-12 03:18:12 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
RakNetInstance *result = (*RakNetInstance_constructor)(rak_net_instance);
2021-09-12 03:18:12 +00:00
// Fix
2024-01-06 11:30:23 +00:00
rak_net_instance->pinging_for_hosts = 0;
2021-09-12 03:18:12 +00:00
// Return
return result;
}
2022-01-02 20:26:56 +00:00
// Close Current Screen On Death To Prevent Bugs
2024-01-06 11:30:23 +00:00
static void LocalPlayer_die_injection(LocalPlayer *entity, Entity *cause) {
2022-01-02 20:26:56 +00:00
// Close Screen
2024-01-06 11:30:23 +00:00
Minecraft *minecraft = entity->minecraft;
2022-01-02 20:26:56 +00:00
(*Minecraft_setScreen)(minecraft, NULL);
// Call Original Method
2024-01-06 11:30:23 +00:00
(*LocalPlayer_die_non_virtual)(entity, cause);
2022-01-02 20:26:56 +00:00
}
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
2024-01-06 11:30:23 +00:00
static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen *furnace_screen, int32_t slot, ItemInstance *item) {
// Get Existing Item
2024-01-06 11:30:23 +00:00
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;
}
}
2022-03-15 01:51:38 +00:00
// 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.
2023-02-24 22:41:49 +00:00
#ifndef MCPI_HEADLESS_MODE
2024-01-06 11:30:23 +00:00
static void GameRenderer_render_injection(GameRenderer *game_renderer, float param_1) {
2022-03-15 01:51:38 +00:00
// Call Original Method
(*GameRenderer_render)(game_renderer, param_1);
// Check If Cursor Should Render
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {
2022-05-11 22:24:03 +00:00
// Fix GL Mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2022-03-15 01:51:38 +00:00
// Get X And Y
2024-01-07 07:59:04 +00:00
float x = (*Mouse_getX)() * Gui_InvGuiScale;
float y = (*Mouse_getY)() * Gui_InvGuiScale;
2022-03-15 01:51:38 +00:00
// Render Cursor
2024-01-06 11:30:23 +00:00
Minecraft *minecraft = game_renderer->minecraft;
(*Common_renderCursor)(x, y, minecraft);
2022-03-15 01:51:38 +00:00
}
}
2023-02-24 22:41:49 +00:00
#endif
2022-03-15 01:51:38 +00:00
2022-07-10 14:37:19 +00:00
// Get Real Selected Slot
2024-01-06 11:30:23 +00:00
int32_t misc_get_real_selected_slot(Player *player) {
2022-07-10 14:37:19 +00:00
// Get Selected Slot
2024-01-06 11:30:23 +00:00
Inventory *inventory = player->inventory;
int32_t selected_slot = inventory->selectedSlot;
2022-07-10 14:37:19 +00:00
// Linked Slots
2024-01-06 11:30:23 +00:00
int32_t linked_slots_length = inventory->linked_slots_length;
2022-07-10 14:37:19 +00:00
if (selected_slot < linked_slots_length) {
2024-01-06 11:30:23 +00:00
int32_t *linked_slots = inventory->linked_slots;
2022-07-10 14:37:19 +00:00
selected_slot = linked_slots[selected_slot];
}
// Return
return selected_slot;
}
2023-12-25 22:29:30 +00:00
#ifndef MCPI_HEADLESS_MODE
2022-09-20 22:25:27 +00:00
// Properly Generate Buffers
static void anGenBuffers_injection(int32_t count, uint32_t *buffers) {
glGenBuffers(count, buffers);
}
2023-12-25 22:29:30 +00:00
#endif
2022-09-20 22:25:27 +00:00
2022-09-21 21:34:19 +00:00
// Fix Graphics Bug When Switching To First-Person While Sneaking
2024-01-06 11:30:23 +00:00
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;
2022-09-21 21:34:19 +00:00
}
2022-09-21 21:54:40 +00:00
// 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);
}
2023-02-25 00:53:41 +00:00
// Change Grass Color
2024-01-06 11:30:23 +00:00
static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) {
Biome *biome = level_source->vtable->getBiome(level_source, x, z);
2023-02-25 00:53:41 +00:00
if (biome == NULL) {
return 0;
}
2024-01-06 11:30:23 +00:00
return biome->color;
2023-02-25 00:53:41 +00:00
}
#define BIOME_BLEND_SIZE 7
2024-01-06 11:30:23 +00:00
static int32_t GrassTile_getColor_injection(__attribute__((unused)) Tile *tile, LevelSource *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) {
2023-02-25 00:53:41 +00:00
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;
}
2024-01-06 11:30:23 +00:00
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);
2023-02-25 00:53:41 +00:00
if (original_color == 0x339933) {
2024-01-06 11:30:23 +00:00
return GrassTile_getColor_injection((Tile *) tile, level_source, x, y, z);
2023-02-25 00:53:41 +00:00
} else {
return original_color;
}
}
2023-02-25 05:26:45 +00:00
// Generate Caves
2024-01-06 11:30:23 +00:00
static void RandomLevelSource_buildSurface_injection(RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) {
2023-02-25 05:26:45 +00:00
// Call Original Method
(*RandomLevelSource_buildSurface)(random_level_source, chunk_x, chunk_y, chunk_data, biomes);
// Get Level
2024-01-06 11:30:23 +00:00
Level *level = random_level_source->level;
2023-02-25 05:26:45 +00:00
// Get Cave Feature
2024-01-06 11:30:23 +00:00
LargeCaveFeature *cave_feature = &random_level_source->cave_feature;
2023-02-25 05:26:45 +00:00
// Generate
2024-01-06 11:30:23 +00:00
cave_feature->vtable->apply(cave_feature, (ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0);
2023-02-25 05:26:45 +00:00
}
2023-09-17 19:51:35 +00:00
// No Block Tinting
static int32_t Tile_getColor_injection() {
return 0xffffff;
}
// Disable Hostile AI In Creative Mode
2024-01-06 11:30:23 +00:00
#define has_vtable(obj, type) (((void *) obj->vtable) == type##_vtable_base)
static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) {
2023-09-17 19:51:35 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
Entity *target = mob->vtable->findAttackTarget(mob);
2023-09-17 19:51:35 +00:00
// Check If Creative Mode
if (target != NULL) {
2024-01-06 11:30:23 +00:00
bool is_player = has_vtable(target, Player) || has_vtable(target, LocalPlayer) || has_vtable(target, ServerPlayer) || has_vtable(target, RemotePlayer);
if (is_player) {
Player *player = (Player *) target;
Inventory *inventory = player->inventory;
bool is_creative = inventory->is_creative;
if (is_creative) {
target = NULL;
}
2023-09-17 19:51:35 +00:00
}
}
// Return
return target;
}
2023-11-24 04:54:36 +00:00
// 3D Chests
2024-01-06 11:30:23 +00:00
static int32_t Tile_getRenderShape_injection(Tile *tile) {
2024-01-07 07:59:04 +00:00
if (tile == Tile_chest) {
2023-11-24 04:54:36 +00:00
// Don't Render "Simple" Chest Model
return -1;
} else {
// Call Original Method
2024-01-06 11:30:23 +00:00
return tile->vtable->getRenderShape(tile);
2023-11-24 04:54:36 +00:00
}
}
2024-01-06 11:30:23 +00:00
static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity *tile_entity) {
2023-11-24 04:54:36 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
(*ChestTileEntity_constructor)(tile_entity);
2023-11-24 04:54:36 +00:00
// Enable Renderer
2024-01-06 11:30:23 +00:00
tile_entity->renderer_id = 1;
2023-11-24 04:54:36 +00:00
// Return
return tile_entity;
}
static bool is_rendering_chest = 0;
2024-01-06 11:30:23 +00:00
static void ModelPart_render_injection(ModelPart *model_part, float scale) {
2023-11-24 04:54:36 +00:00
// Start
is_rendering_chest = 1;
// Call Original Method
(*ModelPart_render)(model_part, scale);
// Stop
is_rendering_chest = 0;
}
2024-01-06 11:30:23 +00:00
static void Tesselator_vertexUV_injection(Tesselator *tesselator, float x, float y, float z, float u, float v) {
2023-11-24 04:54:36 +00:00
// 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;
}
2023-11-24 22:57:39 +00:00
// Animated 3D Chest
2024-01-06 11:30:23 +00:00
static ContainerMenu *ContainerMenu_injection(ContainerMenu *container_menu, Container *container, int32_t param_1) {
2023-11-24 22:57:39 +00:00
// Call Original Method
2024-01-06 11:30:23 +00:00
(*ContainerMenu_constructor)(container_menu, container, param_1);
2023-11-24 22:57:39 +00:00
// Play Animation
2024-01-06 11:30:23 +00:00
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
bool is_client = tile_entity->is_client;
2023-11-24 22:57:39 +00:00
if (!is_client) {
2024-01-06 11:30:23 +00:00
container->vtable->startOpen(container);
2023-11-24 22:57:39 +00:00
}
// Return
return container_menu;
}
2024-01-06 11:30:23 +00:00
static unsigned char *ContainerMenu_destructor_injection(ContainerMenu *container_menu) {
2023-11-24 22:57:39 +00:00
// Play Animation
2024-01-06 11:30:23 +00:00
Container *container = container_menu->container;
ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
bool is_client = tile_entity->is_client;
2023-11-24 22:57:39 +00:00
if (!is_client) {
2024-01-06 11:30:23 +00:00
container->vtable->stopOpen(container);
2023-11-24 22:57:39 +00:00
}
// Call Original Method
2024-01-06 11:30:23 +00:00
return (*ContainerMenu_destructor_non_virtual)(container_menu);
2023-11-24 22:57:39 +00:00
}
2023-12-26 07:31:22 +00:00
#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
2023-12-27 00:22:50 +00:00
glColor4f(0, 0, 0, 0.4);
2023-12-26 07:31:22 +00:00
// 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
2024-01-07 07:59:04 +00:00
line_width = 2 / Gui_InvGuiScale;
2023-12-26 07:31:22 +00:00
}
// 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
// Init
static void nop() {
}
2020-12-02 23:18:49 +00:00
void init_misc() {
2022-01-02 20:26:56 +00:00
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
2022-04-10 00:01:16 +00:00
if (feature_has("Remove Invalid Item Background", server_disabled)) {
2021-03-05 00:27:24 +00:00
unsigned char invalid_item_background_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
2020-12-02 23:18:49 +00:00
patch((void *) 0x63c98, invalid_item_background_patch);
}
2022-07-14 02:11:46 +00:00
// Classic HUD
if (feature_has("Classic HUD", server_disabled)) {
use_classic_hud = 1;
overwrite_call((void *) 0x266f8, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
overwrite_call((void *) 0x26758, (void *) Gui_renderHearts_GuiComponent_blit_hearts_injection);
overwrite_call((void *) 0x267c8, (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);
}
2021-11-14 04:29:48 +00:00
// Render Selected Item Text + Hide Chat Messages
2022-04-10 00:01:16 +00:00
hide_chat_messages = feature_has("Hide Chat Messages", server_disabled);
render_selected_item_text = feature_has("Render Selected Item Text", server_disabled);
2021-11-14 04:29:48 +00:00
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);
2021-02-17 16:31:01 +00:00
2022-07-14 23:52:51 +00:00
// 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
2024-01-06 11:30:23 +00:00
overwrite_calls((void *) Screen_render_non_virtual, (void *) Screen_render_injection);
// Sanitize Username
patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection);
2021-07-16 22:17:49 +00:00
// Fix RakNet::RakString Security Bug
2024-01-06 11:30:23 +00:00
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);
2021-07-16 22:17:49 +00:00
2021-09-12 03:18:12 +00:00
// Fix Bug Where RakNetInstance Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
2024-01-06 11:30:23 +00:00
overwrite_calls((void *) RakNetInstance_constructor, (void *) RakNetInstance_injection);
2021-09-12 03:18:12 +00:00
2022-01-02 20:26:56 +00:00
// Close Current Screen On Death To Prevent Bugs
2022-04-10 00:01:16 +00:00
if (feature_has("Close Current Screen On Death", server_disabled)) {
2022-01-02 20:26:56 +00:00
patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection);
}
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
2022-04-10 00:01:16 +00:00
if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) {
overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection);
}
2023-02-24 22:41:49 +00:00
#ifdef MCPI_HEADLESS_MODE
// Don't Render Game In Headless Mode
overwrite_calls((void *) GameRenderer_render, (void *) nop);
2023-12-25 22:29:30 +00:00
overwrite_calls((void *) NinecraftApp_initGLStates, (void *) nop);
overwrite_calls((void *) Gui_onConfigChanged, (void *) nop);
overwrite_calls((void *) LevelRenderer_generateSky, (void *) nop);
2023-02-24 22:41:49 +00:00
#else
2022-03-15 01:51:38 +00:00
// Improved Cursor Rendering
2022-04-10 00:01:16 +00:00
if (feature_has("Improved Cursor Rendering", server_disabled)) {
2022-03-15 01:51:38 +00:00
// 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);
}
2023-02-24 22:41:49 +00:00
#endif
2022-03-15 01:51:38 +00:00
2022-03-16 23:49:13 +00:00
// Disable V-Sync
if (feature_has("Disable V-Sync", server_enabled)) {
2022-03-16 23:49:13 +00:00
media_disable_vsync();
}
2022-07-16 02:08:12 +00:00
// Force EGL
if (feature_has("Force EGL", server_disabled)) {
media_force_egl();
}
// Remove Forced GUI Lag
2022-07-13 23:32:08 +00:00
if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) {
2024-01-06 11:30:23 +00:00
overwrite_calls((void *) Common_sleepMs, (void *) nop);
}
2023-12-25 22:29:30 +00:00
#ifndef MCPI_HEADLESS_MODE
2022-09-20 22:25:27 +00:00
// Properly Generate Buffers
2024-01-06 11:30:23 +00:00
overwrite((void *) Common_anGenBuffers, (void *) anGenBuffers_injection);
2023-12-25 22:29:30 +00:00
#endif
2022-09-20 22:25:27 +00:00
2022-09-21 21:34:19 +00:00
// Fix Graphics Bug When Switching To First-Person While Sneaking
patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection);
2022-09-23 03:59:44 +00:00
// 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);
}
2022-09-23 21:08:26 +00:00
// 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);
}
2023-02-25 00:53:41 +00:00
// 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);
}
2023-02-25 05:26:45 +00:00
// Generate Caves
if (feature_has("Generate Caves", server_auto)) {
overwrite_calls((void *) RandomLevelSource_buildSurface, (void *) RandomLevelSource_buildSurface_injection);
}
2023-09-17 19:51:35 +00:00
// 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);
2024-01-06 11:30:23 +00:00
overwrite((void *) LiquidTile_getColor_non_virtual, (void *) Tile_getColor_injection);
2023-09-17 19:51:35 +00:00
}
// 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);
}
2023-11-24 04:54:36 +00:00
// 3D Chests
if (feature_has("3D Chest Model", server_disabled)) {
overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection);
2024-01-06 11:30:23 +00:00
overwrite_calls((void *) ChestTileEntity_constructor, (void *) ChestTileEntity_injection);
2023-11-24 04:54:36 +00:00
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);
2023-11-24 22:57:39 +00:00
// Animation
2024-01-06 11:30:23 +00:00
overwrite_calls((void *) ContainerMenu_constructor, (void *) ContainerMenu_injection);
overwrite_calls((void *) ContainerMenu_destructor_non_virtual, (void *) ContainerMenu_destructor_injection);
2023-11-24 22:57:39 +00:00
patch_address(ContainerMenu_destructor_vtable_addr, (void *) ContainerMenu_destructor_injection);
2023-11-24 04:54:36 +00:00
}
patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection);
2023-12-26 07:31:22 +00:00
#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
2021-11-14 04:29:48 +00:00
// Init C++ And Logging
2021-06-17 21:32:24 +00:00
_init_misc_cpp();
2021-11-14 04:29:48 +00:00
_init_misc_logging();
2022-06-27 18:47:55 +00:00
_init_misc_api();
2021-06-17 21:32:24 +00:00
}