Simplify Some Code

This commit is contained in:
TheBrokenRail 2024-01-23 21:57:57 -05:00
parent 233e8d691b
commit 0b252faa5f
11 changed files with 322 additions and 313 deletions

View File

@ -50,7 +50,7 @@ jobs:
- Server - Server
name: Test name: Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: node:16-buster container: node:lts-bullseye
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -71,7 +71,7 @@ jobs:
needs: build needs: build
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: node:16-buster container: node:lts-bullseye
steps: steps:
# Dependencies # Dependencies
- name: Install Go - name: Install Go
@ -87,7 +87,7 @@ jobs:
- name: Create Release - name: Create Release
uses: https://gitea.com/actions/release-action@main uses: https://gitea.com/actions/release-action@main
with: with:
files: ./out files: ./out
api_key: ${{ secrets.RELEASE_TOKEN }} api_key: ${{ secrets.RELEASE_TOKEN }}
title: v${{ github.ref_name }} title: v${{ github.ref_name }}
body: "[View Changelog](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md)" body: "[View Changelog](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md)"

View File

@ -8,6 +8,9 @@ If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout`
### ``--debug`` ### ``--debug``
This sets ``MCPI_DEBUG``. This sets ``MCPI_DEBUG``.
### ``--copy-sdk``
This extracts the modding SDK and immediately exits. (This allows the SDK to be extracted without starting the game.)
### Client Mode Only ### Client Mode Only
#### ``--print-available-feature-flags`` #### ``--print-available-feature-flags``

View File

@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build # Build
add_library(chat-commands SHARED chat-commands.cpp) add_library(chat-commands SHARED chat-commands.cpp)
target_link_libraries(chat-commands mods-headers reborn-patch symbols chat misc) target_link_libraries(chat-commands mods reborn-patch symbols)

View File

@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build # Build
add_library(expanded-creative SHARED expanded-creative.cpp) add_library(expanded-creative SHARED expanded-creative.cpp)
target_link_libraries(expanded-creative mods-headers reborn-patch symbols misc) target_link_libraries(expanded-creative mods reborn-patch symbols)

View File

@ -14,4 +14,4 @@ include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cma
# Build # Build
add_library(recipes SHARED recipes.cpp) add_library(recipes SHARED recipes.cpp)
target_link_libraries(recipes mods-headers reborn-util symbols misc) target_link_libraries(recipes mods reborn-util symbols)

View File

@ -1,7 +1,7 @@
project(launcher) project(launcher)
# Launcher # Launcher
add_executable(launcher src/bootstrap.c src/patchelf.cpp src/util.c src/crash-report.c) add_executable(launcher src/bootstrap.c src/patchelf.cpp src/util.c src/crash-report.c src/sdk.c src/mods.c)
if(MCPI_SERVER_MODE) if(MCPI_SERVER_MODE)
target_sources(launcher PRIVATE src/server/launcher.c) target_sources(launcher PRIVATE src/server/launcher.c)
else() else()

View File

@ -1,13 +1,5 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#include "util.h" #include "util.h"
@ -15,77 +7,6 @@
#include "patchelf.h" #include "patchelf.h"
#include "crash-report.h" #include "crash-report.h"
// Get All Mods In Folder
static void load(char **ld_preload, char *folder) {
int folder_name_length = strlen(folder);
// Retry Until Successful
while (1) {
// Open Folder
DIR *dp = opendir(folder);
if (dp != NULL) {
// Loop Through Folder
struct dirent *entry = NULL;
errno = 0;
while (1) {
errno = 0;
entry = readdir(dp);
if (entry != NULL) {
// Check If File Is Regular
if (entry->d_type == DT_REG) {
// Get Full Name
int name_length = strlen(entry->d_name);
int total_length = folder_name_length + name_length;
char name[total_length + 1];
// Concatenate Folder Name And File Name
for (int i = 0; i < folder_name_length; i++) {
name[i] = folder[i];
}
for (int i = 0; i < name_length; i++) {
name[folder_name_length + i] = entry->d_name[i];
}
// Add Terminator
name[total_length] = '\0';
// Check If File Is Accessible
int result = access(name, R_OK);
if (result == 0) {
// Add To LD_PRELOAD
string_append(ld_preload, "%s%s", *ld_preload == NULL ? "" : ":", name);
} else if (result == -1 && errno != 0) {
// Fail
WARN("Unable To Access: %s: %s", name, strerror(errno));
errno = 0;
}
}
} else if (errno != 0) {
// Error Reading Contents Of Folder
ERR("Error Reading Directory: %s: %s", folder, strerror(errno));
} else {
// Done!
break;
}
}
// Close Folder
closedir(dp);
// Exit Function
return;
} else if (errno == ENOENT) {
// Folder Doesn't Exists, Attempt Creation
int ret = mkdir(folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (ret != 0) {
// Unable To Create Folder
ERR("Error Creating Directory: %s: %s", folder, strerror(errno));
}
// Continue Retrying
} else {
// Unable To Open Folder
ERR("Error Opening Directory: %s: %s", folder, strerror(errno));
}
}
}
#define MCPI_BINARY "minecraft-pi" #define MCPI_BINARY "minecraft-pi"
#define QEMU_BINARY "qemu-arm" #define QEMU_BINARY "qemu-arm"
@ -182,11 +103,11 @@ void pre_bootstrap(int argc, char *argv[]) {
set_and_print_env("GTK_THEME", "Adwaita:dark"); set_and_print_env("GTK_THEME", "Adwaita:dark");
#endif #endif
// Get Binary Directory
char *binary_directory = get_binary_directory();
// Configure PATH // Configure PATH
{ {
// Get Binary Directory
char *binary_directory = get_binary_directory();
// Add Library Directory // Add Library Directory
char *new_path = NULL; char *new_path = NULL;
safe_asprintf(&new_path, "%s/bin", binary_directory); safe_asprintf(&new_path, "%s/bin", binary_directory);
@ -200,10 +121,21 @@ void pre_bootstrap(int argc, char *argv[]) {
// Set And Free // Set And Free
set_and_print_env("PATH", new_path); set_and_print_env("PATH", new_path);
free(new_path); free(new_path);
// Free Binary Directory
free(binary_directory);
} }
// Free Binary Directory // --copy-sdk
free(binary_directory); for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--copy-sdk") == 0) {
char *binary_directory = get_binary_directory();
copy_sdk(binary_directory, 0);
free(binary_directory);
fflush(stdout);
exit(EXIT_SUCCESS);
}
}
// Setup Crash Reports // Setup Crash Reports
setup_crash_report(); setup_crash_report();
@ -242,56 +174,6 @@ void pre_bootstrap(int argc, char *argv[]) {
print_debug_information(); print_debug_information();
} }
// Copy SDK Into ~/.minecraft-pi
#define HOME_SUBDIRECTORY_FOR_SDK HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk"
static void copy_sdk(char *binary_directory) {
// Ensure SDK Directory
{
char *sdk_path = NULL;
safe_asprintf(&sdk_path, "%s" HOME_SUBDIRECTORY_FOR_SDK, getenv("HOME"));
const char *const command[] = {"mkdir", "-p", sdk_path, NULL};
run_simple_command(command, "Unable To Create SDK Directory");
}
// Lock File
char *lock_file_path = NULL;
safe_asprintf(&lock_file_path, "%s" HOME_SUBDIRECTORY_FOR_SDK "/.lock", getenv("HOME"));
int lock_file_fd = lock_file(lock_file_path);
// Output Directory
char *output = NULL;
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_SDK "/" MCPI_SDK_DIR, getenv("HOME"));
// Source Directory
char *source = NULL;
safe_asprintf(&source, "%s/sdk/.", binary_directory);
// Clean
{
const char *const command[] = {"rm", "-rf", output, NULL};
run_simple_command(command, "Unable To Clean SDK Output Directory");
}
// Make Directory
{
const char *const command[] = {"mkdir", "-p", output, NULL};
run_simple_command(command, "Unable To Create SDK Output Directory");
}
// Copy
{
const char *const command[] = {"cp", "-ar", source, output, NULL};
run_simple_command(command, "Unable To Copy SDK");
}
// Free
free(output);
free(source);
// Unlock File
unlock_file(lock_file_path, lock_file_fd);
free(lock_file_path);
}
// Bootstrap // Bootstrap
void bootstrap(int argc, char *argv[]) { void bootstrap(int argc, char *argv[]) {
INFO("Configuring Game..."); INFO("Configuring Game...");
@ -301,7 +183,7 @@ void bootstrap(int argc, char *argv[]) {
DEBUG("Binary Directory: %s", binary_directory); DEBUG("Binary Directory: %s", binary_directory);
// Copy SDK // Copy SDK
copy_sdk(binary_directory); copy_sdk(binary_directory, 1);
// Set MCPI_REBORN_ASSETS_PATH // Set MCPI_REBORN_ASSETS_PATH
{ {
@ -432,44 +314,7 @@ void bootstrap(int argc, char *argv[]) {
set_and_print_env("MCPI_NATIVE_LD_PRELOAD", host_ld_preload); set_and_print_env("MCPI_NATIVE_LD_PRELOAD", host_ld_preload);
// ARM Components // ARM Components
{ bootstrap_mods(binary_directory);
// Prepare
char *preload = NULL;
// ~/.minecraft-pi/mods
{
// Get Mods Folder
char *mods_folder = NULL;
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
// Load Mods From ./mods
load(&preload, mods_folder);
// Free Mods Folder
free(mods_folder);
}
// Built-In Mods
{
// Get Mods Folder
char *mods_folder = NULL;
safe_asprintf(&mods_folder, "%s/mods/", binary_directory);
// Load Mods From ./mods
load(&preload, mods_folder);
// Free Mods Folder
free(mods_folder);
}
// Add LD_PRELOAD
{
char *value = getenv("LD_PRELOAD");
if (value != NULL && strlen(value) > 0) {
string_append(&preload, ":%s", value);
}
}
// Set
set_and_print_env("MCPI_ARM_LD_PRELOAD", preload);
free(preload);
}
} }
// Free Binary Directory // Free Binary Directory

View File

@ -6,6 +6,8 @@ extern "C" {
void pre_bootstrap(int argc, char *argv[]); void pre_bootstrap(int argc, char *argv[]);
void bootstrap(int argc, char *argv[]); void bootstrap(int argc, char *argv[]);
void copy_sdk(char *binary_directory, int log_with_debug);
void bootstrap_mods(char *binary_directory);
#ifdef __cplusplus #ifdef __cplusplus
} }

110
launcher/src/mods.c Normal file
View File

@ -0,0 +1,110 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libreborn/libreborn.h>
#include "bootstrap.h"
// Get All Mods In Folder
static void load(char **ld_preload, const char *folder) {
int folder_name_length = strlen(folder);
// Open Folder
DIR *dp = opendir(folder);
if (dp != NULL) {
// Loop Through Folder
struct dirent *entry = NULL;
errno = 0;
while (1) {
errno = 0;
entry = readdir(dp);
if (entry != NULL) {
// Check If File Is Regular
if (entry->d_type == DT_REG) {
// Get Full Name
int name_length = strlen(entry->d_name);
int total_length = folder_name_length + name_length;
char name[total_length + 1];
// Concatenate Folder Name And File Name
for (int i = 0; i < folder_name_length; i++) {
name[i] = folder[i];
}
for (int i = 0; i < name_length; i++) {
name[folder_name_length + i] = entry->d_name[i];
}
// Add Terminator
name[total_length] = '\0';
// Check If File Is Accessible
int result = access(name, R_OK);
if (result == 0) {
// Add To LD_PRELOAD
string_append(ld_preload, "%s%s", *ld_preload == NULL ? "" : ":", name);
} else if (result == -1 && errno != 0) {
// Fail
WARN("Unable To Access: %s: %s", name, strerror(errno));
errno = 0;
}
}
} else if (errno != 0) {
// Error Reading Contents Of Folder
ERR("Error Reading Directory: %s: %s", folder, strerror(errno));
} else {
// Done!
break;
}
}
// Close Folder
closedir(dp);
} else if (errno == ENOENT) {
// Folder Doesn't Exist
} else {
// Unable To Open Folder
ERR("Error Opening Directory: %s: %s", folder, strerror(errno));
}
}
// Bootstrap Mods
void bootstrap_mods(char *binary_directory) {
// Prepare
char *preload = NULL;
// ~/.minecraft-pi/mods
{
// Get Mods Folder
char *mods_folder = NULL;
safe_asprintf(&mods_folder, "%s" HOME_SUBDIRECTORY_FOR_GAME_DATA "/mods/", getenv("HOME"));
// Load Mods From ./mods
load(&preload, mods_folder);
// Free Mods Folder
free(mods_folder);
}
// Built-In Mods
{
// Get Mods Folder
char *mods_folder = NULL;
safe_asprintf(&mods_folder, "%s/mods/", binary_directory);
// Load Mods From ./mods
load(&preload, mods_folder);
// Free Mods Folder
free(mods_folder);
}
// Add LD_PRELOAD
{
char *value = getenv("LD_PRELOAD");
if (value != NULL && strlen(value) > 0) {
string_append(&preload, ":%s", value);
}
}
// Set
set_and_print_env("MCPI_ARM_LD_PRELOAD", preload);
free(preload);
}

67
launcher/src/sdk.c Normal file
View File

@ -0,0 +1,67 @@
#include <libreborn/libreborn.h>
#include "bootstrap.h"
#include "util.h"
// Log
#define LOG(is_debug, ...) \
{ \
if (is_debug) { \
DEBUG(__VA_ARGS__); \
} else { \
INFO(__VA_ARGS__); \
} \
}
// Copy SDK Into ~/.minecraft-pi
#define HOME_SUBDIRECTORY_FOR_SDK HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk"
void copy_sdk(char *binary_directory, int log_with_debug) {
// Ensure SDK Directory
{
char *sdk_path = NULL;
safe_asprintf(&sdk_path, "%s" HOME_SUBDIRECTORY_FOR_SDK, getenv("HOME"));
const char *const command[] = {"mkdir", "-p", sdk_path, NULL};
run_simple_command(command, "Unable To Create SDK Directory");
}
// Lock File
char *lock_file_path = NULL;
safe_asprintf(&lock_file_path, "%s" HOME_SUBDIRECTORY_FOR_SDK "/.lock", getenv("HOME"));
int lock_file_fd = lock_file(lock_file_path);
// Output Directory
char *output = NULL;
safe_asprintf(&output, "%s" HOME_SUBDIRECTORY_FOR_SDK "/" MCPI_SDK_DIR, getenv("HOME"));
// Source Directory
char *source = NULL;
safe_asprintf(&source, "%s/sdk/.", binary_directory);
// Clean
{
const char *const command[] = {"rm", "-rf", output, NULL};
run_simple_command(command, "Unable To Clean SDK Output Directory");
}
// Make Directory
{
const char *const command[] = {"mkdir", "-p", output, NULL};
run_simple_command(command, "Unable To Create SDK Output Directory");
}
// Copy
{
const char *const command[] = {"cp", "-ar", source, output, NULL};
run_simple_command(command, "Unable To Copy SDK");
}
// Log
LOG(log_with_debug, "Copied SDK To: %s", output);
// Free
free(output);
free(source);
// Unlock File
unlock_file(lock_file_path, lock_file_fd);
free(lock_file_path);
}

View File

@ -1,141 +1,123 @@
project(mods) project(mods)
## Headers # Common Sources
add_library(mods-headers INTERFACE) set(SRC
# compat
src/compat/compat.c
src/compat/egl.c
src/compat/x11.c
src/compat/bcm_host.c
# readdir
src/readdir/readdir.c
# feature
src/feature/feature.c
# version
src/version/version.cpp
# chat
src/chat/chat.cpp
src/chat/ui.c
# creative
src/creative/creative.cpp
# game-mode
src/game-mode/game-mode.c
src/game-mode/ui.cpp
# override
src/override/override.c
# death
src/death/death.cpp
# misc
src/misc/misc.c
src/misc/misc.cpp
src/misc/logging.cpp
src/misc/api.cpp
# options
src/options/options.c
src/options/options.cpp
# bucket
src/bucket/bucket.cpp
# home
src/home/home.c
# test
src/test/test.c
# init
src/init/init.c
)
# Server-Only Sources
if(MCPI_SERVER_MODE)
list(APPEND SRC
# server
src/server/server.cpp
src/server/server_properties.cpp
)
else()
list(APPEND SRC
# multiplayer
src/multiplayer/multiplayer.cpp
# benchmark
src/benchmark/benchmark.cpp
)
endif()
# Headless-Only Sources
if(MCPI_HEADLESS_MODE)
list(APPEND SRC
# textures
src/textures/headless.cpp
)
else()
list(APPEND SRC
# sound
src/sound/sound.cpp
src/sound/repository.cpp
# camera
src/camera/camera.cpp
# input
src/input/input.cpp
src/input/bow.c
src/input/attack.c
src/input/toggle.c
src/input/misc.c
src/input/drop.cpp
src/input/crafting.cpp
# sign
src/sign/sign.cpp
# touch
src/touch/touch.cpp
# atlas
src/atlas/atlas.cpp
# title-screen
src/title-screen/title-screen.cpp
# skin
src/skin/skin.cpp
src/skin/loader.cpp
# screenshot
src/screenshot/screenshot.c
# textures
src/textures/textures.cpp
)
endif()
# Build
add_library(mods SHARED ${SRC})
# Install
install(TARGETS mods DESTINATION "${MCPI_INSTALL_DIR}/mods")
# SDK
install(TARGETS mods EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
# Dependencies
target_link_libraries(mods symbols reborn-patch media-layer-core dl pthread)
if(NOT MCPI_HEADLESS_MODE)
target_link_libraries(mods stb_image)
endif()
# Headers
target_include_directories( target_include_directories(
mods-headers mods
INTERFACE PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/mods>" "$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/mods>"
) )
target_link_libraries(mods-headers INTERFACE symbols)
# SDK # SDK
install(TARGETS mods-headers EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods") install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods")
## Mods
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c src/compat/bcm_host.c)
target_link_libraries(compat mods-headers reborn-patch media-layer-core)
if(NOT MCPI_HEADLESS_MODE)
target_link_libraries(compat screenshot input sign chat home dl)
endif()
add_library(readdir SHARED src/readdir/readdir.c)
add_library(feature SHARED src/feature/feature.c)
target_link_libraries(feature mods-headers reborn-patch)
add_library(version SHARED src/version/version.cpp)
target_link_libraries(version mods-headers reborn-patch symbols)
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
target_link_libraries(chat mods-headers reborn-patch symbols feature)
if(NOT MCPI_HEADLESS_MODE)
target_link_libraries(chat input media-layer-core pthread)
endif()
add_library(creative SHARED src/creative/creative.cpp)
target_link_libraries(creative mods-headers reborn-patch symbols feature misc)
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/ui.cpp)
target_link_libraries(game-mode mods-headers reborn-patch symbols feature)
if(NOT MCPI_SERVER_MODE)
target_link_libraries(game-mode pthread media-layer-core)
endif()
if(MCPI_SERVER_MODE)
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
target_link_libraries(server mods-headers reborn-patch symbols feature home misc compat dl media-layer-core pthread)
else()
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
target_link_libraries(multiplayer mods-headers reborn-patch symbols home feature)
add_library(benchmark SHARED src/benchmark/benchmark.cpp)
target_link_libraries(benchmark mods-headers reborn-patch symbols compat misc media-layer-core)
endif()
if(NOT MCPI_HEADLESS_MODE)
add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp)
target_link_libraries(sound mods-headers reborn-patch symbols feature override media-layer-core)
add_library(camera SHARED src/camera/camera.cpp)
target_link_libraries(camera mods-headers reborn-patch symbols feature home screenshot)
add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp src/input/crafting.cpp)
target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core)
add_library(sign SHARED src/sign/sign.cpp)
target_link_libraries(sign mods-headers reborn-patch symbols feature input media-layer-core)
add_library(touch SHARED src/touch/touch.cpp)
target_link_libraries(touch mods-headers reborn-patch symbols feature)
add_library(atlas SHARED src/atlas/atlas.cpp)
target_link_libraries(atlas mods-headers reborn-patch symbols feature media-layer-core)
add_library(title-screen SHARED src/title-screen/title-screen.cpp)
target_link_libraries(title-screen mods-headers reborn-patch symbols feature compat)
add_library(skin SHARED src/skin/skin.cpp src/skin/loader.cpp)
target_link_libraries(skin mods-headers reborn-patch symbols feature misc textures media-layer-core stb_image)
add_library(screenshot SHARED src/screenshot/screenshot.c)
target_link_libraries(screenshot mods-headers reborn-util media-layer-core stb_image)
endif()
if(NOT MCPI_HEADLESS_MODE)
add_library(textures SHARED src/textures/textures.cpp)
else()
add_library(textures SHARED src/textures/headless.cpp)
endif()
target_link_libraries(textures mods-headers reborn-patch symbols)
if(NOT MCPI_HEADLESS_MODE)
target_link_libraries(textures media-layer-core feature misc stb_image)
endif()
add_library(override SHARED src/override/override.c)
target_link_libraries(override mods-headers reborn-patch symbols dl home)
add_library(death SHARED src/death/death.cpp)
target_link_libraries(death mods-headers reborn-patch symbols feature)
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp src/misc/api.cpp)
target_link_libraries(misc mods-headers reborn-patch symbols media-layer-core feature)
add_library(options SHARED src/options/options.c src/options/options.cpp)
target_link_libraries(options mods-headers reborn-patch symbols feature home)
add_library(bucket SHARED src/bucket/bucket.cpp)
target_link_libraries(bucket mods-headers reborn-patch symbols feature misc)
add_library(home SHARED src/home/home.c)
target_link_libraries(home mods-headers reborn-patch symbols)
add_library(test SHARED src/test/test.c)
target_link_libraries(test mods-headers reborn-patch home)
add_library(init SHARED src/init/init.c)
target_link_libraries(init symbols mods-headers reborn-util compat game-mode misc death options chat creative bucket textures home version test media-layer-core)
if(MCPI_SERVER_MODE)
target_link_libraries(init server)
else()
target_link_libraries(init multiplayer benchmark)
endif()
if(NOT MCPI_HEADLESS_MODE)
target_link_libraries(init sound camera input sign touch atlas title-screen skin)
endif()
## Install Mods
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket textures home version test)
if(MCPI_SERVER_MODE)
list(APPEND MODS_TO_INSTALL server)
else()
list(APPEND MODS_TO_INSTALL multiplayer benchmark)
endif()
if(NOT MCPI_HEADLESS_MODE)
list(APPEND MODS_TO_INSTALL sound camera input sign touch atlas title-screen skin screenshot)
endif()
install(TARGETS ${MODS_TO_INSTALL} DESTINATION "${MCPI_INSTALL_DIR}/mods")
# SDK
install(TARGETS ${MODS_TO_INSTALL} EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")