154 lines
4.1 KiB
C++
154 lines
4.1 KiB
C++
|
#include <cstdlib>
|
||
|
#include <libreborn/libreborn.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#include "bootstrap.h"
|
||
|
#include "options/parser.h"
|
||
|
#include "crash-report.h"
|
||
|
#include "util.h"
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
#include "client/configuration.h"
|
||
|
#endif
|
||
|
|
||
|
// Bind Options To Environmental Variable
|
||
|
static void bind_to_env(const char *env, const bool value) {
|
||
|
const bool force = env[0] == '_';
|
||
|
if (force || value) {
|
||
|
set_and_print_env(env, value ? "1" : nullptr);
|
||
|
}
|
||
|
}
|
||
|
static void setup_environment(const options_t &options) {
|
||
|
// Passthrough Options To Game
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
bind_to_env("_MCPI_BENCHMARK", options.benchmark);
|
||
|
#else
|
||
|
bind_to_env("_MCPI_ONLY_GENERATE", options.only_generate);
|
||
|
#endif
|
||
|
|
||
|
// GTK Dark Mode
|
||
|
#ifndef MCPI_HEADLESS_MODE
|
||
|
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
||
|
#endif
|
||
|
|
||
|
// Configure PATH
|
||
|
{
|
||
|
// Get Binary Directory
|
||
|
char *binary_directory = get_binary_directory();
|
||
|
std::string new_path = std::string(binary_directory) + "/bin";
|
||
|
free(binary_directory);
|
||
|
// Add Existing PATH
|
||
|
{
|
||
|
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());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Non-Launch Commands
|
||
|
static void handle_non_launch_commands(const options_t &options) {
|
||
|
if (options.copy_sdk) {
|
||
|
char *binary_directory = get_binary_directory();
|
||
|
copy_sdk(binary_directory, false);
|
||
|
free(binary_directory);
|
||
|
fflush(stdout);
|
||
|
exit(EXIT_SUCCESS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Exit Handler
|
||
|
static void exit_handler(__attribute__((unused)) int signal_id) {
|
||
|
// Pass Signal To Child
|
||
|
murder_children();
|
||
|
while (wait(nullptr) > 0) {}
|
||
|
_exit(EXIT_SUCCESS);
|
||
|
}
|
||
|
|
||
|
// Start The Game
|
||
|
static void start_game(const options_t &options) {
|
||
|
// Disable stdout Buffering
|
||
|
setvbuf(stdout, nullptr, _IONBF, 0);
|
||
|
|
||
|
// Environemntal Variable Options
|
||
|
setup_environment(options);
|
||
|
|
||
|
// Setup Crash Reporting
|
||
|
if (!options.disable_crash_report) {
|
||
|
setup_log_file();
|
||
|
setup_crash_report();
|
||
|
}
|
||
|
|
||
|
// Install Signal Handlers
|
||
|
struct sigaction act_sigint = {};
|
||
|
act_sigint.sa_flags = SA_RESTART;
|
||
|
act_sigint.sa_handler = &exit_handler;
|
||
|
sigaction(SIGINT, &act_sigint, nullptr);
|
||
|
struct sigaction act_sigterm = {};
|
||
|
act_sigterm.sa_flags = SA_RESTART;
|
||
|
act_sigterm.sa_handler = &exit_handler;
|
||
|
sigaction(SIGTERM, &act_sigterm, nullptr);
|
||
|
|
||
|
// Setup Home
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
// Ensure $HOME
|
||
|
const char *home = getenv("HOME");
|
||
|
if (home == nullptr) {
|
||
|
ERR("$HOME Isn't Set");
|
||
|
}
|
||
|
// Create If Needed
|
||
|
{
|
||
|
std::string minecraft_folder = std::string(home) + HOME_SUBDIRECTORY_FOR_GAME_DATA;
|
||
|
struct stat tmp_stat = {};
|
||
|
bool exists = stat(minecraft_folder.c_str(), &tmp_stat) != 0 ? false : S_ISDIR(tmp_stat.st_mode);
|
||
|
if (!exists) {
|
||
|
// Doesn't Exist
|
||
|
if (mkdir(minecraft_folder.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
|
||
|
ERR("Unable To Create Data Directory: %s", strerror(errno));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
// Set Home To Current Directory, So World Data Is Stored There
|
||
|
char *launch_directory = getcwd(NULL, 0);
|
||
|
set_and_print_env("HOME", launch_directory);
|
||
|
free(launch_directory);
|
||
|
#endif
|
||
|
|
||
|
// Configure Client Options
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
configure_client(options);
|
||
|
#endif
|
||
|
|
||
|
// Bootstrap
|
||
|
bootstrap();
|
||
|
}
|
||
|
|
||
|
// Main
|
||
|
int main(int argc, char *argv[]) {
|
||
|
// Parse Options
|
||
|
options_t options = parse_options(argc, argv);
|
||
|
|
||
|
// Set Debug Tag
|
||
|
reborn_debug_tag = "(Launcher) ";
|
||
|
|
||
|
// Debug Logging
|
||
|
bind_to_env(MCPI_DEBUG_ENV, options.debug);
|
||
|
|
||
|
// Handle Non-Launch Commands (Copy SDK, Print Feature Flags, Etc)
|
||
|
handle_non_launch_commands(options);
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
handle_non_launch_client_only_commands(options);
|
||
|
#endif
|
||
|
|
||
|
// Check Environment
|
||
|
#ifndef MCPI_SERVER_MODE
|
||
|
// Code After This Can Safely Open A Window
|
||
|
check_environment_client();
|
||
|
#endif
|
||
|
|
||
|
// Start The Game
|
||
|
start_game(options);
|
||
|
}
|