#include #include #include #include #include #include // Safe Version Of pipe() Pipe::Pipe(): read(-1), write(-1) { int out[2]; if (pipe(out) != 0) { ERR("Unable To Create Pipe: %s", strerror(errno)); } const_cast(read) = out[0]; const_cast(write) = out[1]; } // Check If Two Percentages Are Different Enough To Be Logged #define SIGNIFICANT_PROGRESS 5 bool is_progress_difference_significant(const int32_t new_val, const int32_t old_val) { if (new_val != old_val) { if (new_val == -1 || old_val == -1) { return true; } else if (new_val == 0 || new_val == 100) { return true; } else { return new_val - old_val >= SIGNIFICANT_PROGRESS; } } else { return false; } } // Lock File int lock_file(const char *file) { const int fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fd == -1) { ERR("Unable To Open Lock File: %s: %s", file, strerror(errno)); } if (flock(fd, LOCK_EX) == -1) { ERR("Unable To Lock File: %s: %s", file, strerror(errno)); } return fd; } void unlock_file(const char *file, const int fd) { if (flock(fd, LOCK_UN) == -1) { ERR("Unable To Unlock File: %s: %s", file, strerror(errno)); } 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")) { ERR("No display attached! Make sure $DISPLAY or $WAYLAND_DISPLAY is set."); } } // Home Subdirectory const char *get_home_subdirectory_for_game_data() { if (getenv(MCPI_PROFILE_DIRECTORY_ENV) != nullptr) { // No Subdirectory When Using Custom Profile Directory return ""; } else if (!reborn_is_server()) { // Store Game Data In "~/.minecraft-pi" Instead Of "~/.minecraft" To Avoid Conflicts return "/.minecraft-pi"; } else { // Store Game Data In $HOME Root (In Server Mode, $HOME Is Changed To The Launch Directory) return ""; } } // Make Sure Directory Exists void ensure_directory(const char *path) { int ret = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (ret != 0 && errno != EEXIST) { ERR("Unable To Create Directory: %s", strerror(errno)); } int is_dir = 0; struct stat obj = {}; ret = stat(path, &obj); if (ret == 0) { is_dir = S_ISDIR(obj.st_mode); } if (!is_dir) { ERR("Not A Directory: %s", path); } } // Write To FD void safe_write(const int fd, const void *buf, const size_t size) { const ssize_t bytes_written = write(fd, buf, size); if (bytes_written < 0) { ERR("Unable To Write Data: %s", strerror(errno)); } }