Compare commits

...

28 Commits

Author SHA1 Message Date
b2c13c8257 Tweak Camera
Some checks failed
CI / Build (AMD64) (push) Failing after 3m49s
CI / Build (ARM64) (push) Failing after 4m34s
CI / Build (ARMHF) (push) Failing after 3m3s
CI / Test (AMD64, Client) (push) Has been skipped
CI / Test (AMD64, Server) (push) Has been skipped
CI / Test (ARM64, Client) (push) Has been skipped
CI / Test (ARM64, Server) (push) Has been skipped
CI / Test (ARMHF, Client) (push) Has been skipped
CI / Test (ARMHF, Server) (push) Has been skipped
CI / Build Example Mods (push) Has been skipped
CI / Release (push) Has been skipped
2024-11-22 04:20:22 -05:00
2eb6a1c5be Rename GUI Flags To UI 2024-11-22 03:35:26 -05:00
ef3292c5e0 Change Flag Grouping 2024-11-22 03:30:34 -05:00
67ceb4ad00 More Feature Flags! 2024-11-22 03:07:54 -05:00
e1d9fc492b Remove Some Macros 2024-11-22 01:09:54 -05:00
acec86b9b5 Update Example Mods 2024-11-22 00:54:34 -05:00
66d2e43f55 Move Some Stuff Around 2024-11-22 00:47:38 -05:00
596ff01f75 Remove libreborn.h: Part 3 2024-11-22 00:22:49 -05:00
57aed4d0b3 Remove libreborn.h: Part 2 2024-11-21 23:46:23 -05:00
fd26000fd4 Remove libreborn.h: Part 1 2024-11-21 22:36:05 -05:00
454734ab68 Improve feature_has 2024-11-21 22:07:50 -05:00
d3b70878be New Crash Report UI 2024-11-21 21:45:57 -05:00
7f9d1d843e Small Fix 2024-11-21 17:41:24 -05:00
900169a728 Add "Revert" Button 2024-11-21 16:16:53 -05:00
633b165af0 Tweak UI 2024-11-21 14:50:26 -05:00
86e8c0dd67 Update GLFW 2024-11-21 14:06:43 -05:00
332acd49fb Better extend_struct 2024-11-21 14:03:59 -05:00
c2750bbaec More Color Tweaking 2024-11-21 04:29:05 -05:00
70ef421780 Move Reset Button 2024-11-21 04:07:50 -05:00
ed59e19c52 Add Reset Button 2024-11-21 03:53:01 -05:00
dd760cc6f2 Disable Obsolete ImGui Functions 2024-11-21 03:29:37 -05:00
00f90afc2a Color UI 2024-11-21 03:16:11 -05:00
4a91937b0a New Launcher UI 2024-11-21 02:16:25 -05:00
a6cc0b88b5 Leaner ImGui Build 2024-11-20 12:36:34 -05:00
0b542701c5 ImGui Hello World 2024-11-20 12:22:36 -05:00
fc7ecd528a Embed ImGui Fonts 2024-11-20 10:16:50 -05:00
2785e3f138 Build ImGui 2024-11-19 22:48:50 -05:00
386f52a85f CMake Refactor 2024-11-19 19:57:43 -05:00
170 changed files with 2116 additions and 1476 deletions

7
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "dependencies/glfw/src"]
path = dependencies/glfw/src
url = https://github.com/glfw/glfw.git
[submodule "dependencies/zenity/src"]
path = dependencies/zenity/src
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/zenity.git
[submodule "dependencies/LIEF/src"]
path = dependencies/LIEF/src
url = https://github.com/lief-project/LIEF.git
@ -23,3 +20,7 @@
[submodule "dependencies/runtime/src"]
path = dependencies/runtime/src
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/runtime.git
[submodule "dependencies/imgui/src"]
path = dependencies/imgui/src
url = https://github.com/ocornut/imgui.git
ignore = dirty

View File

@ -1,12 +1,9 @@
# Read Hex Data
file(READ "${EMBED_IN}" data HEX)
# Convert Hex Data For C Compatibility
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," data "${data}")
# Get C Name
cmake_path(GET EMBED_OUT STEM name)
# Write Data
file(WRITE "${EMBED_OUT}"
"#include <stddef.h>\n"

View File

@ -16,13 +16,17 @@ function(embed_resource target file)
cmake_path(GET file FILENAME name)
string(MAKE_C_IDENTIFIER "${name}" name)
# Add Command
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
set(in "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
set(out "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
set(script "${util_list_dir}/embed-resource.cmake")
add_custom_command(OUTPUT "${out}"
COMMAND "${CMAKE_COMMAND}"
ARGS "-DEMBED_IN=${CMAKE_CURRENT_SOURCE_DIR}/${file}" "-DEMBED_OUT=${CMAKE_CURRENT_BINARY_DIR}/${name}.c" "-P" "${util_list_dir}/embed-resource.cmake"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "${util_list_dir}/embed-resource.cmake"
ARGS "-DEMBED_IN=${in}" "-DEMBED_OUT=${out}" "-P" "${script}"
DEPENDS "${in}" "${script}"
VERBATIM
)
# Add To Target
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
target_sources("${target}" PRIVATE "${out}")
endfunction()
# Nicer Output
@ -31,3 +35,45 @@ function(message log_level)
_message("${log_level}" ${ARGN})
endif()
endfunction()
# Exporting Targets And Headers
macro(_get_sdk_header_dir target)
set(sdk_dir "${MCPI_SDK_INCLUDE_DIR}/${target}")
endmacro()
function(setup_header_dirs target)
_get_sdk_header_dir("${target}")
# Get Header Type
set(header_type "PUBLIC")
get_target_property(type "${target}" TYPE)
if ("${type}" STREQUAL "INTERFACE_LIBRARY")
set(header_type "INTERFACE")
endif()
# Loop
foreach(dir IN LISTS ARGN)
# Add To Target
target_include_directories("${target}" "${header_type}" "$<BUILD_INTERFACE:${dir}>")
# Add To SDK
if(BUILD_ARM_COMPONENTS)
install(
DIRECTORY "${dir}/"
DESTINATION "${sdk_dir}"
FILES_MATCHING
PATTERN "*.h"
)
endif()
endforeach()
# Add SDK Headers To Target
if(BUILD_ARM_COMPONENTS)
target_include_directories("${target}" "${header_type}" "$<INSTALL_INTERFACE:${sdk_dir}>")
endif()
endfunction()
function(setup_library target should_install should_export)
# Install
if(should_install)
install(TARGETS "${target}" DESTINATION "${MCPI_LIB_DIR}")
endif()
# SDK
if(should_export AND BUILD_ARM_COMPONENTS)
install(TARGETS "${target}" EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
endif()
endfunction()

View File

@ -8,10 +8,6 @@ endif()
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
add_subdirectory(minecraft-pi)
endif()
# Zenity (Minimal Build)
if(BUILD_NATIVE_COMPONENTS)
add_subdirectory(zenity)
endif()
# LIEF
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
add_subdirectory(LIEF)
@ -19,12 +15,16 @@ endif()
# Extra Runtime
add_subdirectory(runtime)
# GLFW
if(BUILD_MEDIA_LAYER_CORE)
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
add_subdirectory(glfw)
endif()
# ImGui
if(BUILD_NATIVE_COMPONENTS)
add_subdirectory(imgui)
endif()
# UTF8-CPP
add_subdirectory(utf8cpp)
# Symbol Prcoessor
# Symbol Processor
if(BUILD_ARM_COMPONENTS)
add_subdirectory(symbol-processor)
endif()

View File

@ -29,10 +29,7 @@ add_subdirectory(src EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
# Install
install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}")
if(BUILD_ARM_COMPONENTS)
install(TARGETS LIB_LIEF EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
endif()
setup_library(LIB_LIEF TRUE TRUE)
# License
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/LIEF")

View File

@ -21,7 +21,7 @@ add_subdirectory(src EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
# Install
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
setup_library(glfw TRUE FALSE)
# License
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/glfw")
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/GLFW")

@ -1 +1 @@
Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579
Subproject commit b35641f4a3c62aa86a0b3c983d163bc0fe36026d

50
dependencies/imgui/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,50 @@
project(imgui)
# Silence Warnings
add_compile_options(-w)
## ImGui
# Build
add_library(imgui SHARED
src/imgui.cpp
src/imgui_draw.cpp
src/imgui_tables.cpp
src/imgui_widgets.cpp
src/misc/cpp/imgui_stdlib.cpp
src/backends/imgui_impl_glfw.cpp
src/backends/imgui_impl_opengl2.cpp
)
setup_header_dirs(imgui
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/src/backends"
"${CMAKE_CURRENT_SOURCE_DIR}/src/misc/cpp"
)
find_package(OpenGL REQUIRED)
target_link_libraries(imgui PUBLIC glfw OpenGL::GL)
# Fonts
embed_resource(imgui src/misc/fonts/Roboto-Medium.ttf)
embed_resource(imgui src/misc/fonts/Cousine-Regular.ttf)
# Configure
target_compile_definitions(imgui PUBLIC
IMGUI_DISABLE_DEMO_WINDOWS
IMGUI_DISABLE_DEBUG_TOOLS
IMGUI_DISABLE_DEFAULT_FONT
IMGUI_DISABLE_OBSOLETE_FUNCTIONS
)
# Patch
execute_process(
COMMAND "patch" "-p1" "--forward" "--reject-file=-"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src"
INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/fix-hidpi.patch"
OUTPUT_QUIET
)
# Install
setup_library(imgui TRUE TRUE)
# License
install(FILES src/LICENSE.txt src/docs/FONTS.md DESTINATION "${MCPI_LEGAL_DIR}/ImGui")

55
dependencies/imgui/fix-hidpi.patch vendored Normal file
View File

@ -0,0 +1,55 @@
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -422,6 +422,21 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
io.AddFocusEvent(focused != 0);
}
+static void ImGui_ImplGlfw_ScaleMousePos(GLFWwindow* window, double &x, double &y) {
+ // Get Window Size
+ int window_width, window_height;
+ glfwGetWindowSize(window, &window_width, &window_height);
+ if (window_width <= 0 || window_height <= 0) {
+ return;
+ }
+ // Get Framebuffer Size
+ int framebuffer_width, framebuffer_height;
+ glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
+ // Multiply
+ x *= double(framebuffer_width) / double(window_width);
+ y *= double(framebuffer_height) / double(window_height);
+}
+
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
@@ -429,6 +444,7 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
bd->PrevUserCallbackCursorPos(window, x, y);
ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplGlfw_ScaleMousePos(window, x, y);
io.AddMousePosEvent((float)x, (float)y);
bd->LastValidMousePos = ImVec2((float)x, (float)y);
}
@@ -738,6 +754,7 @@ static void ImGui_ImplGlfw_UpdateMouseData()
{
double mouse_x, mouse_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y);
+ ImGui_ImplGlfw_ScaleMousePos(window, mouse_x, mouse_y);
bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y);
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
}
@@ -831,13 +848,9 @@ void ImGui_ImplGlfw_NewFrame()
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
// Setup display size (every frame to accommodate for window resizing)
- int w, h;
int display_w, display_h;
- glfwGetWindowSize(bd->Window, &w, &h);
glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
- io.DisplaySize = ImVec2((float)w, (float)h);
- if (w > 0 && h > 0)
- io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
+ io.DisplaySize = ImVec2((float)display_w, (float)display_h);
// Setup time step
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)

1
dependencies/imgui/src vendored Submodule

@ -0,0 +1 @@
Subproject commit 551b6c4d662a3938f0cd197e79cc29922feec1ff

View File

@ -10,4 +10,10 @@ if(NOT BUILD_NATIVE_COMPONENTS)
endif()
# Build
add_subdirectory(src)
add_subdirectory(src)
# RPath
if(TARGET runtime)
set_target_properties(runtime PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native")
target_link_options(runtime PRIVATE "LINKER:--disable-new-dtags")
endif()

@ -1 +1 @@
Subproject commit b42021ba5d45c29e22cbdd887e2fae5a1c1334a1
Subproject commit 043d926f32a3315d92bce1d9bbb0ccdcf99c11a2

View File

@ -7,24 +7,12 @@ add_compile_options(-w)
# Build
add_library(stb_image SHARED src/stb_image_impl.c)
target_include_directories(
stb_image
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/stb_image>"
)
target_link_libraries(stb_image PRIVATE m)
target_compile_definitions(stb_image PUBLIC STBI_ONLY_PNG)
setup_header_dirs(stb_image "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Install
install(TARGETS stb_image DESTINATION "${MCPI_LIB_DIR}")
install(
DIRECTORY "include/"
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/stb_image"
FILES_MATCHING
PATTERN "*.h"
)
install(TARGETS stb_image EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
setup_library(stb_image TRUE TRUE)
# License
install(FILES include/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/stb_image")

View File

@ -9,4 +9,4 @@ add_compile_options(-w)
add_subdirectory(src EXCLUDE_FROM_ALL)
# License
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/utf8cpp")
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/UTF8-CPP")

View File

@ -1,20 +0,0 @@
project(zenity)
# Silence Warnings
add_compile_options(-w)
## Zenity
# Download
set(MESSAGE_QUIET TRUE)
add_subdirectory(src EXCLUDE_FROM_ALL)
unset(MESSAGE_QUIET)
# Ensure Build
add_custom_target(zenity-build ALL DEPENDS zenity)
# Install
install(TARGETS zenity DESTINATION "${MCPI_BIN_DIR}")
# License
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/zenity")

@ -1 +0,0 @@
Subproject commit a7496461161c917878d58131711425e7c8e59436

View File

@ -52,6 +52,7 @@
* `Increase Render Chunk Size` (Enabled By Default)
* `Proper Entity Shading` (Enabled By Default)
* `Fix Sugar Position In Hand` (Enabled By Default)
* `Fix Reloading Textures On Resize` (Enabled By Default)
* Existing Functionality (All Enabled By Default)
* `Fix Screen Rendering When Hiding HUD`
* `Sanitize Usernames`
@ -70,14 +71,31 @@
* `Screenshot Support`
* `Fix Camera Functionality`
* `Property Scale Animated Textures`
* `Enable Text Input`
* `Update Default Options`
* `Fix options.txt Loading/Saving`
* `Extend Supported Keycodes`
* Split Up `Remove Creative Mode Restrictions` Feature Flag
* `Remove Creative Mode Restrictions` (Disabled By Default)
* `Display Slot Count In Creative Mode` (Disabled By Default)
* `Force Survival Mode Inventory UI` (Disabled By Default)
* `Force Survival Mode Inventory Behavior` (Disabled By Default)
* `Maximize Creative Mode Inventory Stack Size` (Disabled By Default)
* Rename `Disable Buggy Held Item Caching` Feature Flag To `Fix Held Item Caching`
* Rename `Disable 'gui_blocks' Atlas` Feature Flag To `Regenerate "gui_blocks" Atlas`
* Split Up `Miscellaneous Input Fixes` Feature Flag
* `Fix Escape Key Handling` (Enabled By Default)
* `Stop Locked Mouse From Interacting With HUD` (Enabled By Default)
* Rename Feature Flags
* `Disable Buggy Held Item Caching` To `Fix Held Item Caching`
* `Disable 'gui_blocks' Atlas` To `Regenerate "gui_blocks" Atlas`
* `Fix Sign Placement` To `Enable Sign Screen`
* `Force Touch GUI Inventory` To `Force Touch UI Inventory`
* `Full Touch GUI` To `Full Touch UI`
* `Force Touch GUI Button Behavior` To `Force Touch UI Button Behavior`
* `Remove Forced GUI Lag (Can Break Joining Servers)` To `Remove Forced UI Lag (Can Break Joining Servers)`
* `Hide Block Outline When GUI Is Hidden` To `Hide Block Outline When UI Is Hidden`
* `Fix Camera Functionality` To `Add Camera Functionality`
* `Fix Camera Rendering` To `Enable Camera Rendering`
* `Fix Camera Legs` To `Render Camera Legs`
* Add Milk Buckets
* Included In The `Add Buckets` Feature Flag
* Removed `Property Scale Animated Textures` Feature Flag

View File

@ -27,7 +27,7 @@ The AppImage requires Debian Bullseye or higher. This is equivalent to Ubuntu 20
It also requires some additional packages. To install them, run:
```sh
sudo apt install -y libfuse2 libgtk-3-0 libopenal1 libglib2.0-0
sudo apt install -y libfuse2 libopenal1 libglib2.0-0
```
</details>

View File

@ -1,6 +1,9 @@
// Headers
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <libreborn/util.h>
#include <libreborn/string.h>
#include <symbols/minecraft.h>
#include <mods/chat/chat.h>
#include <mods/misc/misc.h>
#include <mods/server/server.h>

View File

@ -1,628 +1,540 @@
// Headers
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
// The Actual Mod
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
ItemInstance *fire_instance = new ItemInstance;
ALLOC_CHECK(fire_instance);
fire_instance->count = 255;
fire_instance->auxiliary = 0;
fire_instance->id = 51;
filling_container->addItem(fire_instance);
ItemInstance *mushroomStew_instance = new ItemInstance;
ALLOC_CHECK(mushroomStew_instance);
mushroomStew_instance->count = 255;
mushroomStew_instance->auxiliary = 0;
mushroomStew_instance->id = 282;
filling_container->addItem(mushroomStew_instance);
ItemInstance *steak_instance = new ItemInstance;
ALLOC_CHECK(steak_instance);
steak_instance->count = 255;
steak_instance->auxiliary = 0;
steak_instance->id = 364;
filling_container->addItem(steak_instance);
ItemInstance *cookedChicken_instance = new ItemInstance;
ALLOC_CHECK(cookedChicken_instance);
cookedChicken_instance->count = 255;
cookedChicken_instance->auxiliary = 0;
cookedChicken_instance->id = 366;
filling_container->addItem(cookedChicken_instance);
ItemInstance *porkCooked_instance = new ItemInstance;
ALLOC_CHECK(porkCooked_instance);
porkCooked_instance->count = 255;
porkCooked_instance->auxiliary = 0;
porkCooked_instance->id = 320;
filling_container->addItem(porkCooked_instance);
ItemInstance *apple_instance = new ItemInstance;
ALLOC_CHECK(apple_instance);
apple_instance->count = 255;
apple_instance->auxiliary = 0;
apple_instance->id = 260;
filling_container->addItem(apple_instance);
ItemInstance *tallGrass_instance = new ItemInstance;
ALLOC_CHECK(tallGrass_instance);
tallGrass_instance->count = 255;
tallGrass_instance->auxiliary = 0;
tallGrass_instance->id = 31;
filling_container->addItem(tallGrass_instance);
ItemInstance *crops_instance = new ItemInstance;
ALLOC_CHECK(crops_instance);
crops_instance->count = 255;
crops_instance->auxiliary = 0;
crops_instance->id = 59;
filling_container->addItem(crops_instance);
ItemInstance *farmland_instance = new ItemInstance;
ALLOC_CHECK(farmland_instance);
farmland_instance->count = 255;
farmland_instance->auxiliary = 0;
farmland_instance->id = 60;
filling_container->addItem(farmland_instance);
ItemInstance *activeFurnace_instance = new ItemInstance;
ALLOC_CHECK(activeFurnace_instance);
activeFurnace_instance->count = 255;
activeFurnace_instance->auxiliary = 0;
activeFurnace_instance->id = 62;
filling_container->addItem(activeFurnace_instance);
ItemInstance *ironDoor_instance = new ItemInstance;
ALLOC_CHECK(ironDoor_instance);
ironDoor_instance->count = 255;
ironDoor_instance->auxiliary = 0;
ironDoor_instance->id = 330;
filling_container->addItem(ironDoor_instance);
ItemInstance *activeRedstoneOre_instance = new ItemInstance;
ALLOC_CHECK(activeRedstoneOre_instance);
activeRedstoneOre_instance->count = 255;
activeRedstoneOre_instance->auxiliary = 0;
activeRedstoneOre_instance->id = 74;
filling_container->addItem(activeRedstoneOre_instance);
ItemInstance *pumkinStem_instance = new ItemInstance;
ALLOC_CHECK(pumkinStem_instance);
pumkinStem_instance->count = 255;
pumkinStem_instance->auxiliary = 0;
pumkinStem_instance->id = 105;
filling_container->addItem(pumkinStem_instance);
ItemInstance *newGrass_instance = new ItemInstance;
ALLOC_CHECK(newGrass_instance);
newGrass_instance->count = 255;
newGrass_instance->auxiliary = 0;
newGrass_instance->id = 253;
filling_container->addItem(newGrass_instance);
ItemInstance *reserved6_instance = new ItemInstance;
ALLOC_CHECK(reserved6_instance);
reserved6_instance->count = 255;
reserved6_instance->auxiliary = 0;
reserved6_instance->id = 1;
filling_container->addItem(reserved6_instance);
ItemInstance *doubleStoneSlab_instance = new ItemInstance;
ALLOC_CHECK(doubleStoneSlab_instance);
doubleStoneSlab_instance->count = 255;
doubleStoneSlab_instance->auxiliary = 0;
doubleStoneSlab_instance->id = 43;
filling_container->addItem(doubleStoneSlab_instance);
ItemInstance *arrow_instance = new ItemInstance;
ALLOC_CHECK(arrow_instance);
arrow_instance->count = 255;
arrow_instance->auxiliary = 0;
arrow_instance->id = 262;
filling_container->addItem(arrow_instance);
ItemInstance *coal_instance = new ItemInstance;
ALLOC_CHECK(coal_instance);
coal_instance->count = 255;
coal_instance->auxiliary = 0;
coal_instance->id = 263;
filling_container->addItem(coal_instance);
ItemInstance *diamond_instance = new ItemInstance;
ALLOC_CHECK(diamond_instance);
diamond_instance->count = 255;
diamond_instance->auxiliary = 0;
diamond_instance->id = 264;
filling_container->addItem(diamond_instance);
ItemInstance *ironIngot_instance = new ItemInstance;
ALLOC_CHECK(ironIngot_instance);
ironIngot_instance->count = 255;
ironIngot_instance->auxiliary = 0;
ironIngot_instance->id = 265;
filling_container->addItem(ironIngot_instance);
ItemInstance *goldIngot_instance = new ItemInstance;
ALLOC_CHECK(goldIngot_instance);
goldIngot_instance->count = 255;
goldIngot_instance->auxiliary = 0;
goldIngot_instance->id = 266;
filling_container->addItem(goldIngot_instance);
ItemInstance *woodSword_instance = new ItemInstance;
ALLOC_CHECK(woodSword_instance);
woodSword_instance->count = 255;
woodSword_instance->auxiliary = 0;
woodSword_instance->id = 268;
filling_container->addItem(woodSword_instance);
ItemInstance *woodShovel_instance = new ItemInstance;
ALLOC_CHECK(woodShovel_instance);
woodShovel_instance->count = 255;
woodShovel_instance->auxiliary = 0;
woodShovel_instance->id = 269;
filling_container->addItem(woodShovel_instance);
ItemInstance *woodPickaxe_instance = new ItemInstance;
ALLOC_CHECK(woodPickaxe_instance);
woodPickaxe_instance->count = 255;
woodPickaxe_instance->auxiliary = 0;
woodPickaxe_instance->id = 270;
filling_container->addItem(woodPickaxe_instance);
ItemInstance *woodAxe_instance = new ItemInstance;
ALLOC_CHECK(woodAxe_instance);
woodAxe_instance->count = 255;
woodAxe_instance->auxiliary = 0;
woodAxe_instance->id = 271;
filling_container->addItem(woodAxe_instance);
ItemInstance *stoneSword_instance = new ItemInstance;
ALLOC_CHECK(stoneSword_instance);
stoneSword_instance->count = 255;
stoneSword_instance->auxiliary = 0;
stoneSword_instance->id = 272;
filling_container->addItem(stoneSword_instance);
ItemInstance *stoneShovel_instance = new ItemInstance;
ALLOC_CHECK(stoneShovel_instance);
stoneShovel_instance->count = 255;
stoneShovel_instance->auxiliary = 0;
stoneShovel_instance->id = 273;
filling_container->addItem(stoneShovel_instance);
ItemInstance *stonePickaxe_instance = new ItemInstance;
ALLOC_CHECK(stonePickaxe_instance);
stonePickaxe_instance->count = 255;
stonePickaxe_instance->auxiliary = 0;
stonePickaxe_instance->id = 274;
filling_container->addItem(stonePickaxe_instance);
ItemInstance *stoneAxe_instance = new ItemInstance;
ALLOC_CHECK(stoneAxe_instance);
stoneAxe_instance->count = 255;
stoneAxe_instance->auxiliary = 0;
stoneAxe_instance->id = 275;
filling_container->addItem(stoneAxe_instance);
ItemInstance *shovelIron_instance = new ItemInstance;
ALLOC_CHECK(shovelIron_instance);
shovelIron_instance->count = 255;
shovelIron_instance->auxiliary = 0;
shovelIron_instance->id = 256;
filling_container->addItem(shovelIron_instance);
ItemInstance *ironPick_instance = new ItemInstance;
ALLOC_CHECK(ironPick_instance);
ironPick_instance->count = 255;
ironPick_instance->auxiliary = 0;
ironPick_instance->id = 257;
filling_container->addItem(ironPick_instance);
ItemInstance *ironAxe_instance = new ItemInstance;
ALLOC_CHECK(ironAxe_instance);
ironAxe_instance->count = 255;
ironAxe_instance->auxiliary = 0;
ironAxe_instance->id = 258;
filling_container->addItem(ironAxe_instance);
ItemInstance *diamondSword_instance = new ItemInstance;
ALLOC_CHECK(diamondSword_instance);
diamondSword_instance->count = 255;
diamondSword_instance->auxiliary = 0;
diamondSword_instance->id = 276;
filling_container->addItem(diamondSword_instance);
ItemInstance *diamondShovel_instance = new ItemInstance;
ALLOC_CHECK(diamondShovel_instance);
diamondShovel_instance->count = 255;
diamondShovel_instance->auxiliary = 0;
diamondShovel_instance->id = 277;
filling_container->addItem(diamondShovel_instance);
ItemInstance *diamondPickaxe_instance = new ItemInstance;
ALLOC_CHECK(diamondPickaxe_instance);
diamondPickaxe_instance->count = 255;
diamondPickaxe_instance->auxiliary = 0;
diamondPickaxe_instance->id = 278;
filling_container->addItem(diamondPickaxe_instance);
ItemInstance *diamondAxe_instance = new ItemInstance;
ALLOC_CHECK(diamondAxe_instance);
diamondAxe_instance->count = 255;
diamondAxe_instance->auxiliary = 0;
diamondAxe_instance->id = 279;
filling_container->addItem(diamondAxe_instance);
ItemInstance *magicWand_instance = new ItemInstance;
ALLOC_CHECK(magicWand_instance);
magicWand_instance->count = 255;
magicWand_instance->auxiliary = 0;
magicWand_instance->id = 280;
filling_container->addItem(magicWand_instance);
ItemInstance *bowl_instance = new ItemInstance;
ALLOC_CHECK(bowl_instance);
bowl_instance->count = 255;
bowl_instance->auxiliary = 0;
bowl_instance->id = 281;
filling_container->addItem(bowl_instance);
ItemInstance *goldSword_instance = new ItemInstance;
ALLOC_CHECK(goldSword_instance);
goldSword_instance->count = 255;
goldSword_instance->auxiliary = 0;
goldSword_instance->id = 283;
filling_container->addItem(goldSword_instance);
ItemInstance *goldShovel_instance = new ItemInstance;
ALLOC_CHECK(goldShovel_instance);
goldShovel_instance->count = 255;
goldShovel_instance->auxiliary = 0;
goldShovel_instance->id = 284;
filling_container->addItem(goldShovel_instance);
ItemInstance *goldPickaxe_instance = new ItemInstance;
ALLOC_CHECK(goldPickaxe_instance);
goldPickaxe_instance->count = 255;
goldPickaxe_instance->auxiliary = 0;
goldPickaxe_instance->id = 285;
filling_container->addItem(goldPickaxe_instance);
ItemInstance *goldAxe_instance = new ItemInstance;
ALLOC_CHECK(goldAxe_instance);
goldAxe_instance->count = 255;
goldAxe_instance->auxiliary = 0;
goldAxe_instance->id = 286;
filling_container->addItem(goldAxe_instance);
ItemInstance *string_instance = new ItemInstance;
ALLOC_CHECK(string_instance);
string_instance->count = 255;
string_instance->auxiliary = 0;
string_instance->id = 287;
filling_container->addItem(string_instance);
ItemInstance *feather_instance = new ItemInstance;
ALLOC_CHECK(feather_instance);
feather_instance->count = 255;
feather_instance->auxiliary = 0;
feather_instance->id = 288;
filling_container->addItem(feather_instance);
ItemInstance *gunpowder_instance = new ItemInstance;
ALLOC_CHECK(gunpowder_instance);
gunpowder_instance->count = 255;
gunpowder_instance->auxiliary = 0;
gunpowder_instance->id = 289;
filling_container->addItem(gunpowder_instance);
ItemInstance *woodHoe_instance = new ItemInstance;
ALLOC_CHECK(woodHoe_instance);
woodHoe_instance->count = 255;
woodHoe_instance->auxiliary = 0;
woodHoe_instance->id = 290;
filling_container->addItem(woodHoe_instance);
ItemInstance *stoneHoe_instance = new ItemInstance;
ALLOC_CHECK(stoneHoe_instance);
stoneHoe_instance->count = 255;
stoneHoe_instance->auxiliary = 0;
stoneHoe_instance->id = 291;
filling_container->addItem(stoneHoe_instance);
ItemInstance *flint1_instance = new ItemInstance;
ALLOC_CHECK(flint1_instance);
flint1_instance->count = 255;
flint1_instance->auxiliary = 0;
flint1_instance->id = 292;
filling_container->addItem(flint1_instance);
ItemInstance *diamondHoe_instance = new ItemInstance;
ALLOC_CHECK(diamondHoe_instance);
diamondHoe_instance->count = 255;
diamondHoe_instance->auxiliary = 0;
diamondHoe_instance->id = 293;
filling_container->addItem(diamondHoe_instance);
ItemInstance *goldHoe_instance = new ItemInstance;
ALLOC_CHECK(goldHoe_instance);
goldHoe_instance->count = 255;
goldHoe_instance->auxiliary = 0;
goldHoe_instance->id = 294;
filling_container->addItem(goldHoe_instance);
ItemInstance *seeds_instance = new ItemInstance;
ALLOC_CHECK(seeds_instance);
seeds_instance->count = 255;
seeds_instance->auxiliary = 0;
seeds_instance->id = 295;
filling_container->addItem(seeds_instance);
ItemInstance *wheat_instance = new ItemInstance;
ALLOC_CHECK(wheat_instance);
wheat_instance->count = 255;
wheat_instance->auxiliary = 0;
wheat_instance->id = 296;
filling_container->addItem(wheat_instance);
ItemInstance *bread_instance = new ItemInstance;
ALLOC_CHECK(bread_instance);
bread_instance->count = 255;
bread_instance->auxiliary = 0;
bread_instance->id = 297;
filling_container->addItem(bread_instance);
ItemInstance *diamondHelm_instance = new ItemInstance;
ALLOC_CHECK(diamondHelm_instance);
diamondHelm_instance->count = 255;
diamondHelm_instance->auxiliary = 0;
diamondHelm_instance->id = 310;
filling_container->addItem(diamondHelm_instance);
ItemInstance *diamondChest_instance = new ItemInstance;
ALLOC_CHECK(diamondChest_instance);
diamondChest_instance->count = 255;
diamondChest_instance->auxiliary = 0;
diamondChest_instance->id = 311;
filling_container->addItem(diamondChest_instance);
ItemInstance *diamondLeg_instance = new ItemInstance;
ALLOC_CHECK(diamondLeg_instance);
diamondLeg_instance->count = 255;
diamondLeg_instance->auxiliary = 0;
diamondLeg_instance->id = 312;
filling_container->addItem(diamondLeg_instance);
ItemInstance *diamondBoot_instance = new ItemInstance;
ALLOC_CHECK(diamondBoot_instance);
diamondBoot_instance->count = 255;
diamondBoot_instance->auxiliary = 0;
diamondBoot_instance->id = 313;
filling_container->addItem(diamondBoot_instance);
ItemInstance *leatherCap_instance = new ItemInstance;
ALLOC_CHECK(leatherCap_instance);
leatherCap_instance->count = 255;
leatherCap_instance->auxiliary = 0;
leatherCap_instance->id = 298;
filling_container->addItem(leatherCap_instance);
ItemInstance *leatherShirt_instance = new ItemInstance;
ALLOC_CHECK(leatherShirt_instance);
leatherShirt_instance->count = 255;
leatherShirt_instance->auxiliary = 0;
leatherShirt_instance->id = 299;
filling_container->addItem(leatherShirt_instance);
ItemInstance *leatherPants_instance = new ItemInstance;
ALLOC_CHECK(leatherPants_instance);
leatherPants_instance->count = 255;
leatherPants_instance->auxiliary = 0;
leatherPants_instance->id = 300;
filling_container->addItem(leatherPants_instance);
ItemInstance *leatherBoots_instance = new ItemInstance;
ALLOC_CHECK(leatherBoots_instance);
leatherBoots_instance->count = 255;
leatherBoots_instance->auxiliary = 0;
leatherBoots_instance->id = 301;
filling_container->addItem(leatherBoots_instance);
ItemInstance *chainHelm_instance = new ItemInstance;
ALLOC_CHECK(chainHelm_instance);
chainHelm_instance->count = 255;
chainHelm_instance->auxiliary = 0;
chainHelm_instance->id = 302;
filling_container->addItem(chainHelm_instance);
ItemInstance *chainShirt_instance = new ItemInstance;
ALLOC_CHECK(chainShirt_instance);
chainShirt_instance->count = 255;
chainShirt_instance->auxiliary = 0;
chainShirt_instance->id = 303;
filling_container->addItem(chainShirt_instance);
ItemInstance *chainLegs_instance = new ItemInstance;
ALLOC_CHECK(chainLegs_instance);
chainLegs_instance->count = 255;
chainLegs_instance->auxiliary = 0;
chainLegs_instance->id = 304;
filling_container->addItem(chainLegs_instance);
ItemInstance *chainBoots_instance = new ItemInstance;
ALLOC_CHECK(chainBoots_instance);
chainBoots_instance->count = 255;
chainBoots_instance->auxiliary = 0;
chainBoots_instance->id = 305;
filling_container->addItem(chainBoots_instance);
ItemInstance *goldHelm_instance = new ItemInstance;
ALLOC_CHECK(goldHelm_instance);
goldHelm_instance->count = 255;
goldHelm_instance->auxiliary = 0;
goldHelm_instance->id = 314;
filling_container->addItem(goldHelm_instance);
ItemInstance *goldChest_instance = new ItemInstance;
ALLOC_CHECK(goldChest_instance);
goldChest_instance->count = 255;
goldChest_instance->auxiliary = 0;
goldChest_instance->id = 315;
filling_container->addItem(goldChest_instance);
ItemInstance *goldLegs_instance = new ItemInstance;
ALLOC_CHECK(goldLegs_instance);
goldLegs_instance->count = 255;
goldLegs_instance->auxiliary = 0;
goldLegs_instance->id = 316;
filling_container->addItem(goldLegs_instance);
ItemInstance *goldBoots_instance = new ItemInstance;
ALLOC_CHECK(goldBoots_instance);
goldBoots_instance->count = 255;
goldBoots_instance->auxiliary = 0;
goldBoots_instance->id = 317;
filling_container->addItem(goldBoots_instance);
ItemInstance *ironHelm_instance = new ItemInstance;
ALLOC_CHECK(ironHelm_instance);
ironHelm_instance->count = 255;
ironHelm_instance->auxiliary = 0;
ironHelm_instance->id = 306;
filling_container->addItem(ironHelm_instance);
ItemInstance *ironChest_instance = new ItemInstance;
ALLOC_CHECK(ironChest_instance);
ironChest_instance->count = 255;
ironChest_instance->auxiliary = 0;
ironChest_instance->id = 307;
filling_container->addItem(ironChest_instance);
ItemInstance *ironLegs_instance = new ItemInstance;
ALLOC_CHECK(ironLegs_instance);
ironLegs_instance->count = 255;
ironLegs_instance->auxiliary = 0;
ironLegs_instance->id = 308;
filling_container->addItem(ironLegs_instance);
ItemInstance *ironBoots_instance = new ItemInstance;
ALLOC_CHECK(ironBoots_instance);
ironBoots_instance->count = 255;
ironBoots_instance->auxiliary = 0;
ironBoots_instance->id = 309;
filling_container->addItem(ironBoots_instance);
ItemInstance *flint2_instance = new ItemInstance;
ALLOC_CHECK(flint2_instance);
flint2_instance->count = 255;
flint2_instance->auxiliary = 0;
flint2_instance->id = 318;
filling_container->addItem(flint2_instance);
ItemInstance *porkRaw_instance = new ItemInstance;
ALLOC_CHECK(porkRaw_instance);
porkRaw_instance->count = 255;
porkRaw_instance->auxiliary = 0;
porkRaw_instance->id = 319;
filling_container->addItem(porkRaw_instance);
ItemInstance *leather_instance = new ItemInstance;
ALLOC_CHECK(leather_instance);
leather_instance->count = 255;
leather_instance->auxiliary = 0;
leather_instance->id = 334;
filling_container->addItem(leather_instance);
ItemInstance *clayBrick_instance = new ItemInstance;
ALLOC_CHECK(clayBrick_instance);
clayBrick_instance->count = 255;
clayBrick_instance->auxiliary = 0;
clayBrick_instance->id = 336;
filling_container->addItem(clayBrick_instance);
ItemInstance *clay_instance = new ItemInstance;
ALLOC_CHECK(clay_instance);
clay_instance->count = 255;
clay_instance->auxiliary = 0;
clay_instance->id = 337;
filling_container->addItem(clay_instance);
ItemInstance *notepad_instance = new ItemInstance;
ALLOC_CHECK(notepad_instance);
notepad_instance->count = 255;
notepad_instance->auxiliary = 0;
notepad_instance->id = 339;
filling_container->addItem(notepad_instance);
ItemInstance *book_instance = new ItemInstance;
ALLOC_CHECK(book_instance);
book_instance->count = 255;
book_instance->auxiliary = 0;
book_instance->id = 340;
filling_container->addItem(book_instance);
ItemInstance *slimeball_instance = new ItemInstance;
ALLOC_CHECK(slimeball_instance);
slimeball_instance->count = 255;
slimeball_instance->auxiliary = 0;
slimeball_instance->id = 341;
filling_container->addItem(slimeball_instance);
ItemInstance *compass_instance = new ItemInstance;
ALLOC_CHECK(compass_instance);
compass_instance->count = 255;
compass_instance->auxiliary = 0;
compass_instance->id = 345;
filling_container->addItem(compass_instance);
ItemInstance *clock_instance = new ItemInstance;
ALLOC_CHECK(clock_instance);
clock_instance->count = 255;
clock_instance->auxiliary = 0;
clock_instance->id = 347;
filling_container->addItem(clock_instance);
ItemInstance *glowDust_instance = new ItemInstance;
ALLOC_CHECK(glowDust_instance);
glowDust_instance->count = 255;
glowDust_instance->auxiliary = 0;
glowDust_instance->id = 348;
filling_container->addItem(glowDust_instance);
ItemInstance *bone_instance = new ItemInstance;
ALLOC_CHECK(bone_instance);
bone_instance->count = 255;
bone_instance->auxiliary = 0;
bone_instance->id = 352;
filling_container->addItem(bone_instance);
ItemInstance *sugar_instance = new ItemInstance;
ALLOC_CHECK(sugar_instance);
sugar_instance->count = 255;
sugar_instance->auxiliary = 0;
sugar_instance->id = 353;
filling_container->addItem(sugar_instance);
ItemInstance *melon_instance = new ItemInstance;
ALLOC_CHECK(melon_instance);
melon_instance->count = 255;
melon_instance->auxiliary = 0;
melon_instance->id = 360;
filling_container->addItem(melon_instance);
ItemInstance *beefRaw_instance = new ItemInstance;
ALLOC_CHECK(beefRaw_instance);
beefRaw_instance->count = 255;
beefRaw_instance->auxiliary = 0;
beefRaw_instance->id = 363;
filling_container->addItem(beefRaw_instance);
ItemInstance *chickenRaw_instance = new ItemInstance;
ALLOC_CHECK(chickenRaw_instance);
chickenRaw_instance->count = 255;
chickenRaw_instance->auxiliary = 0;
chickenRaw_instance->id = 365;

View File

@ -1,6 +1,7 @@
// Headers
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
// Custom Crafting Recipes

View File

@ -9,16 +9,23 @@ add_executable(launcher
src/bootstrap/debug.cpp
src/util/util.cpp
src/util/sdk.cpp
src/util/env.cpp
src/logger/logger.cpp
src/logger/crash-report.cpp
src/options/parser.cpp
src/main.cpp
src/ui/frame.cpp
src/ui/color.cpp
src/client/configuration.cpp
src/client/cache.cpp
src/client/available-feature-flags # Show In IDE
src/client/ui.cpp
)
target_link_libraries(launcher
reborn-util
LIB_LIEF
imgui
trampoline-headers
)
embed_resource(launcher src/client/available-feature-flags)
target_link_libraries(launcher reborn-util LIB_LIEF trampoline-headers)
# RPath
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
target_link_options(launcher PRIVATE "LINKER:--disable-new-dtags")

View File

@ -1,4 +1,4 @@
#include <libreborn/libreborn.h>
#include <libreborn/env.h>
#include "bootstrap.h"
#include "../util/util.h"

View File

@ -1,7 +1,10 @@
#include <string>
#include <vector>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/env.h>
#include <libreborn/config.h>
#include <libreborn/exec.h>
#include "../util/util.h"
#include "bootstrap.h"

View File

@ -1,4 +1,6 @@
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/exec.h>
#include <libreborn/config.h>
#include "bootstrap.h"

View File

@ -2,10 +2,13 @@
#include <cerrno>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/util.h>
#include "bootstrap.h"
#include "../util/util.h"
// Get All Mods In Folder
static void load(std::vector<std::string> &ld_preload, const std::string &folder, int recursion_limit = 128);
@ -18,10 +21,8 @@ static void handle_file(std::vector<std::string> &ld_preload, const std::string
load(ld_preload, std::string(file) + '/', recursion_limit - 1);
} else if (S_ISLNK(file_stat.st_mode)) {
// Resolve Symlink
char *resolved_file = realpath(file.c_str(), nullptr);
ALLOC_CHECK(resolved_file);
const std::string resolved_file = safe_realpath(file);
handle_file(ld_preload, resolved_file, recursion_limit);
free(resolved_file);
} else if (S_ISREG(file_stat.st_mode)) {
// Check If File Is Accessible
const int result = access(file.c_str(), R_OK);
@ -79,19 +80,13 @@ std::vector<std::string> bootstrap_mods(const std::string &binary_directory) {
// Prepare
std::vector<std::string> preload;
// ~/.minecraft-pi/mods
{
// Get Mods Folder
const std::string mods_folder = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data() + SUBDIRECTORY_FOR_MODS;
// Load Mods From ./mods
load(preload, mods_folder);
}
// Built-In Mods
{
// Get Mods Folder
const std::string mods_folder = binary_directory + SUBDIRECTORY_FOR_MODS;
// Load Mods From ./mods
// Load
const std::vector folders = {
home_get(),
binary_directory
};
for (std::string mods_folder : folders) {
mods_folder += SUBDIRECTORY_FOR_MODS;
load(preload, mods_folder);
}

View File

@ -4,10 +4,8 @@
#include <LIEF/ELF.hpp>
#include <dlfcn.h>
#include <link.h>
#include <libreborn/libreborn.h>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include "bootstrap.h"

View File

@ -1,115 +0,0 @@
FALSE Full Touch GUI
TRUE Fix Bow & Arrow
TRUE Fix Attacking
FALSE Force Mob Spawning
TRUE Disable Autojump By Default
TRUE Display Nametags By Default
TRUE Fix Sign Placement
TRUE Show Block Outlines
FALSE Expand Creative Mode Inventory
FALSE Remove Creative Mode Restrictions
FALSE Display Slot Count In Creative Mode
FALSE Force Survival Mode Inventory UI
FALSE Force Survival Mode Inventory Behavior
FALSE Maximize Creative Mode Inventory Stack Size
TRUE Animated Water
TRUE Animated Lava
TRUE Animated Fire
TRUE Regenerate "gui_blocks" Atlas
TRUE Fix Camera Rendering
TRUE Implement Chat
FALSE Hide Chat Messages
TRUE Implement Death Messages
TRUE Implement Game-Mode Switching
TRUE Allow Joining Survival Mode Servers
TRUE Miscellaneous Input Fixes
TRUE Bind "Q" Key To Item Dropping
TRUE Bind Common Toggleable Options To Function Keys
TRUE Render Selected Item Text
TRUE External Server Support
TRUE Load Language Files
TRUE Implement Sound Engine
TRUE Close Current Screen On Death
FALSE Disable Raw Mouse Motion (Not Recommended)
TRUE Fix Furnace Not Checking Item Auxiliary
TRUE Improved Cursor Rendering
TRUE Disable V-Sync
TRUE Fix Options Screen
TRUE Force Touch GUI Inventory
TRUE Fix Pause Menu
TRUE Add Title Screen Background
TRUE Force Touch GUI Button Behavior
TRUE Improved Button Hover Behavior
TRUE Implement Create World Dialog
FALSE Remove Forced GUI Lag (Can Break Joining Servers)
TRUE Add Buckets
TRUE Classic HUD
TRUE Translucent Toolbar
FALSE Force EGL
TRUE Improved Classic Title Screen
FALSE Disable Speed Bridging
FALSE Disable Creative Mode Mining Delay
FALSE Add Biome Colors To Grass
TRUE Generate Caves
FALSE Disable Block Tinting
TRUE Disable Hostile AI In Creative Mode
TRUE Load Custom Skins
TRUE 3D Chest Model
TRUE Replace Block Highlight With Outline
TRUE Add Cake
TRUE Use Java Beta 1.3 Light Ramp
TRUE Send Full Level When Hosting Game
FALSE Food Overlay
TRUE Add Splashes
TRUE Display Date In Select World Screen
TRUE Optimized Chunk Sorting
TRUE Fix Held Item Caching
TRUE Add Reborn Info To Options
FALSE Log FPS
TRUE Add Welcome Screen
TRUE F3 Debug Information
TRUE Multidraw Rendering
TRUE Add Missing Language Strings
TRUE Fix Pigmen Burning In The Sun
TRUE Fix Carried Grass's Bottom Texture
TRUE Hide Crosshair In Third-Person
TRUE Fix Camera Legs
TRUE Implement Crafting Remainders
TRUE Fix Door Duplication
TRUE Fix Cobweb Lighting
TRUE Fix Sneaking Syncing
TRUE Fix Fire Immunity
TRUE Fix Fire Syncing
TRUE Fix Sunlight Not Properly Setting Mobs On Fire
TRUE Stop Creative Players From Burning
TRUE Render Fire In Third-Person
TRUE Improved Water Rendering
TRUE Classic Item Count UI
TRUE Fix Screen Rendering When Hiding HUD
TRUE Sanitize Usernames
TRUE Patch RakNet Security Bug
TRUE Log RakNet Startup Errors
TRUE Prevent Unnecessary Server Pinging
TRUE Proper OpenGL Buffer Generation
TRUE Fix Furnace Screen Visual Bug
TRUE Fix Text Wrapping
TRUE Fullscreen Support
TRUE Always Save Chest Tile Entities
TRUE Fix Transferring Durability When Using Items
TRUE Fix Switching Perspective While Sneaking
TRUE Log Chat Messages
TRUE Log Game Status
TRUE Screenshot Support
TRUE Fix Camera Functionality
TRUE Allow High-Resolution Title
TRUE Improved Classic Title Positioning
TRUE Use Updated Title
TRUE Hide Block Outline When GUI Is Hidden
TRUE Fix Crash When Generating Certain Seeds
TRUE Click Buttons On Mouse Down
TRUE 3D Dropped Items
TRUE Render Entity Shadows
TRUE Render Vignette
TRUE Increase Render Chunk Size
TRUE Proper Entity Shading
TRUE Fix Sugar Position In Hand

View File

@ -6,18 +6,15 @@
#include <sys/stat.h>
#include <unistd.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/util.h>
#include "configuration.h"
#include "cache.h"
#include "configuration.h"
// Get Cache Path
static std::string get_cache_path() {
const char *home = getenv(_MCPI_HOME_ENV);
if (home == nullptr) {
IMPOSSIBLE();
}
return std::string(home) + get_home_subdirectory_for_game_data() + "/.launcher-cache";
return home_get() + "/.launcher-cache";
}
// Load
@ -37,7 +34,7 @@ launcher_cache load_cache() {
std::ifstream stream(get_cache_path(), std::ios::in | std::ios::binary);
if (!stream) {
// Fail
struct stat s;
struct stat s = {};
// No Warning If File Doesn't Exist
if (stat(get_cache_path().c_str(), &s) == 0) {
WARN("Unable To Open Launcher Cache For Loading");
@ -49,14 +46,12 @@ launcher_cache load_cache() {
// Check Version
unsigned char cache_version;
stream.read((char *) &cache_version, 1);
if (stream.eof() || cache_version != (unsigned char) CACHE_VERSION) {
// Fail
if (!stream.eof()) {
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", (int) CACHE_VERSION, (int) cache_version);
} else {
WARN("Unable To Read Launcher Cache Version");
}
stream.close();
if (stream.eof()) {
// Unable To Read Version
WARN("Unable To Read Launcher Cache Version");
} else if (cache_version != (unsigned char) CACHE_VERSION) {
// Invalid Version
WARN("Invalid Launcher Cache Version (Expected: %i, Actual: %i)", CACHE_VERSION, (int) cache_version);
} else {
// Load Username And Render Distance
launcher_cache cache;
@ -66,16 +61,15 @@ launcher_cache load_cache() {
// Load Feature Flags
std::string flag;
while (!stream.eof() && std::getline(stream, flag, '\0')) {
if (flag.length() > 0) {
unsigned char is_enabled = 0;
stream.read((char *) &is_enabled, 1);
cache.feature_flags[flag] = is_enabled != (unsigned char) 0;
if (!flag.empty()) {
bool is_enabled = false;
stream.read((char *) &is_enabled, sizeof(bool));
cache.feature_flags[flag] = is_enabled;
}
stream.peek();
}
// Finish
stream.close();
if (!stream) {
// Fail
WARN("Failure While Loading Launcher Cache");
@ -85,6 +79,9 @@ launcher_cache load_cache() {
}
}
// Close
stream.close();
// Unlock File
unlock_file(get_cache_path().c_str(), lock_fd);
}
@ -94,15 +91,10 @@ launcher_cache load_cache() {
}
// Save
#define write_env_to_stream(stream, env) \
{ \
const char *env_value = getenv(env); \
if (env == NULL) { \
IMPOSSIBLE(); \
} \
stream.write(env_value, strlen(env_value) + 1); \
}
void save_cache() {
static void write_env_to_stream(std::ofstream &stream, const std::string &value) {
stream.write(value.c_str(), int(value.size()) + 1);
}
void save_cache(const State &state) {
// Log
DEBUG("Saving Launcher Cache...");
@ -116,41 +108,23 @@ void save_cache() {
int lock_fd = lock_file(get_cache_path().c_str());
// Save Cache Version
unsigned char cache_version = (unsigned char) CACHE_VERSION;
constexpr unsigned char cache_version = CACHE_VERSION;
stream.write((const char *) &cache_version, 1);
// Save Username And Render Distance
write_env_to_stream(stream, MCPI_USERNAME_ENV);
write_env_to_stream(stream, MCPI_RENDER_DISTANCE_ENV);
write_env_to_stream(stream, state.username);
write_env_to_stream(stream, state.render_distance);
// Save Feature Flags
std::unordered_map<std::string, bool> flags;
load_available_feature_flags([&flags](std::string flag) {
std::string stripped_flag = strip_feature_flag_default(flag, nullptr);
flags[stripped_flag] = false;
});
{
const char *enabled_flags = getenv(MCPI_FEATURE_FLAGS_ENV);
if (enabled_flags == nullptr) {
IMPOSSIBLE();
}
std::istringstream enabled_flags_stream(enabled_flags);
std::string flag;
while (std::getline(enabled_flags_stream, flag, '|')) {
if (flag.length() > 0) {
flags[flag] = true;
}
}
}
for (auto &it : flags) {
stream.write(it.first.c_str(), it.first.size() + 1);
unsigned char val = it.second ? (unsigned char) 1 : (unsigned char) 0;
stream.write((const char *) &val, 1);
const std::unordered_map<std::string, bool> flags_cache = state.flags.to_cache();
for (const std::pair<const std::string, bool> &it : flags_cache) {
stream.write(it.first.c_str(), int(it.first.size()) + 1);
stream.write((const char *) &it.second, sizeof(bool));
}
// Finish
stream.close();
if (!stream.good()) {
if (!stream) {
WARN("Failure While Saving Launcher Cache");
}

View File

@ -16,7 +16,8 @@ extern launcher_cache empty_cache;
launcher_cache load_cache();
// Save Cache
void save_cache();
struct State;
void save_cache(const State &state);
// Wipe Cache
void wipe_cache();

View File

@ -1,145 +1,45 @@
#include <sstream>
#include <cstring>
#include <cerrno>
#include <sys/wait.h>
#include <sys/stat.h>
#include <vector>
#include <functional>
#include <algorithm>
#include <libreborn/libreborn.h>
#include <libreborn/env.h>
#include "../util/util.h"
#include "configuration.h"
#include "cache.h"
// Strip Feature Flag Default
std::string strip_feature_flag_default(const std::string &flag, bool *default_ret) {
// Valid Values
std::string true_str = "TRUE ";
std::string false_str = "FALSE ";
// Test
if (flag.rfind(true_str, 0) == 0) {
// Enabled By Default
if (default_ret != nullptr) {
*default_ret = true;
}
return flag.substr(true_str.length(), std::string::npos);
} else if (flag.rfind(false_str, 0) == 0) {
// Disabled By Default
if (default_ret != nullptr) {
*default_ret = false;
}
return flag.substr(false_str.length(), std::string::npos);
// State
State::State(const launcher_cache &cache): flags("") {
username = cache.username;
render_distance = cache.render_distance;
flags = Flags::get();
flags.from_cache(cache.feature_flags);
}
template <typename T>
static void update_from_env(const char *env, T &value, const bool save) {
if (save) {
const std::string str = static_cast<std::string>(value);
set_and_print_env(env, str.c_str());
} else {
// Invalid
ERR("Invalid Feature Flag Default");
}
}
// Load Available Feature Flags
extern unsigned char available_feature_flags[];
extern size_t available_feature_flags_len;
void load_available_feature_flags(const std::function<void(std::string)> &callback) {
// Load Data
const std::string data(available_feature_flags, available_feature_flags + available_feature_flags_len);
std::stringstream stream(data);
// Store Lines
std::vector<std::string> lines;
// Read File
{
std::string line;
while (std::getline(stream, line)) {
if (!line.empty()) {
// Verify Line
if (line.find('|') == std::string::npos) {
lines.push_back(line);
} else {
// Invalid Line
ERR("Feature Flag Contains Invalid '|'");
}
}
}
}
// Sort
std::sort(lines.begin(), lines.end(), [](const std::string &a, const std::string &b) {
// Strip Defaults
const std::string stripped_a = strip_feature_flag_default(a, nullptr);
const std::string stripped_b = strip_feature_flag_default(b, nullptr);
// Sort
return stripped_a < stripped_b;
});
// Run Callbacks
for (const std::string &line : lines) {
callback(line);
}
}
// Run Command And Set Environmental Variable
static void run_command_and_set_env(const char *env_name, const char *command[]) {
// Only Run If Environmental Variable Is NULL
if (getenv(env_name) == nullptr) {
// Check $DISPLAY
reborn_check_display();
// Run
int return_code;
const std::vector<unsigned char> *output = run_command(command, &return_code);
std::string output_str = (const char *) output->data();
delete output;
// Trim
const std::string::size_type length = output_str.length();
if (length > 0 && output_str[length - 1] == '\n') {
output_str.pop_back();
}
// Set
set_and_print_env(env_name, output_str.c_str());
// Check Return Code
if (!is_exit_status_success(return_code)) {
// Launch Interrupted
exit(EXIT_SUCCESS);
const char *env_value = getenv(env);
if (env_value != nullptr) {
value = env_value;
}
}
}
// Use Zenity To Set Environmental Variable
#define DIALOG_TITLE "Launcher"
static void run_zenity_and_set_env(const char *env_name, std::vector<std::string> command) {
// Create Full Command
std::vector<std::string> full_command;
full_command.push_back("zenity");
full_command.push_back("--title");
full_command.push_back(DIALOG_TITLE);
full_command.push_back("--name");
full_command.push_back(MCPI_APP_ID);
full_command.insert(full_command.end(), command.begin(), command.end());
// Convert To C Array
const char *full_command_array[full_command.size() + 1];
for (std::vector<std::string>::size_type i = 0; i < full_command.size(); i++) {
full_command_array[i] = full_command[i].c_str();
}
full_command_array[full_command.size()] = nullptr;
// Run
run_command_and_set_env(env_name, full_command_array);
void State::update(const bool save) {
update_from_env(MCPI_FEATURE_FLAGS_ENV, flags, save);
update_from_env(MCPI_USERNAME_ENV, username, save);
update_from_env(MCPI_RENDER_DISTANCE_ENV, render_distance, save);
}
// Set Variable If Not Already Set
static void set_env_if_unset(const char *env_name, const std::function<std::string()> &callback) {
if (getenv(env_name) == nullptr) {
char *value = strdup(callback().c_str());
ALLOC_CHECK(value);
set_and_print_env(env_name, value);
free(value);
}
bool State::operator==(const State &other) const {
#define test(x) static_cast<std::string>(x) == static_cast<std::string>(other.x)
return test(username) && test(render_distance) && test(flags);
#undef test
}
// Handle Non-Launch Commands
void handle_non_launch_client_only_commands(const options_t &options) {
// Print Available Feature Flags
if (options.print_available_feature_flags) {
load_available_feature_flags([](const std::string &line) {
printf("%s\n", line.c_str());
fflush(stdout);
});
const Flags flags = Flags::get();
flags.print();
exit(EXIT_SUCCESS);
}
// Wipe Cache If Needed
@ -150,115 +50,31 @@ void handle_non_launch_client_only_commands(const options_t &options) {
}
// Configure Client Options
#define LIST_DIALOG_SIZE "400"
void configure_client(const options_t &options) {
// Load Cache
launcher_cache cache = options.no_cache ? empty_cache : load_cache();
const launcher_cache cache = options.no_cache ? empty_cache : load_cache();
// Setup State
State state(cache);
state.update(false);
// --default
if (options.use_default) {
// Use Default Feature Flags
set_env_if_unset(MCPI_FEATURE_FLAGS_ENV, [&cache]() {
std::string feature_flags;
load_available_feature_flags([&feature_flags, &cache](const std::string &flag) {
bool value;
// Strip Default Value
std::string stripped_flag = strip_feature_flag_default(flag, &value);
// Use Cache
if (cache.feature_flags.count(stripped_flag) > 0) {
value = cache.feature_flags[stripped_flag];
}
// Specify Default Value
if (value) {
// Enabled By Default
feature_flags += stripped_flag + '|';
}
});
if (!feature_flags.empty() && feature_flags[feature_flags.length() - 1] == '|') {
feature_flags.pop_back();
}
return feature_flags;
});
set_env_if_unset(MCPI_RENDER_DISTANCE_ENV, [&cache]() {
return cache.render_distance;
});
set_env_if_unset(MCPI_USERNAME_ENV, [&cache]() {
return cache.username;
});
}
// Setup MCPI_FEATURE_FLAGS
{
std::vector<std::string> command;
command.push_back("--list");
command.push_back("--checklist");
command.push_back("--width");
command.push_back(LIST_DIALOG_SIZE);
command.push_back("--height");
command.push_back(LIST_DIALOG_SIZE);
command.push_back("--column");
command.push_back("Enabled");
command.push_back("--column");
command.push_back("Feature");
load_available_feature_flags([&command, &cache](const std::string &flag) {
bool value;
// Strip Default Value
std::string stripped_flag = strip_feature_flag_default(flag, &value);
// Use Cache
if (cache.feature_flags.count(stripped_flag) > 0) {
value = cache.feature_flags[stripped_flag];
}
// Specify Default Value
if (value) {
// Enabled By Default
command.push_back("TRUE");
} else {
// Disabled By Default
command.push_back("FALSE");
}
// Specify Name
command.push_back(stripped_flag);
});
// Run
run_zenity_and_set_env(MCPI_FEATURE_FLAGS_ENV, command);
}
// Setup MCPI_RENDER_DISTANCE
{
std::vector<std::string> command;
command.push_back("--list");
command.push_back("--radiolist");
command.push_back("--width");
command.push_back(LIST_DIALOG_SIZE);
command.push_back("--height");
command.push_back(LIST_DIALOG_SIZE);
command.push_back("--text");
command.push_back("Select Minecraft Render Distance:");
command.push_back("--column");
command.push_back("Selected");
command.push_back("--column");
command.push_back("Name");
std::string render_distances[] = {"Far", "Normal", "Short", "Tiny"};
for (std::string &render_distance : render_distances) {
command.push_back(render_distance == cache.render_distance ? "TRUE" : "FALSE");
command.push_back(render_distance);
bool save_settings = !options.no_cache;
if (!options.use_default) {
// Show UI
ConfigurationUI *ui = new ConfigurationUI(state, save_settings);
const int ret = ui->run();
delete ui;
if (ret <= 0) {
exit(EXIT_SUCCESS);
}
// Run
run_zenity_and_set_env(MCPI_RENDER_DISTANCE_ENV, command);
}
// Setup MCPI_USERNAME
{
std::vector<std::string> command;
command.push_back("--entry");
command.push_back("--text");
command.push_back("Enter Minecraft Username:");
command.push_back("--entry-text");
command.push_back(cache.username);
// Run
run_zenity_and_set_env(MCPI_USERNAME_ENV, command);
}
// Save Cache
if (!options.no_cache) {
save_cache();
if (save_settings) {
save_cache(state);
}
// Update Environment
state.update(true);
}

View File

@ -1,17 +1,45 @@
#pragma once
#include <string>
#include <functional>
#include "../options/parser.h"
#include "cache.h"
#include "../ui/frame.h"
// Defaults
#include <libreborn/flags.h>
// Default Configuration
#define DEFAULT_USERNAME "StevePi"
#define DEFAULT_RENDER_DISTANCE "Short"
// Feature Flags
std::string strip_feature_flag_default(const std::string& flag, bool *default_ret);
void load_available_feature_flags(const std::function<void(std::string)> &callback);
// State
struct State {
explicit State(const launcher_cache &cache);
// Methods
void update(bool save);
bool operator==(const State &other) const;
// Properties
std::string username;
std::string render_distance;
Flags flags;
};
// UI
struct ConfigurationUI final : Frame {
explicit ConfigurationUI(State &state_, bool &save_settings_);
int render() override;
private:
void update_render_distance();
int draw_bottom();
void draw_main();
void draw_advanced() const;
static void draw_category(FlagNode &category);
const State default_state;
const State original_state;
State &state;
bool &save_settings;
int render_distance_index;
};
// Handle Non-Launch Commands
void handle_non_launch_client_only_commands(const options_t &options);

143
launcher/src/client/ui.cpp Normal file
View File

@ -0,0 +1,143 @@
#include <vector>
#include "configuration.h"
#include "cache.h"
#include <imgui_stdlib.h>
// Render Distances
static std::vector render_distances = {
"Far",
"Normal",
"Short",
"Tiny"
};
// Construct
static constexpr int size = 400;
ConfigurationUI::ConfigurationUI(State &state_, bool &save_settings_):
Frame("Launcher", size, size),
default_state(empty_cache),
original_state(state_),
state(state_),
save_settings(save_settings_) {
update_render_distance();
}
void ConfigurationUI::update_render_distance() {
render_distance_index = 0;
for (std::vector<std::string>::size_type i = 0; i < render_distances.size(); i++) {
if (std::string(render_distances[i]) == state.render_distance) {
render_distance_index = int(i);
break;
}
}
}
// Render
int ConfigurationUI::render() {
if (ImGui::BeginChild("Main", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() /* Leave Room For Bottom Row */), ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
// Tabs
if (ImGui::BeginTabBar("TabBar")) {
// Main Tab
if (ImGui::BeginTabItem("General")) {
draw_main();
ImGui::EndTabItem();
}
// Advanced Tab
if (ImGui::BeginTabItem("Advanced")) {
draw_advanced();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
ImGui::EndChild();
// Bottom Row
return draw_bottom();
}
// Bottom Row
int ConfigurationUI::draw_bottom() {
// Reset All Settings
std::vector<std::tuple<const char *, const char *, const State *>> reset_options = {
{"Revert", "Last Saved", &original_state},
{"Reset", "Default", &default_state}
};
for (const std::tuple<const char *, const char *, const State *> &option : reset_options) {
const State &new_state = *std::get<2>(option);
ImGui::BeginDisabled(state == new_state);
if (ImGui::Button(std::get<0>(option))) {
state = new_state;
update_render_distance();
}
ImGui::SetItemTooltip("Use %s Settings", std::get<1>(option));
ImGui::EndDisabled();
ImGui::SameLine();
}
// Right-Align Buttons
int ret = 0;
draw_right_aligned_buttons({"Quit", "Launch"}, [&ret](const int id, const bool was_clicked) {
if (id == 0) {
// Quit
if (was_clicked) {
ret = -1;
}
ImGui::SetItemTooltip("Changes Will Not Be Saved!");
} else if (was_clicked) {
// Launch
ret = 1;
}
});
// Return
return ret;
}
// Main Tab
void ConfigurationUI::draw_main() {
const ImGuiStyle &style = ImGui::GetStyle();
const char *labels[] = {"Username", "Render Distance"};
// Calculate Label Size
float label_size = 0;
for (const char *label : labels) {
label_size = std::max(label_size, ImGui::CalcTextSize(label).x + style.ItemInnerSpacing.x);
}
ImGui::PushItemWidth(-label_size);
// Options
ImGui::InputText(labels[0], &state.username);
ImGui::Combo(labels[1], &render_distance_index, render_distances.data(), int(render_distances.size()));
state.render_distance = render_distances[render_distance_index];
ImGui::PopItemWidth();
ImGui::Checkbox("Save Settings On Launch", &save_settings);
}
// Advanced Tab
static std::string get_label(const FlagNode &node) {
return node.name + "##" + std::to_string(node.id);
}
void ConfigurationUI::draw_advanced() const {
if (ImGui::BeginChild("Features", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar)) {
// Categories
for (FlagNode &category : state.flags.root.children) {
std::string label = get_label(category);
if (ImGui::CollapsingHeader(label.c_str())) {
draw_category(category);
}
}
}
ImGui::EndChild();
}
// Feature Categories
void ConfigurationUI::draw_category(FlagNode &category) {
for (FlagNode &child : category.children) {
std::string label = get_label(child);
if (!child.children.empty()) {
if (ImGui::TreeNode(label.c_str())) {
draw_category(child);
ImGui::TreePop();
}
} else {
ImGui::Checkbox(label.c_str(), &child.value);
}
}
}

View File

@ -1,35 +1,92 @@
#include <libreborn/libreborn.h>
#include <fstream>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include <libreborn/exec.h>
#include "logger.h"
#include "../ui/frame.h"
// UI
struct CrashReport final : Frame {
explicit CrashReport(const char *filename): Frame("Crash Report", 640, 480) {
// Open File
std::ifstream stream(filename, std::ios_base::binary | std::ios_base::ate);
if (stream) {
// Read File
const std::streamoff size = stream.tellg();
stream.seekg(0, std::ifstream::beg);
log.resize(size);
stream.read(log.data(), size);
// Close File
stream.close();
}
}
bool first_render = true;
int render() override {
// Text
ImGui::TextWrapped("%s", MCPI_APP_TITLE " has crashed!");
ImGui::Spacing();
ImGui::TextWrapped("Need help? Consider asking on the Discord server!");
ImGui::Spacing();
ImGui::TextWrapped("If you believe this is a problem with " MCPI_APP_TITLE " itself, please upload this crash report to the #bugs Discord channel.");
// Log
if (ImGui::BeginChild("Log", ImVec2(0, -ImGui::GetFrameHeightWithSpacing() /* Leave Room For Bottom Row */), ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar)) {
ImGui::PushFont(monospace);
ImGui::TextUnformatted(log.data(), log.data() + log.size());
ImGui::PopFont();
if (first_render) {
ImGui::SetScrollHereY(1.0f);
first_render = false;
}
}
ImGui::EndChild();
// Buttons
if (ImGui::Button("Join Discord")) {
open_url(MCPI_DISCORD_INVITE);
}
ImGui::SameLine();
if (ImGui::Button("View All Logs")) {
open_url("file://" + get_logs_folder());
}
ImGui::SameLine();
// Right-Aligned
int ret = 0;
const std::string &log_ref = log;
draw_right_aligned_buttons({"Copy", "Quit"}, [&ret, &log_ref](const int id, const bool was_clicked) {
if (was_clicked) {
if (id == 0) {
// Copy Log
ImGui::SetClipboardText(log_ref.c_str());
} else {
// Exit
ret = 1;
}
}
});
return ret;
}
std::string log;
};
// Show Crash Report Dialog
#define DIALOG_TITLE "Crash Report"
#define CRASH_REPORT_DIALOG_WIDTH "640"
#define CRASH_REPORT_DIALOG_HEIGHT "480"
static void redirect_file(FILE *file, const char *mode) {
const FILE *ret = freopen("/dev/null", mode, file);
if (!ret) {
IMPOSSIBLE();
}
}
void show_report(const char *log_filename) {
// Fork
pid_t pid = fork();
const pid_t pid = fork();
if (pid == 0) {
// Child
setsid();
ALLOC_CHECK(freopen("/dev/null", "w", stdout));
ALLOC_CHECK(freopen("/dev/null", "w", stderr));
ALLOC_CHECK(freopen("/dev/null", "r", stdin));
const char *command[] = {
"zenity",
"--title", DIALOG_TITLE,
"--name", MCPI_APP_ID,
"--width", CRASH_REPORT_DIALOG_WIDTH,
"--height", CRASH_REPORT_DIALOG_HEIGHT,
"--text-info",
"--text", MCPI_APP_TITLE " has crashed!\n\nNeed help? Consider asking on the <a href=\"" MCPI_DISCORD_INVITE "\">Discord server</a>! <i>If you believe this is a problem with " MCPI_APP_TITLE " itself, please upload this crash report to the #bugs Discord channel.</i>",
"--filename", log_filename,
"--no-wrap",
"--font", "Monospace",
"--save-filename", MCPI_VARIANT_NAME "-crash-report.log",
"--ok-label", "Exit",
nullptr
};
safe_execvpe(command, (const char *const *) environ);
redirect_file(stdout, "w");
redirect_file(stderr, "w");
redirect_file(stdin, "r");
CrashReport ui(log_filename);
ui.run();
exit(EXIT_SUCCESS);
}
}

View File

@ -3,16 +3,16 @@
#include <cerrno>
#include <cstdlib>
#include <cstdio>
#include <cstdint>
#include <csignal>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <ctime>
#include <string>
#include <fcntl.h>
#include <libreborn/libreborn.h>
#include <libreborn/exec.h>
#include <libreborn/log.h>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include "logger.h"
@ -26,12 +26,16 @@ static void exit_handler(__attribute__((unused)) int signal) {
// Log File
static std::string log_filename;
static int log_fd;
static void setup_log_file() {
// Get Log Directory
const std::string home = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
std::string get_logs_folder() {
const std::string home = home_get();
ensure_directory(home.c_str());
const std::string logs = home + "/logs";
ensure_directory(logs.c_str());
return logs;
}
static void setup_log_file() {
// Get Log Directory
const std::string logs = get_logs_folder();
// Get Timestamp
time_t raw_time;
@ -129,7 +133,7 @@ void setup_logger() {
// Close Log File
close(log_fd);
unsetenv(_MCPI_LOG_FD_ENV);
reborn_set_log(-1);
// Show Crash Log
if (is_crash && !reborn_is_headless()) {

View File

@ -1,4 +1,7 @@
#pragma once
#include <string>
std::string get_logs_folder();
void setup_logger();
void show_report(const char *log_filename);

View File

@ -1,5 +1,8 @@
#include <cstdlib>
#include <libreborn/libreborn.h>
#include <libreborn/env.h>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include "bootstrap/bootstrap.h"
#include "options/parser.h"
@ -24,49 +27,13 @@ static void setup_environment(const options_t &options) {
bind_to_env(_MCPI_FORCE_HEADLESS_ENV, options.force_headless);
bind_to_env(_MCPI_FORCE_NON_HEADLESS_ENV, options.force_non_headless);
// GTK Dark Mode
set_and_print_env("GTK_THEME", "Adwaita:dark");
// Configure PATH
{
// Get Binary Directory
const std::string binary_directory = get_binary_directory();
std::string new_path = binary_directory + "/bin";
// Add Existing PATH
{
const char *value = getenv("PATH");
if (value != nullptr && strlen(value) > 0) {
new_path += std::string(":") + value;
}
}
// Set And Free
set_and_print_env("PATH", new_path.c_str());
}
setup_path();
// Setup MCPI_HOME
const char *custom_profile_directory = getenv(MCPI_PROFILE_DIRECTORY_ENV);
if (custom_profile_directory != nullptr) {
// Custom Directory
custom_profile_directory = realpath(custom_profile_directory, nullptr);
ALLOC_CHECK(custom_profile_directory);
set_and_print_env(_MCPI_HOME_ENV, custom_profile_directory);
free((void *) custom_profile_directory);
} else if (!reborn_is_server()) {
// Ensure $HOME
const char *home = getenv("HOME");
if (home == nullptr) {
ERR("$HOME Is Not Set");
}
set_and_print_env(_MCPI_HOME_ENV, home);
} else {
// Set Home To Current Directory, So World Data Is Stored There
char *launch_directory = getcwd(nullptr, 0);
ALLOC_CHECK(launch_directory);
set_and_print_env(_MCPI_HOME_ENV, launch_directory);
free(launch_directory);
}
setup_home();
// Create If Needed
const std::string minecraft_folder = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
const std::string minecraft_folder = home_get();
ensure_directory(minecraft_folder.c_str());
}

View File

@ -1,6 +1,9 @@
#include <argp.h>
#include <libreborn/config.h>
#include <libreborn/env.h>
#include <trampoline/types.h>
#include "parser.h"
// Globals

View File

@ -1,7 +1,5 @@
#pragma once
#include <libreborn/libreborn.h>
#define OPTION(name, ...) bool name;
struct options_t {
#include "option-list.h"

83
launcher/src/ui/color.cpp Normal file
View File

@ -0,0 +1,83 @@
#include "frame.h"
// Calculate Perceived Brightness Of Color
// See: https://en.wikipedia.org/w/index.php?title=Relative_luminance&useskin=vector
static float compute_luma(const ImVec4 &color) {
return (0.2126f * color.x) + (0.7152f * color.y) + (0.0722f * color.z);
}
// Apply Luma To RGB
static float clamp(const float value) {
return std::max(0.0f, std::min(value, 1.0f));
}
static ImVec4 apply_luma_to_color(const float target_luma, const ImVec4 &color) {
const float current_luma = compute_luma(color);
const float luma_ratio = (current_luma != 0) ? target_luma / current_luma : 0;
ImVec4 out = color;
for (float *x : {&out.x, &out.y, &out.z}) {
*x = clamp(*x * luma_ratio);
}
return out;
}
// Blend Color
static ImVec4 blend_color(const ImVec4 &top, const ImVec4 &bottom) {
const float luma = compute_luma(bottom);
ImVec4 out = apply_luma_to_color(luma, top);
out.w = bottom.w;
return out;
}
static ImVec4 blend_with_primary(const ImVec4 &color) {
static constexpr ImVec4 primary_color = {1.0f, (69.0f / 255.0f), 0.0f, 1.0f};
return blend_color(primary_color, color);
}
// Modify Colors
void Frame::patch_colors(ImGuiStyle &style) {
// Blend Colors
static int target_colors_blend[] = {
ImGuiCol_FrameBg,
ImGuiCol_FrameBgHovered,
ImGuiCol_FrameBgActive,
ImGuiCol_TitleBgActive,
ImGuiCol_CheckMark,
ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive,
ImGuiCol_Button,
ImGuiCol_ButtonHovered,
ImGuiCol_ButtonActive,
ImGuiCol_Header,
ImGuiCol_HeaderHovered,
ImGuiCol_HeaderActive,
ImGuiCol_SeparatorHovered,
ImGuiCol_SeparatorActive,
ImGuiCol_ResizeGrip,
ImGuiCol_ResizeGripHovered,
ImGuiCol_ResizeGripActive,
ImGuiCol_TabHovered,
ImGuiCol_Tab,
ImGuiCol_TabSelected,
ImGuiCol_TabSelectedOverline,
ImGuiCol_TabDimmed,
ImGuiCol_TabDimmedSelected,
ImGuiCol_TextLink,
ImGuiCol_TextSelectedBg,
ImGuiCol_NavCursor
};
for (const int target_color : target_colors_blend) {
ImVec4 &color = style.Colors[target_color];
color = blend_with_primary(color);
}
// Remove Blue Accent From Colors
static int target_colors_modify[] = {
ImGuiCol_Separator,
ImGuiCol_Border,
ImGuiCol_TableHeaderBg,
ImGuiCol_TableBorderStrong,
ImGuiCol_TableBorderLight
};
for (const int target_color : target_colors_modify) {
ImVec4 &color = style.Colors[target_color];
color.y = color.z = color.x;
}
}

113
launcher/src/ui/frame.cpp Normal file
View File

@ -0,0 +1,113 @@
#include <cmath>
#include "frame.h"
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl2.h>
#include <libreborn/log.h>
#include <libreborn/glfw.h>
#include <libreborn/util.h>
// Init/Cleanup
Frame::Frame(const char *title, const int width, const int height) {
// Create Window
init_glfw();
window = create_glfw_window(title, width, height);
// Disable V-Sync
// (On Wayland, This Fixes Issues With The Clipboard)
glfwSwapInterval(0);
// Setup ImGui Context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.IniFilename = nullptr;
io.LogFilename = nullptr;
// Setup Platform/Renderer Backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL2_Init();
}
Frame::~Frame() {
// Shutdown ImGui
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
// Cleanup GLFW
cleanup_glfw(window);
}
// Run Loop
int Frame::run() {
int ret = 0;
while (!glfwWindowShouldClose(window) && ret == 0) {
glfwPollEvents();
// Update Style
static float last_scale = -1.0f;
float scale;
get_glfw_scale(window, &scale, nullptr);
if (scale != last_scale) {
last_scale = scale;
setup_style(scale);
}
// Start Frame
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Main Window
ImGui::SetNextWindowPos({0, 0});
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ImGui::SetNextWindowSize({float(width), float(height)});
if (ImGui::Begin("###Frame", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoScrollWithMouse)) {
ret = render();
}
ImGui::End();
// Render To OpenGL
ImGui::Render();
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
return ret;
}
// Style
EMBEDDED_RESOURCE(Roboto_Medium_ttf);
EMBEDDED_RESOURCE(Cousine_Regular_ttf);
void Frame::setup_style(const float scale) {
// Fonts
const ImGuiIO &io = ImGui::GetIO();
io.Fonts->Clear();
ImFontConfig font_cfg;
font_cfg.FontDataOwnedByAtlas = false;
io.Fonts->AddFontFromMemoryTTF(Roboto_Medium_ttf, int(Roboto_Medium_ttf_len), std::floor(20.0f * scale), &font_cfg);
monospace = io.Fonts->AddFontFromMemoryTTF(Cousine_Regular_ttf, int(Cousine_Regular_ttf_len), std::floor(18.0f * scale), &font_cfg);
// Style
ImGuiStyle &style = ImGui::GetStyle();
style = ImGuiStyle();
style.WindowBorderSize = 0;
ImGui::StyleColorsDark(&style);
style.ScaleAllSizes(scale);
patch_colors(style);
}
// Right-Aligned Buttons
void Frame::draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback) {
// Calculate Position
const ImGuiStyle &style = ImGui::GetStyle();
float width_needed = 0;
for (const char *text : buttons) {
if (width_needed > 0) {
width_needed += style.ItemSpacing.x;
}
width_needed += ImGui::CalcTextSize(text).x + style.FramePadding.x * 2.0f;
}
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - width_needed);
// Draw
for (std::vector<const char *>::size_type id = 0; id < buttons.size(); id++) {
if (id > 0) {
ImGui::SameLine();
}
callback(int(id), ImGui::Button(buttons[id]));
}
}

30
launcher/src/ui/frame.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <vector>
#include <functional>
#include <imgui.h>
#include <GLFW/glfw3.h>
// UI Frame
struct Frame {
Frame(const char *title, int width, int height);
virtual ~Frame();
// Prevent Copying
Frame(const Frame &) = delete;
Frame &operator=(const Frame &) = delete;
// Run
int run();
virtual int render() = 0;
protected:
// API For Sub-Classes
ImFont *monospace = nullptr;
static void draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback);
private:
// Properties
GLFWwindow *window = nullptr;
// Internal Methods
float get_scale();
void setup_style(float scale);
static void patch_colors(ImGuiStyle &style);
};

52
launcher/src/util/env.cpp Normal file
View File

@ -0,0 +1,52 @@
#include <cstring>
#include "util.h"
#include <libreborn/log.h>
#include <libreborn/env.h>
#include <libreborn/config.h>
// $PATH
void setup_path() {
// Get Binary Directory
const std::string binary_directory = get_binary_directory();
std::string new_path = binary_directory + "/bin";
// Add Existing PATH
const char *value = getenv("PATH");
if (value != nullptr && strlen(value) > 0) {
new_path += std::string(":") + value;
}
// Set And Free
set_and_print_env("PATH", new_path.c_str());
}
// Profile Directory
void setup_home() {
const char *custom_profile_directory = getenv(MCPI_PROFILE_DIRECTORY_ENV);
std::string home;
if (custom_profile_directory != nullptr) {
// Custom Directory
home = safe_realpath(custom_profile_directory);
} else if (!reborn_is_server()) {
// Ensure $HOME
const char *value = getenv("HOME");
if (value == nullptr) {
ERR("$HOME Is Not Set");
}
home = value;
// Flatpak
#ifdef MCPI_IS_FLATPAK_BUILD
home += "/.var/app/" MCPI_APP_ID;
#endif
} else {
// Set Home To Current Directory, So World Data Is Stored There
char *launch_directory = getcwd(nullptr, 0);
if (launch_directory == nullptr) {
IMPOSSIBLE();
}
home = launch_directory;
free(launch_directory);
}
// Set
set_and_print_env(_MCPI_HOME_ENV, home.c_str());
}

View File

@ -1,4 +1,6 @@
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include "../bootstrap/bootstrap.h"
#include "util.h"
@ -14,12 +16,12 @@
}
// Copy SDK Into ~/.minecraft-pi
#define HOME_SUBDIRECTORY_FOR_SDK (std::string(get_home_subdirectory_for_game_data()) + "/sdk")
#define HOME_SUBDIRECTORY_FOR_SDK "/sdk"
void copy_sdk(const std::string &binary_directory, const bool log_with_debug) {
// Ensure SDK Directory
std::string sdk_path;
{
sdk_path = std::string(getenv(_MCPI_HOME_ENV)) + HOME_SUBDIRECTORY_FOR_SDK;
sdk_path = home_get() + HOME_SUBDIRECTORY_FOR_SDK;
const char *const command[] = {"mkdir", "-p", sdk_path.c_str(), nullptr};
run_simple_command(command, "Unable To Create SDK Directory");
}

View File

@ -1,4 +1,5 @@
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/exec.h>
#include "util.h"

View File

@ -8,4 +8,7 @@ void chop_last_component(std::string &str);
std::string safe_realpath(const std::string &path);
std::string get_binary_directory();
void copy_sdk(const std::string &binary_directory, bool log_with_debug);
void copy_sdk(const std::string &binary_directory, bool log_with_debug);
void setup_path();
void setup_home();

View File

@ -12,23 +12,22 @@ add_library(reborn-util SHARED
src/util/log.cpp
src/util/cp437.cpp
src/util/env.cpp
src/util/config.cpp
src/util/flags/node.cpp
src/util/flags/flags.cpp
src/util/flags/available-feature-flags # Show In IDE
)
target_include_directories(
reborn-util
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/libreborn>"
)
embed_resource(reborn-util src/util/flags/available-feature-flags)
target_link_libraries(reborn-util PRIVATE utf8cpp)
# Install
install(TARGETS reborn-util DESTINATION "${MCPI_LIB_DIR}")
# SDK
if(BUILD_ARM_COMPONENTS)
install(TARGETS reborn-util EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/libreborn")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/libreborn")
if(TARGET glfw)
target_sources(reborn-util PRIVATE src/util/glfw.cpp)
target_link_libraries(reborn-util PRIVATE glfw)
endif()
setup_header_dirs(reborn-util
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}/include"
)
setup_library(reborn-util TRUE TRUE)
# Patch
if(BUILD_ARM_COMPONENTS)
@ -39,11 +38,9 @@ if(BUILD_ARM_COMPONENTS)
src/patch/instruction.cpp
)
target_link_libraries(reborn-patch dl pthread reborn-util)
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
target_compile_definitions(reborn-patch PUBLIC REBORN_HAS_PATCH_CODE)
# Install
install(TARGETS reborn-patch DESTINATION "${MCPI_LIB_DIR}")
# SDK
install(TARGETS reborn-patch EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
setup_library(reborn-patch TRUE TRUE)
endif()
# Fake LibPNG To Satisfy Symbol Versioning Requirement
@ -55,5 +52,5 @@ if(BUILD_ARM_COMPONENTS)
)
target_link_options(fake-libpng PRIVATE "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/fake-libpng/empty.vers")
# Install
install(TARGETS fake-libpng DESTINATION "${MCPI_LIB_DIR}")
setup_library(fake-libpng TRUE FALSE)
endif()

View File

@ -3,7 +3,6 @@
#cmakedefine MCPI_IS_APPIMAGE_BUILD
#cmakedefine MCPI_IS_FLATPAK_BUILD
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
#cmakedefine MCPI_APP_BASE_TITLE "@MCPI_APP_BASE_TITLE@"
#cmakedefine MCPI_APP_TITLE "@MCPI_APP_TITLE@"
#cmakedefine MCPI_APP_ID "@MCPI_APP_ID@"
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
@ -12,3 +11,8 @@
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"
#cmakedefine MCPI_DOCUMENTATION "@MCPI_DOCUMENTATION@"
// Access Configuration At Runtime
const char *reborn_get_version();
bool reborn_is_headless();
bool reborn_is_server();

View File

@ -20,12 +20,12 @@ void poll_fds(const std::vector<int> &fds, const std::function<void(int, size_t,
// Safe execvpe()
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
// Debug Tag
#define CHILD_PROCESS_TAG "(Child Process) "
// Run Command And Get Output
std::vector<unsigned char> *run_command(const char *const command[], int *exit_status);
#define is_exit_status_success(status) (WIFEXITED(status) && WEXITSTATUS(status) == 0)
bool is_exit_status_success(int status);
// Get Exit Status String
std::string get_exit_status_string(int status);
std::string get_exit_status_string(int status);
// Open URL
void open_url(const std::string &url);

View File

@ -0,0 +1,48 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <functional>
// Seperator
#define FLAG_SEPERATOR_CHAR '|'
// Flag
struct FlagNode {
private:
explicit FlagNode(const std::string &name_);
public:
FlagNode();
// Methods
void sort();
void for_each(const std::function<void(FlagNode &)> &callback);
void for_each_const(const std::function<void(const FlagNode &)> &callback) const;
void add_flag(std::string line);
FlagNode &add_category(const std::string &new_name);
// Properties
std::string name;
bool value;
std::vector<FlagNode> children;
int id;
// Internal
static bool handle_line_prefix(const std::string &prefix, std::string &line);
static std::unordered_map<std::string, bool> flag_prefixes;
static void reset_id_counter();
};
// All Flags
struct Flags {
explicit Flags(const std::string &data);
static Flags get();
// To/From Strings
explicit operator std::string() const;
Flags &operator=(const std::string &str);
// To/From Cache
[[nodiscard]] std::unordered_map<std::string, bool> to_cache() const;
void from_cache(const std::unordered_map<std::string, bool> &cache);
// Print
void print() const;
// Properties
FlagNode root;
};

View File

@ -0,0 +1,11 @@
#pragma once
// GLFW Helpers
#ifndef GLFW_VERSION_MAJOR
#error "Missing GLFW"
#endif
void init_glfw();
GLFWwindow *create_glfw_window(const char *title, int width, int height);
void cleanup_glfw(GLFWwindow *window);
void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale);

View File

@ -1,9 +0,0 @@
#pragma once
#include <libreborn/config.h>
#include "env.h"
#include "log.h"
#include "util.h"
#include "string.h"
#include "exec.h"
#include "patch.h"

View File

@ -2,6 +2,7 @@
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
// Log File
int reborn_get_log_fd();
@ -13,15 +14,18 @@ int reborn_get_debug_fd();
// Logging
#define INFO(format, ...) fprintf(stderr, "[INFO]: " format "\n", ##__VA_ARGS__)
#define WARN(format, ...) fprintf(stderr, "[WARN]: " format "\n", ##__VA_ARGS__)
#define RAW_DEBUG(tag, format, ...) dprintf(reborn_get_debug_fd(), "[DEBUG]: %s" format "\n", tag, ##__VA_ARGS__)
#define DEBUG(format, ...) RAW_DEBUG(reborn_debug_tag, format, ##__VA_ARGS__)
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); _exit(EXIT_FAILURE); }
#define DEBUG(format, ...) dprintf(reborn_get_debug_fd(), "[DEBUG]: %s" format "\n", reborn_debug_tag, ##__VA_ARGS__)
#define ERR(format, ...) \
({ \
fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
_exit(EXIT_FAILURE); \
})
#define IMPOSSIBLE() ERR("This Should Never Be Called")
#define CONDITIONAL_ERR(is_error, ...) \
{ \
({ \
if ((is_error)) { \
ERR(__VA_ARGS__); \
} else { \
WARN(__VA_ARGS__); \
} \
}
})

View File

@ -1,9 +1,11 @@
#pragma once
#include <string>
#include "log.h"
// Patching Functions
#if defined(REBORN_HAS_PATCH_CODE)
#ifndef REBORN_HAS_PATCH_CODE
#error "Missing Patching Functions"
#endif
// Init
void reborn_init_patch();
@ -27,7 +29,7 @@ void *reborn_thunk_enabler(void *target, void *thunk);
// Replace All Calls To start With target Within [to, from)
void overwrite_calls_within_manual(void *from, void *to, void *start, void *target);
template <typename T>
void _overwrite_calls_within(void *from, void *to, T *start, typename T::ptr_type target) {
void overwrite_calls_within(void *from, void *to, T *start, typename T::ptr_type target) {
overwrite_calls_within_manual(from, to, (void *) start->get(), (void *) target);
}
@ -49,6 +51,4 @@ void patch_vtable(const T *start, typename T::ptr_type target) {
WARN("Use overwrite_calls() Instead!");
}
patch_address((void *) start->get_vtable_addr(), (void *) target);
}
#endif
}

View File

@ -1,35 +1,15 @@
#pragma once
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <dlfcn.h>
#include <array>
#include <string>
#include "log.h"
// Check Memory Allocation
#define ALLOC_CHECK(obj) \
{ \
if ((obj) == nullptr) { \
ERR("Memory Allocation Failed"); \
} \
}
// Align Number
#define ALIGN_UP(x, alignment) \
({ \
int _align_x = (x); \
int _align_alignment = (alignment); \
int _align_diff = _align_x % _align_alignment; \
if (_align_diff > 0) { \
_align_x += (_align_alignment - _align_diff); \
} \
_align_x; \
})
int align_up(int x, int alignment);
// Hook Library Function
#define EXTERNAL_FUNC(name, return_type, args) \
#define HOOK(name, return_type, args) \
typedef return_type (*real_##name##_t)args; \
__attribute__((__unused__)) static real_##name##_t real_##name() { \
static real_##name##_t func = NULL; \
@ -41,9 +21,7 @@
} \
} \
return func; \
}
#define HOOK(name, return_type, args) \
EXTERNAL_FUNC(name, return_type, args) \
} \
extern "C" __attribute__((__used__)) return_type name args
// Safe Version Of pipe()
@ -52,6 +30,7 @@ struct Pipe {
const int read;
const int write;
};
// Check If Two Percentages Are Different Enough To Be Logged
bool is_progress_difference_significant(int32_t new_val, int32_t old_val);
@ -59,11 +38,6 @@ bool is_progress_difference_significant(int32_t new_val, int32_t old_val);
int lock_file(const char *file);
void unlock_file(const char *file, int fd);
// Access Configuration At Runtime
const char *reborn_get_version();
bool reborn_is_headless();
bool reborn_is_server();
// Check $DISPLAY
void reborn_check_display();
@ -74,4 +48,12 @@ const char *get_home_subdirectory_for_game_data();
void ensure_directory(const char *path);
// Safe write()
void safe_write(int fd, const void *buf, size_t size);
void safe_write(int fd, const void *buf, size_t size);
// embed_resource()
#define EMBEDDED_RESOURCE(name) \
extern unsigned char name[]; \
extern size_t name##_len
// Profile Directory
std::string home_get();

View File

@ -1,6 +1,8 @@
#include <sys/mman.h>
#include <cstring>
#include <cerrno>
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include "patch-internal.h"
// Limit Amount Of overwrite_calls() Calls

View File

@ -1,4 +1,4 @@
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include "patch-internal.h"
// Check Instruction

View File

@ -6,7 +6,7 @@
#include <cstdint>
#include <cerrno>
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include "patch-internal.h"
// Overwrite Specific B(L) Instruction

View File

@ -1,10 +1,11 @@
#include <vector>
#include <cstring>
#include <elf.h>
#include <dlfcn.h>
#include <link.h>
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include "patch-internal.h"
// Track Segments

View File

@ -0,0 +1,32 @@
#include <cstdlib>
#include <libreborn/config.h>
#include <libreborn/env.h>
// Access Configuration At Runtime
const char *reborn_get_version() {
return MCPI_VERSION;
}
bool reborn_is_headless() {
static bool ret;
static bool is_set = false;
if (!is_set) {
ret = reborn_is_server();
if (getenv(_MCPI_FORCE_HEADLESS_ENV)) {
ret = true;
} else if (getenv(_MCPI_FORCE_NON_HEADLESS_ENV)) {
ret = false;
}
is_set = true;
}
return ret;
}
bool reborn_is_server() {
static int ret;
static bool is_set = false;
if (!is_set) {
ret = getenv(_MCPI_SERVER_MODE_ENV) != nullptr;
is_set = true;
}
return ret;
}

View File

@ -4,6 +4,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <sys/poll.h>
#include <cstring>
#include <libreborn/util.h>
#include <libreborn/log.h>
@ -101,6 +102,10 @@ void poll_fds(const std::vector<int> &fds, const std::function<void(int, size_t,
on_data(int(i), size_t(bytes_read), buf);
} else {
// File Descriptor No Longer Accessible
if (poll_fd.fd == STDIN_FILENO) {
// This Shouldn't Happen
IMPOSSIBLE();
}
poll_fd.events = 0;
open_fds--;
}
@ -120,7 +125,7 @@ __attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char
DEBUG(" %s", argv[i]);
}
// Run
int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp);
const int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp);
if (ret == -1) {
ERR("Unable To Execute Program: %s: %s", argv[0], strerror(errno));
} else {
@ -129,6 +134,7 @@ __attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char
}
// Run Command And Get Output
#define CHILD_PROCESS_TAG "(Child Process) "
std::vector<unsigned char> *run_command(const char *const command[], int *exit_status) {
// Run
const std::optional<Process> child = fork_with_stdio();
@ -174,3 +180,26 @@ std::string get_exit_status_string(const int status) {
return "";
}
}
// Check Exit Status
bool is_exit_status_success(const int status) {
if (WIFEXITED(status)) {
return WEXITSTATUS(status) == 0;
} else if (WIFSIGNALED(status)) {
const int signal_no = WTERMSIG(status);
return signal_no == SIGINT || signal_no == SIGTERM;
} else {
return false;
}
}
// Open URL
void open_url(const std::string &url) {
int return_code;
const char *command[] = {"xdg-open", url.c_str(), nullptr};
const std::vector<unsigned char> *output = run_command(command, &return_code);
delete output;
if (!is_exit_status_success(return_code)) {
WARN("Unable To Open URL: %s", url.c_str());
}
}

View File

@ -0,0 +1,145 @@
CATEGORY Creative Mode
CATEGORY Inventory
FALSE Expand Creative Mode Inventory
FALSE Maximize Creative Mode Inventory Stack Size
FALSE Force Survival Mode Inventory UI
FALSE Force Survival Mode Inventory Behavior
FALSE Display Slot Count In Creative Mode
FALSE Remove Creative Mode Restrictions
TRUE Disable Hostile AI In Creative Mode
TRUE Stop Creative Players From Burning
CATEGORY User Interface
CATEGORY Screens
CATEGORY Title
TRUE Add Title Screen Background
TRUE Improved Classic Title Screen
TRUE Add Splashes
TRUE Allow High-Resolution Title
TRUE Improved Classic Title Positioning
TRUE Use Updated Title
CATEGORY Options
TRUE Fix Options Screen
TRUE Add Reborn Info To Options
TRUE Force Touch UI Inventory
TRUE Fix Pause Menu
TRUE Close Current Screen On Death
TRUE Implement Create World Dialog
TRUE Display Date In Select World Screen
TRUE Add Welcome Screen
TRUE Enable Sign Screen
CATEGORY HUD
TRUE Classic HUD
TRUE Translucent Toolbar
FALSE Food Overlay
TRUE Render Selected Item Text
TRUE F3 Debug Information
TRUE Hide Crosshair In Third-Person
CATEGORY Text
TRUE Load Language Files
TRUE Add Missing Language Strings
FALSE Full Touch UI
TRUE Force Touch UI Button Behavior
TRUE Improved Cursor Rendering
FALSE Remove Forced UI Lag (Can Break Joining Servers)
TRUE Improved Button Hover Behavior
TRUE Classic Item Count UI
TRUE Click Buttons On Mouse Down
CATEGORY Rendering
CATEGORY Optimizations
TRUE Optimized Chunk Sorting
TRUE Multidraw Rendering
TRUE Increase Render Chunk Size
CATEGORY Camera
TRUE Enable Camera Rendering
TRUE Render Camera Legs
CATEGORY Block Outline
TRUE Show Block Outlines
TRUE Replace Block Highlight With Outline
TRUE Hide Block Outline When UI Is Hidden
CATEGORY Block Tinting
FALSE Add Biome Colors To Grass
FALSE Disable Block Tinting
TRUE Display Nametags By Default
TRUE Disable V-Sync
TRUE 3D Chest Model
TRUE Use Java Beta 1.3 Light Ramp
TRUE Render Fire In Third-Person
TRUE Improved Water Rendering
TRUE Proper OpenGL Buffer Generation
TRUE 3D Dropped Items
TRUE Render Entity Shadows
TRUE Render Vignette
TRUE Proper Entity Shading
CATEGORY Textures
TRUE Regenerate "gui_blocks" Atlas
TRUE Animated Water
TRUE Animated Lava
TRUE Animated Fire
CATEGORY Input
TRUE Disable Autojump By Default
TRUE Bind "Q" Key To Item Dropping
TRUE Bind Common Toggleable Options To Function Keys
FALSE Disable Raw Mouse Motion (Not Recommended)
FALSE Disable Speed Bridging
FALSE Disable Creative Mode Mining Delay
TRUE Enable Text Input
TRUE Extend Supported Keycodes
CATEGORY Multiplayer
CATEGORY Chat
TRUE Implement Chat
FALSE Hide Chat Messages
TRUE Allow Joining Survival Mode Servers
TRUE External Server Support
TRUE Send Full Level When Hosting Game
TRUE Sanitize Usernames
CATEGORY Gameplay
TRUE Implement Death Messages
TRUE Implement Game-Mode Switching
FALSE Force Mob Spawning
TRUE Add Buckets
TRUE Load Custom Skins
TRUE Add Cake
TRUE Implement Crafting Remainders
TRUE Implement Sound Engine
TRUE Generate Caves
CATEGORY Bug Fixes
CATEGORY Visual
TRUE Fix Held Item Caching
TRUE Fix Cobweb Lighting
TRUE Fix Furnace Screen Visual Bug
TRUE Fix Text Wrapping
TRUE Fix Carried Grass's Bottom Texture
TRUE Fix Screen Rendering When Hiding HUD
TRUE Fix Sugar Position In Hand
TRUE Fix Switching Perspective While Sneaking
CATEGORY Network
TRUE Patch RakNet Security Bug
TRUE Prevent Unnecessary Server Pinging
TRUE Fix Fire Syncing
TRUE Fix Sneaking Syncing
CATEGORY Input
TRUE Fix Bow & Arrow
TRUE Fix Attacking
TRUE Fix Escape Key Handling
TRUE Stop Locked Mouse From Interacting With HUD
CATEGORY Gameplay
TRUE Fix Furnace Not Checking Item Auxiliary
TRUE Fix Pigmen Burning In The Sun
TRUE Fix Door Duplication
TRUE Fix Fire Immunity
TRUE Fix Sunlight Not Properly Setting Mobs On Fire
TRUE Fix Transferring Durability When Using Items
TRUE Fix Crash When Generating Certain Seeds
TRUE Fix Reloading Textures On Resize
TRUE Fix options.txt Loading/Saving
CATEGORY Logging
FALSE Log FPS
TRUE Log Chat Messages
TRUE Log Game Status
TRUE Log RakNet Startup Errors
CATEGORY Miscellaneous
TRUE Fullscreen Support
TRUE Always Save Chest Tile Entities
TRUE Screenshot Support
TRUE Add Camera Functionality
TRUE Update Default Options

View File

@ -0,0 +1,128 @@
#include <sstream>
#include <algorithm>
#include <unordered_set>
#include <libreborn/log.h>
#include <libreborn/flags.h>
#include <libreborn/util.h>
// All Flags
static unsigned int find_indent_level(std::string &str) {
constexpr unsigned int INDENT = 4;
unsigned int count = 0;
for (const char c : str) {
if (c == ' ') {
count++;
} else {
break;
}
}
str = str.substr(count);
return count / INDENT;
}
Flags::Flags(const std::string &data) {
FlagNode::reset_id_counter();
// Read Lines
std::stringstream stream(data);
std::string line;
std::vector stack = {&root};
while (std::getline(stream, line)) {
if (!line.empty()) {
// Get Parent
const unsigned int indent = find_indent_level(line);
if (indent >= stack.size()) {
ERR("Bad Feature Flag Indent: %s", line.c_str());
}
stack.resize(indent + 1);
FlagNode &parent = *stack.back();
// Add New Node
if (FlagNode::handle_line_prefix("CATEGORY", line)) {
// New Category
FlagNode &category = parent.add_category(line);
stack.push_back(&category);
} else {
// Add Flag
if (indent == 0) {
ERR("Feature Flag Outside Of Category: %s", line.c_str());
}
parent.add_flag(line);
}
}
}
// Sort
root.sort();
// Check For Duplicates
std::unordered_set<std::string> seen;
root.for_each_const([&seen](const FlagNode &node) {
const std::string &name = node.name;
if (seen.contains(name)) {
ERR("Duplicate Feature Flag: %s", name.c_str());
} else {
seen.insert(name);
}
});
}
Flags::operator std::string() const {
std::string out;
root.for_each_const([&out](const FlagNode &flag) {
if (flag.value) {
if (!out.empty()) {
out += FLAG_SEPERATOR_CHAR;
}
out += flag.name;
}
});
return out;
}
Flags &Flags::operator=(const std::string &str) {
// Find Flags To Enable
std::unordered_set<std::string> to_enable;
std::stringstream stream(str);
std::string flag_name;
while (std::getline(stream, flag_name, FLAG_SEPERATOR_CHAR)) {
if (!flag_name.empty()) {
to_enable.insert(flag_name);
}
}
// Update Flags
root.for_each([&to_enable](FlagNode &flag) {
flag.value = to_enable.contains(flag.name);
});
return *this;
}
std::unordered_map<std::string, bool> Flags::to_cache() const {
std::unordered_map<std::string, bool> out;
root.for_each_const([&out](const FlagNode &flag) {
out[flag.name] = flag.value;
});
return out;
}
void Flags::from_cache(const std::unordered_map<std::string, bool> &cache) {
root.for_each([&cache](FlagNode &flag) {
if (cache.contains(flag.name)) {
flag.value = cache.at(flag.name);
}
});
}
void Flags::print() const {
root.for_each_const([](const FlagNode &flag) {
std::string prefix;
for (const std::pair<const std::string, bool> &it : FlagNode::flag_prefixes) {
if (it.second == flag.value) {
prefix = it.first;
break;
}
}
if (prefix.empty()) {
IMPOSSIBLE();
}
printf("%s %s\n", prefix.c_str(), flag.name.c_str());
fflush(stdout);
});
}
// Instance
EMBEDDED_RESOURCE(available_feature_flags);
Flags Flags::get() {
return Flags(std::string(available_feature_flags, available_feature_flags + available_feature_flags_len));
}

View File

@ -0,0 +1,89 @@
#include <algorithm>
#include <libreborn/log.h>
#include <libreborn/flags.h>
// Flag
static int next_id;
void FlagNode::reset_id_counter() {
next_id = 1;
}
FlagNode::FlagNode(const std::string &name_) {
name = name_;
value = false;
id = next_id++;
}
FlagNode::FlagNode(): FlagNode("Root") {}
void FlagNode::sort() {
// Sort
std::ranges::sort(children, [](const FlagNode &a, const FlagNode &b) {
// Place Categories Before Flags
if (a.children.empty() != b.children.empty()) {
return a.children.empty() < b.children.empty();
} else {
// Sort Alphabetically
return a.name < b.name;
}
});
// Recurse
for (FlagNode &child : children) {
child.sort();
}
}
// Iteration
void FlagNode::for_each(const std::function<void(FlagNode &)> &callback) {
for (FlagNode &child : children) {
if (child.children.empty()) {
callback(child);
} else {
child.for_each(callback);
}
}
}
void FlagNode::for_each_const(const std::function<void(const FlagNode &)> &callback) const {
const_cast<FlagNode &>(*this).for_each(callback);
}
// Parsing
bool FlagNode::handle_line_prefix(const std::string &prefix, std::string &line) {
const std::string full_prefix = prefix + ' ';
if (line.starts_with(full_prefix)) {
line = line.substr(full_prefix.size());
return true;
} else {
return false;
}
}
std::unordered_map<std::string, bool> FlagNode::flag_prefixes = {
{"TRUE", true},
{"FALSE", false}
};
void FlagNode::add_flag(std::string line) {
// Parse
bool value_set = false;
bool new_value = false;
for (const std::pair<const std::string, bool> &it : flag_prefixes) {
if (handle_line_prefix(it.first, line)) {
new_value = it.second;
value_set = true;
break;
}
}
// Check
if (!value_set) {
ERR("Invalid Feature Flag Line: %s", line.c_str());
}
if (line.rfind(FLAG_SEPERATOR_CHAR, 0) != std::string::npos) {
ERR("Feature Flag Contains Invalid Character");
}
// Create
FlagNode out(line);
out.value = new_value;
children.push_back(out);
}
FlagNode &FlagNode::add_category(const std::string &new_name) {
const FlagNode out(new_name);
children.push_back(out);
return children.back();
}

View File

@ -0,0 +1,68 @@
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <libreborn/glfw.h>
#include <libreborn/util.h>
#include <libreborn/log.h>
#include <libreborn/config.h>
// Handle GLFW Error
static void glfw_error(__attribute__((unused)) int error, const char *description) {
WARN("GLFW Error: %s", description);
}
// Init
void init_glfw() {
reborn_check_display();
glfwSetErrorCallback(glfw_error);
if (!glfwInit()) {
ERR("Unable To Initialize GLFW");
}
}
// Create Window
GLFWwindow *create_glfw_window(const char *title, const int width, const int height) {
// App ID
glfwWindowHintString(GLFW_X11_CLASS_NAME, MCPI_APP_ID);
glfwWindowHintString(GLFW_WAYLAND_APP_ID, MCPI_APP_ID);
// Create Window
GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr);
if (!window) {
ERR("Unable To Create GLFW Window");
}
// Make Window Context Current
glfwMakeContextCurrent(window);
// Return
return window;
}
// Cleanup
void cleanup_glfw(GLFWwindow *window) {
// Ignore GLFW Errors During Termination
glfwSetErrorCallback(nullptr);
// Terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
}
// Framebuffer Scaling
void get_glfw_scale(GLFWwindow *window, float *x_scale, float *y_scale) {
// Get Window Size
int window_width;
int window_height;
glfwGetWindowSize(window, &window_width, &window_height);
if (window_width <= 0 || window_height <= 0) {
return;
}
// Get Framebuffer Size
int framebuffer_width;
int framebuffer_height;
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
// Calculate Scale
if (x_scale) {
*x_scale = float(framebuffer_width) / float(window_width);
}
if (y_scale) {
*y_scale = float(framebuffer_height) / float(window_height);
}
}

View File

@ -39,7 +39,7 @@ int reborn_get_log_fd() {
void reborn_set_log(const int fd) {
// Set Variable
log_fd = -1;
set_and_print_env(_MCPI_LOG_FD_ENV, std::to_string(fd).c_str());
set_and_print_env(_MCPI_LOG_FD_ENV, fd >= 0 ? std::to_string(fd).c_str() : nullptr);
}
// Debug Logging

View File

@ -1,11 +1,21 @@
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <cstring>
#include <libreborn/util.h>
#include <libreborn/config.h>
#include <libreborn/env.h>
// Align Number
int align_up(int x, const int alignment) {
const int diff = x % alignment;
if (diff > 0) {
x += (alignment - diff);
}
return x;
}
// Safe Version Of pipe()
Pipe::Pipe(): read(-1), write(-1) {
int out[2];
@ -50,34 +60,6 @@ void unlock_file(const char *file, const int fd) {
close(fd);
}
// Access Configuration At Runtime
const char *reborn_get_version() {
return MCPI_VERSION;
}
bool reborn_is_headless() {
static bool ret;
static bool is_set = false;
if (!is_set) {
ret = reborn_is_server();
if (getenv(_MCPI_FORCE_HEADLESS_ENV)) {
ret = true;
} else if (getenv(_MCPI_FORCE_NON_HEADLESS_ENV)) {
ret = false;
}
is_set = true;
}
return ret;
}
bool reborn_is_server() {
static int ret;
static int is_set = 0;
if (!is_set) {
ret = getenv(_MCPI_SERVER_MODE_ENV) != nullptr;
is_set = 1;
}
return ret;
}
// Check $DISPLAY
void reborn_check_display() {
if (!getenv("DISPLAY") && !getenv("WAYLAND_DISPLAY")) {
@ -122,4 +104,13 @@ void safe_write(const int fd, const void *buf, const size_t size) {
if (bytes_written < 0) {
ERR("Unable To Write Data: %s", strerror(errno));
}
}
// Get MCPI Home Directory
std::string home_get() {
const char *home = getenv(_MCPI_HOME_ENV);
if (home == nullptr) {
IMPOSSIBLE();
}
return std::string(home) + std::string(get_home_subdirectory_for_game_data());
}

View File

@ -2,22 +2,8 @@ project(media-layer)
# Add Headers
add_library(media-layer-headers INTERFACE)
target_include_directories(
media-layer-headers
INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/media-layer>"
)
# SDK
if(BUILD_ARM_COMPONENTS)
install(TARGETS media-layer-headers EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
# Copy Headers
set(GLES_HEADERS "include/GLES")
install(
DIRECTORY "include/"
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/media-layer"
)
endif()
setup_header_dirs(media-layer-headers "${CMAKE_CURRENT_SOURCE_DIR}/include")
setup_library(media-layer-headers FALSE TRUE)
# Add Core
if(BUILD_MEDIA_LAYER_CORE)

View File

@ -1,7 +1,7 @@
project(media-layer-core)
# SDL Re-Implementation Using GLFW
set(CORE_SRC
# Build
add_library(media-layer-core-real SHARED
src/base.cpp
src/window/media.cpp
src/window/cursor.cpp
@ -14,14 +14,14 @@ set(CORE_SRC
src/audio/file.cpp
)
# Build
add_library(media-layer-core-real SHARED ${CORE_SRC}) # Dependencies Are Setup Later
# Set Name
set_target_properties(media-layer-core-real PROPERTIES OUTPUT_NAME "media-layer-core")
if(BUILD_NATIVE_COMPONENTS)
add_library(media-layer-core ALIAS media-layer-core-real)
endif()
# Install
install(TARGETS media-layer-core-real DESTINATION "${MCPI_LIB_DIR}")
setup_library(media-layer-core-real TRUE FALSE)
# Link
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)

View File

@ -4,11 +4,9 @@
#include <AL/al.h>
#include <media-layer/audio.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include "file.h"
#include "engine.h"
#include "api.h"
#include "audio.h"
// Store Audio Sources
static std::vector<ALuint> sources;
@ -18,7 +16,6 @@ static std::vector<ALuint> sources;
static std::vector<ALuint> idle_sources;
// Error Checking
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
#define AL_ERROR_CHECK_MANUAL(val) \
{ \
ALenum __err = val; \
@ -26,6 +23,7 @@ static std::vector<ALuint> idle_sources;
ERR("OpenAL Error: %s", alGetString(__err)); \
} \
}
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
// Delete Sources
void _media_audio_delete_sources() {

View File

@ -1,3 +0,0 @@
#pragma once
__attribute__((visibility("internal"))) void _media_audio_delete_sources();

View File

@ -0,0 +1,12 @@
#pragma once
#include <AL/al.h>
__attribute__((visibility("internal"))) void _media_audio_delete_sources();
__attribute__((visibility("internal"))) void _media_audio_init();
__attribute__((visibility("internal"))) void _media_audio_cleanup();
__attribute__((visibility("internal"))) int _media_audio_is_loaded();
__attribute__((visibility("internal"))) ALuint _media_audio_get_buffer(const char *source, const char *name);
__attribute__((visibility("internal"))) void _media_audio_delete_buffers();

View File

@ -2,11 +2,9 @@
#include <AL/alc.h>
#include <AL/alext.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include "engine.h"
#include "file.h"
#include "api.h"
#include "audio.h"
// Store Device
static ALCdevice *device = nullptr;

View File

@ -1,7 +0,0 @@
#pragma once
#include <AL/al.h>
__attribute__((visibility("internal"))) void _media_audio_init();
__attribute__((visibility("internal"))) void _media_audio_cleanup();
__attribute__((visibility("internal"))) int _media_audio_is_loaded();

View File

@ -6,10 +6,9 @@
#include <LIEF/ELF.hpp>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include "file.h"
#include "engine.h"
#include "audio.h"
// Load Symbol From ELF File
static void load_symbol(const char *source, const char *name, std::function<void(const unsigned char *, uint32_t)> callback) {
@ -53,7 +52,7 @@ static ALuint load_sound(const char *source, const char *name) {
WARN("Symbol Too Small To Contain Audio Metadata: %s", name);
return;
}
audio_metadata *meta = (audio_metadata *) symbol;
const audio_metadata *meta = (audio_metadata *) symbol;
// Check Frame Size
if (meta->frame_size != 1 && meta->frame_size != 2) {
@ -73,7 +72,7 @@ static ALuint load_sound(const char *source, const char *name) {
}
// Load Data
const int remaining_size = size - sizeof (audio_metadata);
const int remaining_size = int(size - sizeof (audio_metadata));
const int data_size = meta->channels * meta->frames * meta->frame_size;
if (remaining_size < data_size) {
WARN("Symbol Too Small To Contain Specified Audio Data: %s", name);
@ -107,7 +106,7 @@ static std::unordered_map<std::string, ALuint> buffers;
ALuint _media_audio_get_buffer(const char *source, const char *name) {
// Check
if (_media_audio_is_loaded()) {
if (buffers.count(name) > 0) {
if (buffers.contains(name)) {
// Return
return buffers[name];
} else {

View File

@ -1,6 +0,0 @@
#pragma once
#include <AL/al.h>
__attribute__((visibility("internal"))) ALuint _media_audio_get_buffer(const char *source, const char *name);
__attribute__((visibility("internal"))) void _media_audio_delete_buffers();

View File

@ -2,8 +2,6 @@
#include <SDL/SDL.h>
#include <libreborn/libreborn.h>
#include "window/media.h"
// SDL Is Replaced With GLFW

View File

@ -179,20 +179,13 @@ static void convert_to_pixels(GLFWwindow *window, double *xpos, double *ypos) {
if (media_SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON && raw_mouse_motion_enabled) {
return;
}
// Get Window Size
int window_width;
int window_height;
glfwGetWindowSize(window, &window_width, &window_height);
// Get Framebuffer Size
int framebuffer_width;
int framebuffer_height;
glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
// Calculate Ratios
const double width_ratio = ((double) framebuffer_width) / ((double) window_width);
const double height_ratio = ((double) framebuffer_height) / ((double) window_height);
// Get Scale
float x_scale = 1;
float y_scale = 1;
get_glfw_scale(window, &x_scale, &y_scale);
// Multiply
*xpos *= width_ratio;
*ypos *= height_ratio;
*xpos *= x_scale;
*ypos *= y_scale;
}
// Last Mouse Location

View File

@ -2,7 +2,7 @@
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include "media.h"

View File

@ -2,16 +2,11 @@
#include <unistd.h>
#include "media.h"
#include "../audio/engine.h"
#include "../audio/audio.h"
// Window
GLFWwindow *glfw_window = nullptr;
// Handle GLFW Error
static void glfw_error(__attribute__((unused)) int error, const char *description) {
WARN("GLFW Error: %s", description);
}
// Disable V-Sync
static bool disable_vsync = false;
void media_disable_vsync() {
@ -21,15 +16,6 @@ void media_disable_vsync() {
}
}
// Force EGL
static int force_egl = 0;
void media_force_egl() {
if (force_egl == -1) {
IMPOSSIBLE();
}
force_egl = 1;
}
// Init Media Layer
#define GL_VERSION 0x1f02
typedef const char *(*glGetString_t)(unsigned int name);
@ -40,39 +26,21 @@ void media_SDL_WM_SetCaption(const char *title, __attribute__((unused)) const ch
}
// Init GLFW
reborn_check_display();
glfwSetErrorCallback(glfw_error);
if (!glfwInit()) {
ERR("Unable To Initialize GLFW");
}
init_glfw();
// Create OpenGL Context
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
// Use EGL
if (force_egl) {
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
}
force_egl = -1;
// Extra Settings
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
glfwWindowHint(GLFW_ALPHA_BITS, 0); // Fix Transparent Window On Wayland
// App ID
glfwWindowHintString(GLFW_X11_CLASS_NAME, MCPI_APP_ID);
glfwWindowHintString(GLFW_WAYLAND_APP_ID, MCPI_APP_ID);
glfwWindowHint(GLFW_ALPHA_BITS, 0);
// Create Window
glfw_window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, title, nullptr, nullptr);
if (!glfw_window) {
ERR("Unable To Create GLFW Window");
}
glfw_window = create_glfw_window(title, DEFAULT_WIDTH, DEFAULT_HEIGHT);
// Event Handlers
_media_register_event_listeners();
// Make Window Context Current
glfwMakeContextCurrent(glfw_window);
// Debug
const glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString");
DEBUG("Using OpenGL %s", (*glGetString)(GL_VERSION));
@ -93,12 +61,8 @@ void media_SDL_WM_SetCaption(const char *title, __attribute__((unused)) const ch
// Cleanup Media Layer
void media_cleanup() {
if (glfw_window) {
// Ignore GLFW Errors During Termination
glfwSetErrorCallback(nullptr);
// Terminate GLFW
glfwDestroyWindow(glfw_window);
glfwTerminate();
cleanup_glfw(glfw_window);
// Cleanup OpenAL
_media_audio_cleanup();

View File

@ -1,11 +1,14 @@
#pragma once
#include <SDL/SDL.h>
#include <libreborn/libreborn.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <SDL/SDL.h>
#include <libreborn/log.h>
#include <libreborn/string.h>
#include <libreborn/glfw.h>
#include <libreborn/config.h>
#include <media-layer/core.h>
// Interactivity

View File

@ -14,6 +14,7 @@ void media_begin_offscreen_render(const int width, const int height) {
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
// Open Window
offscreen_window = glfwCreateWindow(width, height, "Offscreen Rendering", nullptr, nullptr);
if (!offscreen_window) {

View File

@ -16,9 +16,8 @@ void media_toggle_fullscreen();
void media_swap_buffers();
void media_cleanup();
void media_get_framebuffer_size(int *width, int *height);
void media_set_interactable(int is_interactable);
void media_set_interactable(int toggle);
void media_disable_vsync();
void media_force_egl();
void media_set_raw_mouse_motion_enabled(int enabled);
int media_has_extension(const char *name);
void media_begin_offscreen_render(int width, int height);

View File

@ -10,7 +10,7 @@ if(BUILD_NATIVE_COMPONENTS)
target_link_libraries(media-layer-trampoline reborn-util media-layer-core trampoline-headers)
target_compile_definitions(media-layer-trampoline PRIVATE MEDIA_LAYER_TRAMPOLINE_HOST)
# Install
install(TARGETS media-layer-trampoline DESTINATION "${MCPI_LIB_DIR}")
setup_library(media-layer-trampoline TRUE TRUE)
elseif(BUILD_ARM_COMPONENTS)
# Guest Component
add_library(media-layer-core SHARED src/guest/guest.cpp ${MEDIA_LAYER_TRAMPOLINE_SRC})
@ -24,8 +24,5 @@ elseif(BUILD_ARM_COMPONENTS)
)
target_compile_definitions(media-layer-core PRIVATE MEDIA_LAYER_TRAMPOLINE_GUEST)
# Install
if(MCPI_USE_MEDIA_LAYER_TRAMPOLINE)
install(TARGETS media-layer-core DESTINATION "${MCPI_LIB_DIR}")
endif()
install(TARGETS media-layer-core EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
setup_library(media-layer-core "${MCPI_USE_MEDIA_LAYER_TRAMPOLINE}" TRUE)
endif()

View File

@ -1,7 +1,8 @@
#include <cstdint>
#include <GLES/gl.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <libreborn/util.h>
#include "common/common.h"
@ -301,7 +302,7 @@ static int get_texture_size(const GLsizei width, const GLsizei height, const GLe
int alignment;
media_glGetIntegerv(is_upload ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT, &alignment);
// Round
line_size = ALIGN_UP(line_size, alignment);
line_size = align_up(line_size, alignment);
}
// Return
return line_size * height;

View File

@ -1,5 +1,5 @@
#include <unistd.h>
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include <string>
#include <sys/mman.h>

View File

@ -1,4 +1,4 @@
#include <libreborn/libreborn.h>
#include <libreborn/log.h>
#include "host.h"

View File

@ -7,8 +7,6 @@
#include "common/common.h"
#include <libreborn/libreborn.h>
// SDL Functions
CALL(0, media_SDL_Init, int, (uint32_t flags))
@ -165,15 +163,6 @@ CALL(64, media_set_raw_mouse_motion_enabled, void, (int enabled))
#endif
}
CALL(66, media_force_egl, void, ())
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(true);
#else
func();
return 0;
#endif
}
CALL(71, media_has_extension, int, (const char *name))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
return trampoline(false, copy_array(name));

View File

@ -1,15 +1,15 @@
project(mods)
# Common Sources
set(SRC
# Build
add_library(mods SHARED
# compat
src/compat/compat.cpp
src/compat/egl.cpp
src/compat/x11.cpp
src/compat/bcm_host.cpp
src/compat/readdir.cpp
src/compat/sdl.cpp
# readdir
src/readdir/readdir.cpp
src/compat/stubs/egl.cpp
src/compat/stubs/x11.cpp
src/compat/stubs/bcm_host.cpp
src/compat/stubs/sdl.cpp
# feature
src/feature/feature.cpp
# version
@ -33,6 +33,7 @@ set(SRC
src/misc/graphics.cpp
src/misc/ui.cpp
src/misc/tinting.cpp
src/misc/home.cpp
# extend
src/extend/Screen.cpp
src/extend/DynamicTexture.cpp
@ -44,15 +45,11 @@ set(SRC
src/bucket/bucket.cpp
# cake
src/cake/cake.cpp
# home
src/home/home.cpp
# touch
src/touch/touch.cpp
# text-input-box
src/text-input-box/TextInputBox.cpp
src/text-input-box/TextInputScreen.cpp
# test
src/test/test.cpp
# sound
src/sound/sound.cpp
src/sound/repository.cpp
@ -66,8 +63,6 @@ set(SRC
src/input/misc.cpp
src/input/drop.cpp
src/input/keys.cpp
# sign
src/sign/sign.cpp
# atlas
src/atlas/atlas.cpp
# title-screen
@ -109,29 +104,30 @@ set(SRC
src/shading/lighting.cpp
src/shading/normals.cpp
)
# Install Splashes
install(
FILES "src/title-screen/splashes.txt"
DESTINATION "${MCPI_INSTALL_DIR}/data"
)
# Build
add_library(mods SHARED ${SRC})
# Headers
setup_header_dirs(mods "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Install
install(TARGETS mods DESTINATION "${MCPI_INSTALL_DIR}/mods")
# SDK
install(TARGETS mods EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
set(old_lib_dir "${MCPI_LIB_DIR}")
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/mods")
setup_library(mods TRUE TRUE)
set(MCPI_LIB_DIR "${old_lib_dir}")
# Dependencies
target_link_libraries(mods symbols reborn-patch media-layer-core stb_image dl pthread)
# Headers
target_include_directories(
mods
target_link_libraries(mods
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/mods>"
symbols
reborn-patch
media-layer-core
PRIVATE
stb_image
dl
pthread
)
# SDK
install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods")

View File

@ -2,7 +2,6 @@
#include <string>
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
extern "C" {

View File

@ -1,5 +1,5 @@
#pragma once
extern "C" {
int creative_is_restricted();
bool creative_is_restricted();
}

View File

@ -41,7 +41,7 @@ template <typename Self, typename Data>
Data *extend_get_data(Self *self) {
return (Data *) (self + 1);
}
template <typename Self, typename Data>
template <typename Data, typename Self = typename Data::_Self>
auto extend_struct(auto&&... args) -> decltype(Self::allocate()) {
constexpr size_t size = sizeof(Self) + sizeof(Data);
Self *out = (Self *) ::operator new(size);
@ -53,11 +53,12 @@ auto extend_struct(auto&&... args) -> decltype(Self::allocate()) {
// Helpers
#define CREATE_HELPER(name) \
struct Custom##name { \
using _Self = name; \
explicit Custom##name(auto&&... args): self(((name *) this) - 1) { \
self->constructor(std::forward<decltype(args)>(args)...); \
self->vtable = get_vtable(); \
} \
name *const self; \
_Self *const self; \
static name##_vtable *get_vtable(); \
private: \
static void setup_vtable(name##_vtable *vtable); \

View File

@ -1,5 +0,0 @@
#pragma once
extern "C" {
const char *home_get();
}

View File

@ -1,7 +1,6 @@
#pragma once
extern "C" {
void run_tests();
void init_version();
void init_compat();
void init_server();
@ -9,7 +8,6 @@ void init_multiplayer();
void init_benchmark();
void init_sound();
void init_input();
void init_sign();
void init_camera();
void init_atlas();
void init_title_screen();
@ -25,7 +23,6 @@ void init_options();
void init_chat();
void init_bucket();
void init_cake();
void init_home();
void init_override();
void init_screenshot();
void init_f3();

View File

@ -2,8 +2,4 @@
#include <string>
#define CHANGELOG_FILE "CHANGELOG.md"
extern "C" {
void open_url(const std::string &url);
}
#define CHANGELOG_FILE "CHANGELOG.md"

View File

@ -1,5 +0,0 @@
#pragma once
extern "C" {
void sign_key_press(char key);
}

View File

@ -1,7 +1,10 @@
#include <GLES/gl.h>
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <libreborn/util.h>
#include <symbols/minecraft.h>
#include <media-layer/core.h>
#include <mods/feature/feature.h>
@ -127,7 +130,7 @@ static void generate_atlas(Minecraft *minecraft) {
int alignment;
media_glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
// Round
line_size = ALIGN_UP(line_size, alignment);
line_size = align_up(line_size, alignment);
}
Texture texture;
texture.width = atlas_texture_size;

View File

@ -1,6 +1,10 @@
#include <ctime>
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <libreborn/util.h>
#include <libreborn/env.h>
#include <libreborn/config.h>
#include <symbols/minecraft.h>
#include <media-layer/core.h>
@ -41,7 +45,6 @@ static void start_world(Minecraft *minecraft) {
// Open ProgressScreen
ProgressScreen *screen = ProgressScreen::allocate();
ALLOC_CHECK(screen);
screen = screen->constructor();
minecraft->setScreen((Screen *) screen);
}

View File

@ -1,4 +1,5 @@
#include <libreborn/libreborn.h>
#include <libreborn/patch.h>
#include <symbols/minecraft.h>
#include <mods/feature/feature.h>
@ -22,7 +23,7 @@ static std::string BucketItem_getDescriptionId(__attribute__((unused)) FoodItem
return "item.bucket";
}
}
static int32_t BucketItem_getIcon(__attribute__((unused)) FoodItem *item, int32_t auxiliary) {
static int32_t BucketItem_getIcon(__attribute__((unused)) FoodItem *item, const int32_t auxiliary) {
if (auxiliary == Tile::water->id) {
return 75;
} else if (auxiliary == Tile::lava->id) {
@ -35,7 +36,7 @@ static int32_t BucketItem_getIcon(__attribute__((unused)) FoodItem *item, int32_
}
// Filling
static bool fill_bucket(ItemInstance *item_instance, Player *player, int new_auxiliary) {
static bool fill_bucket(ItemInstance *item_instance, const Player *player, const int new_auxiliary) {
bool success = false;
if (item_instance->count == 1) {
item_instance->auxiliary = new_auxiliary;
@ -57,7 +58,7 @@ static bool fill_bucket(ItemInstance *item_instance, Player *player, int new_aux
// Use Bucket
static int32_t BucketItem_useOn(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance, Player *player, Level *level, int32_t x, int32_t y, int32_t z, int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) {
static int32_t BucketItem_useOn(__attribute__((unused)) FoodItem *item, ItemInstance *item_instance, Player *player, Level *level, int32_t x, int32_t y, int32_t z, const int32_t hit_side, __attribute__((unused)) float hit_x, __attribute__((unused)) float hit_y, __attribute__((unused)) float hit_z) {
if (item_instance->count < 1 || item_instance->auxiliary == 1) {
return 0;
} else if (item_instance->auxiliary == 0) {
@ -188,7 +189,6 @@ CUSTOM_VTABLE(bucket, FoodItem) {
static FoodItem *create_bucket(const int32_t id, int32_t texture_x, int32_t texture_y, std::string name) {
// Construct
FoodItem *item = FoodItem::allocate();
ALLOC_CHECK(item);
Item_constructor->get(false)((Item *) item, id); // FoodItem's Constructor Was Inlined
// Set VTable
@ -237,7 +237,6 @@ bool Cow_interact_injection(Cow_interact_t original, Cow *self, Player *player)
// Creative Inventory
static void inventory_add_item(FillingContainer *inventory, FoodItem *item, int32_t auxiliary) {
ItemInstance *item_instance = new ItemInstance;
ALLOC_CHECK(item_instance);
item_instance = item_instance->constructor_item_extra((Item *) item, 1, auxiliary);
inventory->addItem(item_instance);
}

View File

@ -1,4 +1,3 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/feature/feature.h>
@ -45,7 +44,7 @@ static int Cake_getTexture3(__attribute__((unused)) Tile *tile, LevelSource *lev
// Rendering
static bool Cake_isSolidRender(__attribute__((unused)) Tile *tile) {
// Stop it from turning other blocks invisable
return 0;
return false;
}
static int Cake_getRenderLayer(__attribute__((unused)) Tile *tile) {
@ -70,7 +69,7 @@ static AABB *Cake_getAABB(Tile *tile, Level *level, int x, int y, int z) {
// Get the size of the slices
int data = level->getData(x, y, z);
if (data >= 6) data = 0;
const float slice_size = (1.0 / 7.0) * (float) data;
const float slice_size = (1.0f / 7.0f) * (float) data;
// Corner 1
AABB *aabb = &tile->aabb;
@ -79,9 +78,9 @@ static AABB *Cake_getAABB(Tile *tile, Level *level, int x, int y, int z) {
aabb->z1 = (float) z + CAKE_LEN;
// Corner 2
aabb->x2 = (float) x + (1.0 - CAKE_LEN);
aabb->y2 = (float) y + 0.5;
aabb->z2 = (float) z + (1.0 - CAKE_LEN) - slice_size;
aabb->x2 = (float) x + (1.0f - CAKE_LEN);
aabb->y2 = (float) y + 0.5f;
aabb->z2 = (float) z + (1.0f - CAKE_LEN) - slice_size;
return aabb;
}
@ -91,7 +90,7 @@ static void Cake_updateShape(Tile *tile, LevelSource *level, int x, int y, int z
int data = level->getData(x, y, z);
if (data >= 6) data = 0;
// Get slice amount
const float slice_size = (1.0 / 7.0) * (float) data;
const float slice_size = (1.0f / 7.0f) * (float) data;
tile->setShape(
CAKE_LEN, 0.0, CAKE_LEN,
1.0 - CAKE_LEN, 0.5, (1.0 - CAKE_LEN) - slice_size
@ -118,14 +117,12 @@ static int Cake_use(__attribute__((unused)) Tile *tile, Level *level, int x, int
static void make_cake() {
// Construct
cake = Tile::allocate();
ALLOC_CHECK(cake);
int texture = 122;
cake->constructor(92, texture, Material::dirt);
cake->texture = texture;
// Set VTable
cake->vtable = extend_dup_vtable(Tile_vtable::base);
ALLOC_CHECK(cake->vtable);
// Set shape
cake->setShape(
@ -161,7 +158,6 @@ static void Tile_initTiles_injection() {
// Add cake to creative inventory
static void Inventory_setupDefault_FillingContainer_addItem_call_injection(FillingContainer *filling_container) {
ItemInstance *cake_instance = new ItemInstance;
ALLOC_CHECK(cake_instance);
cake_instance->count = 255;
cake_instance->auxiliary = 0;
cake_instance->id = 92;

Some files were not shown because too many files have changed in this diff Show More