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
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")
# Documentation URL
mcpi_option(DOCUMENTATION "Documentation URL" STRING "https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/")

View File

@ -67,3 +67,4 @@ TRUE Optimized Chunk Sorting
TRUE Fix Held Item Caching
TRUE Add Reborn Info To Options
FALSE Track FPS
TRUE Add Welcome Screen

View File

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

View File

@ -94,6 +94,7 @@ else()
# title-screen
src/title-screen/title-screen.cpp
src/title-screen/splashes.txt # Show In IDE
src/title-screen/welcome.cpp
# skin
src/skin/skin.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/misc/misc.h>
#include <mods/options/info.h>
#include "options-internal.h"
@ -63,7 +64,7 @@ static info_line info[] = {
.get_text = []() {
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"
},
{
@ -77,7 +78,7 @@ static info_line info[] = {
.get_text = []() {
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"
},
};
@ -148,7 +149,7 @@ static void position_info(Font *font, int width, int height) {
}
// Open URL
static void open_url(const std::string &url) {
void open_url(const std::string &url) {
int return_code;
const char *command[] = {"xdg-open", url.c_str(), 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/title-screen/title-screen.h>
#include "title-screen-internal.h"
// Improved Title Screen Background
static void StartMenuScreen_render_Screen_renderBackground_injection(Screen *screen) {
// Draw
@ -165,4 +167,9 @@ void init_title_screen() {
// Init Random
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;
property Minecraft *minecraft = 0x0;