diff --git a/launcher/src/client/available-feature-flags b/launcher/src/client/available-feature-flags index c0988047..2f684d51 100644 --- a/launcher/src/client/available-feature-flags +++ b/launcher/src/client/available-feature-flags @@ -76,4 +76,5 @@ 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 \ No newline at end of file +TRUE Fix Door Duplication +TRUE Fix Cobweb Lighting \ No newline at end of file diff --git a/launcher/src/crash-report.cpp b/launcher/src/crash-report.cpp index b85ea175..3f9f7924 100644 --- a/launcher/src/crash-report.cpp +++ b/launcher/src/crash-report.cpp @@ -68,7 +68,7 @@ static void setup_log_file() { // Get Timestamp time_t raw_time; time(&raw_time); - tm *time_info = localtime(&raw_time); + const tm *time_info = localtime(&raw_time); char time[512]; strftime(time, 512, "%Y-%m-%d", time_info); diff --git a/launcher/src/main.cpp b/launcher/src/main.cpp index e642bd61..43f8d7d6 100644 --- a/launcher/src/main.cpp +++ b/launcher/src/main.cpp @@ -45,7 +45,13 @@ static void setup_environment(const options_t &options) { } // Setup MCPI_HOME - if (!reborn_is_server()) { + if (const char *custom_profile_directory = getenv(MCPI_PROFILE_DIRECTORY_ENV); 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) { diff --git a/launcher/src/mods.cpp b/launcher/src/mods.cpp index a5cd30f8..ec44b019 100644 --- a/launcher/src/mods.cpp +++ b/launcher/src/mods.cpp @@ -8,46 +8,68 @@ #include "bootstrap.h" // Get All Mods In Folder -static void load(std::string &ld_preload, const std::string &folder) { +static void load(std::string &ld_preload, const std::string &folder, int recursion_limit = 128); +static void handle_file(std::string &ld_preload, const std::string &file, const int recursion_limit) { + // Check Type + struct stat file_stat = {}; + lstat(file.c_str(), &file_stat); + if (S_ISDIR(file_stat.st_mode)) { + // Recurse Into Directory + 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); + 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); + if (result == 0) { + // Add To LD_PRELOAD + ld_preload += file + ":"; + } else if (result == -1 && errno != 0) { + // Fail + WARN("Unable To Access: %s: %s", file.c_str(), strerror(errno)); + errno = 0; + } + } +} +static void load(std::string &ld_preload, const std::string &folder, const int recursion_limit) { + // Check Recursion + if (recursion_limit <= 0) { + ERR("Reached Recursion Limit While Loading Mods"); + } // Open Folder ensure_directory(folder.c_str()); DIR *dp = opendir(folder.c_str()); - if (dp != nullptr) { - // Loop Through Folder - while (true) { - errno = 0; - dirent *entry = readdir(dp); - if (entry != nullptr) { - // Check If File Is Regular - if (entry->d_type == DT_REG) { - // Get Full Name - std::string name = folder + entry->d_name; - - // Check If File Is Accessible - int result = access(name.c_str(), R_OK); - if (result == 0) { - // Add To LD_PRELOAD - ld_preload += name + ":"; - } else if (result == -1 && errno != 0) { - // Fail - WARN("Unable To Access: %s: %s", name.c_str(), strerror(errno)); - errno = 0; - } - } - } else if (errno != 0) { - // Error Reading Contents Of Folder - ERR("Error Reading Directory: %s: %s", folder.c_str(), strerror(errno)); - } else { - // Done! - break; - } - } - // Close Folder - closedir(dp); - } else { + if (dp == nullptr) { // Unable To Open Folder ERR("Error Opening Directory: %s: %s", folder.c_str(), strerror(errno)); } + // Loop Through Folder + while (true) { + errno = 0; + const dirent *entry = readdir(dp); + if (entry != nullptr) { + // Block Pseudo-Directories + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + // Get Full Name + std::string name = folder + entry->d_name; + // Handle + handle_file(ld_preload, name, recursion_limit); + } else if (errno != 0) { + // Error Reading Contents Of Folder + ERR("Error Reading Directory: %s: %s", folder.c_str(), strerror(errno)); + } else { + // Done! + break; + } + } + // Close Folder + closedir(dp); } // Bootstrap Mods @@ -59,7 +81,7 @@ std::string bootstrap_mods(const std::string &binary_directory) { // ~/.minecraft-pi/mods { // Get Mods Folder - std::string mods_folder = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data() + SUBDIRECTORY_FOR_MODS; + 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); } @@ -67,7 +89,7 @@ std::string bootstrap_mods(const std::string &binary_directory) { // Built-In Mods { // Get Mods Folder - std::string mods_folder = binary_directory + SUBDIRECTORY_FOR_MODS; + const std::string mods_folder = binary_directory + SUBDIRECTORY_FOR_MODS; // Load Mods From ./mods load(preload, mods_folder); } diff --git a/launcher/src/sdk.cpp b/launcher/src/sdk.cpp index 3f5b1b9a..a28e61ff 100644 --- a/launcher/src/sdk.cpp +++ b/launcher/src/sdk.cpp @@ -25,13 +25,13 @@ void copy_sdk(const std::string &binary_directory, const bool log_with_debug) { } // Lock File - std::string lock_file_path = sdk_path + "/.lock"; - int lock_file_fd = lock_file(lock_file_path.c_str()); + const std::string lock_file_path = sdk_path + "/.lock"; + const int lock_file_fd = lock_file(lock_file_path.c_str()); // Output Directory - std::string output = sdk_path + "/" MCPI_SDK_DIR; + const std::string output = sdk_path + "/" MCPI_SDK_DIR; // Source Directory - std::string source = binary_directory + "/sdk/."; + const std::string source = binary_directory + "/sdk/."; // Clean { diff --git a/libreborn/include/libreborn/env-list.h b/libreborn/include/libreborn/env-list.h index 4ef6428c..8b9f59f6 100644 --- a/libreborn/include/libreborn/env-list.h +++ b/libreborn/include/libreborn/env-list.h @@ -21,4 +21,5 @@ ENV(MCPI_API_PORT, "Custom API Port") ENV(MCPI_BLOCK_OUTLINE_WIDTH, "Custom Width For Block Outline (In Pixels)") ENV(MCPI_GUI_SCALE, "Custom GUI Scale") // $HOME -ENV(_MCPI_HOME, "") \ No newline at end of file +ENV(_MCPI_HOME, "") +ENV(MCPI_PROFILE_DIRECTORY, "Custom Profile Directory") \ No newline at end of file diff --git a/libreborn/src/util/util.c b/libreborn/src/util/util.c index 680cf539..7bbfccec 100644 --- a/libreborn/src/util/util.c +++ b/libreborn/src/util/util.c @@ -40,7 +40,7 @@ int lock_file(const char *file) { } return fd; } -void unlock_file(const char *file, int 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)); } @@ -84,7 +84,10 @@ void reborn_check_display() { // Home Subdirectory const char *get_home_subdirectory_for_game_data() { - if (!reborn_is_server()) { + if (getenv(MCPI_PROFILE_DIRECTORY_ENV) != NULL) { + // 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 { diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index b19977c8..7bc0ecec 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -781,6 +781,11 @@ static void DoorTile_neighborChanged_Tile_spawnResources_injection(DoorTile *sel self->spawnResources(level, x, y, z, data2, 1); } +// Fix Cobweb Lighting +static Tile *Tile_initTiles_WebTile_setLightBlock_injection(Tile *self, __attribute__((unused)) int strength) { + return self; +} + // Init template static void nop(__attribute__((unused)) Args... args) { @@ -1055,6 +1060,11 @@ void init_misc() { overwrite_call((void *) 0xbe110, (void *) DoorTile_neighborChanged_Tile_spawnResources_injection); } + // Fix Cobweb Lighting + if (feature_has("Fix Cobweb Lighting", server_enabled)) { + overwrite_call((void *) 0xc444c, (void *) Tile_initTiles_WebTile_setLightBlock_injection); + } + // Init Logging _init_misc_logging(); _init_misc_api(); diff --git a/mods/src/options/info.cpp b/mods/src/options/info.cpp index 5148c7ee..753cca58 100644 --- a/mods/src/options/info.cpp +++ b/mods/src/options/info.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -45,11 +46,19 @@ static std::string profile_directory_suffix = std::string(get_home_subdirectory_for_game_data()) ; static std::string get_profile_directory_url() { - const char *home = getenv("HOME"); - if (home == nullptr) { - IMPOSSIBLE(); + std::string directory; + if (getenv(MCPI_PROFILE_DIRECTORY_ENV) != nullptr) { + // Using Custom Directory + directory = home_get(); + } else { + // Determine Proper Directory + const char *home = getenv("HOME"); + if (home == nullptr) { + IMPOSSIBLE(); + } + directory = home + profile_directory_suffix; } - return std::string("file://") + home + profile_directory_suffix; + return std::string("file://") + directory; } // Info Data diff --git a/symbols/src/tile/Tile.def b/symbols/src/tile/Tile.def index 023b4dc1..cec5e486 100644 --- a/symbols/src/tile/Tile.def +++ b/symbols/src/tile/Tile.def @@ -55,6 +55,7 @@ virtual-method Tile *setLightEmission(float light) = 0xf0; virtual-method Tile *setExplodeable(float explodeable) = 0xf4; virtual-method Tile *setDestroyTime(float destroy_time) = 0xf8; virtual-method void spawnResources(Level *level, int x, int y, int z, int data, float chance) = 0x80; +virtual-method Tile *setLightBlock(int strength) = 0xec; property int texture = 0x4; property int id = 0x8;