New Crash Report UI
This commit is contained in:
parent
7f9d1d843e
commit
d3b70878be
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,9 +1,6 @@
|
|||||||
[submodule "dependencies/glfw/src"]
|
[submodule "dependencies/glfw/src"]
|
||||||
path = dependencies/glfw/src
|
path = dependencies/glfw/src
|
||||||
url = https://github.com/glfw/glfw.git
|
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"]
|
[submodule "dependencies/LIEF/src"]
|
||||||
path = dependencies/LIEF/src
|
path = dependencies/LIEF/src
|
||||||
url = https://github.com/lief-project/LIEF.git
|
url = https://github.com/lief-project/LIEF.git
|
||||||
|
4
dependencies/CMakeLists.txt
vendored
4
dependencies/CMakeLists.txt
vendored
@ -8,10 +8,6 @@ endif()
|
|||||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
||||||
add_subdirectory(minecraft-pi)
|
add_subdirectory(minecraft-pi)
|
||||||
endif()
|
endif()
|
||||||
# Zenity (Minimal Build)
|
|
||||||
if(BUILD_NATIVE_COMPONENTS)
|
|
||||||
add_subdirectory(zenity)
|
|
||||||
endif()
|
|
||||||
# LIEF
|
# LIEF
|
||||||
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
|
if(BUILD_NATIVE_COMPONENTS OR BUILD_MEDIA_LAYER_CORE)
|
||||||
add_subdirectory(LIEF)
|
add_subdirectory(LIEF)
|
||||||
|
20
dependencies/zenity/CMakeLists.txt
vendored
20
dependencies/zenity/CMakeLists.txt
vendored
@ -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
dependencies/zenity/src
vendored
1
dependencies/zenity/src
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit a7496461161c917878d58131711425e7c8e59436
|
|
@ -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:
|
It also requires some additional packages. To install them, run:
|
||||||
```sh
|
```sh
|
||||||
sudo apt install -y libfuse2 libgtk-3-0 libopenal1 libglib2.0-0
|
sudo apt install -y libfuse2 libopenal1 libglib2.0-0
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ add_executable(launcher
|
|||||||
src/bootstrap/debug.cpp
|
src/bootstrap/debug.cpp
|
||||||
src/util/util.cpp
|
src/util/util.cpp
|
||||||
src/util/sdk.cpp
|
src/util/sdk.cpp
|
||||||
|
src/util/env.cpp
|
||||||
src/logger/logger.cpp
|
src/logger/logger.cpp
|
||||||
src/logger/crash-report.cpp
|
src/logger/crash-report.cpp
|
||||||
src/options/parser.cpp
|
src/options/parser.cpp
|
||||||
|
@ -75,28 +75,21 @@ int ConfigurationUI::draw_bottom() {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
// Right-Align Buttons
|
// Right-Align Buttons
|
||||||
const ImGuiStyle &style = ImGui::GetStyle();
|
int ret = 0;
|
||||||
const char *bottom_row_text[] = {"Quit", "Launch"};
|
draw_right_aligned_buttons({"Quit", "Launch"}, [&ret](const int id, const bool was_clicked) {
|
||||||
float width_needed = 0;
|
if (id == 0) {
|
||||||
for (const char *text : bottom_row_text) {
|
// Quit
|
||||||
if (width_needed > 0) {
|
if (was_clicked) {
|
||||||
width_needed += style.ItemSpacing.x;
|
ret = -1;
|
||||||
|
}
|
||||||
|
ImGui::SetItemTooltip("Changes Will Not Be Saved!");
|
||||||
|
} else if (was_clicked) {
|
||||||
|
// Launch
|
||||||
|
ret = 1;
|
||||||
}
|
}
|
||||||
width_needed += ImGui::CalcTextSize(text).x + style.FramePadding.x * 2.f;
|
});
|
||||||
}
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - width_needed);
|
|
||||||
// Quit
|
|
||||||
if (ImGui::Button(bottom_row_text[0])) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ImGui::SetItemTooltip("Changes Will Not Be Saved!");
|
|
||||||
ImGui::SameLine();
|
|
||||||
// Launch
|
|
||||||
if (ImGui::Button(bottom_row_text[1])) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// Return
|
// Return
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main Tab
|
// Main Tab
|
||||||
|
@ -1,35 +1,84 @@
|
|||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "logger.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
|
// Show Crash Report Dialog
|
||||||
#define DIALOG_TITLE "Crash Report"
|
|
||||||
#define CRASH_REPORT_DIALOG_WIDTH "640"
|
|
||||||
#define CRASH_REPORT_DIALOG_HEIGHT "480"
|
|
||||||
void show_report(const char *log_filename) {
|
void show_report(const char *log_filename) {
|
||||||
// Fork
|
// Fork
|
||||||
pid_t pid = fork();
|
const pid_t pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
// Child
|
// Child
|
||||||
setsid();
|
setsid();
|
||||||
ALLOC_CHECK(freopen("/dev/null", "w", stdout));
|
ALLOC_CHECK(freopen("/dev/null", "w", stdout));
|
||||||
ALLOC_CHECK(freopen("/dev/null", "w", stderr));
|
ALLOC_CHECK(freopen("/dev/null", "w", stderr));
|
||||||
ALLOC_CHECK(freopen("/dev/null", "r", stdin));
|
ALLOC_CHECK(freopen("/dev/null", "r", stdin));
|
||||||
const char *command[] = {
|
CrashReport ui(log_filename);
|
||||||
"zenity",
|
ui.run();
|
||||||
"--title", DIALOG_TITLE,
|
exit(EXIT_SUCCESS);
|
||||||
"--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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,6 @@
|
|||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -26,12 +25,18 @@ static void exit_handler(__attribute__((unused)) int signal) {
|
|||||||
// Log File
|
// Log File
|
||||||
static std::string log_filename;
|
static std::string log_filename;
|
||||||
static int log_fd;
|
static int log_fd;
|
||||||
static void setup_log_file() {
|
std::string get_logs_folder() {
|
||||||
// Get Log Directory
|
|
||||||
const std::string home = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
|
const std::string home = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
|
||||||
ensure_directory(home.c_str());
|
ensure_directory(home.c_str());
|
||||||
const std::string logs = home + "/logs";
|
const std::string logs = home + "/logs";
|
||||||
ensure_directory(logs.c_str());
|
ensure_directory(logs.c_str());
|
||||||
|
return logs;
|
||||||
|
}
|
||||||
|
static void setup_log_file() {
|
||||||
|
// Get Log Directory
|
||||||
|
const std::string home = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
|
||||||
|
ensure_directory(home.c_str());
|
||||||
|
const std::string logs = get_logs_folder();
|
||||||
|
|
||||||
// Get Timestamp
|
// Get Timestamp
|
||||||
time_t raw_time;
|
time_t raw_time;
|
||||||
@ -129,7 +134,7 @@ void setup_logger() {
|
|||||||
|
|
||||||
// Close Log File
|
// Close Log File
|
||||||
close(log_fd);
|
close(log_fd);
|
||||||
unsetenv(_MCPI_LOG_FD_ENV);
|
reborn_set_log(-1);
|
||||||
|
|
||||||
// Show Crash Log
|
// Show Crash Log
|
||||||
if (is_crash && !reborn_is_headless()) {
|
if (is_crash && !reborn_is_headless()) {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string get_logs_folder();
|
||||||
void setup_logger();
|
void setup_logger();
|
||||||
void show_report(const char *log_filename);
|
void show_report(const char *log_filename);
|
@ -24,47 +24,11 @@ static void setup_environment(const options_t &options) {
|
|||||||
bind_to_env(_MCPI_FORCE_HEADLESS_ENV, options.force_headless);
|
bind_to_env(_MCPI_FORCE_HEADLESS_ENV, options.force_headless);
|
||||||
bind_to_env(_MCPI_FORCE_NON_HEADLESS_ENV, options.force_non_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
|
// Configure PATH
|
||||||
{
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup MCPI_HOME
|
// Setup MCPI_HOME
|
||||||
const char *custom_profile_directory = getenv(MCPI_PROFILE_DIRECTORY_ENV);
|
setup_home();
|
||||||
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);
|
|
||||||
}
|
|
||||||
// Create If Needed
|
// 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 = std::string(getenv(_MCPI_HOME_ENV)) + get_home_subdirectory_for_game_data();
|
||||||
ensure_directory(minecraft_folder.c_str());
|
ensure_directory(minecraft_folder.c_str());
|
||||||
|
@ -12,8 +12,9 @@ Frame::Frame(const char *title, const int width, const int height) {
|
|||||||
// Create Window
|
// Create Window
|
||||||
init_glfw();
|
init_glfw();
|
||||||
window = create_glfw_window(title, width, height);
|
window = create_glfw_window(title, width, height);
|
||||||
// V-Sync
|
// Disable V-Sync
|
||||||
glfwSwapInterval(1);
|
// (On Wayland, This Fixes Issues With The Clipboard)
|
||||||
|
glfwSwapInterval(0);
|
||||||
// Setup ImGui Context
|
// Setup ImGui Context
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
@ -26,9 +27,11 @@ Frame::Frame(const char *title, const int width, const int height) {
|
|||||||
ImGui_ImplOpenGL2_Init();
|
ImGui_ImplOpenGL2_Init();
|
||||||
}
|
}
|
||||||
Frame::~Frame() {
|
Frame::~Frame() {
|
||||||
|
// Shutdown ImGui
|
||||||
ImGui_ImplOpenGL2_Shutdown();
|
ImGui_ImplOpenGL2_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
// Cleanup GLFW
|
||||||
cleanup_glfw(window);
|
cleanup_glfw(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,3 +88,24 @@ void Frame::setup_style(const float scale) {
|
|||||||
style.ScaleAllSizes(scale);
|
style.ScaleAllSizes(scale);
|
||||||
patch_colors(style);
|
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]));
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <string>
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
// UI Frame
|
// UI Frame
|
||||||
struct Frame {
|
struct Frame {
|
||||||
Frame(const char *title, int width, int height);
|
Frame(const char *title, int width, int height);
|
||||||
virtual ~Frame();
|
virtual ~Frame();
|
||||||
|
// Prevent Copying
|
||||||
|
Frame(const Frame &) = delete;
|
||||||
|
Frame &operator=(const Frame &) = delete;
|
||||||
// Run
|
// Run
|
||||||
int run();
|
int run();
|
||||||
virtual int render() = 0;
|
virtual int render() = 0;
|
||||||
// Properties
|
|
||||||
protected:
|
protected:
|
||||||
|
// API For Sub-Classes
|
||||||
ImFont *monospace = nullptr;
|
ImFont *monospace = nullptr;
|
||||||
|
static void draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback);
|
||||||
private:
|
private:
|
||||||
|
// Properties
|
||||||
GLFWwindow *window = nullptr;
|
GLFWwindow *window = nullptr;
|
||||||
// Internal
|
// Internal Methods
|
||||||
float get_scale();
|
float get_scale();
|
||||||
void setup_style(float scale);
|
void setup_style(float scale);
|
||||||
static void patch_colors(ImGuiStyle &style);
|
static void patch_colors(ImGuiStyle &style);
|
||||||
|
46
launcher/src/util/env.cpp
Normal file
46
launcher/src/util/env.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.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);
|
||||||
|
ALLOC_CHECK(launch_directory);
|
||||||
|
home = launch_directory;
|
||||||
|
free(launch_directory);
|
||||||
|
}
|
||||||
|
// Set
|
||||||
|
set_and_print_env(_MCPI_HOME_ENV, home.c_str());
|
||||||
|
}
|
@ -8,4 +8,7 @@ void chop_last_component(std::string &str);
|
|||||||
std::string safe_realpath(const std::string &path);
|
std::string safe_realpath(const std::string &path);
|
||||||
std::string get_binary_directory();
|
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();
|
@ -28,4 +28,7 @@ std::vector<unsigned char> *run_command(const char *const command[], int *exit_s
|
|||||||
bool is_exit_status_success(int status);
|
bool is_exit_status_success(int status);
|
||||||
|
|
||||||
// Get Exit Status String
|
// 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);
|
@ -101,6 +101,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);
|
on_data(int(i), size_t(bytes_read), buf);
|
||||||
} else {
|
} else {
|
||||||
// File Descriptor No Longer Accessible
|
// File Descriptor No Longer Accessible
|
||||||
|
if (poll_fd.fd == STDIN_FILENO) {
|
||||||
|
// This Shouldn't Happen
|
||||||
|
IMPOSSIBLE();
|
||||||
|
}
|
||||||
poll_fd.events = 0;
|
poll_fd.events = 0;
|
||||||
open_fds--;
|
open_fds--;
|
||||||
}
|
}
|
||||||
@ -186,3 +190,14 @@ bool is_exit_status_success(const int status) {
|
|||||||
return false;
|
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());
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,7 @@ int reborn_get_log_fd() {
|
|||||||
void reborn_set_log(const int fd) {
|
void reborn_set_log(const int fd) {
|
||||||
// Set Variable
|
// Set Variable
|
||||||
log_fd = -1;
|
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
|
// Debug Logging
|
||||||
|
@ -2,8 +2,4 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define CHANGELOG_FILE "CHANGELOG.md"
|
#define CHANGELOG_FILE "CHANGELOG.md"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void open_url(const std::string &url);
|
|
||||||
}
|
|
@ -9,7 +9,6 @@
|
|||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
|
|
||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
#include <SDL/SDL.h>
|
|
||||||
#include <media-layer/core.h>
|
#include <media-layer/core.h>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
@ -209,7 +208,7 @@ static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injectio
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// Read File
|
// Read File
|
||||||
std::streamoff len = stream.tellg();
|
const std::streamoff len = stream.tellg();
|
||||||
char *buf = new char[len];
|
char *buf = new char[len];
|
||||||
ALLOC_CHECK(buf);
|
ALLOC_CHECK(buf);
|
||||||
stream.seekg(0, std::ifstream::beg);
|
stream.seekg(0, std::ifstream::beg);
|
||||||
|
@ -38,29 +38,6 @@ static std::string extra_version_info =
|
|||||||
;
|
;
|
||||||
static std::string extra_version_info_full = !extra_version_info.empty() ? (" (" + extra_version_info + ")") : "";
|
static std::string extra_version_info_full = !extra_version_info.empty() ? (" (" + extra_version_info + ")") : "";
|
||||||
|
|
||||||
// Profile Directory
|
|
||||||
static std::string profile_directory_suffix =
|
|
||||||
#ifdef MCPI_IS_FLATPAK_BUILD
|
|
||||||
"/.var/app/" MCPI_APP_ID +
|
|
||||||
#endif
|
|
||||||
std::string(get_home_subdirectory_for_game_data())
|
|
||||||
;
|
|
||||||
static std::string get_profile_directory_url() {
|
|
||||||
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://") + directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info Data
|
// Info Data
|
||||||
struct info_line {
|
struct info_line {
|
||||||
std::string (*get_text)();
|
std::string (*get_text)();
|
||||||
@ -80,7 +57,7 @@ static info_line info[] = {
|
|||||||
.get_text = []() {
|
.get_text = []() {
|
||||||
return std::string("Profile Directory");
|
return std::string("Profile Directory");
|
||||||
},
|
},
|
||||||
.button_url = get_profile_directory_url(),
|
.button_url = std::string("file://") + home_get(),
|
||||||
.button_text = "Open"
|
.button_text = "Open"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -157,17 +134,6 @@ static void position_info(Font *font, const int width, const int height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create VTable
|
// Create VTable
|
||||||
struct InfoScreen final : CustomScreen {
|
struct InfoScreen final : CustomScreen {
|
||||||
// Buttons
|
// Buttons
|
||||||
|
@ -59,8 +59,7 @@ run_build() {
|
|||||||
"libxinerama-dev:$1" \
|
"libxinerama-dev:$1" \
|
||||||
"libxrandr-dev:$1" \
|
"libxrandr-dev:$1" \
|
||||||
"libxext-dev:$1" \
|
"libxext-dev:$1" \
|
||||||
`# Zenity Dependencies` \
|
`# QEMU Dependencies` \
|
||||||
"libgtk-3-dev:$1" \
|
|
||||||
"libglib2.0-dev:$1" \
|
"libglib2.0-dev:$1" \
|
||||||
`# AppStream Verification` \
|
`# AppStream Verification` \
|
||||||
appstream
|
appstream
|
||||||
|
Loading…
Reference in New Issue
Block a user