Add Chat
This commit is contained in:
parent
b037ff6d98
commit
032490c7b2
3
.gitignore
vendored
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);
|
||||
|
||||
|
108
mods/src/chat/chat.cpp
Normal file
108
mods/src/chat/chat.cpp
Normal file
@ -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);
|
||||
}
|
13
mods/src/chat/chat.h
Normal file
13
mods/src/chat/chat.h
Normal file
@ -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
|
95
mods/src/chat/ui.c
Normal file
95
mods/src/chat/ui.c
Normal file
@ -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…
Reference in New Issue
Block a user