Fix TripodCamera

This commit is contained in:
TheBrokenRail 2020-11-24 17:12:23 -05:00
parent 3244b87be0
commit 81f0c6bbc9
6 changed files with 143 additions and 65 deletions

View File

@ -16,13 +16,16 @@ target_link_libraries(core dl)
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp src/server/playerdata.cpp)
target_link_libraries(server core dl SDL pthread)
add_library(screenshot SHARED src/screenshot/screenshot.c)
target_link_libraries(screenshot GLESv1_CM freeimage)
add_library(extra SHARED src/extra.c src/extra.cpp src/cxx11_util.cpp)
target_link_libraries(extra core dl server)
target_link_libraries(extra core dl server screenshot)
find_package(glfw3 3.3 REQUIRED)
add_library(compat SHARED src/compat.c)
target_link_libraries(compat core extra SDL GLESv1_CM GLESv2 X11 dl freeimage glfw Xfixes)
target_link_libraries(compat core extra screenshot SDL GLESv1_CM GLESv2 X11 dl glfw Xfixes)
# Force GLESv1 Link
target_link_options(compat PRIVATE "-Wl,--no-as-needed")

View File

@ -1,10 +1,7 @@
#define _GNU_SOURCE
#include <time.h>
#include <unistd.h>
#include <FreeImage.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_INCLUDE_ES1
#include <GLFW/glfw3.h>
@ -20,6 +17,7 @@
#include <libcore/libcore.h>
#include "extra.h"
#include "screenshot/screenshot.h"
static GLFWwindow *glfw_window;
static Display *x11_display;
@ -185,8 +183,6 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_
// Init GLFW
HOOK(SDL_WM_SetCaption, void, (const char *title, __attribute__((unused)) const char *icon)) {
FreeImage_Initialise(0);
// Don't Enable GLFW In Server Mode
if (!is_server) {
glfwSetErrorCallback(glfw_error);
@ -256,63 +252,6 @@ static void toggle_fullscreen() {
is_fullscreen = !is_fullscreen;
}
// 4 (Year + 1 (Hyphen) + 2 (Month) + 1 (Hyphen) + 2 (Day) + 1 (Underscore) + 2 (Hour) + 1 (Period) + 2 (Minute) + 1 (Period) + 2 (Second) + 1 (Terminator)
#define TIME_SIZE 20
// Take Screenshot
static void screenshot() {
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
char time[TIME_SIZE];
strftime(time, TIME_SIZE, "%Y-%m-%d_%H.%M.%S", timeinfo);
char *screenshots = NULL;
asprintf(&screenshots, "%s/.minecraft/screenshots", getenv("HOME"));
int num = 1;
char *file = NULL;
asprintf(&file, "%s/%s.png", screenshots, time);
while (access(file, F_OK) != -1) {
asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
num++;
}
int width;
int height;
glfwGetWindowSize(glfw_window, &width, &height);
int line_size = width * 3;
int size = height * line_size;
unsigned char pixels[size];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
// Swap Red And Blue
for (int i = 0; i < (size / 3); i++) {
int pixel = i * 3;
int red = pixels[pixel];
int blue = pixels[pixel + 2];
pixels[pixel] = blue;
pixels[pixel + 2] = red;
}
#endif
FIBITMAP *image = FreeImage_ConvertFromRawBits(pixels, width, height, line_size, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0);
if (!FreeImage_Save(FIF_PNG, image, file, 0)) {
INFO("Screenshot Failed: %s", file);
} else {
INFO("Screenshot Saved: %s", file);
}
FreeImage_Unload(image);
free(file);
free(screenshots);
}
// Intercept SDL Events
HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
// Process GLFW Events
@ -339,7 +278,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
toggle_fullscreen();
handled = 1;
} else if (event->key.keysym.sym == SDLK_F2) {
screenshot();
take_screenshot();
handled = 1;
} else if (event->key.keysym.sym == SDLK_F1) {
extra_hide_gui();

View File

@ -9,6 +9,7 @@
#include "extra.h"
#include "cxx11_util.h"
#include "screenshot/screenshot.h"
#include "minecraft.h"
@ -24,6 +25,11 @@ extern "C" {
return create_cxx11_string(str.c_str());
}
// Take Screenshot Using TripodCamera
static void AppPlatform_linux_saveScreenshot_injection(__attribute__((unused)) unsigned char *app_platform, __attribute__((unused)) std::string const& param1, __attribute__((unused)) std::string const& param_2) {
take_screenshot();
}
// Open Sign Screen
static void LocalPlayer_openTextEdit_injection(unsigned char *local_player, unsigned char *sign) {
if (*(int *)(sign + 0x18) == 4) {
@ -91,6 +97,7 @@ extern "C" {
item_instance = (*ItemInstance_damage)(item_instance, *item_dye_powder, 1, i);
(*FillingContainer_addItem)(filling_container, item_instance);
}
inventory_add_item(filling_container, *item_camera, false);
// Add Tiles
inventory_add_item(filling_container, *tile_water, true);
inventory_add_item(filling_container, *tile_lava, true);
@ -160,9 +167,27 @@ extern "C" {
}
}
// Enable TripodCameraRenderer
static unsigned char *EntityRenderDispatcher_injection(unsigned char *dispatcher) {
// Call Original Method
(*EntityRenderDispatcher)(dispatcher);
// Register TripodCameraRenderer
unsigned char *renderer = (unsigned char *) ::operator new(0x193);
(*TripodCameraRenderer)(renderer);
(*EntityRenderDispatcher_assign)(dispatcher, (unsigned char) 0x5, renderer);
return dispatcher;
}
__attribute((constructor)) static void init() {
// Implement AppPlatform::readAssetFile So Translations Work
overwrite((void *) AppPlatform_readAssetFile, (void *) AppPlatform_readAssetFile_injection);
// Implement AppPlatform_linux::saveScreenshot So Cameras Work
patch_address(AppPlatform_linux_saveScreenshot_vtable_addr, (void *) AppPlatform_linux_saveScreenshot_injection);
// Enable TripodCameraRenderer
overwrite_calls((void *) EntityRenderDispatcher, (void *) EntityRenderDispatcher_injection);
if (extra_has_feature("Fix Sign Placement")) {
// Fix Signs

View File

@ -16,6 +16,7 @@ static unsigned char **item_snowball = (unsigned char **) 0x17bbb0;
static unsigned char **item_shears = (unsigned char **) 0x17bbf0;
static unsigned char **item_egg = (unsigned char **) 0x17bbd0;
static unsigned char **item_dye_powder = (unsigned char **) 0x17bbe0;
static unsigned char **item_camera = (unsigned char **) 0x17bc14;
static unsigned char **tile_water = (unsigned char **) 0x181b3c;
static unsigned char **tile_lava = (unsigned char **) 0x181cc8;
@ -246,6 +247,19 @@ static NbtIo_read_t NbtIo_read = (NbtIo_read_t) 0xb98cc;
typedef void (*Inventory_clearInventoryWithDefault_t)(unsigned char *inventory);
static Inventory_clearInventoryWithDefault_t Inventory_clearInventoryWithDefault = (Inventory_clearInventoryWithDefault_t) 0x8e7c8;
// TripodCameraRenderer
typedef unsigned char *(*TripodCameraRenderer_t)(unsigned char *renderer);
static TripodCameraRenderer_t TripodCameraRenderer = (TripodCameraRenderer_t) 0x6583c;
// EntityRenderDispatcher
typedef unsigned char *(*EntityRenderDispatcher_t)(unsigned char *dispatcher);
static EntityRenderDispatcher_t EntityRenderDispatcher = (EntityRenderDispatcher_t) 0x6096c;
typedef void (*EntityRenderDispatcher_assign_t)(unsigned char *dispatcher, unsigned char entity_id, unsigned char *renderer);
static EntityRenderDispatcher_assign_t EntityRenderDispatcher_assign = (EntityRenderDispatcher_assign_t) 0x6094c;
// Method That Require C++ Types
#ifdef __cplusplus
@ -255,6 +269,9 @@ static Inventory_clearInventoryWithDefault_t Inventory_clearInventoryWithDefault
// AppPlatform
typedef void (*AppPlatform_saveScreenshot_t)(unsigned char *app_platform, std::string const& param1, std::string const& param_2);
static void *AppPlatform_linux_saveScreenshot_vtable_addr = (void *) 0x102160;
typedef cxx11_string (*AppPlatform_readAssetFile_t)(unsigned char *app_platform, std::string const& path);
static AppPlatform_readAssetFile_t AppPlatform_readAssetFile = (AppPlatform_readAssetFile_t) 0x12b10;

View File

@ -0,0 +1,79 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <FreeImage.h>
#include <GLES/gl.h>
#include <libcore/libcore.h>
#include "screenshot.h"
// 4 (Year + 1 (Hyphen) + 2 (Month) + 1 (Hyphen) + 2 (Day) + 1 (Underscore) + 2 (Hour) + 1 (Period) + 2 (Minute) + 1 (Period) + 2 (Second) + 1 (Terminator)
#define TIME_SIZE 20
// Take Screenshot
void take_screenshot() {
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
char time[TIME_SIZE];
strftime(time, TIME_SIZE, "%Y-%m-%d_%H.%M.%S", timeinfo);
char *screenshots = NULL;
asprintf(&screenshots, "%s/.minecraft/screenshots", getenv("HOME"));
int num = 1;
char *file = NULL;
asprintf(&file, "%s/%s.png", screenshots, time);
while (access(file, F_OK) != -1) {
asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
num++;
}
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
int x = viewport[0];
int y = viewport[1];
int width = viewport[2];
int height = viewport[3];
int line_size = width * 3;
int size = height * line_size;
unsigned char pixels[size];
glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
// Swap Red And Blue
for (int i = 0; i < (size / 3); i++) {
int pixel = i * 3;
int red = pixels[pixel];
int blue = pixels[pixel + 2];
pixels[pixel] = blue;
pixels[pixel + 2] = red;
}
#endif
FIBITMAP *image = FreeImage_ConvertFromRawBits(pixels, width, height, line_size, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0);
if (!FreeImage_Save(FIF_PNG, image, file, 0)) {
INFO("Screenshot Failed: %s", file);
} else {
INFO("Screenshot Saved: %s", file);
}
FreeImage_Unload(image);
free(file);
free(screenshots);
}
// Init FreeImage
__attribute__((constructor)) static void init() {
FreeImage_Initialise(0);
}

View File

@ -0,0 +1,15 @@
#ifndef SCREENSHOT_H
#define SCREENSHOT_H
#ifdef __cplusplus
extern "C" {
#endif
void take_screenshot();
#ifdef __cplusplus
}
#endif
#endif