Remove GL Stubs From Headless Mode
This commit is contained in:
parent
35c6adf94b
commit
ef29e4fc0e
@ -14,6 +14,9 @@ void _overwrite_call(const char *file, int line, void *start, void *target);
|
|||||||
void _overwrite_calls(const char *file, int line, void *start, void *target);
|
void _overwrite_calls(const char *file, int line, void *start, void *target);
|
||||||
#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target);
|
#define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target);
|
||||||
|
|
||||||
|
void _overwrite_calls_within(const char *file, int line, void *from, void *to, void *start, void *target);
|
||||||
|
#define overwrite_calls_within(from, to, start, target) _overwrite_calls(__FILE__, __LINE__, from, to, start, target);
|
||||||
|
|
||||||
void *extract_from_bl_instruction(unsigned char *from);
|
void *extract_from_bl_instruction(unsigned char *from);
|
||||||
|
|
||||||
void _overwrite(const char *file, int line, void *start, void *target);
|
void _overwrite(const char *file, int line, void *start, void *target);
|
||||||
|
@ -40,6 +40,26 @@ static uint32_t generate_bl_instruction(void *from, void *to, int use_b_instruct
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run For Every .text Section
|
// Run For Every .text Section
|
||||||
|
static int _overwrite_calls_within_internal(const char *file, int line, void *from, void *to, void *target, void *replacement) {
|
||||||
|
int found = 0;
|
||||||
|
for (uint32_t i = (uint32_t) from; i < (uint32_t) to; i = i + 4) {
|
||||||
|
unsigned char *addr = (unsigned char *) i;
|
||||||
|
int use_b_instruction = addr[3] == B_INSTRUCTION;
|
||||||
|
// Check If Instruction is B Or BL
|
||||||
|
if (addr[3] == BL_INSTRUCTION || use_b_instruction) {
|
||||||
|
uint32_t check_instruction = generate_bl_instruction(addr, target, use_b_instruction);
|
||||||
|
unsigned char *check_instruction_array = (unsigned char *) &check_instruction;
|
||||||
|
// Check If Instruction Calls Target
|
||||||
|
if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) {
|
||||||
|
// Patch Instruction
|
||||||
|
uint32_t new_instruction = generate_bl_instruction(addr, replacement, use_b_instruction);
|
||||||
|
_patch(file, line, addr, (unsigned char *) &new_instruction);
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
struct overwrite_data {
|
struct overwrite_data {
|
||||||
const char *file;
|
const char *file;
|
||||||
int line;
|
int line;
|
||||||
@ -50,23 +70,7 @@ struct overwrite_data {
|
|||||||
static void overwrite_calls_callback(ElfW(Addr) section_addr, ElfW(Word) size, void *data) {
|
static void overwrite_calls_callback(ElfW(Addr) section_addr, ElfW(Word) size, void *data) {
|
||||||
struct overwrite_data *args = (struct overwrite_data *) data;
|
struct overwrite_data *args = (struct overwrite_data *) data;
|
||||||
void *section = (void *) section_addr;
|
void *section = (void *) section_addr;
|
||||||
|
args->found += _overwrite_calls_within_internal(args->file, args->line, section, (void *) (section_addr + size), args->target, args->replacement);
|
||||||
for (uint32_t i = 0; i < size; i = i + 4) {
|
|
||||||
unsigned char *addr = ((unsigned char *) section) + i;
|
|
||||||
int use_b_instruction = addr[3] == B_INSTRUCTION;
|
|
||||||
// Check If Instruction is B Or BL
|
|
||||||
if (addr[3] == BL_INSTRUCTION || use_b_instruction) {
|
|
||||||
uint32_t check_instruction = generate_bl_instruction(addr, args->target, use_b_instruction);
|
|
||||||
unsigned char *check_instruction_array = (unsigned char *) &check_instruction;
|
|
||||||
// Check If Instruction Calls Target
|
|
||||||
if (addr[0] == check_instruction_array[0] && addr[1] == check_instruction_array[1] && addr[2] == check_instruction_array[2]) {
|
|
||||||
// Patch Instruction
|
|
||||||
uint32_t new_instruction = generate_bl_instruction(addr, args->replacement, use_b_instruction);
|
|
||||||
_patch(args->file, args->line, addr, (unsigned char *) &new_instruction);
|
|
||||||
args->found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit To 512 overwrite_calls() Uses
|
// Limit To 512 overwrite_calls() Uses
|
||||||
@ -139,6 +143,20 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
|||||||
ERR("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) start);
|
ERR("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void _overwrite_calls_within(const char *file, int line, void *from, void *to, void *target, void *replacement) {
|
||||||
|
// Add New Target To Code Block
|
||||||
|
update_code_block(replacement);
|
||||||
|
|
||||||
|
// Patch
|
||||||
|
int found = _overwrite_calls_within_internal(file, line, from, to, target, code_block);
|
||||||
|
// Check
|
||||||
|
if (found < 1) {
|
||||||
|
ERR("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment Code Block Position
|
||||||
|
increment_code_block();
|
||||||
|
}
|
||||||
|
|
||||||
// Extract Target Address From B(L) Instruction
|
// Extract Target Address From B(L) Instruction
|
||||||
void *extract_from_bl_instruction(unsigned char *from) {
|
void *extract_from_bl_instruction(unsigned char *from) {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
project(media-layer-core)
|
project(media-layer-core)
|
||||||
|
|
||||||
# OpenGL
|
# OpenGL
|
||||||
|
if(NOT MCPI_HEADLESS_MODE)
|
||||||
add_subdirectory(gles)
|
add_subdirectory(gles)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
set(CORE_SRC src/base.cpp src/media.c $<TARGET_OBJECTS:media-layer-extras>) # SDL Re-Implementation Using GLFW
|
set(CORE_SRC src/base.cpp src/media.c $<TARGET_OBJECTS:media-layer-extras>) # SDL Re-Implementation Using GLFW
|
||||||
@ -21,10 +23,10 @@ endif()
|
|||||||
install(TARGETS media-layer-core-real DESTINATION "${MCPI_LIB_DIR}")
|
install(TARGETS media-layer-core-real DESTINATION "${MCPI_LIB_DIR}")
|
||||||
|
|
||||||
# Link
|
# Link
|
||||||
target_link_libraries(media-layer-core-real PUBLIC media-layer-headers PUBLIC reborn-util PUBLIC GLESv1_CM PUBLIC dl)
|
target_link_libraries(media-layer-core-real PUBLIC media-layer-headers PUBLIC reborn-util PUBLIC dl)
|
||||||
if(NOT MCPI_HEADLESS_MODE)
|
if(NOT MCPI_HEADLESS_MODE)
|
||||||
# OpenAL
|
# OpenAL
|
||||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||||
# Link
|
# Link
|
||||||
target_link_libraries(media-layer-core-real PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw PRIVATE LIB_LIEF)
|
target_link_libraries(media-layer-core-real PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw PUBLIC GLESv1_CM PRIVATE LIB_LIEF)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
project(media-layer-gles)
|
project(media-layer-gles)
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
if(MCPI_HEADLESS_MODE)
|
if(MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||||
# Stubs For Headless Mode
|
|
||||||
add_library(GLESv1_CM OBJECT src/stubs.c)
|
|
||||||
target_link_libraries(GLESv1_CM PRIVATE media-layer-headers)
|
|
||||||
elseif(MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
|
||||||
# GLESv1_CM Compatibility Layer
|
# GLESv1_CM Compatibility Layer
|
||||||
add_library(GLESv1_CM INTERFACE)
|
add_library(GLESv1_CM INTERFACE)
|
||||||
target_link_libraries(GLESv1_CM INTERFACE gles-compatibility-layer)
|
target_link_libraries(GLESv1_CM INTERFACE gles-compatibility-layer)
|
||||||
|
@ -1,170 +0,0 @@
|
|||||||
#include <GLES/gl.h>
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
|
|
||||||
void glFogfv(GLenum pname, const GLfloat *params) {
|
|
||||||
}
|
|
||||||
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
}
|
|
||||||
void glLineWidth(GLfloat width) {
|
|
||||||
}
|
|
||||||
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
|
||||||
}
|
|
||||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
||||||
}
|
|
||||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
|
||||||
}
|
|
||||||
void glClear(GLbitfield mask) {
|
|
||||||
}
|
|
||||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
|
||||||
}
|
|
||||||
void glFogx(GLenum pname, GLfixed param) {
|
|
||||||
}
|
|
||||||
void glFogf(GLenum pname, GLfloat param) {
|
|
||||||
}
|
|
||||||
void glMatrixMode(GLenum mode) {
|
|
||||||
}
|
|
||||||
void glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
}
|
|
||||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
||||||
}
|
|
||||||
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|
||||||
}
|
|
||||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
|
|
||||||
}
|
|
||||||
void glEnable(GLenum cap) {
|
|
||||||
}
|
|
||||||
void glEnableClientState(GLenum array) {
|
|
||||||
}
|
|
||||||
void glPolygonOffset(GLfloat factor, GLfloat units) {
|
|
||||||
}
|
|
||||||
void glDisableClientState(GLenum array) {
|
|
||||||
}
|
|
||||||
void glDepthRangef(GLclampf near, GLclampf far) {
|
|
||||||
}
|
|
||||||
void glDepthFunc(GLenum func) {
|
|
||||||
}
|
|
||||||
static GLuint current_buffer = 0;
|
|
||||||
void glBindBuffer(GLenum target, GLuint buffer) {
|
|
||||||
if (target == GL_ARRAY_BUFFER) {
|
|
||||||
current_buffer = buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
|
||||||
}
|
|
||||||
void glPopMatrix() {
|
|
||||||
}
|
|
||||||
void glLoadIdentity() {
|
|
||||||
}
|
|
||||||
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
|
||||||
}
|
|
||||||
void glPushMatrix() {
|
|
||||||
}
|
|
||||||
void glDepthMask(GLboolean flag) {
|
|
||||||
}
|
|
||||||
void glHint(GLenum target, GLenum mode) {
|
|
||||||
}
|
|
||||||
void glMultMatrixf(const GLfloat *m) {
|
|
||||||
}
|
|
||||||
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
|
||||||
}
|
|
||||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers) {
|
|
||||||
}
|
|
||||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
|
||||||
}
|
|
||||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
|
||||||
}
|
|
||||||
void glGenTextures(GLsizei n, GLuint *textures) {
|
|
||||||
static int i = 1;
|
|
||||||
for (int j = 0; j < n; j++) {
|
|
||||||
textures[j] = i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void glDeleteTextures(GLsizei n, const GLuint *textures) {
|
|
||||||
}
|
|
||||||
void glAlphaFunc(GLenum func, GLclampf ref) {
|
|
||||||
}
|
|
||||||
void glGetFloatv(GLenum pname, GLfloat *params) {
|
|
||||||
switch (pname) {
|
|
||||||
case GL_MODELVIEW_MATRIX:
|
|
||||||
case GL_PROJECTION_MATRIX: {
|
|
||||||
params[0] = 1;
|
|
||||||
params[1] = 0;
|
|
||||||
params[2] = 0;
|
|
||||||
params[3] = 0;
|
|
||||||
params[4] = 0;
|
|
||||||
params[5] = 1;
|
|
||||||
params[6] = 0;
|
|
||||||
params[7] = 0;
|
|
||||||
params[8] = 0;
|
|
||||||
params[9] = 0;
|
|
||||||
params[10] = 1;
|
|
||||||
params[11] = 0;
|
|
||||||
params[12] = 0;
|
|
||||||
params[13] = 0;
|
|
||||||
params[14] = 0;
|
|
||||||
params[15] = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
params[0] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static GLuint current_texture = 0;
|
|
||||||
void glBindTexture(GLenum target, GLuint texture) {
|
|
||||||
if (target == GL_TEXTURE_2D) {
|
|
||||||
current_texture = texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
|
||||||
}
|
|
||||||
void glShadeModel(GLenum mode) {
|
|
||||||
}
|
|
||||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) {
|
|
||||||
}
|
|
||||||
void glDisable(GLenum cap) {
|
|
||||||
}
|
|
||||||
void glCullFace(GLenum mode) {
|
|
||||||
}
|
|
||||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
|
||||||
}
|
|
||||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
||||||
}
|
|
||||||
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) {
|
|
||||||
}
|
|
||||||
GLboolean glIsEnabled(GLenum cap) {
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
void glGetIntegerv(GLenum pname, GLint *data) {
|
|
||||||
switch (pname) {
|
|
||||||
case GL_TEXTURE_BINDING_2D: {
|
|
||||||
data[0] = current_texture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_ARRAY_BUFFER_BINDING: {
|
|
||||||
data[0] = current_buffer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_UNPACK_ALIGNMENT: {
|
|
||||||
data[0] = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
data[0] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data) {
|
|
||||||
}
|
|
||||||
void glGenBuffers(GLsizei n, GLuint *buffers) {
|
|
||||||
static int i = 1;
|
|
||||||
for (int j = 0; j < n; j++) {
|
|
||||||
buffers[j] = i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
|
@ -301,10 +301,12 @@ int32_t misc_get_real_selected_slot(unsigned char *player) {
|
|||||||
return selected_slot;
|
return selected_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
// Properly Generate Buffers
|
// Properly Generate Buffers
|
||||||
static void anGenBuffers_injection(int32_t count, uint32_t *buffers) {
|
static void anGenBuffers_injection(int32_t count, uint32_t *buffers) {
|
||||||
glGenBuffers(count, buffers);
|
glGenBuffers(count, buffers);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||||
static void HumanoidMobRenderer_render_injection(unsigned char *model_renderer, unsigned char *entity, float param_2, float param_3, float param_4, float param_5, float param_6) {
|
static void HumanoidMobRenderer_render_injection(unsigned char *model_renderer, unsigned char *entity, float param_2, float param_3, float param_4, float param_5, float param_6) {
|
||||||
@ -554,6 +556,9 @@ void init_misc() {
|
|||||||
#ifdef MCPI_HEADLESS_MODE
|
#ifdef MCPI_HEADLESS_MODE
|
||||||
// Don't Render Game In Headless Mode
|
// Don't Render Game In Headless Mode
|
||||||
overwrite_calls((void *) GameRenderer_render, (void *) nop);
|
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
|
#else
|
||||||
// Improved Cursor Rendering
|
// Improved Cursor Rendering
|
||||||
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
||||||
@ -580,8 +585,10 @@ void init_misc() {
|
|||||||
overwrite_calls((void *) sleepMs, (void *) nop);
|
overwrite_calls((void *) sleepMs, (void *) nop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MCPI_HEADLESS_MODE
|
||||||
// Properly Generate Buffers
|
// Properly Generate Buffers
|
||||||
overwrite((void *) anGenBuffers, (void *) anGenBuffers_injection);
|
overwrite((void *) anGenBuffers, (void *) anGenBuffers_injection);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
// Fix Graphics Bug When Switching To First-Person While Sneaking
|
||||||
patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection);
|
patch_address(PlayerRenderer_render_vtable_addr, (void *) HumanoidMobRenderer_render_injection);
|
||||||
|
@ -170,6 +170,11 @@ static TileRenderer_tesselateBlockInWorld_t TileRenderer_tesselateBlockInWorld =
|
|||||||
typedef void (*GameMode_releaseUsingItem_t)(unsigned char *game_mode, unsigned char *player);
|
typedef void (*GameMode_releaseUsingItem_t)(unsigned char *game_mode, unsigned char *player);
|
||||||
static uint32_t GameMode_releaseUsingItem_vtable_offset = 0x5c;
|
static uint32_t GameMode_releaseUsingItem_vtable_offset = 0x5c;
|
||||||
|
|
||||||
|
// NinecraftApp
|
||||||
|
|
||||||
|
typedef void (*NinecraftApp_initGLStates_t)(unsigned char *minecraft);
|
||||||
|
static NinecraftApp_initGLStates_t NinecraftApp_initGLStates = (NinecraftApp_initGLStates_t) 0x148c8;
|
||||||
|
|
||||||
// Minecraft
|
// Minecraft
|
||||||
|
|
||||||
typedef void (*Minecraft_init_t)(unsigned char *minecraft);
|
typedef void (*Minecraft_init_t)(unsigned char *minecraft);
|
||||||
@ -506,6 +511,9 @@ static Gui_renderToolBar_t Gui_renderToolBar = (Gui_renderToolBar_t) 0x26c30;
|
|||||||
typedef void (*Gui_renderChatMessages_t)(unsigned char *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, unsigned char *font);
|
typedef void (*Gui_renderChatMessages_t)(unsigned char *gui, int32_t y_offset, uint32_t max_messages, bool disable_fading, unsigned char *font);
|
||||||
static Gui_renderChatMessages_t Gui_renderChatMessages = (Gui_renderChatMessages_t) 0x273d8;
|
static Gui_renderChatMessages_t Gui_renderChatMessages = (Gui_renderChatMessages_t) 0x273d8;
|
||||||
|
|
||||||
|
typedef void (*Gui_onConfigChanged_t)(unsigned char *gui, unsigned char *config);
|
||||||
|
static Gui_onConfigChanged_t Gui_onConfigChanged = (Gui_onConfigChanged_t) 0x255bc;
|
||||||
|
|
||||||
static uint32_t Gui_minecraft_property_offset = 0x9f4; // Minecraft *
|
static uint32_t Gui_minecraft_property_offset = 0x9f4; // Minecraft *
|
||||||
static uint32_t Gui_selected_item_text_timer_property_offset = 0x9fc; // float
|
static uint32_t Gui_selected_item_text_timer_property_offset = 0x9fc; // float
|
||||||
|
|
||||||
@ -563,6 +571,9 @@ static LevelRenderer_render_t LevelRenderer_render = (LevelRenderer_render_t) 0x
|
|||||||
typedef void (*LevelRenderer_renderDebug_t)(unsigned char *level_renderer, struct AABB *aabb, float delta);
|
typedef void (*LevelRenderer_renderDebug_t)(unsigned char *level_renderer, struct AABB *aabb, float delta);
|
||||||
static LevelRenderer_renderDebug_t LevelRenderer_renderDebug = (LevelRenderer_renderDebug_t) 0x4d310;
|
static LevelRenderer_renderDebug_t LevelRenderer_renderDebug = (LevelRenderer_renderDebug_t) 0x4d310;
|
||||||
|
|
||||||
|
typedef void (*LevelRenderer_generateSky_t)(unsigned char *level_renderer);
|
||||||
|
static LevelRenderer_generateSky_t LevelRenderer_generateSky = (LevelRenderer_generateSky_t) 0x4d0d4;
|
||||||
|
|
||||||
static uint32_t LevelRenderer_minecraft_property_offset = 0x4; // Minecraft *
|
static uint32_t LevelRenderer_minecraft_property_offset = 0x4; // Minecraft *
|
||||||
|
|
||||||
// PerfRenderer
|
// PerfRenderer
|
||||||
|
Loading…
Reference in New Issue
Block a user