Add Welcome Screen

This commit is contained in:
TheBrokenRail 2024-05-21 19:16:19 -04:00
parent 3088a13725
commit 0e44bb5f06
10 changed files with 184 additions and 6 deletions

View File

@ -78,5 +78,8 @@ mcpi_option(APP_TITLE "App Title" STRING "${DEFAULT_APP_TITLE}")
# Skin Server # Skin Server
mcpi_option(SKIN_SERVER "Skin Server" STRING "https://raw.githubusercontent.com/MCPI-Revival/Skins/data") mcpi_option(SKIN_SERVER "Skin Server" STRING "https://raw.githubusercontent.com/MCPI-Revival/Skins/data")
# Discord Invite # Discord Invite URL
mcpi_option(DISCORD_INVITE "Discord Invite URL" STRING "https://discord.gg/mcpi-revival-740287937727561779") mcpi_option(DISCORD_INVITE "Discord Invite URL" STRING "https://discord.gg/mcpi-revival-740287937727561779")
# Documentation URL
mcpi_option(DOCUMENTATION "Documentation URL" STRING "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/")

View File

@ -66,4 +66,5 @@ TRUE Display Date In Select World Screen
TRUE Optimized Chunk Sorting TRUE Optimized Chunk Sorting
TRUE Fix Held Item Caching TRUE Fix Held Item Caching
TRUE Add Reborn Info To Options TRUE Add Reborn Info To Options
FALSE Track FPS FALSE Track FPS
TRUE Add Welcome Screen

View File

@ -15,3 +15,4 @@
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@" #cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
#cmakedefine MCPI_USE_QEMU #cmakedefine MCPI_USE_QEMU
#cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@" #cmakedefine MCPI_DISCORD_INVITE "@MCPI_DISCORD_INVITE@"
#cmakedefine MCPI_DOCUMENTATION "@MCPI_DOCUMENTATION@"

View File

@ -94,6 +94,7 @@ else()
# title-screen # title-screen
src/title-screen/title-screen.cpp src/title-screen/title-screen.cpp
src/title-screen/splashes.txt # Show In IDE src/title-screen/splashes.txt # Show In IDE
src/title-screen/welcome.cpp
# skin # skin
src/skin/skin.cpp src/skin/skin.cpp
src/skin/loader.cpp src/skin/loader.cpp

View File

@ -0,0 +1,9 @@
#pragma once
#include <string>
#define CHANGELOG_FILE "CHANGELOG.md"
extern "C" {
void open_url(const std::string &url);
}

View File

@ -4,6 +4,7 @@
#include <mods/touch/touch.h> #include <mods/touch/touch.h>
#include <mods/misc/misc.h> #include <mods/misc/misc.h>
#include <mods/options/info.h>
#include "options-internal.h" #include "options-internal.h"
@ -63,7 +64,7 @@ static info_line info[] = {
.get_text = []() { .get_text = []() {
return std::string("Version: v") + reborn_get_version() + extra_version_info_full; return std::string("Version: v") + reborn_get_version() + extra_version_info_full;
}, },
.button_url = "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md", .button_url = MCPI_DOCUMENTATION CHANGELOG_FILE,
.button_text = "Changelog" .button_text = "Changelog"
}, },
{ {
@ -77,7 +78,7 @@ static info_line info[] = {
.get_text = []() { .get_text = []() {
return std::string("Sound Data: ") + info_sound_data_state; return std::string("Sound Data: ") + info_sound_data_state;
}, },
.button_url = "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/SOUND.md", .button_url = MCPI_DOCUMENTATION "SOUND.md",
.button_text = "More Info" .button_text = "More Info"
}, },
}; };
@ -148,7 +149,7 @@ static void position_info(Font *font, int width, int height) {
} }
// Open URL // Open URL
static void open_url(const std::string &url) { void open_url(const std::string &url) {
int return_code; int return_code;
const char *command[] = {"xdg-open", url.c_str(), nullptr}; const char *command[] = {"xdg-open", url.c_str(), nullptr};
char *output = run_command(command, &return_code, nullptr); char *output = run_command(command, &return_code, nullptr);

View File

@ -0,0 +1,3 @@
#pragma once
__attribute__((visibility("internal"))) void _init_welcome();

View File

@ -11,6 +11,8 @@
#include <mods/touch/touch.h> #include <mods/touch/touch.h>
#include <mods/title-screen/title-screen.h> #include <mods/title-screen/title-screen.h>
#include "title-screen-internal.h"
// Improved Title Screen Background // Improved Title Screen Background
static void StartMenuScreen_render_Screen_renderBackground_injection(Screen *screen) { static void StartMenuScreen_render_Screen_renderBackground_injection(Screen *screen) {
// Draw // Draw
@ -165,4 +167,9 @@ void init_title_screen() {
// Init Random // Init Random
srand(time(nullptr)); srand(time(nullptr));
} }
// Init Welcome Screen
if (feature_has("Add Welcome Screen", server_disabled)) {
_init_welcome();
}
} }

View File

@ -0,0 +1,150 @@
#include <fstream>
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/home/home.h>
#include <mods/touch/touch.h>
#include <mods/options/info.h>
#include "title-screen-internal.h"
// Constants
static std::string line1 = "Welcome to " MCPI_APP_BASE_TITLE " v" MCPI_VERSION "!";
static int line_height = 8;
static int button_width = 120;
static int button_height = 24;
static int line_padding = 28;
static int button_padding = 4;
// Track Whether To Show Screen
static std::string get_tracker_file() {
return std::string(home_get()) + "/.welcome-tracker";
}
static bool should_show_welcome() {
// Open File
std::ifstream stream(get_tracker_file());
if (!stream) {
return true;
}
// Read Line
std::string line;
std::getline(stream, line);
bool invalid = line != MCPI_VERSION;
// Close File
stream.close();
// Return
return invalid;
}
static void mark_welcome_as_shown() {
// Open File
std::ofstream stream(get_tracker_file());
if (!stream) {
return;
}
// Write
stream << MCPI_VERSION << std::endl;
// Close File
stream.close();
}
// Position GUI
static Button *getting_started;
static Button *changelog;
static Button *proceed;
static int text_y;
static void position_screen(int width, int height) {
// Width/Height
getting_started->width = changelog->width = proceed->width = button_width;
getting_started->height = changelog->height = proceed->height = button_height;
// X
proceed->x = (width / 2) - (button_width / 2);
getting_started->x = (width / 2) - button_padding - button_width;
changelog->x = (width / 2) + button_padding;
// Y
text_y = 0;
getting_started->y = changelog->y = line_height + line_padding;
proceed->y = getting_started->y + button_height + (button_padding * 2);
// Center
int content_height = proceed->y + proceed->height;
int y_offset = (height - content_height) / 2;
text_y += y_offset;
getting_started->y += y_offset;
changelog->y += y_offset;
proceed->y += y_offset;
}
// Welcome Screen
CUSTOM_VTABLE(welcome_screen, Screen) {
// Init
vtable->init = [](__attribute__((unused)) Screen *self) {
// Buttons
getting_started = touch_create_button(0, "Getting Started");
changelog = touch_create_button(1, "Changelog");
proceed = touch_create_button(2, "Proceed");
for (Button *button : {getting_started, changelog, proceed}) {
self->rendered_buttons.push_back(button);
self->selectable_buttons.push_back(button);
}
};
// Rendering
static Screen_render_t original_render = vtable->render;
vtable->render = [](Screen *self, int x, int y, float param_1) {
// Background
self->renderBackground();
// Call Original Method
original_render(self, x, y, param_1);
// Text
self->drawCenteredString(self->font, &line1, self->width / 2, text_y, 0xFFFFFFFF);
};
// Positioning
vtable->setupPositions = [](Screen *self) {
position_screen(self->width, self->height);
};
// Cleanup
vtable->removed = [](Screen *self) {
for (Button *button : self->rendered_buttons) {
button->destructor_deleting();
}
};
// Handle Button Click
vtable->buttonClicked = [](Screen *self, Button *button) {
if (button == getting_started) {
open_url(MCPI_DOCUMENTATION "GETTING_STARTED.md");
} else if (button == changelog) {
open_url(MCPI_DOCUMENTATION CHANGELOG_FILE);
} else if (button == proceed) {
mark_welcome_as_shown();
self->minecraft->screen_chooser.setScreen(1);
}
};
}
static Screen *create_welcome_screen() {
// Allocate
Screen *screen = new Screen;
ALLOC_CHECK(screen);
screen->constructor();
// Set VTable
screen->vtable = get_welcome_screen_vtable();
// Return
return screen;
}
// Show Welcome Screen
static void NinecraftApp_init_ScreenChooser_setScreen_injection(ScreenChooser *self, int id) {
if (should_show_welcome()) {
// Show Welcome Screen
self->minecraft->setScreen(create_welcome_screen());
} else {
// Show Start Screen
self->setScreen(id);
}
}
// Init
void _init_welcome() {
// Hijack Start Screen
overwrite_call((void *) 0x14a34, (void *) NinecraftApp_init_ScreenChooser_setScreen_injection);
}

View File

@ -1 +1,3 @@
method void setScreen(uint id) = 0x29490; method void setScreen(uint id) = 0x29490;
property Minecraft *minecraft = 0x0;