Basic About

This commit is contained in:
TheBrokenRail 2025-01-03 05:36:28 -05:00
parent 9428a5a1e1
commit c5f9a519c5
20 changed files with 246 additions and 76 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 TheBrokenRail
Copyright (c) 2025 TheBrokenRail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -35,17 +35,17 @@ execute_process(
"${CMAKE_COMMAND}" "-E" "env"
"ARCH=${APPIMAGE_ARCH}"
"appimagetool"
"--updateinformation" "zsync|https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases/download/latest/${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync"
"--updateinformation" "zsync|${CPACK_MCPI_REPO}/releases/download/latest/${CPACK_PACKAGE_FILE_NAME_ZSYNC}${CPACK_MCPI_APPIMAGE_ZSYNC_EXT}"
"--runtime-file" "${RUNTIME}"
"--comp" "xz"
"${CPACK_TEMPORARY_DIRECTORY}"
"${CPACK_PACKAGE_FILE_NAME}.AppImage"
"${CPACK_PACKAGE_FILE_NAME}${CPACK_MCPI_APPIMAGE_EXT}"
WORKING_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}"
COMMAND_ERROR_IS_FATAL ANY
)
# Rename ZSync File
file(RENAME "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}.AppImage.zsync" "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync")
file(RENAME "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_MCPI_APPIMAGE_ZSYNC_EXT}" "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME_ZSYNC}${CPACK_MCPI_APPIMAGE_ZSYNC_EXT}")
# Summary Message
function(check_file name)
@ -55,5 +55,5 @@ function(check_file name)
message(FATAL_ERROR "Missing File: ${name}")
endif()
endfunction()
check_file("${CPACK_PACKAGE_FILE_NAME}.AppImage")
check_file("${CPACK_PACKAGE_FILE_NAME_ZSYNC}.AppImage.zsync")
check_file("${CPACK_PACKAGE_FILE_NAME}${CPACK_MCPI_APPIMAGE_EXT}")
check_file("${CPACK_PACKAGE_FILE_NAME_ZSYNC}${CPACK_MCPI_APPIMAGE_ZSYNC_EXT}")

View File

@ -1,25 +1,10 @@
# Determine Architecture
set(CPACK_MCPI_ARCH "unknown")
include(CheckSymbolExists)
function(check_arch symbol name)
set(CMAKE_REQUIRED_QUIET TRUE)
check_symbol_exists("${symbol}" "" "IS_ARCH_${name}")
unset(CMAKE_REQUIRED_QUIET)
if("${IS_ARCH_${name}}")
set(CPACK_MCPI_ARCH "${name}" PARENT_SCOPE)
endif()
endfunction()
check_arch("__arm__" "armhf")
check_arch("__aarch64__" "arm64")
check_arch("__x86_64__" "amd64")
# CPack
set(CPACK_PACKAGE_NAME "${MCPI_VARIANT_NAME}")
set(CPACK_PACKAGE_VENDOR "TheBrokenRail & Mojang AB")
set(CPACK_PACKAGE_NAME "${MCPI_APP_NAME}")
set(CPACK_PACKAGE_VENDOR "${MCPI_AUTHOR} & Mojang AB")
set(CPACK_VERBATIM_VARIABLES TRUE)
set(CPACK_MONOLITHIC_INSTALL TRUE)
set(CPACK_PACKAGE_FILE_NAME "${MCPI_VARIANT_NAME}-${MCPI_VERSION}-${CPACK_MCPI_ARCH}")
set(CPACK_PACKAGE_FILE_NAME_ZSYNC "${MCPI_VARIANT_NAME}-latest-${CPACK_MCPI_ARCH}")
get_package_file_name(CPACK_PACKAGE_FILE_NAME "${MCPI_VERSION}")
get_package_file_name(CPACK_PACKAGE_FILE_NAME_ZSYNC "latest")
# Version
string(REPLACE "." ";" VERSION_LIST "${MCPI_VERSION}")
@ -32,6 +17,14 @@ if(MCPI_IS_APPIMAGE_BUILD)
set(CPACK_GENERATOR "External")
set(CPACK_EXTERNAL_ENABLE_STAGING TRUE)
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/appimage.cmake")
# Pass Variable To CPack
macro(pass_to_cpack var)
set("CPACK_MCPI_${var}" "${MCPI_${var}}")
endmacro()
pass_to_cpack(ARCH)
pass_to_cpack(REPO)
pass_to_cpack(APPIMAGE_EXT)
pass_to_cpack(APPIMAGE_ZSYNC_EXT)
endif()
# Package

View File

View File

@ -29,13 +29,9 @@ else()
set(BUILD_MEDIA_LAYER_CORE "${BUILD_ARM_COMPONENTS}")
endif()
# Specify Variant Name
set(MCPI_VARIANT_NAME "minecraft-pi-reborn")
# App ID
# App Information
mcpi_option(APP_NAME "App Name" STRING "minecraft-pi-reborn")
mcpi_option(APP_ID "App ID" STRING "com.thebrokenrail.MCPIReborn")
# App Title
mcpi_option(APP_TITLE "App Title" STRING "Minecraft: Pi Edition: Reborn")
# Skin Server
@ -53,5 +49,41 @@ set_property(
file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/../../VERSION" MCPI_VERSION)
file(TIMESTAMP "${CMAKE_CURRENT_LIST_DIR}/../../VERSION" MCPI_VERSION_DATE "%Y-%m-%d" UTC)
# Author
mcpi_option(AUTHOR "Author" STRING "TheBrokenRail")
# Homepage
mcpi_option(REPO_HOST "Repository Host" STRING "https://gitea.thebrokenrail.com")
mcpi_option(REPO_PATH "Repository Path" STRING "minecraft-pi-reborn/minecraft-pi-reborn")
mcpi_option(REPO "Repository URL" STRING "${MCPI_REPO_HOST}/${MCPI_REPO_PATH}")
# Documentation URL
mcpi_option(DOCUMENTATION "Documentation URL" STRING "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/tag/${MCPI_VERSION}/docs/")
mcpi_option(DOCS "Documentation URL" STRING "${MCPI_REPO}/src/tag/${MCPI_VERSION}/docs/")
# Packaging
set(MCPI_ARCH "unknown")
include(CheckSymbolExists)
function(check_arch symbol name)
set(CMAKE_REQUIRED_QUIET TRUE)
check_symbol_exists("${symbol}" "" "IS_ARCH_${name}")
unset(CMAKE_REQUIRED_QUIET)
if("${IS_ARCH_${name}}")
set(MCPI_ARCH "${name}" PARENT_SCOPE)
endif()
endfunction()
check_arch("__arm__" "armhf")
check_arch("__aarch64__" "arm64")
check_arch("__x86_64__" "amd64")
macro(get_package_file_name out version)
set("${out}" "${MCPI_APP_NAME}-${version}-${MCPI_ARCH}")
endmacro()
# AppImage
if(MCPI_IS_APPIMAGE_BUILD)
mcpi_option(APPIMAGE_EXT "AppImage Extension" STRING ".AppImage")
mcpi_option(APPIMAGE_ZSYNC_EXT "AppImage Update Extension" STRING "${MCPI_APPIMAGE_EXT}.zsync")
mcpi_option(APPIMAGE_JSON_URL "AppImage Update Checker URL" STRING "${MCPI_REPO_HOST}/api/v1/repos/${MCPI_REPO_PATH}/releases/latest")
mcpi_option(APPIMAGE_VERSION_PLACEHOLDER "Version Placeholder In AppImage Download URL" STRING "%VERSION%")
get_package_file_name(appimage_package_file_name "${MCPI_APPIMAGE_VERSION_PLACEHOLDER}")
mcpi_option(APPIMAGE_DOWNLOAD_URL "AppImage Download URL" STRING "${MCPI_REPO}/releases/download/${MCPI_APPIMAGE_VERSION_PLACEHOLDER}/${appimage_package_file_name}${MCPI_APPIMAGE_EXT}")
endif()

View File

@ -1,5 +1,5 @@
# Specify Installation Paths
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
set(MCPI_INSTALL_DIR "lib/${MCPI_APP_NAME}")
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
set(MCPI_LEGAL_DIR "${MCPI_INSTALL_DIR}/legal") # For Software Licenses
set(MCPI_SDK_DIR "${MCPI_INSTALL_DIR}/sdk")

@ -1 +1 @@
Subproject commit f5f11e94be35078c3bbb5196f55269f88634b9bd
Subproject commit 6982ce43f5b143c5dce5fab0ce07dd4867b705ae

View File

@ -19,6 +19,7 @@ add_executable(launcher
src/client/configuration.cpp
src/client/cache.cpp
src/client/ui.cpp
src/updater/updater.cpp
)
target_link_libraries(launcher
reborn-util
@ -34,7 +35,7 @@ target_compile_definitions(launcher PRIVATE _FILE_OFFSET_BITS=64)
# Install
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
install_symlink("../${MCPI_INSTALL_DIR}/launcher" "bin/${MCPI_VARIANT_NAME}")
install_symlink("../${MCPI_INSTALL_DIR}/launcher" "bin/${MCPI_APP_NAME}")
# Install Desktop Entry
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
@ -42,7 +43,7 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/launcher.desktop"
"Name=${MCPI_APP_TITLE}\n"
"Comment=Fun with Blocks\n"
"Icon=${MCPI_APP_ID}\n"
"Exec=${MCPI_VARIANT_NAME}\n"
"Exec=${MCPI_APP_NAME}\n"
"Type=Application\n"
"Categories=Game;\n"
)
@ -69,13 +70,13 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
" <p>Minecraft: Pi Edition Modding Project.</p>\n"
" <p>NOTE: This is not verified by, affiliated with, or supported by Mojang or Microsoft.</p>\n"
" </description>\n"
" <url type=\"homepage\">https://gitea.thebrokenrail.com/TheBrokenRail/minecraft-pi-reborn</url>\n"
" <url type=\"homepage\">${MCPI_REPO}</url>\n"
" <launchable type=\"desktop-id\">${MCPI_APP_ID}.desktop</launchable>\n"
" <provides>\n"
" <id>com.thebrokenrail.MCPIRebornClient.desktop</id>\n"
" <id>${MCPI_APP_ID}.desktop</id>\n"
" </provides>\n"
" <project_license>LicenseRef-proprietary</project_license>\n"
" <developer_name>TheBrokenRail &amp; Mojang AB</developer_name>\n"
" <developer_name>${MCPI_AUTHOR} &amp; Mojang AB</developer_name>\n"
" <content_rating type=\"oars-1.0\">\n"
" <content_attribute id=\"violence-cartoon\">moderate</content_attribute>\n"
" <content_attribute id=\"violence-fantasy\">none</content_attribute>\n"
@ -103,7 +104,7 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/appstream.xml"
" </releases>\n"
" <screenshots>\n"
" <screenshot type=\"default\">\n"
" <image>https://gitea.thebrokenrail.com/TheBrokenRail/minecraft-pi-reborn/raw/branch/master/images/start.png</image>\n"
" <image>${MCPI_REPO}/raw/branch/master/images/start.png</image>\n"
" </screenshot>\n"
" </screenshots>\n"
"</component>\n"
@ -116,6 +117,8 @@ install(
# AppImage
if(MCPI_IS_APPIMAGE_BUILD)
install_symlink("bin/${MCPI_VARIANT_NAME}" "AppRun")
install_symlink("bin/${MCPI_APP_NAME}" "AppRun")
install_symlink("${MCPI_SHARE_DIR}/applications/${MCPI_APP_ID}.desktop" "${MCPI_APP_ID}.desktop")
# Updater
target_sources(launcher PRIVATE src/updater/appimage.cpp)
endif()

View File

@ -30,16 +30,9 @@ void print_debug_information() {
DEBUG("Reborn Version: v%s", MCPI_VERSION);
// Architecture
const char *arch =
#ifdef __x86_64__
"AMD64"
#elif defined(__aarch64__)
"ARM64"
#elif defined(__arm__)
"ARM32"
#else
"Unknown"
#endif
;
DEBUG("Reborn Target Architecture: %s", arch);
std::string arch = MCPI_ARCH;
for (char &c : arch) {
c = char(std::toupper(c));
}
DEBUG("Reborn Target Architecture: %s", arch.c_str());
}

View File

@ -43,6 +43,10 @@ private:
// Server List
void draw_servers() const;
void draw_server_list() const;
// About
static void draw_centered_text(const std::string &str);
static void draw_links(const std::vector<std::pair<std::string, std::string>> &links);
static void draw_about();
// State
const State original_state;
State &state;

View File

@ -1,9 +1,13 @@
#include <vector>
#include <limits>
#include <ranges>
#include <libreborn/util/util.h>
#include <libreborn/config.h>
#include <libreborn/util/exec.h>
#include "configuration.h"
#include "../updater/updater.h"
#include <imgui_stdlib.h>
@ -43,6 +47,11 @@ int ConfigurationUI::render() {
draw_servers();
ImGui::EndTabItem();
}
// About Tab
if (ImGui::BeginTabItem("About")) {
draw_about();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
@ -248,3 +257,44 @@ void ConfigurationUI::draw_server_list() const {
}
}
}
// About
void ConfigurationUI::draw_centered_text(const std::string &str) {
const float width = ImGui::GetWindowSize().x;
const float text_width = ImGui::CalcTextSize(str.c_str()).x;
ImGui::SetCursorPosX((width - text_width) / 2.0f);
ImGui::Text("%s", str.c_str());
}
void ConfigurationUI::draw_links(const std::vector<std::pair<std::string, std::string>> &links) {
std::vector<const char *> buttons;
for (const std::string &text : links | std::views::keys) {
buttons.push_back(text.c_str());
}
draw_right_aligned_buttons(buttons, [&links](const int id, const bool was_clicked) {
if (was_clicked) {
open_url(links[id].second);
}
}, true);
}
void ConfigurationUI::draw_about() {
// Text
draw_centered_text("By " MCPI_AUTHOR);
draw_centered_text("Version " MCPI_VERSION);
// Links
ImGui::Separator();
draw_links({
{"Home", MCPI_REPO},
{"Changelog", MCPI_DOCS_CHANGELOG},
{"Credits", MCPI_DOCS "CREDITS.md"}
});
// Updater
Updater *updater = Updater::instance;
if (updater) {
ImGui::Separator();
draw_right_aligned_buttons({updater->get_status().c_str()}, [&updater](__attribute__((unused)) int id, const bool was_clicked) {
if (was_clicked) {
updater->start();
}
}, true);
}
}

View File

@ -107,7 +107,7 @@ float Frame::get_frame_width(const char *str) {
const ImGuiStyle &style = ImGui::GetStyle();
return ImGui::CalcTextSize(str).x + style.FramePadding.x * 2.0f;
}
void Frame::draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback) {
void Frame::draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback, const bool should_actually_center) {
// Calculate Position
const ImGuiStyle &style = ImGui::GetStyle();
float width_needed = 0;
@ -117,7 +117,14 @@ void Frame::draw_right_aligned_buttons(const std::vector<const char *> &buttons,
}
width_needed += get_frame_width(text);
}
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - width_needed);
float cursor_pos;
if (should_actually_center) {
cursor_pos = ImGui::GetWindowSize().x - width_needed;
cursor_pos /= 2.0f;
} else {
cursor_pos = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - width_needed;
}
ImGui::SetCursorPosX(cursor_pos);
// Draw
for (std::vector<const char *>::size_type id = 0; id < buttons.size(); id++) {
if (id > 0) {

View File

@ -20,7 +20,7 @@ protected:
// API For Sub-Classes
ImFont *monospace = nullptr;
static float get_frame_width(const char *str);
static void draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback);
static void draw_right_aligned_buttons(const std::vector<const char *> &buttons, const std::function<void(int, bool)> &callback, bool should_actually_center = false);
static constexpr const char *quit_text = "Quit";
private:
// Properties

View File

View File

@ -0,0 +1,46 @@
#include <pthread.h>
#include <libreborn/log.h>
#include "updater.h"
// Instance
Updater *Updater::instance = nullptr;
Updater::Updater() {
instance = this;
}
// Check Status
bool Updater::can_start() const {
return status == NOT_STARTED || status == RESTART_NEEDED;
}
std::string Updater::get_status() const {
switch (status) {
case NOT_STARTED: return "Update";
case RESTART_NEEDED: return "Restart!";
case CHECKING: return "Checking...";
case UP_TO_DATE: return "Up-To-Date";
case DOWNLOADING: return "Downloading...";
default: return "";
}
}
// Run
static void *update_thread(void *data) {
Updater *updater = (Updater *) data;
updater->update();
return nullptr;
}
void Updater::start() {
switch (status) {
case NOT_STARTED: {
pthread_t thread;
pthread_create(&thread, nullptr, update_thread, this);
break;
}
case RESTART_NEEDED: {
restart();
break;
}
default: IMPOSSIBLE();
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <string>
// Update Status
enum UpdateStatus {
NOT_STARTED,
CHECKING,
UP_TO_DATE,
DOWNLOADING,
RESTART_NEEDED
};
// Updater
struct Updater {
// Instance
static Updater *instance;
// Constructor
Updater();
virtual ~Updater() = default;
// Implementation
virtual void update() = 0;
virtual void restart() = 0;
// Methods
[[nodiscard]] std::string get_status() const;
[[nodiscard]] bool can_start() const;
void start();
// Properties
UpdateStatus status = NOT_STARTED;
};

View File

@ -1,16 +1,37 @@
#pragma once
#cmakedefine MCPI_IS_APPIMAGE_BUILD
#cmakedefine MCPI_IS_FLATPAK_BUILD
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
// General
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
#cmakedefine MCPI_AUTHOR "@MCPI_AUTHOR@"
#cmakedefine MCPI_ARCH "@MCPI_ARCH@"
// App Information
#cmakedefine MCPI_APP_TITLE "@MCPI_APP_TITLE@"
#cmakedefine MCPI_APP_ID "@MCPI_APP_ID@"
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
#cmakedefine MCPI_APP_NAME "@MCPI_APP_NAME@"
// Extra Options
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"
#cmakedefine MCPI_DOCUMENTATION "@MCPI_DOCUMENTATION@"
#cmakedefine MCPI_REPO "@MCPI_REPO@"
// Documentation
#cmakedefine MCPI_DOCS "@MCPI_DOCUMENTATION@"
#define MCPI_DOCS_CHANGELOG MCPI_DOCS "CHANGELOG.md"
#define MCPI_DOCS_GETTING_STARTED MCPI_DOCS "GETTING_STARTED.md"
// Internal
#cmakedefine MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
// AppImage
#cmakedefine MCPI_IS_APPIMAGE_BUILD
#cmakedefine MCPI_APPIMAGE_JSON_URL "@MCPI_APPIMAGE_JSON_URL@"
#cmakedefine MCPI_APPIMAGE_VERSION_PLACEHOLDER "@MCPI_APPIMAGE_VERSION_PLACEHOLDER@"
#cmakedefine MCPI_APPIMAGE_DOWNLOAD_URL "@MCPI_APPIMAGE_DOWNLOAD_URL@"
// Flatpak
#cmakedefine MCPI_IS_FLATPAK_BUILD
// Access Configuration At Runtime
const char *reborn_get_version();

View File

@ -1,5 +0,0 @@
#pragma once
#include <string>
#define CHANGELOG_FILE "CHANGELOG.md"

View File

@ -1,14 +1,11 @@
#include <libreborn/log.h>
#include <libreborn/util/exec.h>
#include <libreborn/config.h>
#include <libreborn/util/util.h>
#include <symbols/minecraft.h>
#include <GLES/gl.h>
#include <mods/touch/touch.h>
#include <mods/misc/misc.h>
#include <mods/options/info.h>
#include <mods/extend/extend.h>
#include "options-internal.h"
@ -53,7 +50,7 @@ static info_line info[] = {
.get_text = []() {
return std::string("Version: v") + reborn_get_version() + extra_version_info_full;
},
.button_url = MCPI_DOCUMENTATION CHANGELOG_FILE,
.button_url = MCPI_DOCS_CHANGELOG,
.button_text = "Changelog"
},
{
@ -67,7 +64,7 @@ static info_line info[] = {
.get_text = []() {
return std::string("Sound Data: ") + info_sound_data_state;
},
.button_url = MCPI_DOCUMENTATION "GETTING_STARTED.md#sound",
.button_url = MCPI_DOCS_GETTING_STARTED "#sound",
.button_text = "More Info"
},
};

View File

@ -8,7 +8,6 @@
#include <symbols/minecraft.h>
#include <mods/touch/touch.h>
#include <mods/options/info.h>
#include <mods/misc/misc.h>
#include <mods/extend/extend.h>
@ -115,9 +114,9 @@ struct WelcomeScreen final : CustomScreen {
// Handle Button Click
void buttonClicked(Button *button) override {
if (button == getting_started) {
open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md");
open_url(MCPI_DOCS_GETTING_STARTED);
} else if (button == changelog) {
open_url(MCPI_DOCUMENTATION CHANGELOG_FILE);
open_url(MCPI_DOCS_CHANGELOG);
} else if (button == proceed) {
mark_welcome_as_shown();
self->minecraft->screen_chooser.setScreen(1);