Merge branch 'master' into master
This commit is contained in:
commit
b9f9e3aafb
|
@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND noninteractive
|
||||||
RUN \
|
RUN \
|
||||||
# Install Runtime Dependencies
|
# Install Runtime Dependencies
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y --no-install-recommends tini libgles1 libx11-6 libsdl1.2debian zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu tk && \
|
apt-get install -y --no-install-recommends tini libgles1 libx11-6 zlib1g libfreeimage3 libglfw3 xinput libxfixes3 gosu tk && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Compile Environment
|
# Compile Environment
|
||||||
|
@ -43,9 +43,7 @@ RUN \
|
||||||
mkdir -p /home && \
|
mkdir -p /home && \
|
||||||
chmod -R a+rw /home
|
chmod -R a+rw /home
|
||||||
|
|
||||||
# Include Exported Libraries
|
# Copy Build
|
||||||
COPY --from=build /app/export /
|
|
||||||
# Include Mods
|
|
||||||
COPY --from=build /app/minecraft-pi /app/minecraft-pi
|
COPY --from=build /app/minecraft-pi /app/minecraft-pi
|
||||||
|
|
||||||
WORKDIR /app/minecraft-pi
|
WORKDIR /app/minecraft-pi
|
||||||
|
|
|
@ -6,10 +6,12 @@ git clone --depth 1 https://git.code.sf.net/p/libpng/code libpng -b libpng12
|
||||||
|
|
||||||
cd libpng
|
cd libpng
|
||||||
|
|
||||||
./configure --prefix /usr
|
./configure
|
||||||
|
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
make install DESTDIR=/app/export
|
|
||||||
|
mkdir -p ../minecraft-pi/lib
|
||||||
|
cp -L .libs/libpng12.so.0 ../minecraft-pi/lib
|
||||||
|
|
||||||
cd ../
|
cd ../
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ RET=$?
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Kill Logging
|
# Kill Logging
|
||||||
kill ${TAIL_PID}
|
kill ${TAIL_PID} > /dev/null 2>&1 || :
|
||||||
|
|
||||||
# Exit
|
# Exit
|
||||||
exit ${RET}
|
exit ${RET}
|
|
@ -3,4 +3,4 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Launch Minecraft
|
# Launch Minecraft
|
||||||
docker-compose -f "${DOCKER_COMPOSE_YML}" run --rm minecraft-pi
|
exec docker-compose -f "${DOCKER_COMPOSE_YML}" run --rm minecraft-pi
|
|
@ -13,6 +13,7 @@ RET=$?
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Kill VirGL
|
# Kill VirGL
|
||||||
kill ${VIRGL_PID} > /dev/null 2>&1
|
kill ${VIRGL_PID} > /dev/null 2>&1 || :
|
||||||
|
|
||||||
|
# Exit
|
||||||
exit ${RET}
|
exit ${RET}
|
|
@ -4,8 +4,31 @@ project(launcher)
|
||||||
|
|
||||||
add_compile_options(-Wall -Wextra -Werror)
|
add_compile_options(-Wall -Wextra -Werror)
|
||||||
|
|
||||||
|
## Launcher
|
||||||
|
|
||||||
add_executable(launcher src/launcher.c)
|
add_executable(launcher src/launcher.c)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
install(TARGETS launcher DESTINATION /)
|
install(TARGETS launcher DESTINATION /)
|
||||||
install(PROGRAMS src/run.sh DESTINATION /)
|
install(PROGRAMS src/run.sh DESTINATION /)
|
||||||
|
|
||||||
|
## Stubs
|
||||||
|
|
||||||
|
# Stub RPI-Specific Graphics
|
||||||
|
add_library(bcm_host SHARED src/stubs/bcm_host.c)
|
||||||
|
|
||||||
|
# Stub EGL
|
||||||
|
add_library(EGL SHARED src/stubs/EGL.c)
|
||||||
|
|
||||||
|
# Stub SDL
|
||||||
|
add_library(SDL-1.2 SHARED src/stubs/SDL.cpp)
|
||||||
|
target_link_libraries(SDL-1.2 pthread)
|
||||||
|
set_target_properties(SDL-1.2 PROPERTIES SOVERSION "0")
|
||||||
|
|
||||||
|
# MCPI Links Against GLESv2 But Uses GLESv1_CM
|
||||||
|
add_library(GLESv2 SHARED src/stubs/GLESv2.c)
|
||||||
|
target_link_libraries(GLESv2 GLESv1_CM)
|
||||||
|
target_link_options(GLESv2 PRIVATE "-Wl,--no-as-needed")
|
||||||
|
|
||||||
|
# Install Stubs
|
||||||
|
install(TARGETS bcm_host EGL SDL-1.2 GLESv2 DESTINATION /lib)
|
|
@ -9,10 +9,10 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// Check String Prefix/Suffix
|
||||||
static int starts_with(const char *s, const char *t) {
|
static int starts_with(const char *s, const char *t) {
|
||||||
return strncmp(s, t, strlen(t)) == 0;
|
return strncmp(s, t, strlen(t)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ends_with(const char *s, const char *t) {
|
static int ends_with(const char *s, const char *t) {
|
||||||
size_t slen = strlen(s);
|
size_t slen = strlen(s);
|
||||||
size_t tlen = strlen(t);
|
size_t tlen = strlen(t);
|
||||||
|
@ -20,6 +20,7 @@ static int ends_with(const char *s, const char *t) {
|
||||||
return strcmp(s + slen - tlen, t) == 0;
|
return strcmp(s + slen - tlen, t) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set Environmental Variable
|
||||||
static void trim(char *value) {
|
static void trim(char *value) {
|
||||||
// Remove Trailing Colon
|
// Remove Trailing Colon
|
||||||
int length = strlen(value);
|
int length = strlen(value);
|
||||||
|
@ -27,26 +28,30 @@ static void trim(char *value) {
|
||||||
value[length - 1] = '\0';
|
value[length - 1] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_and_print_env(char *name, char *value) {
|
static void set_and_print_env(char *name, char *value) {
|
||||||
// Set Variable With Not Trailing Colon
|
// Set Variable With No Trailing Colon
|
||||||
trim(value);
|
trim(value);
|
||||||
|
|
||||||
fprintf(stderr, "Set %s = %s\n", name, value);
|
fprintf(stderr, "Set %s = %s\n", name, value);
|
||||||
setenv(name, value, 1);
|
setenv(name, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Environmental Variable
|
||||||
static char *get_env_safe(const char *name) {
|
static char *get_env_safe(const char *name) {
|
||||||
// Get Variable Or Blank String If Not Set
|
// Get Variable Or Blank String If Not Set
|
||||||
char *ret = getenv(name);
|
char *ret = getenv(name);
|
||||||
return ret != NULL ? ret : "";
|
return ret != NULL ? ret : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load(char **ld_path, char **ld_preload, char *folder) {
|
// Get All SO Files In Folder
|
||||||
|
static void load(char **ld_preload, char *folder) {
|
||||||
int folder_name_length = strlen(folder);
|
int folder_name_length = strlen(folder);
|
||||||
|
// Retry Until Successful
|
||||||
while (1) {
|
while (1) {
|
||||||
|
// Open Folder
|
||||||
DIR *dp = opendir(folder);
|
DIR *dp = opendir(folder);
|
||||||
if (dp != NULL) {
|
if (dp != NULL) {
|
||||||
|
// Loop Through Folder
|
||||||
struct dirent *entry = NULL;
|
struct dirent *entry = NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -75,14 +80,14 @@ static void load(char **ld_path, char **ld_preload, char *folder) {
|
||||||
fprintf(stderr, "Error Reading Directory: %s: %s\n", folder, strerror(errno));
|
fprintf(stderr, "Error Reading Directory: %s: %s\n", folder, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
|
// Done!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Close Folder
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
|
||||||
// Add To LD_LIBRARY_PATH
|
// Exit Function
|
||||||
asprintf(ld_path, "%s:%s", *ld_path, folder);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (errno == ENOENT) {
|
} else if (errno == ENOENT) {
|
||||||
// Folder Doesn't Exists, Attempt Creation
|
// Folder Doesn't Exists, Attempt Creation
|
||||||
|
@ -92,6 +97,7 @@ static void load(char **ld_path, char **ld_preload, char *folder) {
|
||||||
fprintf(stderr, "Error Creating Directory: %s: %s\n", folder, strerror(errno));
|
fprintf(stderr, "Error Creating Directory: %s: %s\n", folder, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
// Continue Retrying
|
||||||
} else {
|
} else {
|
||||||
// Unable To Open Folder
|
// Unable To Open Folder
|
||||||
fprintf(stderr, "Error Opening Directory: %s: %s\n", folder, strerror(errno));
|
fprintf(stderr, "Error Opening Directory: %s: %s\n", folder, strerror(errno));
|
||||||
|
@ -121,31 +127,25 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
free(minecraft_folder);
|
free(minecraft_folder);
|
||||||
|
|
||||||
char *ld_path = NULL;
|
// Configure LD_LIBRARY_PATH
|
||||||
|
char *ld_path;
|
||||||
// Start Configuring LD_LIBRARY_PATH
|
asprintf(&ld_path, "./lib:/usr/arm-linux-gnueabihf/lib:%s", get_env_safe("LD_LIBRARY_PATH"));
|
||||||
asprintf(&ld_path, "/usr/arm-linux-gnueabihf/lib");
|
set_and_print_env("LD_LIBRARY_PATH", ld_path);
|
||||||
|
free(ld_path);
|
||||||
|
|
||||||
// Start Configuring LD_PRELOAD
|
// Start Configuring LD_PRELOAD
|
||||||
char *ld_preload = NULL;
|
char *ld_preload = NULL;
|
||||||
asprintf(&ld_preload, "%s", get_env_safe("LD_PRELOAD"));
|
asprintf(&ld_preload, "%s", get_env_safe("LD_PRELOAD"));
|
||||||
|
|
||||||
// Load Mods From ./mods
|
// Load Mods From ./mods
|
||||||
load(&ld_path, &ld_preload, "./mods/");
|
load(&ld_preload, "./mods/");
|
||||||
|
|
||||||
// Loads Mods From ~/.minecraft-pi/mods
|
// Loads Mods From ~/.minecraft-pi/mods
|
||||||
char *home_mods = NULL;
|
char *home_mods = NULL;
|
||||||
asprintf(&home_mods, "%s/.minecraft-pi/mods/", getenv("HOME"));
|
asprintf(&home_mods, "%s/.minecraft-pi/mods/", getenv("HOME"));
|
||||||
load(&ld_path, &ld_preload, home_mods);
|
load(&ld_preload, home_mods);
|
||||||
free(home_mods);
|
free(home_mods);
|
||||||
|
|
||||||
// Add Existing LD_LIBRARY_PATH
|
|
||||||
asprintf(&ld_path, "%s:%s", ld_path, get_env_safe("LD_LIBRARY_PATH"));
|
|
||||||
|
|
||||||
// Set LD_LIBRARY_PATH
|
|
||||||
set_and_print_env("LD_LIBRARY_PATH", ld_path);
|
|
||||||
free(ld_path);
|
|
||||||
|
|
||||||
// Set LD_PRELOAD
|
// Set LD_PRELOAD
|
||||||
set_and_print_env("LD_PRELOAD", ld_preload);
|
set_and_print_env("LD_PRELOAD", ld_preload);
|
||||||
free(ld_preload);
|
free(ld_preload);
|
||||||
|
|
|
@ -32,4 +32,4 @@ if ! id user > /dev/null 2>&1; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Start
|
# Start
|
||||||
exec gosu "${USER_UID}" ./launcher
|
exec gosu user ./launcher
|
|
@ -1,8 +1,6 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
#include "../compat/compat.h"
|
// EGL Is Replaced With GLFW
|
||||||
|
|
||||||
// EGL/SDL Is Replaced With GLFW
|
|
||||||
|
|
||||||
EGLDisplay eglGetDisplay(__attribute__((unused)) NativeDisplayType native_display) {
|
EGLDisplay eglGetDisplay(__attribute__((unused)) NativeDisplayType native_display) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -34,9 +32,6 @@ EGLBoolean eglDestroyContext(__attribute__((unused)) EGLDisplay display, __attri
|
||||||
EGLBoolean eglTerminate(__attribute__((unused)) EGLDisplay display) {
|
EGLBoolean eglTerminate(__attribute__((unused)) EGLDisplay display) {
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send Buffer Swap Request To GLFW
|
|
||||||
EGLBoolean eglSwapBuffers(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
EGLBoolean eglSwapBuffers(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
|
||||||
compat_eglSwapBuffers();
|
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
|
||||||
|
// SDL Is Replaced With GLFW
|
||||||
|
|
||||||
|
int SDL_Init(__attribute__((unused)) uint32_t flags) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDL_Quit() {
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event Queue
|
||||||
|
|
||||||
|
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static std::vector<SDL_Event> queue;
|
||||||
|
|
||||||
|
int SDL_PollEvent(SDL_Event *event) {
|
||||||
|
pthread_mutex_lock(&queue_mutex);
|
||||||
|
int ret;
|
||||||
|
if (queue.size() > 0) {
|
||||||
|
*event = queue[0];
|
||||||
|
queue.erase(queue.begin());
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&queue_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDL_PushEvent(SDL_Event *event) {
|
||||||
|
pthread_mutex_lock(&queue_mutex);
|
||||||
|
queue.push_back(*event);
|
||||||
|
pthread_mutex_unlock(&queue_mutex);
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ extern "C" {
|
||||||
// Set obj To NULL On asprintf() Failure
|
// Set obj To NULL On asprintf() Failure
|
||||||
#define asprintf(obj, ...) if (asprintf(obj, __VA_ARGS__) == -1) { *obj = NULL; }
|
#define asprintf(obj, ...) if (asprintf(obj, __VA_ARGS__) == -1) { *obj = NULL; }
|
||||||
|
|
||||||
|
// Hook Library Function
|
||||||
#define HOOK(name, return_type, args) \
|
#define HOOK(name, return_type, args) \
|
||||||
typedef return_type (*name##_t)args; \
|
typedef return_type (*name##_t)args; \
|
||||||
static name##_t real_##name = NULL; \
|
static name##_t real_##name = NULL; \
|
||||||
|
@ -34,6 +35,11 @@ extern "C" {
|
||||||
\
|
\
|
||||||
__attribute__((__used__)) return_type name args
|
__attribute__((__used__)) return_type name args
|
||||||
|
|
||||||
|
// Sanitize String
|
||||||
|
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
|
||||||
|
|
||||||
|
// Patching Functions
|
||||||
|
|
||||||
void _overwrite_call(const char *file, int line, void *start, void *target);
|
void _overwrite_call(const char *file, int line, void *start, void *target);
|
||||||
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target);
|
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target);
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,17 @@ static uint32_t Minecraft_gui_property_offset = 0x198; // Gui
|
||||||
|
|
||||||
static uint32_t CommandServer_minecraft_property_offset = 0x18; // Minecraft *
|
static uint32_t CommandServer_minecraft_property_offset = 0x18; // Minecraft *
|
||||||
|
|
||||||
|
// Packet
|
||||||
|
|
||||||
|
typedef void (*Packet_read_t)(unsigned char *packet, unsigned char *bit_stream);
|
||||||
|
|
||||||
|
// LoginPacket
|
||||||
|
|
||||||
|
static Packet_read_t LoginPacket_read = (Packet_read_t) 0x6e5f8;
|
||||||
|
static void *LoginPacket_read_vtable_addr = (void *) 0x108dcc;
|
||||||
|
|
||||||
|
static uint32_t LoginPacket_username_property_offset = 0xc; // RakString
|
||||||
|
|
||||||
// ChatPacket
|
// ChatPacket
|
||||||
|
|
||||||
static uint32_t ChatPacket_message_property_offset = 0xc; // char *
|
static uint32_t ChatPacket_message_property_offset = 0xc; // char *
|
||||||
|
@ -293,6 +304,17 @@ static uint32_t ItemInstance_auxilary_property_offset = 0x8;
|
||||||
typedef int32_t (*FillingContainer_addItem_t)(unsigned char *filling_container, unsigned char *item_instance);
|
typedef int32_t (*FillingContainer_addItem_t)(unsigned char *filling_container, unsigned char *item_instance);
|
||||||
static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_addItem_t) 0x92aa0;
|
static FillingContainer_addItem_t FillingContainer_addItem = (FillingContainer_addItem_t) 0x92aa0;
|
||||||
|
|
||||||
|
// RakNet::RakString
|
||||||
|
|
||||||
|
typedef void (*RakNet_RakString_Assign_t)(unsigned char *rak_string, const char *str);
|
||||||
|
static RakNet_RakString_Assign_t RakNet_RakString_Assign = (RakNet_RakString_Assign_t) 0xe9e34;
|
||||||
|
|
||||||
|
static uint32_t RakNet_RakString_sharedString_property_offset = 0x0; // RakNet::RakString::SharedString *
|
||||||
|
|
||||||
|
// RakNet::RakString::SharedString
|
||||||
|
|
||||||
|
static uint32_t RakNet_RakString_SharedString_c_str_property_offset = 0x10; // char *
|
||||||
|
|
||||||
// RakNetInstance
|
// RakNetInstance
|
||||||
|
|
||||||
typedef void (*RakNetInstance_send_t)(unsigned char *rak_net_instance, unsigned char *packet);
|
typedef void (*RakNetInstance_send_t)(unsigned char *rak_net_instance, unsigned char *packet);
|
||||||
|
@ -301,7 +323,7 @@ static uint32_t RakNetInstance_send_vtable_offset = 0x38;
|
||||||
typedef uint32_t (*RakNetInstance_isServer_t)(unsigned char *rak_net_instance);
|
typedef uint32_t (*RakNetInstance_isServer_t)(unsigned char *rak_net_instance);
|
||||||
static uint32_t RakNetInstance_isServer_vtable_offset = 0x48;
|
static uint32_t RakNetInstance_isServer_vtable_offset = 0x48;
|
||||||
|
|
||||||
static uint32_t RakNetInstance_peer_property_offset = 0x4;
|
static uint32_t RakNetInstance_peer_property_offset = 0x4; // RakNet::RakPeer *
|
||||||
|
|
||||||
// RakNet::RakPeer
|
// RakNet::RakPeer
|
||||||
|
|
||||||
|
|
|
@ -210,3 +210,27 @@ void _patch_address(const char *file, int line, void *start, void *target) {
|
||||||
unsigned char patch_data[4] = {addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, (addr >> 24) & 0xff};
|
unsigned char patch_data[4] = {addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, (addr >> 24) & 0xff};
|
||||||
_patch(file, line, start, patch_data);
|
_patch(file, line, start, patch_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize String
|
||||||
|
#define MINIMUM_SAFE_CHARACTER 32
|
||||||
|
#define MAXIMUM_SAFE_CHARACTER 126
|
||||||
|
#define MINIMUM_EXTENDED_SAFE_CHARACTER 128
|
||||||
|
void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
|
||||||
|
// Store Message Length
|
||||||
|
int length = strlen(*str);
|
||||||
|
// Truncate Message
|
||||||
|
if (max_length != -1 && length > max_length) {
|
||||||
|
(*str)[max_length] = '\0';
|
||||||
|
length = max_length;
|
||||||
|
}
|
||||||
|
// Loop Through Message
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (allow_newlines && ((*str)[i] == '\n' || (*str)[i] == '\r')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((*str)[i] < MINIMUM_SAFE_CHARACTER || (*str)[i] > MAXIMUM_SAFE_CHARACTER) && (*str)[i] < MINIMUM_EXTENDED_SAFE_CHARACTER) {
|
||||||
|
// Replace Illegal Character
|
||||||
|
(*str)[i] = '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,6 @@ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||||
# Add libreborn
|
# Add libreborn
|
||||||
add_subdirectory(../libreborn libreborn)
|
add_subdirectory(../libreborn libreborn)
|
||||||
|
|
||||||
# Include Libraries Exported To Runtime Environment
|
|
||||||
include_directories(/app/export/include)
|
|
||||||
|
|
||||||
# Find GLFW
|
# Find GLFW
|
||||||
find_package(glfw3 3.3 REQUIRED)
|
find_package(glfw3 3.3 REQUIRED)
|
||||||
|
|
||||||
|
@ -64,19 +61,5 @@ target_link_libraries(test reborn)
|
||||||
add_library(init SHARED src/init/init.c)
|
add_library(init SHARED src/init/init.c)
|
||||||
target_link_libraries(init compat server game_mode camera input misc options textures chat test)
|
target_link_libraries(init compat server game_mode camera input misc options textures chat test)
|
||||||
|
|
||||||
## Stubs
|
## Install Mods
|
||||||
|
install(TARGETS init compat readdir feature screenshot override server game_mode camera input misc options textures chat test DESTINATION /mods)
|
||||||
# Stub RPI-Specific Graphics
|
|
||||||
add_library(bcm_host SHARED src/stubs/bcm_host.c)
|
|
||||||
|
|
||||||
# Stub EGL
|
|
||||||
add_library(EGL SHARED src/stubs/EGL.c)
|
|
||||||
target_link_libraries(EGL compat)
|
|
||||||
|
|
||||||
# MCPI Links Against GLESv2 But Uses GLESv1_CM
|
|
||||||
add_library(GLESv2 SHARED src/stubs/GLESv2.c)
|
|
||||||
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 chat test bcm_host EGL GLESv2 DESTINATION /mods)
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -10,6 +11,9 @@
|
||||||
|
|
||||||
#include "chat.h"
|
#include "chat.h"
|
||||||
|
|
||||||
|
// Message Limitations
|
||||||
|
#define MAX_CHAT_MESSAGE_LENGTH 512
|
||||||
|
|
||||||
// Send API Command
|
// Send API Command
|
||||||
static void send_api_command(unsigned char *minecraft, char *str) {
|
static void send_api_command(unsigned char *minecraft, char *str) {
|
||||||
struct ConnectedClient client;
|
struct ConnectedClient client;
|
||||||
|
@ -35,6 +39,7 @@ static void send_message(unsigned char *server_side_network_handler, char *usern
|
||||||
char *full_message = NULL;
|
char *full_message = NULL;
|
||||||
asprintf(&full_message, "<%s> %s", username, message);
|
asprintf(&full_message, "<%s> %s", username, message);
|
||||||
ALLOC_CHECK(full_message);
|
ALLOC_CHECK(full_message);
|
||||||
|
sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0);
|
||||||
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message));
|
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message));
|
||||||
free(full_message);
|
free(full_message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <SDL/SDL_syswm.h>
|
#include <SDL/SDL_syswm.h>
|
||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
@ -22,8 +23,6 @@
|
||||||
#include "../chat/chat.h"
|
#include "../chat/chat.h"
|
||||||
#include "../init/init.h"
|
#include "../init/init.h"
|
||||||
|
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
static GLFWwindow *glfw_window;
|
static GLFWwindow *glfw_window;
|
||||||
|
|
||||||
static int is_server = 0;
|
static int is_server = 0;
|
||||||
|
@ -212,11 +211,12 @@ HOOK(SDL_WM_SetCaption, void, (const char *title, __attribute__((unused)) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void compat_eglSwapBuffers() {
|
HOOK(eglSwapBuffers, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface)) {
|
||||||
if (!is_server) {
|
if (!is_server) {
|
||||||
// Don't Swap Buffers In A Context-Less Window
|
// Don't Swap Buffers In A Context-Less Window
|
||||||
glfwSwapBuffers(glfw_window);
|
glfwSwapBuffers(glfw_window);
|
||||||
}
|
}
|
||||||
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_fullscreen = 0;
|
static int is_fullscreen = 0;
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
void compat_eglSwapBuffers();
|
|
|
@ -1,13 +1,18 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
#include <libreborn/minecraft.h>
|
||||||
|
|
||||||
#include "../feature/feature.h"
|
#include "../feature/feature.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "../init/init.h"
|
#include "../init/init.h"
|
||||||
|
|
||||||
#include <libreborn/minecraft.h>
|
// Minecraft Pi User Data Root
|
||||||
|
|
||||||
#define NEW_PATH "/.minecraft-pi/"
|
#define NEW_PATH "/.minecraft-pi/"
|
||||||
|
|
||||||
|
// Maximum Username Length
|
||||||
|
#define MAX_USERNAME_LENGTH 16
|
||||||
|
|
||||||
// Render Selected Item Text
|
// Render Selected Item Text
|
||||||
static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t param_1, uint32_t param_2, uint32_t param_3, unsigned char *font) {
|
static void Gui_renderChatMessages_injection(unsigned char *gui, int32_t param_1, uint32_t param_2, uint32_t param_3, unsigned char *font) {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
|
@ -40,6 +45,26 @@ static void Inventory_selectSlot_injection(unsigned char *inventory, int32_t slo
|
||||||
reset_selected_item_text_timer = 1;
|
reset_selected_item_text_timer = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize Username
|
||||||
|
static void LoginPacket_read_injection(unsigned char *packet, unsigned char *bit_stream) {
|
||||||
|
// Call Original Method
|
||||||
|
(*LoginPacket_read)(packet, bit_stream);
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
unsigned char *rak_string = packet + LoginPacket_username_property_offset;
|
||||||
|
// Get Original Username
|
||||||
|
unsigned char *shared_string = *(unsigned char **) (rak_string + RakNet_RakString_sharedString_property_offset);
|
||||||
|
char *c_str = *(char **) (shared_string + RakNet_RakString_SharedString_c_str_property_offset);
|
||||||
|
// Sanitize
|
||||||
|
char *new_username = strdup(c_str);
|
||||||
|
ALLOC_CHECK(new_username);
|
||||||
|
sanitize_string(&new_username, MAX_USERNAME_LENGTH, 0);
|
||||||
|
// Set New Username
|
||||||
|
(*RakNet_RakString_Assign)(rak_string, new_username);
|
||||||
|
// Free
|
||||||
|
free(new_username);
|
||||||
|
}
|
||||||
|
|
||||||
void init_misc() {
|
void init_misc() {
|
||||||
// Store Data In ~/.minecraft-pi Instead Of ~/.minecraft
|
// Store Data In ~/.minecraft-pi Instead Of ~/.minecraft
|
||||||
patch_address((void *) default_path, (void *) NEW_PATH);
|
patch_address((void *) default_path, (void *) NEW_PATH);
|
||||||
|
@ -55,6 +80,9 @@ void init_misc() {
|
||||||
overwrite_calls((void *) Gui_tick, (void *) Gui_tick_injection);
|
overwrite_calls((void *) Gui_tick, (void *) Gui_tick_injection);
|
||||||
overwrite_calls((void *) Inventory_selectSlot, (void *) Inventory_selectSlot_injection);
|
overwrite_calls((void *) Inventory_selectSlot, (void *) Inventory_selectSlot_injection);
|
||||||
|
|
||||||
|
// Sanitize Username
|
||||||
|
patch_address(LoginPacket_read_vtable_addr, (void *) LoginPacket_read_injection);
|
||||||
|
|
||||||
// Init C++
|
// Init C++
|
||||||
init_misc_cpp();
|
init_misc_cpp();
|
||||||
}
|
}
|
|
@ -71,22 +71,31 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
|
||||||
// Print Chat To Log
|
// Print Chat To Log
|
||||||
static bool Gui_addMessage_recursing = false;
|
static bool Gui_addMessage_recursing = false;
|
||||||
static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) {
|
static void Gui_addMessage_injection(unsigned char *gui, std::string const& text) {
|
||||||
|
// Sanitize Message
|
||||||
|
char *new_message = strdup(text.c_str());
|
||||||
|
ALLOC_CHECK(new_message);
|
||||||
|
sanitize_string(&new_message, -1, 1);
|
||||||
|
|
||||||
|
// Process Message
|
||||||
if (!Gui_addMessage_recursing) {
|
if (!Gui_addMessage_recursing) {
|
||||||
// Start Recursing
|
// Start Recursing
|
||||||
Gui_addMessage_recursing = true;
|
Gui_addMessage_recursing = true;
|
||||||
|
|
||||||
// Print Log Message
|
// Print Log Message
|
||||||
fprintf(stderr, "[CHAT]: %s\n", text.c_str());
|
fprintf(stderr, "[CHAT]: %s\n", new_message);
|
||||||
|
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
(*Gui_addMessage)(gui, text);
|
(*Gui_addMessage)(gui, std::string(new_message));
|
||||||
|
|
||||||
// End Recursing
|
// End Recursing
|
||||||
Gui_addMessage_recursing = false;
|
Gui_addMessage_recursing = false;
|
||||||
} else {
|
} else {
|
||||||
// Call Original Method
|
// Call Original Method
|
||||||
(*Gui_addMessage)(gui, text);
|
(*Gui_addMessage)(gui, std::string(new_message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free
|
||||||
|
free(new_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Death Messages
|
// Death Messages
|
||||||
|
|
Loading…
Reference in New Issue