Split Up misc.cpp
All checks were successful
CI / Build (AMD64) (push) Successful in 21m28s
CI / Build (ARM64) (push) Successful in 23m24s
CI / Build (ARMHF) (push) Successful in 13m9s
CI / Test (AMD64, Server) (push) Successful in 2m14s
CI / Build Example Mods (push) Successful in 1m41s
CI / Test (ARM64, Client) (push) Successful in 4m2s
CI / Test (ARM64, Server) (push) Successful in 59s
CI / Test (AMD64, Client) (push) Successful in 6m14s
CI / Test (ARMHF, Client) (push) Successful in 4m15s
CI / Test (ARMHF, Server) (push) Successful in 1m11s
CI / Release (push) Has been skipped
All checks were successful
CI / Build (AMD64) (push) Successful in 21m28s
CI / Build (ARM64) (push) Successful in 23m24s
CI / Build (ARMHF) (push) Successful in 13m9s
CI / Test (AMD64, Server) (push) Successful in 2m14s
CI / Build Example Mods (push) Successful in 1m41s
CI / Test (ARM64, Client) (push) Successful in 4m2s
CI / Test (ARM64, Server) (push) Successful in 59s
CI / Test (AMD64, Client) (push) Successful in 6m14s
CI / Test (ARMHF, Client) (push) Successful in 4m15s
CI / Test (ARMHF, Server) (push) Successful in 1m11s
CI / Release (push) Has been skipped
This commit is contained in:
parent
c5937e6794
commit
8ef6e0885a
@ -8,6 +8,7 @@
|
||||
* Proper Create New World Screen
|
||||
* Proper Chat Screen
|
||||
* New Feature Flags
|
||||
* New Functionality
|
||||
* `Animated Lava` (Enabled By Default)
|
||||
* `Animated Fire` (Enabled By Default)
|
||||
* `Add Cake` (Enabled By Default)
|
||||
@ -39,6 +40,19 @@
|
||||
* `Render Fire In Third-Person` (Enabled By Default)
|
||||
* `Improved Water Rendering` (Enabled By Default)
|
||||
* `Classic Item Count UI` (Enabled By Default)
|
||||
* Existing Functionality (All Enabled By Default)
|
||||
* `Fix Screen Rendering When Hiding HUD`
|
||||
* `Sanitize Usernames`
|
||||
* `Patch RakNet Security Bug`
|
||||
* `Log RakNet Startup Errors`
|
||||
* `Prevent Unnecessary Server Pinging`
|
||||
* `Proper OpenGL Buffer Generation`
|
||||
* `Fix Furnace Screen Visual Bug`
|
||||
* `Fix Text Wrapping`
|
||||
* `Fullscreen Support`
|
||||
* `Always Save Chest Tile Entities`
|
||||
* `Fix Transferring Durability When Using Items`
|
||||
* `Fix Switching Perspective While Sneaking`
|
||||
* Split Up `Remove Creative Mode Restrictions` Feature Flag
|
||||
* `Remove Creative Mode Restrictions` (Disabled By Default)
|
||||
* `Display Slot Count In Creative Mode` (Disabled By Default)
|
||||
|
@ -86,3 +86,15 @@ TRUE Stop Creative Players From Burning
|
||||
TRUE Render Fire In Third-Person
|
||||
TRUE Improved Water Rendering
|
||||
TRUE Classic Item Count UI
|
||||
TRUE Fix Screen Rendering When Hiding HUD
|
||||
TRUE Sanitize Usernames
|
||||
TRUE Patch RakNet Security Bug
|
||||
TRUE Log RakNet Startup Errors
|
||||
TRUE Prevent Unnecessary Server Pinging
|
||||
TRUE Proper OpenGL Buffer Generation
|
||||
TRUE Fix Furnace Screen Visual Bug
|
||||
TRUE Fix Text Wrapping
|
||||
TRUE Fullscreen Support
|
||||
TRUE Always Save Chest Tile Entities
|
||||
TRUE Fix Transferring Durability When Using Items
|
||||
TRUE Fix Switching Perspective While Sneaking
|
@ -29,6 +29,9 @@ set(SRC
|
||||
src/misc/misc.cpp
|
||||
src/misc/logging.cpp
|
||||
src/misc/api.cpp
|
||||
src/misc/graphics.cpp
|
||||
src/misc/ui.cpp
|
||||
src/misc/tinting.cpp
|
||||
# options
|
||||
src/options/options.cpp
|
||||
src/options/ui.cpp
|
||||
@ -93,6 +96,8 @@ set(SRC
|
||||
src/multidraw/glue.cpp
|
||||
src/multidraw/buffer.cpp
|
||||
src/multidraw/storage.cpp
|
||||
# classic-ui
|
||||
src/classic-ui/classic-ui.cpp
|
||||
)
|
||||
# Install Splashes
|
||||
install(
|
||||
|
8
mods/include/mods/classic-ui/classic-ui.h
Normal file
8
mods/include/mods/classic-ui/classic-ui.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
extern "C" {
|
||||
GuiComponent_blit_t get_blit_with_classic_hud_offset();
|
||||
int get_classic_hud_y_offset(Minecraft *minecraft);
|
||||
}
|
@ -30,4 +30,5 @@ void init_override();
|
||||
void init_screenshot();
|
||||
void init_f3();
|
||||
void init_multidraw();
|
||||
void init_classic_ui();
|
||||
}
|
||||
|
2
mods/src/classic-ui/README.md
Normal file
2
mods/src/classic-ui/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# `classic-ui` Mod
|
||||
This mod adjusts the UI to make it more similar to Java Edition.
|
142
mods/src/classic-ui/classic-ui.cpp
Normal file
142
mods/src/classic-ui/classic-ui.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include <symbols/minecraft.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include <mods/init/init.h>
|
||||
#include <mods/feature/feature.h>
|
||||
#include <mods/classic-ui/classic-ui.h>
|
||||
|
||||
// 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 bool use_classic_hud = false;
|
||||
static void Gui_renderHearts_GuiComponent_blit_hearts_injection(GuiComponent *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) {
|
||||
const Minecraft *minecraft = ((Gui *) component)->minecraft;
|
||||
x_dest -= DEFAULT_HUD_PADDING;
|
||||
const float width = float(minecraft->screen_width) * Gui::InvGuiScale;
|
||||
const float height = float(minecraft->screen_height) * Gui::InvGuiScale;
|
||||
x_dest += int32_t(width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
||||
y_dest -= DEFAULT_HUD_PADDING;
|
||||
y_dest += int32_t(height) - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
||||
// Call Original Method
|
||||
component->blit(x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
||||
}
|
||||
GuiComponent_blit_t get_blit_with_classic_hud_offset() {
|
||||
return use_classic_hud ? Gui_renderHearts_GuiComponent_blit_hearts_injection : GuiComponent_blit->get(false);
|
||||
}
|
||||
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) {
|
||||
const Minecraft *minecraft = component->minecraft;
|
||||
x_dest -= DEFAULT_HUD_PADDING + HUD_ELEMENT_WIDTH;
|
||||
const float width = float(minecraft->screen_width) * Gui::InvGuiScale;
|
||||
const float height = float(minecraft->screen_height) * Gui::InvGuiScale;
|
||||
x_dest += int32_t(width) - ((int32_t(width) - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2) - HUD_ELEMENT_WIDTH;
|
||||
y_dest -= DEFAULT_HUD_PADDING;
|
||||
y_dest += int32_t(height) - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - NEW_HUD_PADDING;
|
||||
// Call Original Method
|
||||
component->blit(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) {
|
||||
const Minecraft *minecraft = component->minecraft;
|
||||
x_dest -= DEFAULT_HUD_PADDING;
|
||||
const float width = float(minecraft->screen_width) * Gui::InvGuiScale;
|
||||
const float height = float(minecraft->screen_height) * Gui::InvGuiScale;
|
||||
x_dest += int32_t(width - (NUMBER_OF_SLOTS * SLOT_WIDTH)) / 2;
|
||||
y_dest -= DEFAULT_HUD_PADDING + DEFAULT_BUBBLES_PADDING + HUD_ELEMENT_HEIGHT;
|
||||
y_dest += int32_t(height) - HUD_ELEMENT_HEIGHT - TOOLBAR_HEIGHT - HUD_ELEMENT_HEIGHT - NEW_HUD_PADDING;
|
||||
// Call Original Method
|
||||
component->blit(x_dest, y_dest, x_src, y_src, width_dest, height_dest, width_src, height_src);
|
||||
}
|
||||
int get_classic_hud_y_offset(Minecraft *minecraft) {
|
||||
int ret = 0;
|
||||
if (use_classic_hud && !minecraft->isCreativeMode()) {
|
||||
ret += (HUD_ELEMENT_HEIGHT * 2) + NEW_HUD_PADDING;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Classic Slot Count Location
|
||||
static void Gui_renderSlotText_injection_common(Gui *self, const ItemInstance *item, float x, float y, const bool param_1, const bool param_2) {
|
||||
// Position
|
||||
x += 17;
|
||||
y += 9;
|
||||
// Call Original Method
|
||||
self->renderSlotText(item, x, y, param_1, param_2);
|
||||
}
|
||||
static void Gui_renderSlotText_injection_furnace(Gui *self, const ItemInstance *item, float x, float y, const bool param_1, const bool param_2) {
|
||||
// Position
|
||||
x += 4;
|
||||
y += 5;
|
||||
// Call Original Method
|
||||
Gui_renderSlotText_injection_common(self, item, x, y, param_1, param_2);
|
||||
}
|
||||
static void unscale_slot_text(float &x, float &y) {
|
||||
const float factor = 0.5f * Gui::GuiScale;
|
||||
x /= factor;
|
||||
y /= factor;
|
||||
}
|
||||
static void Gui_renderSlotText_injection_classic_inventory(Gui *self, const ItemInstance *item, float x, float y, const bool param_1, const bool param_2) {
|
||||
// Position
|
||||
unscale_slot_text(x, y);
|
||||
// Call Original Method
|
||||
Gui_renderSlotText_injection_common(self, item, x, y, param_1, param_2);
|
||||
}
|
||||
static void Gui_renderSlotText_injection_toolbar(Gui *self, const ItemInstance *item, float x, float y, const bool param_1, const bool param_2) {
|
||||
// Position
|
||||
y--;
|
||||
unscale_slot_text(x, y);
|
||||
// Call Original Method
|
||||
Gui_renderSlotText_injection_common(self, item, x, y, param_1, param_2);
|
||||
}
|
||||
static void Gui_renderSlotText_injection_inventory(Gui *self, const ItemInstance *item, float x, float y, const bool param_1, const bool param_2) {
|
||||
// Position
|
||||
unscale_slot_text(x, y);
|
||||
x++;
|
||||
y++;
|
||||
// Call Original Method
|
||||
Gui_renderSlotText_injection_common(self, item, x, y, param_1, param_2);
|
||||
}
|
||||
template <auto *const func>
|
||||
static void Gui_renderSlotText_Font_draw_injection(Font *self, const char *raw_string, float x, float y, uint color) {
|
||||
// Fix X
|
||||
std::string string = raw_string;
|
||||
x -= self->width(string);
|
||||
// Fix Color
|
||||
if (color == 0xffcccccc) {
|
||||
color = 0xffffffff;
|
||||
}
|
||||
// Call
|
||||
(*func)->get(false)(self, string, x, y, color);
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_classic_ui() {
|
||||
// Classic HUD
|
||||
if (feature_has("Classic HUD", server_disabled)) {
|
||||
use_classic_hud = true;
|
||||
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);
|
||||
}
|
||||
|
||||
// Classic Slot Count Location
|
||||
if (feature_has("Classic Item Count UI", server_disabled)) {
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x27074, nop_patch);
|
||||
patch((void *) 0x33984, nop_patch);
|
||||
patch((void *) 0x1e424, nop_patch);
|
||||
overwrite_call((void *) 0x1e4b8, (void *) Gui_renderSlotText_injection_inventory);
|
||||
overwrite_call((void *) 0x27100, (void *) Gui_renderSlotText_injection_toolbar);
|
||||
overwrite_call((void *) 0x339b4, (void *) Gui_renderSlotText_injection_classic_inventory);
|
||||
overwrite_call((void *) 0x2b268, (void *) Gui_renderSlotText_injection_furnace);
|
||||
overwrite_call((void *) 0x320c4, (void *) Gui_renderSlotText_injection_furnace);
|
||||
overwrite_call((void *) 0x25e84, (void *) Gui_renderSlotText_Font_draw_injection<&Font_draw>);
|
||||
overwrite_call((void *) 0x25e74, (void *) Gui_renderSlotText_Font_draw_injection<&Font_drawShadow>);
|
||||
}
|
||||
}
|
@ -46,5 +46,6 @@ __attribute__((constructor)) static void init() {
|
||||
init_screenshot();
|
||||
init_f3();
|
||||
init_multidraw();
|
||||
init_classic_ui();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# `misc` Mod
|
||||
This mod has several miscellaneous mods that are too small to be their own mod, including:
|
||||
* Rendering text above the hotbar when an item is selected.
|
||||
* Rendering text above the toolbar when an item is selected.
|
||||
* Sanitizing player usernames for invalid characters.
|
||||
* Removing the red background from unobtainable items in the inventory.
|
||||
* Loading the bundled language file.
|
||||
|
352
mods/src/misc/graphics.cpp
Normal file
352
mods/src/misc/graphics.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
#include <mods/feature/feature.h>
|
||||
#include <mods/multidraw/multidraw.h>
|
||||
|
||||
#include "misc-internal.h"
|
||||
|
||||
// Properly Generate Buffers
|
||||
static void anGenBuffers_injection(__attribute__((unused)) Common_anGenBuffers_t original, const int32_t count, uint32_t *buffers) {
|
||||
if (!reborn_is_headless()) {
|
||||
glGenBuffers(count, buffers);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom Outline Color
|
||||
static void LevelRenderer_render_AABB_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
|
||||
const char *custom_line_width = getenv(MCPI_BLOCK_OUTLINE_WIDTH_ENV);
|
||||
float line_width;
|
||||
if (custom_line_width != nullptr) {
|
||||
// Custom
|
||||
line_width = strtof(custom_line_width, nullptr);
|
||||
} else {
|
||||
// Guess
|
||||
line_width = 1.5f / 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);
|
||||
}
|
||||
|
||||
// Java Light Ramp
|
||||
static void Dimension_updateLightRamp_injection(__attribute__((unused)) Dimension_updateLightRamp_t original, Dimension *self) {
|
||||
// https://github.com/ReMinecraftPE/mcpe/blob/d7a8b6baecf8b3b050538abdbc976f690312aa2d/source/world/level/Dimension.cpp#L92-L105
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
const 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Chunks
|
||||
struct chunk_data {
|
||||
Chunk *chunk;
|
||||
float distance;
|
||||
};
|
||||
#define MAX_CHUNKS_SIZE 24336
|
||||
static chunk_data data[MAX_CHUNKS_SIZE];
|
||||
static void sort_chunks(Chunk **chunks_begin, Chunk **chunks_end, const DistanceChunkSorter sorter) {
|
||||
// Calculate Distances
|
||||
const int chunks_size = chunks_end - chunks_begin;
|
||||
if (chunks_size > MAX_CHUNKS_SIZE) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
for (int i = 0; i < chunks_size; i++) {
|
||||
Chunk *chunk = chunks_begin[i];
|
||||
float distance = chunk->distanceToSqr((Entity *) sorter.mob);
|
||||
if ((1024.0 <= distance) && chunk->y < 0x40) {
|
||||
distance *= 10.0;
|
||||
}
|
||||
data[i].chunk = chunk;
|
||||
data[i].distance = distance;
|
||||
}
|
||||
|
||||
// Sort
|
||||
std::sort(data, data + chunks_size, [](chunk_data &a, chunk_data &b) {
|
||||
return a.distance < b.distance;
|
||||
});
|
||||
for (int i = 0; i < chunks_size; i++) {
|
||||
chunks_begin[i] = data[i].chunk;
|
||||
}
|
||||
}
|
||||
|
||||
// Fire Rendering
|
||||
static void EntityRenderDispatcher_render_EntityRenderer_render_injection(EntityRenderer *self, Entity *entity, float x, float y, float z, float rot, float unknown) {
|
||||
// Call Original Method
|
||||
self->render(entity, x, y, z, rot, unknown);
|
||||
|
||||
// Render Fire
|
||||
if (entity->isOnFire()) {
|
||||
// Here Be Decompiled Code
|
||||
y -= entity->height_offset;
|
||||
const int texture = Tile::fire->texture;
|
||||
const int xt = (texture & 0xf) << 4;
|
||||
const int yt = texture & 0xf0;
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
const float s = entity->hitbox_width * 1.4f;
|
||||
glScalef(s, s, s);
|
||||
self->bindTexture("terrain.png");
|
||||
Tesselator &t = Tesselator::instance;
|
||||
float r = 0.5f;
|
||||
float h = entity->hitbox_height / s;
|
||||
float yo = entity->y - entity->height_offset - entity->hitbox.y1;
|
||||
float player_rot_y = EntityRenderer::entityRenderDispatcher->player_rot_y;
|
||||
if (EntityRenderer::entityRenderDispatcher->minecraft->options.third_person == 2) {
|
||||
// Handle Front-Facing
|
||||
player_rot_y -= 180.f;
|
||||
}
|
||||
glRotatef(-player_rot_y, 0, 1, 0);
|
||||
glTranslatef(0, 0, -0.3f + float(int(h)) * 0.02f);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
float zo = 0;
|
||||
int ss = 0;
|
||||
t.begin(7);
|
||||
while (h > 0) {
|
||||
constexpr float xo = 0.0f;
|
||||
float u0;
|
||||
float u1;
|
||||
float v0;
|
||||
float v1;
|
||||
if (ss % 2 == 0) {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = float(yt) / 256.0f;
|
||||
v1 = (float(yt) + 15.99f) / 256.0f;
|
||||
} else {
|
||||
u0 = float(xt) / 256.0f;
|
||||
u1 = (float(xt) + 15.99f) / 256.0f;
|
||||
v0 = (float(yt) + 16) / 256.0f;
|
||||
v1 = (float(yt) + 16 + 15.99f) / 256.0f;
|
||||
}
|
||||
if (ss / 2 % 2 == 0) {
|
||||
std::swap(u1, u0);
|
||||
}
|
||||
t.vertexUV(r - xo, 0 - yo, zo, u1, v1);
|
||||
t.vertexUV(-r - xo, 0 - yo, zo, u0, v1);
|
||||
t.vertexUV(-r - xo, 1.4f - yo, zo, u0, v0);
|
||||
t.vertexUV(r - xo, 1.4f - yo, zo, u1, v0);
|
||||
h -= 0.45f;
|
||||
yo -= 0.45f;
|
||||
r *= 0.9f;
|
||||
zo += 0.03f;
|
||||
ss++;
|
||||
}
|
||||
t.draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
// Nicer Water Rendering
|
||||
static bool game_render_anaglyph_color_mask[4];
|
||||
static void GameRenderer_render_glColorMask_injection(const bool red, const bool green, const bool blue, const bool alpha) {
|
||||
game_render_anaglyph_color_mask[0] = red;
|
||||
game_render_anaglyph_color_mask[1] = green;
|
||||
game_render_anaglyph_color_mask[2] = blue;
|
||||
game_render_anaglyph_color_mask[3] = alpha;
|
||||
glColorMask(red, green, blue, alpha);
|
||||
}
|
||||
static int GameRenderer_render_LevelRenderer_render_injection(LevelRenderer *self, Mob *mob, int param_1, float delta) {
|
||||
glColorMask(false, false, false, false);
|
||||
const int water_chunks = self->render(mob, param_1, delta);
|
||||
glColorMask(true, true, true, true);
|
||||
if (self->minecraft->options.anaglyph_3d) {
|
||||
glColorMask(game_render_anaglyph_color_mask[0], game_render_anaglyph_color_mask[1], game_render_anaglyph_color_mask[2], game_render_anaglyph_color_mask[3]);
|
||||
}
|
||||
if (water_chunks > 0) {
|
||||
LevelRenderer_renderSameAsLast(self, delta);
|
||||
}
|
||||
return water_chunks;
|
||||
}
|
||||
|
||||
// Fix grass_carried's Bottom Texture
|
||||
static int CarriedTile_getTexture2_injection(CarriedTile_getTexture2_t original, CarriedTile *self, const int face, const int metadata) {
|
||||
if (face == 0) return 2;
|
||||
return original(self, face, metadata);
|
||||
}
|
||||
|
||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||
static void PlayerRenderer_render_injection(PlayerRenderer *model_renderer, Entity *entity, const float param_2, const float param_3, const float param_4, const float param_5, const float param_6) {
|
||||
HumanoidMobRenderer_vtable_base->render((HumanoidMobRenderer *) model_renderer, entity, param_2, param_3, param_4, param_5, param_6);
|
||||
HumanoidModel *model = model_renderer->model;
|
||||
model->is_sneaking = false;
|
||||
}
|
||||
|
||||
// 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->getRenderShape();
|
||||
}
|
||||
}
|
||||
static ChestTileEntity *ChestTileEntity_injection(ChestTileEntity_constructor_t original, ChestTileEntity *tile_entity) {
|
||||
// Call Original Method
|
||||
original(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
|
||||
model_part->render(scale);
|
||||
|
||||
// Stop
|
||||
is_rendering_chest = false;
|
||||
}
|
||||
static void Tesselator_vertexUV_injection(Tesselator_vertexUV_t original, Tesselator *tesselator, const float x, const float y, const float z, const float u, float v) {
|
||||
// Fix Chest Texture
|
||||
if (is_rendering_chest) {
|
||||
v /= 2;
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
original(tesselator, x, y, z, u, v);
|
||||
}
|
||||
static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) ChestTileEntity_shouldSave_t original, __attribute__((unused)) ChestTileEntity *tile_entity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Animated 3D Chest
|
||||
static ContainerMenu *ContainerMenu_injection(ContainerMenu_constructor_t original, ContainerMenu *container_menu, Container *container, const int32_t param_1) {
|
||||
// Call Original Method
|
||||
original(container_menu, container, param_1);
|
||||
|
||||
// Play Animation
|
||||
const ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
||||
const bool is_client = tile_entity->is_client;
|
||||
if (!is_client) {
|
||||
container->startOpen();
|
||||
}
|
||||
|
||||
// Return
|
||||
return container_menu;
|
||||
}
|
||||
static ContainerMenu *ContainerMenu_destructor_injection(ContainerMenu_destructor_complete_t original, ContainerMenu *container_menu) {
|
||||
// Play Animation
|
||||
Container *container = container_menu->container;
|
||||
const ChestTileEntity *tile_entity = (ChestTileEntity *) (((unsigned char *) container) - offsetof(ChestTileEntity, container));
|
||||
const bool is_client = tile_entity->is_client;
|
||||
if (!is_client) {
|
||||
container->stopOpen();
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
return original(container_menu);
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_misc_graphics() {
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Properly Generate Buffers
|
||||
if (feature_has("Proper OpenGL Buffer Generation", server_enabled)) {
|
||||
overwrite_calls(Common_anGenBuffers, anGenBuffers_injection);
|
||||
}
|
||||
|
||||
// Replace Block Highlight With Outline
|
||||
if (feature_has("Replace Block Highlight With Outline", server_disabled)) {
|
||||
overwrite_calls(LevelRenderer_renderHitSelect, [](__attribute__((unused)) LevelRenderer_renderHitSelect_t original, LevelRenderer *self, Player *player, const HitResult &hit_result, int i, void *vp, float f) {
|
||||
self->renderHitOutline(player, hit_result, i, vp, f);
|
||||
});
|
||||
unsigned char fix_outline_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x4d830, fix_outline_patch);
|
||||
overwrite_call((void *) 0x4d764, (void *) LevelRenderer_render_AABB_glColor4f_injection);
|
||||
}
|
||||
|
||||
// Java Light Ramp
|
||||
if (feature_has("Use Java Beta 1.3 Light Ramp", server_disabled)) {
|
||||
overwrite_calls(Dimension_updateLightRamp, Dimension_updateLightRamp_injection);
|
||||
}
|
||||
|
||||
// Replace 2011 std::sort With Optimized(TM) Code
|
||||
if (feature_has("Optimized Chunk Sorting", server_enabled)) {
|
||||
overwrite_calls_manual((void *) 0x51fac, (void *) sort_chunks);
|
||||
}
|
||||
|
||||
// Render Fire In Third-Person
|
||||
if (feature_has("Render Fire In Third-Person", server_disabled)) {
|
||||
overwrite_call((void *) 0x606c0, (void *) EntityRenderDispatcher_render_EntityRenderer_render_injection);
|
||||
}
|
||||
|
||||
// Slightly Nicer Water Rendering
|
||||
if (feature_has("Improved Water Rendering", server_disabled)) {
|
||||
overwrite_call((void *) 0x49ed4, (void *) GameRenderer_render_glColorMask_injection);
|
||||
overwrite_call((void *) 0x4a18c, (void *) GameRenderer_render_LevelRenderer_render_injection);
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x4a12c, nop_patch);
|
||||
}
|
||||
|
||||
// Fix grass_carried's Bottom Texture
|
||||
if (feature_has("Fix Carried Grass's Bottom Texture", server_disabled)) {
|
||||
overwrite_calls(CarriedTile_getTexture2, CarriedTile_getTexture2_injection);
|
||||
}
|
||||
|
||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||
if (feature_has("Fix Switching Perspective While Sneaking", server_disabled)) {
|
||||
patch_vtable(PlayerRenderer_render, PlayerRenderer_render_injection);
|
||||
}
|
||||
|
||||
// 3D Chests
|
||||
if (feature_has("3D Chest Model", server_disabled)) {
|
||||
overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection);
|
||||
overwrite_calls(ChestTileEntity_constructor, 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(Tesselator_vertexUV, 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(ContainerMenu_constructor, ContainerMenu_injection);
|
||||
overwrite_calls(ContainerMenu_destructor_complete, ContainerMenu_destructor_injection);
|
||||
}
|
||||
if (feature_has("Always Save Chest Tile Entities", server_enabled)) {
|
||||
overwrite_calls(ChestTileEntity_shouldSave, ChestTileEntity_shouldSave_injection);
|
||||
}
|
||||
|
||||
// Don't Render Game In Headless Mode
|
||||
if (reborn_is_headless()) {
|
||||
overwrite_calls(GameRenderer_render, nop<GameRenderer_render_t, GameRenderer *, float>);
|
||||
overwrite_calls(NinecraftApp_initGLStates, nop<NinecraftApp_initGLStates_t, NinecraftApp *>);
|
||||
overwrite_calls(Gui_onConfigChanged, nop<Gui_onConfigChanged_t, Gui *, const Config &>);
|
||||
overwrite_calls(LevelRenderer_generateSky, nop<LevelRenderer_generateSky_t, LevelRenderer *>);
|
||||
}
|
||||
}
|
@ -2,3 +2,10 @@
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_misc_logging();
|
||||
__attribute__((visibility("internal"))) void _init_misc_api();
|
||||
__attribute__((visibility("internal"))) void _init_misc_graphics();
|
||||
__attribute__((visibility("internal"))) void _init_misc_ui();
|
||||
__attribute__((visibility("internal"))) void _init_misc_tinting();
|
||||
|
||||
template <typename... Args>
|
||||
static void nop(__attribute__((unused)) Args... args) {
|
||||
}
|
File diff suppressed because it is too large
Load Diff
69
mods/src/misc/tinting.cpp
Normal file
69
mods/src/misc/tinting.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <mods/feature/feature.h>
|
||||
|
||||
#include "misc-internal.h"
|
||||
|
||||
// Change Grass Color
|
||||
static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) {
|
||||
const Biome *biome = level_source->getBiome(x, z);
|
||||
if (biome == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return biome->color;
|
||||
}
|
||||
#define BIOME_BLEND_SIZE 7
|
||||
static int32_t GrassTile_getColor_injection(__attribute__((unused)) GrassTile_getColor_t original, __attribute__((unused)) GrassTile *tile, LevelSource *level_source, const int32_t x, __attribute__((unused)) int32_t y, const int32_t z) {
|
||||
int r_sum = 0;
|
||||
int g_sum = 0;
|
||||
int b_sum = 0;
|
||||
int color_sum = 0;
|
||||
const int x_start = x - (BIOME_BLEND_SIZE / 2);
|
||||
const 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++) {
|
||||
const 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++;
|
||||
}
|
||||
}
|
||||
const int r_avg = r_sum / color_sum;
|
||||
const int g_avg = g_sum / color_sum;
|
||||
const int b_avg = b_sum / color_sum;
|
||||
return (r_avg << 16) | (g_avg << 8) | b_avg;
|
||||
}
|
||||
static int32_t TallGrass_getColor_injection(TallGrass_getColor_t original, TallGrass *tile, LevelSource *level_source, const int32_t x, const int32_t y, const int32_t z) {
|
||||
const int32_t original_color = original(tile, level_source, x, y, z);
|
||||
if (original_color == 0x339933) {
|
||||
return GrassTile_getColor_injection(nullptr, nullptr, level_source, x, y, z);
|
||||
} else {
|
||||
return original_color;
|
||||
}
|
||||
}
|
||||
|
||||
// No Block Tinting
|
||||
template <typename T>
|
||||
static int32_t Tile_getColor_injection(__attribute__((unused)) std::function<int(T *, LevelSource *, int, int, int)> original, __attribute__((unused)) T *self, __attribute__((unused)) LevelSource *level_source, __attribute__((unused)) int x, __attribute__((unused)) int y, __attribute__((unused)) int z) {
|
||||
return 0xffffff;
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_misc_tinting() {
|
||||
// Change Grass Color
|
||||
if (feature_has("Add Biome Colors To Grass", server_disabled)) {
|
||||
overwrite_calls(GrassTile_getColor, GrassTile_getColor_injection);
|
||||
overwrite_calls(TallGrass_getColor, TallGrass_getColor_injection);
|
||||
}
|
||||
|
||||
// Disable Block Tinting
|
||||
if (feature_has("Disable Block Tinting", server_disabled)) {
|
||||
overwrite_calls(GrassTile_getColor, Tile_getColor_injection<GrassTile>);
|
||||
overwrite_calls(TallGrass_getColor, Tile_getColor_injection<TallGrass>);
|
||||
overwrite_calls(StemTile_getColor, Tile_getColor_injection<StemTile>);
|
||||
overwrite_calls(LeafTile_getColor, Tile_getColor_injection<LeafTile>);
|
||||
overwrite_calls(LiquidTile_getColor, Tile_getColor_injection<LiquidTile>);
|
||||
}
|
||||
}
|
291
mods/src/misc/ui.cpp
Normal file
291
mods/src/misc/ui.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <mods/feature/feature.h>
|
||||
#include <mods/classic-ui/classic-ui.h>
|
||||
#include <mods/misc/misc.h>
|
||||
|
||||
#include "misc-internal.h"
|
||||
|
||||
// Heart Food Overlay
|
||||
static int heal_amount = 0, heal_amount_drawing = 0;
|
||||
static void Gui_renderHearts_injection(Gui_renderHearts_t original, Gui *gui) {
|
||||
// Get heal_amount
|
||||
heal_amount = heal_amount_drawing = 0;
|
||||
|
||||
Inventory *inventory = gui->minecraft->player->inventory;
|
||||
const ItemInstance *held_ii = inventory->getSelected();
|
||||
if (held_ii) {
|
||||
Item *held = Item::items[held_ii->id];
|
||||
if (held->isFood() && held_ii->id) {
|
||||
const int nutrition = ((FoodItem *) held)->nutrition;
|
||||
const int cur_health = gui->minecraft->player->health;
|
||||
const int heal_num = std::min(cur_health + nutrition, 20) - cur_health;
|
||||
heal_amount = heal_amount_drawing = heal_num;
|
||||
}
|
||||
}
|
||||
|
||||
// Call original
|
||||
original(gui);
|
||||
}
|
||||
#define PINK_HEART_FULL 70
|
||||
#define PINK_HEART_HALF 79
|
||||
static 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 Method
|
||||
get_blit_with_classic_hud_offset()((GuiComponent *) gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
||||
// Render The Overlay
|
||||
if (heal_amount_drawing == 1) {
|
||||
// Half Heart
|
||||
get_blit_with_classic_hud_offset()((GuiComponent *) gui, x1, y1, PINK_HEART_HALF, 0, w1, h1, w2, h2);
|
||||
heal_amount_drawing = 0;
|
||||
} else if (heal_amount_drawing > 0) {
|
||||
// Full Heart
|
||||
get_blit_with_classic_hud_offset()((GuiComponent *) gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
||||
heal_amount_drawing -= 2;
|
||||
}
|
||||
}
|
||||
static 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
|
||||
get_blit_with_classic_hud_offset()((GuiComponent *) gui, x1, y1, PINK_HEART_FULL, 0, w1, h1, w2, h2);
|
||||
heal_amount_drawing += 1;
|
||||
}
|
||||
// Call Original Method
|
||||
get_blit_with_classic_hud_offset()((GuiComponent *) gui, x1, y1, x2, y2, w1, h1, w2, h2);
|
||||
heal_amount_drawing = std::min(heal_amount_drawing, heal_amount);
|
||||
}
|
||||
|
||||
// Additional GUI Rendering
|
||||
static bool hide_chat_messages = false;
|
||||
bool is_in_chat = false;
|
||||
static bool render_selected_item_text = false;
|
||||
static void Gui_renderChatMessages_injection(Gui_renderChatMessages_t original, Gui *gui, int32_t y_offset, const uint32_t max_messages, const bool disable_fading, Font *font) {
|
||||
// Handle Classic HUD
|
||||
y_offset -= get_classic_hud_y_offset(gui->minecraft);
|
||||
|
||||
// Call Original Method
|
||||
if (!hide_chat_messages && (!is_in_chat || disable_fading)) {
|
||||
original(gui, y_offset, max_messages, disable_fading, font);
|
||||
}
|
||||
|
||||
// Render Selected Item Text
|
||||
if (render_selected_item_text && !disable_fading) {
|
||||
// Fix GL Mode
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
// Calculate Selected Item Text Scale
|
||||
const Minecraft *minecraft = gui->minecraft;
|
||||
const int32_t screen_width = minecraft->screen_width;
|
||||
const float scale = float(screen_width) * Gui::InvGuiScale;
|
||||
// Render Selected Item Text
|
||||
gui->renderOnSelectItemNameText((int32_t) scale, font, y_offset - 0x13);
|
||||
}
|
||||
}
|
||||
// Reset Selected Item Text Timer On Slot Select
|
||||
static bool reset_selected_item_text_timer = false;
|
||||
static void Gui_tick_injection(Gui_tick_t original, Gui *gui) {
|
||||
// Call Original Method
|
||||
original(gui);
|
||||
|
||||
// Handle Reset
|
||||
if (render_selected_item_text && reset_selected_item_text_timer) {
|
||||
// Reset
|
||||
gui->selected_item_text_timer = 0;
|
||||
reset_selected_item_text_timer = false;
|
||||
}
|
||||
}
|
||||
// Trigger Reset Selected Item Text Timer On Slot Select
|
||||
static void Inventory_selectSlot_injection(Inventory_selectSlot_t original, Inventory *inventory, int32_t slot) {
|
||||
// Call Original Method
|
||||
original(inventory, slot);
|
||||
|
||||
// Trigger Reset Selected Item Text Timer
|
||||
if (render_selected_item_text) {
|
||||
reset_selected_item_text_timer = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Translucent Toolbar
|
||||
static void Gui_renderToolBar_injection(Gui_renderToolBar_t original, Gui *gui, const float param_1, const int32_t param_2, const int32_t param_3) {
|
||||
// Call Original Method
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
original(gui, param_1, param_2, param_3);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
static void Gui_renderToolBar_glColor4f_injection(const GLfloat red, const GLfloat green, const GLfloat blue, __attribute__((unused)) GLfloat alpha) {
|
||||
// Fix Alpha
|
||||
glColor4f(red, green, blue, 1.0f);
|
||||
}
|
||||
|
||||
// Fix Screen Rendering When GUI is Hidden
|
||||
static void Screen_render_injection(Screen_render_t original, Screen *screen, const int32_t param_1, const int32_t param_2, const float param_3) {
|
||||
// Fix
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
// Call Original Method
|
||||
original(screen, param_1, param_2, param_3);
|
||||
}
|
||||
|
||||
// Close Current Screen On Death To Prevent Bugs
|
||||
static void LocalPlayer_die_injection(LocalPlayer_die_t original, LocalPlayer *entity, Entity *cause) {
|
||||
// Close Screen
|
||||
Minecraft *minecraft = entity->minecraft;
|
||||
minecraft->setScreen(nullptr);
|
||||
|
||||
// Call Original Method
|
||||
original(entity, cause);
|
||||
}
|
||||
|
||||
// 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.
|
||||
static void GameRenderer_render_injection(GameRenderer_render_t original, GameRenderer *game_renderer, const float param_1) {
|
||||
// Call Original Method
|
||||
original(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);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix Furnace Visual Bug
|
||||
static int FurnaceTileEntity_getLitProgress_injection(FurnaceTileEntity_getLitProgress_t original, FurnaceTileEntity *furnace, const int max) {
|
||||
// Call Original Method
|
||||
int ret = original(furnace, max);
|
||||
|
||||
// Fix Bug
|
||||
if (ret > max) {
|
||||
ret = max;
|
||||
}
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Add Missing Buttons To Pause Menu
|
||||
static void PauseScreen_init_injection(PauseScreen_init_t original, PauseScreen *screen) {
|
||||
// Call Original Method
|
||||
original(screen);
|
||||
|
||||
// Check If Server
|
||||
const Minecraft *minecraft = screen->minecraft;
|
||||
RakNetInstance *rak_net_instance = minecraft->rak_net_instance;
|
||||
if (rak_net_instance != nullptr) {
|
||||
if (rak_net_instance->isServer()) {
|
||||
// Add Button
|
||||
std::vector<Button *> *rendered_buttons = &screen->rendered_buttons;
|
||||
std::vector<Button *> *selectable_buttons = &screen->selectable_buttons;
|
||||
Button *button = screen->server_visibility_button;
|
||||
rendered_buttons->push_back(button);
|
||||
selectable_buttons->push_back(button);
|
||||
|
||||
// Update Button Text
|
||||
screen->updateServerVisibilityText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_misc_ui() {
|
||||
// Food Overlay
|
||||
if (feature_has("Food Overlay", server_disabled)) {
|
||||
overwrite_calls(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(Gui_renderChatMessages, Gui_renderChatMessages_injection);
|
||||
overwrite_calls(Gui_tick, Gui_tick_injection);
|
||||
overwrite_calls(Inventory_selectSlot, Inventory_selectSlot_injection);
|
||||
|
||||
// Translucent Toolbar
|
||||
if (feature_has("Translucent Toolbar", server_disabled)) {
|
||||
overwrite_calls(Gui_renderToolBar, Gui_renderToolBar_injection);
|
||||
overwrite_call((void *) 0x26c5c, (void *) Gui_renderToolBar_glColor4f_injection);
|
||||
}
|
||||
|
||||
// Fix Screen Rendering When GUI is Hidden
|
||||
if (feature_has("Fix Screen Rendering When Hiding HUD", server_disabled)) {
|
||||
overwrite_calls(Screen_render, Screen_render_injection);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Close Current Screen On Death To Prevent Bugs
|
||||
if (feature_has("Close Current Screen On Death", server_disabled)) {
|
||||
overwrite_calls(LocalPlayer_die, LocalPlayer_die_injection);
|
||||
}
|
||||
|
||||
// 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(GameRenderer_render, GameRenderer_render_injection);
|
||||
}
|
||||
|
||||
// Fix Furnace Visual Bug
|
||||
if (feature_has("Fix Furnace Screen Visual Bug", server_disabled)) {
|
||||
overwrite_calls(FurnaceTileEntity_getLitProgress, FurnaceTileEntity_getLitProgress_injection);
|
||||
}
|
||||
|
||||
// Fix Pause Menu
|
||||
if (feature_has("Fix Pause Menu", server_disabled)) {
|
||||
// Add Missing Buttons To Pause Menu
|
||||
overwrite_calls(PauseScreen_init, PauseScreen_init_injection);
|
||||
}
|
||||
|
||||
// Remove Forced GUI Lag
|
||||
if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) {
|
||||
overwrite_calls(Common_sleepMs, nop<Common_sleepMs_t, int>);
|
||||
}
|
||||
|
||||
// Custom GUI Scale
|
||||
const char *gui_scale_str = getenv(MCPI_GUI_SCALE_ENV);
|
||||
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);
|
||||
const 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);
|
||||
}
|
||||
|
||||
// Don't Wrap Text On '\r' Or '\t' Because They Are Actual Characters In MCPI
|
||||
if (feature_has("Fix Text Wrapping", server_disabled)) {
|
||||
patch_address(&Strings::text_wrapping_delimiter, (void *) " \n");
|
||||
}
|
||||
|
||||
// Fix Invalid ItemInHandRenderer Texture Cache
|
||||
if (feature_has("Fix Held Item Caching", server_disabled)) {
|
||||
// This works by forcing MCPI to always use the branch that enables using the
|
||||
// cache, but then patches that 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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user