diff --git a/VERSION b/VERSION index 530cdd9..21bb5e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.4 +2.2.5 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 86bafae..a81d699 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +**2.2.5** +* Scale Animated Textures +* Add More Blocks To Expanded Creative Inventory +* Reduce Unnecessary Logging +* Log IPs In Server Mode + **2.2.4** * Instead Of Crashing, Disable Polling Block Hits In Survival Mode Using The API diff --git a/images/start.png b/images/start.png index c56ab70..6566e27 100644 Binary files a/images/start.png and b/images/start.png differ diff --git a/media-layer/include/GLES/gl.h b/media-layer/include/GLES/gl.h index ba1d9fd..935917b 100644 --- a/media-layer/include/GLES/gl.h +++ b/media-layer/include/GLES/gl.h @@ -7,6 +7,7 @@ extern "C" { #define GL_FALSE 0 #define GL_FOG_COLOR 0xb66 #define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_TEXTURE_BINDING_2D 0x8069 #define GL_UNSIGNED_BYTE 0x1401 #define GL_RGB 0x1907 #define GL_RGBA 0x1908 diff --git a/media-layer/proxy/src/GLESv1_CM.c b/media-layer/proxy/src/GLESv1_CM.c index 2eb0c6c..8d7d095 100644 --- a/media-layer/proxy/src/GLESv1_CM.c +++ b/media-layer/proxy/src/GLESv1_CM.c @@ -1099,6 +1099,7 @@ CALL(58, glIsEnabled, GLboolean, (GLenum cap)) { static int get_glGetIntegerv_params_size(GLenum pname) { switch (pname) { + case GL_TEXTURE_BINDING_2D: case GL_UNPACK_ALIGNMENT: { return 1; } diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 7b3e4f2..d6e16b0 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -54,7 +54,7 @@ else() target_link_libraries(override reborn symbols dl home) add_library(textures SHARED src/textures/textures.cpp) - target_link_libraries(textures reborn symbols feature) + target_link_libraries(textures reborn symbols media-layer-core feature) add_library(atlas SHARED src/atlas/atlas.cpp) target_link_libraries(atlas reborn symbols feature GLESv1_CM) diff --git a/mods/src/chat/chat.cpp b/mods/src/chat/chat.cpp index ed17e87..f086b7e 100644 --- a/mods/src/chat/chat.cpp +++ b/mods/src/chat/chat.cpp @@ -71,7 +71,7 @@ static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned } // Handle ChatPacket Server-Side -static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *server_side_network_handler, unsigned char *rak_net_guid, unsigned char *chat_packet) { +static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, unsigned char *chat_packet) { unsigned char *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid); if (player != NULL) { char *username = *(char **) (player + Player_username_property_offset); diff --git a/mods/src/creative/creative.cpp b/mods/src/creative/creative.cpp index 8f869ae..998e592 100644 --- a/mods/src/creative/creative.cpp +++ b/mods/src/creative/creative.cpp @@ -44,6 +44,9 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un inventory_add_item(filling_container, *Tile_topSnow, true); inventory_add_item(filling_container, *Tile_ice, true); inventory_add_item(filling_container, *Tile_invisible_bedrock, true); + inventory_add_item(filling_container, *Tile_bedrock, true); + inventory_add_item(filling_container, *Tile_info_updateGame1, true); + inventory_add_item(filling_container, *Tile_info_updateGame2, true); return ret; } diff --git a/mods/src/feature/feature.c b/mods/src/feature/feature.c index 476af7d..fda15db 100644 --- a/mods/src/feature/feature.c +++ b/mods/src/feature/feature.c @@ -29,7 +29,7 @@ int feature_has(const char *name, int server_default) { tok = strtok(NULL, "|"); } free(features); -#ifndef MCPI_SERVER_MODE +#ifdef DEBUG INFO("Feature: %s: %s", name, ret ? "Enabled" : "Disabled"); #endif return ret; diff --git a/mods/src/server/server.cpp b/mods/src/server/server.cpp index a748c57..9b4468c 100644 --- a/mods/src/server/server.cpp +++ b/mods/src/server/server.cpp @@ -198,16 +198,20 @@ static unsigned char *get_rak_peer(unsigned char *minecraft) { unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); return *(unsigned char **) (rak_net_instance + RakNetInstance_peer_property_offset); } - -// Get IP From Player -static char *get_player_ip(unsigned char *minecraft, unsigned char *player) { - RakNet_RakNetGUID guid = get_rak_net_guid(player); - unsigned char *rak_peer = get_rak_peer(minecraft); +static char *get_rak_net_guid_ip(unsigned char *rak_peer, RakNet_RakNetGUID guid) { RakNet_SystemAddress address = get_system_address(rak_peer, guid); // Get IP return (*RakNet_SystemAddress_ToString)(&address, false, '|'); } +// Get IP From Player +static char *get_player_ip(unsigned char *minecraft, unsigned char *player) { + unsigned char *rak_peer = get_rak_peer(minecraft); + RakNet_RakNetGUID guid = get_rak_net_guid(player); + // Return + return get_rak_net_guid_ip(rak_peer,guid); +} + // Ban Player static void ban_callback(unsigned char *minecraft, std::string username, unsigned char *player) { // Get IP @@ -275,25 +279,34 @@ static unsigned char *get_server_side_network_handler(unsigned char *minecraft) static volatile bool stdin_buffer_complete = false; static volatile char *stdin_buffer = NULL; static void *read_stdin_thread(__attribute__((unused)) void *data) { - while (1) { - if (!stdin_buffer_complete) { - int x = getchar(); - if (x != EOF) { - if (x == '\n') { - if (stdin_buffer == NULL) { - stdin_buffer = strdup(""); + // Check If STDIN Is A TTY + if (isatty(fileno(stdin))) { + // Loop + while (1) { + if (!stdin_buffer_complete) { + // Read Data + int x = fgetc(stdin); + if (x != EOF) { + if (x == '\n') { + if (stdin_buffer == NULL) { + stdin_buffer = strdup(""); + } + stdin_buffer_complete = true; + break; + } else { + string_append((char **) &stdin_buffer, "%c", (char) x); } - stdin_buffer_complete = true; - } else { - string_append((char **) &stdin_buffer, "%c", (char) x); } } } } + return NULL; } __attribute__((destructor)) static void _free_stdin_buffer() { - free((void *) stdin_buffer); - stdin_buffer = NULL; + if (stdin_buffer != NULL) { + free((void *) stdin_buffer); + stdin_buffer = NULL; + } } // Handle Commands @@ -385,6 +398,7 @@ static void Minecraft_update_injection(unsigned char *minecraft) { handle_server_stop(minecraft); } +// Ban Players static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned char *rakpeer, const char *ip) { // Check banned-ips.txt std::string blacklist_file_path = get_blacklist_file(); @@ -420,6 +434,27 @@ static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned c } } +// Log IPs +static unsigned char *ServerSideNetworkHandler_onReady_ClientGeneration_ServerSideNetworkHandler_popPendingPlayer_injection(unsigned char *server_side_network_handler, RakNet_RakNetGUID *guid) { + // Call Original Method + unsigned char *player = (*ServerSideNetworkHandler_popPendingPlayer)(server_side_network_handler, guid); + + // Check If Player Is Null + if (player != NULL) { + // Get Data + char *username = (char *) *(unsigned char **) (player + Player_username_property_offset); + unsigned char *minecraft = *(unsigned char **) (server_side_network_handler + ServerSideNetworkHandler_minecraft_property_offset); + unsigned char *rak_peer = get_rak_peer(minecraft); + char *ip = get_rak_net_guid_ip(rak_peer, *guid); + + // Log + INFO("%s Has Joined (IP: %s)", username, ip); + } + + // Return + return player; +} + // Get MOTD static std::string get_motd() { std::string motd(get_server_properties().get_string("motd", DEFAULT_MOTD)); @@ -532,6 +567,9 @@ static void server_init() { patch((void *) 0x737e4, minecon_badge_patch); } + // Log IPs + overwrite_call((void *) 0x75e54, (void *) ServerSideNetworkHandler_onReady_ClientGeneration_ServerSideNetworkHandler_popPendingPlayer_injection); + // Start Reading STDIN pthread_t read_stdin_thread_obj; pthread_create(&read_stdin_thread_obj, NULL, read_stdin_thread, NULL); diff --git a/mods/src/textures/textures.cpp b/mods/src/textures/textures.cpp index 450e2e9..4b54f91 100644 --- a/mods/src/textures/textures.cpp +++ b/mods/src/textures/textures.cpp @@ -1,3 +1,9 @@ +#include +#include +#include + +#include + #include #include @@ -16,10 +22,154 @@ static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, } } +// Store Texture Sizes +struct texture_data { + GLint id; + GLsizei width; + GLsizei height; +}; +static std::vector &get_texture_data() { + static std::vector data; + return data; +} +HOOK(glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)) { + // Store + texture_data data; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &data.id); + data.width = width; + data.height = height; + get_texture_data().push_back(data); + + // Call Original Method + ensure_glTexImage2D(); + (*real_glTexImage2D)(target, level, internalformat, width, height, border, format, type, pixels); +} +HOOK(glDeleteTextures, void, (GLsizei n, const GLuint *textures)) { + // Remove Old Data + for (int i = 0; i < n; i++) { + GLint id = textures[n]; + std::vector::iterator it = get_texture_data().begin(); + while (it != get_texture_data().end()) { + texture_data data = *it; + if (data.id == id) { + it = get_texture_data().erase(it); + } else { + ++it; + } + } + } + + // Call Original Method + ensure_glDeleteTextures(); + (*real_glDeleteTextures)(n, textures); +} +static void get_texture_size(GLint id, GLsizei *width, GLsizei *height) { + // Iterate + std::vector::iterator it = get_texture_data().begin(); + while (it != get_texture_data().end()) { + texture_data data = *it; + if (data.id == id) { + // Found + *width = data.width; + *height = data.height; + return; + } + ++it; + } + // Not Found + ERR("Unable To Find Size Of Texture: %i", id); +} + +// Scale Texture (Remember To Free) +#define PIXEL_SIZE 4 +static int get_line_size(int width) { + int line_size = width * PIXEL_SIZE; + { + // Handle Alignment + int alignment; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + // Round + int diff = line_size % alignment; + if (diff > 0) { + line_size = line_size + (alignment - diff); + } + } + return line_size; +} +static void *scale_texture(const unsigned char *src, GLsizei old_width, GLsizei old_height, GLsizei new_width, GLsizei new_height) { + int old_line_size = get_line_size(old_width); + int new_line_size = get_line_size(new_width); + + // Allocate + unsigned char *dst = (unsigned char *) malloc(new_height * new_line_size); + ALLOC_CHECK(dst); + + // Scale + for (int new_x = 0; new_x < new_width; new_x++) { + int old_x = (int) (((float) new_x / (float) new_width) * (float) old_width); + for (int new_y = 0; new_y < new_height; new_y++) { + int old_y = (int) (((float) new_y / (float) new_height) * (float) old_height); + + // Find Position + int new_position = (new_y * new_line_size) + (new_x * PIXEL_SIZE); + int old_position = (old_y * old_line_size) + (old_x * PIXEL_SIZE); + + // Copy + static_assert(sizeof (int32_t) == PIXEL_SIZE, "Pixel Size Doesn't Match 32-Bit Integer Size"); + *(int32_t *) &dst[new_position] = *(int32_t *) &src[old_position]; + } + } + + // Return + return dst; +} + +// Scale Animated Textures +static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) { + // Get Current Texture Size + GLint current_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); + GLsizei texture_width; + GLsizei texture_height; + get_texture_size(current_texture, &texture_width, &texture_height); + + // Calculate Factor + float width_factor = ((float) texture_width) / 256.0f; + float height_factor = ((float) texture_height) / 256.0f; + + // Only Scale If Needed + if (width_factor == 1.0f && height_factor == 1.0f) { + // No Scaling + glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + } else { + // Check + if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) { + // Pixels Must Be 4 Bytes + ERR("%s", "Unsupported Texture Format For Scaling"); + } + + // Scale + GLsizei new_width = width * width_factor; + GLsizei new_height = height * height_factor; + void *new_pixels = scale_texture((const unsigned char *) pixels, width, height, new_width, new_height); + + // Call Original Method + GLint new_xoffset = xoffset * width_factor; + GLint new_yoffset = yoffset * height_factor; + glTexSubImage2D(target, level, new_xoffset, new_yoffset, new_width, new_height, format, type, new_pixels); + + // Free + free(new_pixels); + } +} + // Init void init_textures() { // Tick Dynamic Textures (Animated Water) if (feature_has("Animated Water", 0)) { overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); } + + // Scale Animated Textures + overwrite_call((void *) 0x53274, (void *) Textures_tick_glTexSubImage2D_injection); } diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index 2c89729..70ad00d 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -36,6 +36,9 @@ static unsigned char **Tile_topSnow = (unsigned char **) 0x181b30; static unsigned char **Tile_ice = (unsigned char **) 0x181d80; static unsigned char **Tile_invisible_bedrock = (unsigned char **) 0x181d94; static unsigned char **Tile_netherReactor = (unsigned char **) 0x181dd0; +static unsigned char **Tile_info_updateGame1 = (unsigned char **) 0x181c68; +static unsigned char **Tile_info_updateGame2 = (unsigned char **) 0x181c6c; +static unsigned char **Tile_bedrock = (unsigned char **) 0x181cc4; static unsigned char **Tile_leaves = (unsigned char **) 0x18120c; static unsigned char **Tile_leaves_carried = (unsigned char **) 0x181dd8; @@ -456,17 +459,22 @@ static RakNet_SystemAddress_ToString_t RakNet_SystemAddress_ToString = (RakNet_S // ServerSideNetworkHandler -typedef void (*ServerSideNetworkHandler_onDisconnect_t)(unsigned char *server_side_network_handler, unsigned char *guid); +typedef void (*ServerSideNetworkHandler_onDisconnect_t)(unsigned char *server_side_network_handler, struct RakNet_RakNetGUID *guid); static ServerSideNetworkHandler_onDisconnect_t ServerSideNetworkHandler_onDisconnect = (ServerSideNetworkHandler_onDisconnect_t) 0x75164; static void *ServerSideNetworkHandler_onDisconnect_vtable_addr = (void *) 0x109bb0; -typedef unsigned char *(*ServerSideNetworkHandler_getPlayer_t)(unsigned char *server_side_network_handler, unsigned char *guid); +typedef unsigned char *(*ServerSideNetworkHandler_getPlayer_t)(unsigned char *server_side_network_handler, struct RakNet_RakNetGUID *guid); static ServerSideNetworkHandler_getPlayer_t ServerSideNetworkHandler_getPlayer = (ServerSideNetworkHandler_getPlayer_t) 0x75464; -typedef void (*ServerSideNetworkHandler_handle_t)(unsigned char *server_side_network_handler, unsigned char *rak_net_guid, unsigned char *packet); +typedef unsigned char *(*ServerSideNetworkHandler_popPendingPlayer_t)(unsigned char *server_side_network_handler, struct RakNet_RakNetGUID *guid); +static ServerSideNetworkHandler_popPendingPlayer_t ServerSideNetworkHandler_popPendingPlayer = (ServerSideNetworkHandler_popPendingPlayer_t) 0x75db4; + +typedef void (*ServerSideNetworkHandler_handle_t)(unsigned char *server_side_network_handler, struct RakNet_RakNetGUID *rak_net_guid, unsigned char *packet); static void *ServerSideNetworkHandler_handle_ChatPacket_vtable_addr = (void *) 0x109c60; +static uint32_t ServerSideNetworkHandler_minecraft_property_offset = 0x8; // Minecraft * + // Inventory typedef void (*Inventory_selectSlot_t)(unsigned char *inventory, int32_t slot);