Add Chat
minecraft-pi-reborn/pipeline/head This commit looks good Details

pull/10/head
TheBrokenRail 2 years ago
parent b037ff6d98
commit 032490c7b2

3
.gitignore vendored

@ -1,2 +1,3 @@
/out
/debian/tmp
/debian/tmp
/.vscode

@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND noninteractive
RUN \
# Install Runtime Dependencies
apt-get update && \
apt-get install -y --no-install-recommends tini libgles1 libx11-6 libsdl1.2debian zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu && \
apt-get install -y --no-install-recommends tini libgles1 libx11-6 libsdl1.2debian zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu tk && \
rm -rf /var/lib/apt/lists/*
# Compile Environment

@ -8,9 +8,16 @@ extern "C" {
#include <stdlib.h>
#include <dlfcn.h>
// Logging
#define INFO(msg, ...) fprintf(stderr, "[INFO]: " msg "\n", __VA_ARGS__);
#define ERR(msg, ...) fprintf(stderr, "[ERR]: " msg "\n", __VA_ARGS__); exit(EXIT_FAILURE);
// Check Memory Allocation
#define ALLOC_CHECK(obj) if (obj == NULL) { ERR("(%s:%i) Memory Allocation Failed", __FILE__, __LINE__); }
// Set obj To NULL On asprintf() Failure
#define asprintf(obj, ...) if (asprintf(obj, __VA_ARGS__) == -1) { *obj = NULL; }
#define HOOK(name, return_type, args) \
typedef return_type (*name##_t)args; \
static name##_t real_##name = NULL; \

@ -102,6 +102,15 @@ static uint32_t Minecraft_player_property_offset = 0x18c; // LocalPlayer *
static uint32_t Minecraft_options_property_offset = 0x3c; // Options
static uint32_t Minecraft_hit_result_property_offset = 0xc38; // HitResult
static uint32_t Minecraft_progress_property_offset = 0xc60; // int32_t
static uint32_t Minecraft_command_server_property_offset = 0xcc0; // CommandServer *
// CommandServer
static uint32_t CommandServer_minecraft_property_offset = 0x18; // Minecraft *
// ChatPacket
static uint32_t ChatPacket_message_property_offset = 0xc; // char *
// HitResult
@ -245,6 +254,12 @@ static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_a
// RakNetInstance
typedef void (*RakNetInstance_send_t)(unsigned char *rak_net_instance, unsigned char *packet);
static uint32_t RakNetInstance_send_vtable_offset = 0x38;
typedef uint32_t (*RakNetInstance_isServer_t)(unsigned char *rak_net_instance);
static uint32_t RakNetInstance_isServer_vtable_offset = 0x48;
static uint32_t RakNetInstance_peer_property_offset = 0x4;
// RakNet::RakPeer
@ -261,6 +276,8 @@ static void *ServerSideNetworkHandler_onDisconnect_vtable_addr = (void *) 0x109b
typedef unsigned char *(*ServerSideNetworkHandler_getPlayer_t)(unsigned char *server_side_network_handler, unsigned char *guid);
static ServerSideNetworkHandler_getPlayer_t ServerSideNetworkHandler_getPlayer = (ServerSideNetworkHandler_getPlayer_t) 0x75464;
static void *ServerSideNetworkHandler_handle_ChatPacket_vtable_addr = (void *) 0x109c60;
// Entity
typedef void (*Entity_die_t)(unsigned char *entity, unsigned char *cause);
@ -300,6 +317,14 @@ static ItemRenderer_renderGuiItemCorrect_t ItemRenderer_renderGuiItemCorrect = (
#include <string>
// Structures
struct ConnectedClient {
uint32_t sock;
std::string str;
long time;
};
// AppPlatform
typedef void (*AppPlatform_saveScreenshot_t)(unsigned char *app_platform, std::string const& param1, std::string const& param_2);
@ -320,6 +345,11 @@ static Minecraft_selectLevel_t Minecraft_selectLevel = (Minecraft_selectLevel_t)
typedef void (*Minecraft_leaveGame_t)(unsigned char *minecraft, bool save_remote_level);
static Minecraft_leaveGame_t Minecraft_leaveGame = (Minecraft_leaveGame_t) 0x15ea0;
// CommandServer
typedef std::string (*CommandServer_parse_t)(unsigned char *command_server, struct ConnectedClient &client, std::string const& command);
static CommandServer_parse_t CommandServer_parse = (CommandServer_parse_t) 0x6aa8c;
// Level
typedef void (*Level_addParticle_t)(unsigned char *level, std::string const& particle, float x, float y, float z, float deltaX, float deltaY, float deltaZ, int count);
@ -340,7 +370,7 @@ static Textures_tick_t Textures_tick = (Textures_tick_t) 0x531c4;
// RakNet::RakPeer
typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rakpeer, const char *ip);
typedef bool (*RakNet_RakPeer_IsBanned_t)(unsigned char *rak_peer, const char *ip);
static RakNet_RakPeer_IsBanned_t RakNet_RakPeer_IsBanned = (RakNet_RakPeer_IsBanned_t) 0xda3b4;
// RakNet::SystemAddress

@ -41,7 +41,7 @@ add_library(game_mode SHARED src/game_mode/game_mode.c src/game_mode/game_mode.c
target_link_libraries(game_mode reborn)
add_library(input SHARED src/input/input.c src/input/input.cpp)
target_link_libraries(input reborn feature SDL)
target_link_libraries(input reborn feature SDL chat)
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp)
target_link_libraries(misc reborn feature util)
@ -55,11 +55,14 @@ target_link_libraries(override reborn dl)
add_library(textures SHARED src/textures/textures.cpp)
target_link_libraries(textures reborn feature GLESv1_CM)
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
target_link_libraries(chat reborn pthread)
add_library(test SHARED src/test/test.c)
target_link_libraries(test reborn)
add_library(init SHARED src/init/init.c)
target_link_libraries(init compat server game_mode camera input misc options textures test)
target_link_libraries(init compat server game_mode camera input misc options textures chat test)
## Stubs
@ -76,4 +79,4 @@ target_link_libraries(GLESv2 GLESv1_CM)
target_link_options(GLESv2 PRIVATE "-Wl,--no-as-needed")
## Install
install(TARGETS init compat readdir feature screenshot override server game_mode camera input misc options textures test bcm_host EGL GLESv2 DESTINATION /mods)
install(TARGETS init compat readdir feature screenshot override server game_mode camera input misc options textures chat test bcm_host EGL GLESv2 DESTINATION /mods)

@ -17,6 +17,7 @@ static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher
// Register TripodCameraRenderer
unsigned char *renderer = (unsigned char *) ::operator new(TRIPOD_CAMERA_RENDERER_SIZE);
ALLOC_CHECK(renderer);
(*TripodCameraRenderer)(renderer);
(*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer);

@ -0,0 +1,108 @@
#include <string>
#include <cstdio>
#include <vector>
#include <pthread.h>
#include <libreborn/libreborn.h>
#include <libreborn/minecraft.h>
#include "../init/init.h"
#include "chat.h"
// Send API Command
static void send_api_command(unsigned char *minecraft, char *str) {
struct ConnectedClient client;
client.sock = -1;
client.str = "";
client.time = 0;
unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset);
if (command_server != NULL) {
(*CommandServer_parse)(command_server, client, str);
}
}
// Send API Chat Command
static void send_api_chat_command(unsigned char *minecraft, char *str) {
char *command = NULL;
asprintf(&command, "chat.post(%s)\n", str);
ALLOC_CHECK(command);
send_api_command(minecraft, command);
free(command);
}
// Send Message To Players
static void send_message(unsigned char *server_side_network_handler, char *username, char *message) {
char *full_message = NULL;
asprintf(&full_message, "<%s> %s", username, message);
ALLOC_CHECK(full_message);
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message));
free(full_message);
}
// Manually Send (And Loopback) ChatPacket
static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned char *command_server, unsigned char *packet) {
unsigned char *minecraft = *(unsigned char **) (command_server + CommandServer_minecraft_property_offset);
if (minecraft != NULL) {
unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset);
unsigned char *rak_net_instance_vtable = *(unsigned char **) rak_net_instance;
RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset);
if ((*RakNetInstance_isServer)(rak_net_instance)) {
// Hosting Multiplayer
char *message = *(char **) (packet + ChatPacket_message_property_offset);
unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_server_side_network_handler_property_offset);
send_message(server_side_network_handler, *default_username, message);
} else {
// Client
RakNetInstance_send_t RakNetInstance_send = *(RakNetInstance_send_t *) (rak_net_instance_vtable + RakNetInstance_send_vtable_offset);
(*RakNetInstance_send)(rak_net_instance, packet);
}
}
}
// 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) {
unsigned char *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid);
if (player != NULL) {
char *username = *(char **) (player + Player_username_property_offset);
char *message = *(char **) (chat_packet + ChatPacket_message_property_offset);
send_message(server_side_network_handler, username, message);
}
}
// Message Queue
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
static std::vector<std::string> queue;
// Add To Queue
void chat_queue_message(char *message) {
// Lock
pthread_mutex_lock(&queue_mutex);
// Add
std::string str;
str.append(message);
queue.push_back(str);
// Unlock
pthread_mutex_unlock(&queue_mutex);
}
// Empty Queue
void chat_send_messages(unsigned char *minecraft) {
// Lock
pthread_mutex_lock(&queue_mutex);
// Loop
for (unsigned int i = 0; i < queue.size(); i++) {
send_api_chat_command(minecraft, (char *) queue[i].c_str());
}
queue.clear();
// Unlock
pthread_mutex_unlock(&queue_mutex);
}
// Init
void init_chat() {
// Disable Original ChatPacket Loopback
unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3};
patch((void *) 0x6b490, disable_chat_packet_loopback_patch);
// Manually Send (And Loopback) ChatPacket
overwrite_call((void *) 0x6b518, (void *) CommandServer_parse_CommandServer_dispatchPacket_injection);
// Re-Broadcast ChatPacket
patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, (void *) ServerSideNetworkHandler_handle_ChatPacket_injection);
}

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void chat_open();
void chat_queue_message(char *message);
void chat_send_messages(unsigned char *minecraft);
#ifdef __cplusplus
}
#endif

@ -0,0 +1,95 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <libreborn/libreborn.h>
#include "chat.h"
#define CHAT_WINDOW_TCL \
"set message \"\"\n" \
"proc submit {} {\n" \
"global message\n" \
"puts \"$message\"\n" \
"exit\n" \
"}\n" \
\
"wm resizable . false false\n" \
"wm title . \"Chat\"\n" \
"wm attributes . -topmost true -type {dialog}\n" \
\
"ttk::label .label -text \"Enter Chat Message:\"\n" \
\
"ttk::entry .entry -textvariable message\n" \
"focus .entry\n" \
"bind .entry <Key-Return> submit\n" \
\
"ttk::frame .button\n" \
"ttk::button .button.submit -text \"Submit\" -command submit\n" \
"ttk::button .button.cancel -text \"Cancel\" -command exit\n" \
\
"grid .label -row 0 -padx 6 -pady 6\n" \
"grid .entry -row 1 -padx 6\n" \
"grid .button -row 2 -padx 3 -pady 6\n" \
"grid .button.cancel -row 0 -column 0 -padx 3\n" \
"grid .button.submit -row 0 -column 1 -padx 3\n"
// Run Command
static char *run_command(char *command, int *return_code) {
// Don't Contaminate Child Process
unsetenv("LD_LIBRARY_PATH");
unsetenv("LD_PRELOAD");
// Start
FILE *out = popen(command, "r");
if (!out) {
ERR("%s", "Failed To Run Command");
}
// Record
char *output = NULL;
int c;
while ((c = fgetc(out)) != EOF) {
asprintf(&output, "%s%c", output == NULL ? "" : output, (char) c);
ALLOC_CHECK(output);
}
// Return
*return_code = pclose(out);
return output;
}
// Chat Thread
static void *chat_thread(__attribute__((unused)) void *nop) {
// Prepare
setenv("CHAT_WINDOW_TCL", CHAT_WINDOW_TCL, 1);
// Open
int return_code;
char *output = run_command("echo \"${CHAT_WINDOW_TCL}\" | wish -name \"Minecraft - Pi edition\"", &return_code);
// Handle Message
if (output != NULL) {
if (return_code == 0) {
// Remove Ending Newline
int length = strlen(output);
if (output[length - 1] == '\n') {
output[length - 1] = '\0';
}
length = strlen(output);
// Submit
chat_queue_message(output);
}
// Free
free(output);
}
// Return
return NULL;
}
// Create Chat Thead
void chat_open() {
pthread_t thread;
pthread_create(&thread, NULL, chat_thread, NULL);
}

@ -19,6 +19,7 @@
#include "../feature/feature.h"
#include "../input/input.h"
#include "../screenshot/screenshot.h"
#include "../chat/chat.h"
#include "../init/init.h"
#include "compat.h"
@ -99,6 +100,9 @@ static SDLKey glfw_key_to_sdl_key(int key) {
// Third Person
case GLFW_KEY_F5:
return SDLK_F5;
// Chat
case GLFW_KEY_T:
return SDLK_t;
// Unknown
default:
return SDLK_UNKNOWN;
@ -189,6 +193,8 @@ HOOK(SDL_WM_SetCaption, void, (const char *title, __attribute__((unused)) const
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Extra Settings
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, NULL, NULL);
if (!glfw_window) {
@ -274,6 +280,15 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
} else if (event->key.keysym.sym == SDLK_F5) {
input_third_person();
handled = 1;
} else if (event->key.keysym.sym == SDLK_t) {
// Release Mouse Immediately
SDL_WM_GrabInput(SDL_GRAB_OFF);
// Stop Tracking Mouse
glfw_key(glfw_window, GLFW_KEY_TAB, -1, GLFW_PRESS, -1);
glfw_key(glfw_window, GLFW_KEY_TAB, -1, GLFW_RELEASE, -1);
// Open Chat
chat_open();
handled = 1;
}
} else if (event->type == SDL_MOUSEBUTTONDOWN || event->type == SDL_MOUSEBUTTONUP) {
if (event->button.button == SDL_BUTTON_RIGHT) {

@ -18,6 +18,7 @@ static void SelectWorldScreen_tick_injection(unsigned char *screen) {
std::string new_name = (*SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
ALLOC_CHECK(new_screen);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);
@ -35,6 +36,7 @@ static void Touch_SelectWorldScreen_tick_injection(unsigned char *screen) {
std::string new_name = (*Touch_SelectWorldScreen_getUniqueLevelName)(screen, WORLD_NAME);
// Create SimpleLevelChooseScreen
unsigned char *new_screen = (unsigned char *) ::operator new(SIMPLE_LEVEL_CHOOSE_SCREEN_SIZE);
ALLOC_CHECK(new_screen);
(*SimpleChooseLevelScreen)(new_screen, new_name);
// Set Screen
unsigned char *minecraft = get_minecraft_from_screen(screen);

@ -10,4 +10,5 @@ __attribute__((constructor)) static void init() {
init_camera();
init_options();
init_textures();
init_chat();
}

@ -13,6 +13,7 @@ void init_misc();
void init_camera();
void init_options();
void init_textures();
void init_chat();
#ifdef __cplusplus
}

@ -3,6 +3,7 @@
#include "../feature/feature.h"
#include "input.h"
#include "../init/init.h"
#include "../chat/chat.h"
#include <libreborn/minecraft.h>
@ -57,6 +58,9 @@ static void Minecraft_tickInput_injection(unsigned char *minecraft) {
*(options + Options_third_person_property_offset) = *(options + Options_third_person_property_offset) ^ 1;
}
third_person_toggle = 0;
// Send Queued Chat Message
chat_send_messages(minecraft);
}
#include <SDL/SDL_events.h>

@ -12,6 +12,7 @@ static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsi
if (*(int32_t *) (sign + TileEntity_id_property_offset) == 4) {
unsigned char *minecraft = *(unsigned char **) (local_player + LocalPlayer_minecraft_property_offset);
unsigned char *screen = (unsigned char *) ::operator new(TEXT_EDIT_SCREEN_SIZE);
ALLOC_CHECK(screen);
screen = (*TextEditScreen)(screen, sign);
(*Minecraft_setScreen)(minecraft, screen);
}

@ -27,10 +27,12 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio
static void inventory_add_item(unsigned char *inventory, unsigned char *item, bool is_tile) {
unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
ALLOC_CHECK(item_instance);
item_instance = (*(is_tile ? ItemInstance_constructor_tile : ItemInstance_constructor_item))(item_instance, item);
(*FillingContainer_addItem)(inventory, item_instance);
}
// Expand Creative Inventory
static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(unsigned char *filling_container, unsigned char *item_instance) {
// Call Original
int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance);
@ -46,6 +48,7 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
continue;
}
unsigned char *item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
ALLOC_CHECK(item_instance);
item_instance = (*ItemInstance_constructor_item_extra)(item_instance, *Item_dye_powder, 1, i);
(*FillingContainer_addItem)(filling_container, item_instance);
}
@ -96,6 +99,15 @@ static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slo
reset_selected_item_text_timer = true;
}
// Print Chat To Log
static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) {
// Print Log Message
fprintf(stderr, "[CHAT]: %s\n", text.c_str());
// Call Original Method
(*Gui_addMessage)(gui, text);
}
void init_misc_cpp() {
// Implement AppPlatform::readAssetFile So Translations Work
overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection);
@ -109,4 +121,7 @@ void init_misc_cpp() {
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);
// Print Chat To Log
overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection);
}

@ -18,10 +18,12 @@ static char *get_override_path(const char *filename) {
// Get Asset Override Path
char *overrides = NULL;
asprintf(&overrides, "%s/.minecraft-pi/overrides", getenv("HOME"));
ALLOC_CHECK(overrides);
// Get data Path
char *data = NULL;
char *cwd = getcwd(NULL, 0);
asprintf(&data, "%s/data", cwd);
ALLOC_CHECK(data);
free(cwd);
// Get Full Path
char *new_path = NULL;
@ -29,6 +31,7 @@ static char *get_override_path(const char *filename) {
if (full_path != NULL) {
if (starts_with(full_path, data)) {
asprintf(&new_path, "%s%s", overrides, &full_path[strlen(data)]);
ALLOC_CHECK(new_path);
if (access(new_path, F_OK) == -1) {
free(new_path);
new_path = NULL;

@ -31,12 +31,15 @@ void take_screenshot() {
char *screenshots = NULL;
asprintf(&screenshots, "%s/.minecraft-pi/screenshots", getenv("HOME"));
ALLOC_CHECK(screenshots);
int num = 1;
char *file = NULL;
asprintf(&file, "%s/%s.png", screenshots, time);
ALLOC_CHECK(file);
while (access(file, F_OK) != -1) {
asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
ALLOC_CHECK(file);
num++;
}
@ -84,6 +87,7 @@ __attribute__((constructor)) static void init() {
// Screenshots Folder
char *screenshots_folder = NULL;
asprintf(&screenshots_folder, "%s/.minecraft-pi/screenshots", getenv("HOME"));
ALLOC_CHECK(screenshots_folder);
{
// Check Screenshots Folder
struct stat obj;

@ -53,11 +53,8 @@ static void *read_stdin_thread(__attribute__((unused)) void *data) {
}
stdin_buffer_complete = true;
} else {
if (stdin_buffer == NULL) {
asprintf((char **) &stdin_buffer, "%c", (char) x);
} else {
asprintf((char **) &stdin_buffer, "%s%c", stdin_buffer, (char) x);
}
asprintf((char **) &stdin_buffer, "%s%c", stdin_buffer == NULL ? "" : stdin_buffer, (char) x);
ALLOC_CHECK(stdin_buffer);
}
}
}
@ -87,6 +84,7 @@ static void start_world(unsigned char *minecraft) {
INFO("Listening On: %i", port);
void *screen = ::operator new(PROGRESS_SCREEN_SIZE);
ALLOC_CHECK(screen);
screen = (*ProgressScreen)((unsigned char *) screen);
(*Minecraft_setScreen)(minecraft, (unsigned char *) screen);
}
@ -348,14 +346,6 @@ static void Minecraft_update_injection(unsigned char *minecraft) {
handle_server_stop(minecraft);
}
static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) {
// Print Log Message
fprintf(stderr, "[CHAT]: %s\n", text.c_str());
// Call Original Method
(*Gui_addMessage)(gui, text);
}
static bool RakNet_RakPeer_IsBanned_injection(__attribute__((unused)) unsigned char *rakpeer, const char *ip) {
// Check banned-ips.txt
std::string banned_ips_file_path = get_banned_ips_file();
@ -483,8 +473,6 @@ static void server_init() {
// Exit handler
signal(SIGINT, exit_handler);
signal(SIGTERM, exit_handler);
// Print Chat To Log
overwrite_calls((void *) Gui_addMessage, (void *) Gui_addMessage_injection);
// Set Max Players
unsigned char max_players_patch[4] = {get_max_players(), 0x30, 0xa0, 0xe3};
patch((void *) 0x166d0, max_players_patch);

@ -48,6 +48,7 @@ void run_tests() {
{
char *path = NULL;
asprintf(&path, "%s/.minecraft-pi", getenv("HOME"));
ALLOC_CHECK(path);
int ret = access(path, R_OK | W_OK);
free(path);

@ -30,9 +30,11 @@ static float ItemRenderer_renderGuiItemCorrect_injection(unsigned char *font, un
int32_t auxilary = *(int32_t *) (item_instance + ItemInstance_auxilary_property_offset);
if (id == leaves_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
ALLOC_CHECK(carried_item_instance);
(*ItemInstance_constructor_tile_extra)(carried_item_instance, *Tile_leaves_carried, count, auxilary);
} else if (id == grass_id) {
carried_item_instance = (unsigned char *) ::operator new(ITEM_INSTANCE_SIZE);
ALLOC_CHECK(carried_item_instance);
(*ItemInstance_constructor_tile_extra)(carried_item_instance, *Tile_grass_carried, count, auxilary);
}
}

@ -22,9 +22,12 @@ mkdir -p out/deb
rm -rf debian/tmp
mkdir debian/tmp
# Version Time
DEB_VERSION_TIME="$(date --utc '+%Y%m%d.%H%M')"
# Prepare DEBIAN/control
prepare_control() {
sed -i 's/${VERSION}/'"${DEB_VERSION}.$(date --utc '+%Y%m%d.%H%M')"'/g' "$1/DEBIAN/control"
sed -i 's/${VERSION}/'"${DEB_VERSION}.${DEB_VERSION_TIME}"'/g' "$1/DEBIAN/control"
sed -i 's/${DEPENDENCIES}/'"${COMMON_DEPENDENCIES}$2"'/g' "$1/DEBIAN/control"
sed -i 's/${RECOMMENDED_DEPENDENCIES}/'"${RECOMMENDED_DEPENDENCIES}$2"'/g' "$1/DEBIAN/control"
}

Loading…
Cancel
Save