1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-27 00:34:46 +01:00

Pester users to update to latest release

This commit is contained in:
Michał Janiszewski
2020-07-21 23:22:48 +02:00
committed by Aaron van Geffen
parent 6282335873
commit 55835456a0
14 changed files with 426 additions and 5 deletions

View File

@@ -3635,6 +3635,10 @@ STR_6376 :{WINDOW_COLOUR_2}Ride vehicle:{NEWLINE}{BLACK}{STRINGID} for {STRIN
STR_6377 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} for {STRINGID}
STR_6378 :Receiving objects list: {INT32} / {INT32}
STR_6379 :Received invalid data
STR_6380 :Update available!
STR_6381 :Join OpenRCT2 Discord!
STR_6382 :Newer release of OpenRCT2 is available: {STRING}!
STR_6383 :Open download page
#############
# Scenarios #

View File

@@ -135,6 +135,8 @@ public:
return window_water_open();
case WC_NETWORK:
return window_network_open();
case WC_NEW_VERSION:
return window_new_version_open();
default:
Console::Error::WriteLine("Unhandled window class (%d)", wc);
return nullptr;

View File

@@ -15,9 +15,10 @@
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/LocalisationService.h>
#include <openrct2/sprites.h>
#include <openrct2/ui/UiContext.h>
static constexpr const int32_t WW = 400;
static constexpr const int32_t WH = 350;
static constexpr const int32_t WH = 385;
static constexpr const rct_string_id WINDOW_TITLE = STR_ABOUT;
constexpr int32_t TABHEIGHT = 50;
@@ -40,6 +41,8 @@ enum WINDOW_ABOUT_WIDGET_IDX {
// About OpenRCT2
WIDX_CHANGELOG = WIDX_PAGE_START,
WIDX_JOIN_DISCORD,
WIDX_NEW_VERSION,
// About RCT2
WIDX_MUSIC_CREDITS = WIDX_PAGE_START,
@@ -53,7 +56,9 @@ enum WINDOW_ABOUT_WIDGET_IDX {
static rct_widget window_about_openrct2_widgets[] = {
WIDGETS_MAIN,
MakeWidget({100, WH - TABHEIGHT}, {200, 14}, WWT_BUTTON, 1, STR_CHANGELOG_ELLIPSIS), // changelog button
MakeWidget({100, WH - TABHEIGHT - (14 + 3) * 2}, {200, 14}, WWT_BUTTON, 1, STR_CHANGELOG_ELLIPSIS), // changelog button
MakeWidget({100, WH - TABHEIGHT - (14 + 3) * 1}, {200, 14}, WWT_BUTTON, 1, STR_JOIN_DISCORD), // "join discord" button
MakeWidget({100, WH - TABHEIGHT - (14 + 3) * 0}, {200, 14}, WWT_PLACEHOLDER, 1, STR_UPDATE_AVAILABLE), // "new version" button
{ WIDGETS_END }
};
@@ -72,12 +77,13 @@ static rct_widget *window_about_page_widgets[] = {
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_ABOUT_OPENRCT2) | (1ULL << WIDX_TAB_ABOUT_RCT2)
static uint64_t window_about_page_enabled_widgets[] = {
DEFAULT_ENABLED_WIDGETS | (1ULL << WIDX_CHANGELOG),
DEFAULT_ENABLED_WIDGETS | (1ULL << WIDX_CHANGELOG) | (1 << WIDX_JOIN_DISCORD),
DEFAULT_ENABLED_WIDGETS | (1ULL << WIDX_MUSIC_CREDITS),
};
static void window_about_openrct2_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_about_openrct2_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_about_openrct2_invalidate(rct_window *w);
static void window_about_rct2_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_about_rct2_paint(rct_window *w, rct_drawpixelinfo *dpi);
@@ -109,7 +115,7 @@ static rct_window_event_list window_about_openrct2_events = {
nullptr,
nullptr,
nullptr,
nullptr,
window_about_openrct2_invalidate,
window_about_openrct2_paint,
nullptr
};
@@ -191,9 +197,15 @@ static void window_about_openrct2_mouseup(rct_window* w, rct_widgetindex widgetI
case WIDX_TAB_ABOUT_RCT2:
window_about_set_page(w, widgetIndex - WIDX_TAB_ABOUT_OPENRCT2);
break;
case WIDX_JOIN_DISCORD:
OpenRCT2::GetContext()->GetUiContext()->OpenURL("https://discord.gg/ZXZd8D8");
break;
case WIDX_CHANGELOG:
context_open_window(WC_CHANGELOG);
break;
case WIDX_NEW_VERSION:
context_open_window(WC_NEW_VERSION);
break;
}
}
@@ -261,6 +273,16 @@ static void window_about_openrct2_paint(rct_window* w, rct_drawpixelinfo* dpi)
gfx_draw_string_centred_wrapped(dpi, &ch, aboutCoords, width, STR_STRING, w->colours[2]);
}
static void window_about_openrct2_invalidate(rct_window* w)
{
if (w->page == WINDOW_ABOUT_PAGE_OPENRCT2 && OpenRCT2::GetContext()->HasNewVersionInfo())
{
w->enabled_widgets |= (1ULL << WIDX_NEW_VERSION);
w->widgets[WIDX_NEW_VERSION].type = WWT_BUTTON;
window_about_openrct2_widgets[WIDX_NEW_VERSION].type = WWT_BUTTON;
}
}
#pragma endregion OpenRCT2
#pragma region RCT2

View File

@@ -0,0 +1,273 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <algorithm>
#include <fstream>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/PlatformEnvironment.h>
#include <openrct2/Version.h>
#include <openrct2/core/String.hpp>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/platform/platform.h>
#include <openrct2/ui/UiContext.h>
#include <openrct2/util/Util.h>
#include <vector>
using namespace OpenRCT2;
// clang-format off
enum {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_CONTENT_PANEL,
WIDX_SCROLL,
WIDX_OPEN_URL,
};
static constexpr const int32_t WW = 500;
static constexpr const int32_t WH = 400;
static constexpr const rct_string_id WINDOW_TITLE = STR_CHANGELOG_TITLE;
constexpr int32_t MIN_WW = 300;
constexpr int32_t MIN_WH = 250;
static rct_widget window_new_version_widgets[] = {
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
MakeWidget({0, 14}, {500, 382}, WWT_RESIZE, 1 ), // content panel
MakeWidget({3, 16}, {495, 366}, WWT_SCROLL, 1, SCROLL_BOTH), // scroll area
MakeWidget({3, 473}, {300, 14}, WWT_BUTTON, 1, STR_NEW_RELEASE_DOWNLOAD_PAGE), // changelog button
{ WIDGETS_END },
};
static void window_new_version_close(rct_window *w);
static void window_new_version_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_new_version_resize(rct_window *w);
static void window_new_version_scrollgetsize(rct_window *w, int32_t scrollIndex, int32_t *width, int32_t *height);
static void window_new_version_invalidate(rct_window *w);
static void window_new_version_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_new_version_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int32_t scrollIndex);
static rct_window_event_list window_new_version_events = {
window_new_version_close,
window_new_version_mouseup,
window_new_version_resize,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_new_version_scrollgetsize,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_new_version_invalidate,
window_new_version_paint,
window_new_version_scrollpaint
};
// clang-format on
static void window_new_version_process_info();
static void window_new_version_dispose_data();
static const NewVersionInfo* _newVersionInfo;
static std::vector<std::string> _changelogLines;
static int32_t _changelogLongestLineWidth = 0;
rct_window* window_new_version_open()
{
rct_window* window;
window = window_bring_to_front_by_class(WC_NEW_VERSION);
if (window != nullptr)
{
return window;
}
if (!GetContext()->HasNewVersionInfo())
{
return nullptr;
}
window_new_version_process_info();
int32_t screenWidth = context_get_width();
int32_t screenHeight = context_get_height();
window = window_create_centred(
screenWidth * 4 / 5, screenHeight * 4 / 5, &window_new_version_events, WC_NEW_VERSION, WF_RESIZABLE);
window->widgets = window_new_version_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_OPEN_URL);
window_init_scroll_widgets(window);
window->min_width = MIN_WW;
window->min_height = MIN_WH;
window->max_width = MIN_WW;
window->max_height = MIN_WH;
window->colours[0] = COLOUR_GREY;
window->colours[1] = COLOUR_LIGHT_BLUE;
window->colours[2] = COLOUR_LIGHT_BLUE;
return window;
}
static void window_new_version_close([[maybe_unused]] rct_window* w)
{
window_new_version_dispose_data();
}
static void window_new_version_mouseup(rct_window* w, rct_widgetindex widgetIndex)
{
switch (widgetIndex)
{
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_OPEN_URL:
GetContext()->GetUiContext()->OpenURL(_newVersionInfo->url);
break;
}
}
static void window_new_version_resize(rct_window* w)
{
int32_t screenWidth = context_get_width();
int32_t screenHeight = context_get_height();
w->max_width = (screenWidth * 4) / 5;
w->max_height = (screenHeight * 4) / 5;
w->min_width = MIN_WW;
w->min_height = MIN_WH;
auto download_button_width = window_new_version_widgets[WIDX_OPEN_URL].width();
window_new_version_widgets[WIDX_OPEN_URL].left = (w->width - download_button_width) / 2;
window_new_version_widgets[WIDX_OPEN_URL].right = window_new_version_widgets[WIDX_OPEN_URL].left + download_button_width;
if (w->width < w->min_width)
{
w->Invalidate();
w->width = w->min_width;
}
if (w->height < w->min_height)
{
w->Invalidate();
w->height = w->min_height;
}
}
static void window_new_version_scrollgetsize(
[[maybe_unused]] rct_window* w, [[maybe_unused]] int32_t scrollIndex, int32_t* width, int32_t* height)
{
*width = _changelogLongestLineWidth + 4;
const int32_t lineHeight = font_get_line_height(gCurrentFontSpriteBase);
*height = static_cast<int32_t>(_changelogLines.size() * lineHeight);
}
static void window_new_version_invalidate(rct_window* w)
{
window_new_version_widgets[WIDX_BACKGROUND].right = w->width - 1;
window_new_version_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
window_new_version_widgets[WIDX_TITLE].right = w->width - 2;
window_new_version_widgets[WIDX_CLOSE].left = w->width - 13;
window_new_version_widgets[WIDX_CLOSE].right = w->width - 3;
window_new_version_widgets[WIDX_CONTENT_PANEL].right = w->width - 1;
window_new_version_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1;
window_new_version_widgets[WIDX_SCROLL].right = w->width - 3;
window_new_version_widgets[WIDX_SCROLL].bottom = w->height - 22;
window_new_version_widgets[WIDX_OPEN_URL].bottom = w->height - 5;
window_new_version_widgets[WIDX_OPEN_URL].top = w->height - 19;
}
static void window_new_version_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
window_draw_widgets(w, dpi);
}
static void window_new_version_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, [[maybe_unused]] int32_t scrollIndex)
{
gCurrentFontFlags = 0;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
const int32_t lineHeight = font_get_line_height(gCurrentFontSpriteBase);
ScreenCoordsXY screenCoords(3, 3 - lineHeight);
for (auto line : _changelogLines)
{
screenCoords.y += lineHeight;
if (screenCoords.y + lineHeight < dpi->y || screenCoords.y >= dpi->y + dpi->height)
continue;
gfx_draw_string(dpi, line.c_str(), w->colours[0], screenCoords);
}
}
static void window_new_version_process_info()
{
_newVersionInfo = GetContext()->GetNewVersionInfo();
std::string::size_type pos = 0;
std::string::size_type prev = 0;
char version_info[256];
const char* version_info_ptr = _newVersionInfo->name.c_str();
format_string(version_info, 256, STR_NEW_RELEASE_VERSION_INFO, &version_info_ptr);
_changelogLines.push_back(version_info);
_changelogLines.push_back("");
while ((pos = _newVersionInfo->changelog.find("\n", prev)) != std::string::npos)
{
std::string line = _newVersionInfo->changelog.substr(prev, pos - prev);
for (char* ch = line.data(); *ch != '\0'; ch++)
{
if (utf8_is_format_code(*ch))
{
*ch = FORMAT_OUTLINE_OFF;
}
}
_changelogLines.push_back(line);
prev = pos + 1;
}
// To get the last substring (or only, if delimiter is not found)
_changelogLines.push_back(_newVersionInfo->changelog.substr(prev));
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
_changelogLongestLineWidth = 0;
for (auto line : _changelogLines)
{
auto width = gfx_get_string_width(line.c_str());
_changelogLongestLineWidth = std::max(width, _changelogLongestLineWidth);
}
}
static void window_new_version_dispose_data()
{
_changelogLines.clear();
_changelogLines.shrink_to_fit();
}

View File

@@ -209,11 +209,13 @@ static void window_title_menu_dropdown(rct_window* w, rct_widgetindex widgetInde
Editor::LoadTrackManager();
break;
case 4:
{
auto context = OpenRCT2::GetContext();
auto env = context->GetPlatformEnvironment();
auto uiContext = context->GetUiContext();
uiContext->OpenFolder(env->GetDirectoryPath(OpenRCT2::DIRBASE::USER));
break;
}
}
}
}

View File

@@ -37,6 +37,7 @@ extern bool gWindowSceneryEyedropperEnabled;
rct_window* window_about_open();
void WindowCampaignRefreshRides();
rct_window* window_changelog_open();
rct_window* window_new_version_open();
rct_window* window_cheats_open();
rct_window* window_clear_scenery_open();
rct_window* custom_currency_window_open();

View File

@@ -68,6 +68,7 @@
#include <algorithm>
#include <cmath>
#include <exception>
#include <future>
#include <iterator>
#include <memory>
#include <string>
@@ -125,6 +126,10 @@ namespace OpenRCT2
// false.
bool _finished = false;
std::future<void> _versionCheckFuture;
NewVersionInfo _newVersionInfo;
bool _hasNewVersionInfo = false;
public:
// Singleton of Context.
// Remove this when GetContext() is no longer called so that
@@ -334,6 +339,17 @@ namespace OpenRCT2
crash_init();
if (!_versionCheckFuture.valid())
{
_versionCheckFuture = std::async(std::launch::async, [this] {
_newVersionInfo = get_latest_version();
if (!String::StartsWith(gVersionInfoTag, _newVersionInfo.tag))
{
_hasNewVersionInfo = true;
}
});
}
if (gConfigGeneral.last_run_version != nullptr && String::Equals(gConfigGeneral.last_run_version, OPENRCT2_VERSION))
{
gOpenRCT2ShowChangelog = false;
@@ -1154,6 +1170,16 @@ namespace OpenRCT2
return parkData;
}
#endif
bool HasNewVersionInfo() const override
{
return _hasNewVersionInfo;
}
const NewVersionInfo* GetNewVersionInfo() const override
{
return &_newVersionInfo;
}
};
Context* Context::Instance = nullptr;

View File

@@ -28,6 +28,7 @@ struct IGameStateSnapshots;
class Intent;
struct rct_window;
using rct_windowclass = uint8_t;
struct NewVersionInfo;
struct CursorState
{
@@ -140,6 +141,8 @@ namespace OpenRCT2
virtual void Finish() abstract;
virtual void Quit() abstract;
virtual bool HasNewVersionInfo() const abstract;
virtual const NewVersionInfo* GetNewVersionInfo() const abstract;
/**
* This is deprecated, use IPlatformEnvironment.
*/

View File

@@ -9,12 +9,25 @@
#include "Version.h"
#include <string>
#include "config/Config.h"
#include "core/Console.hpp"
#include "core/Http.h"
#include "core/Json.hpp"
#include <chrono>
#ifdef OPENRCT2_BUILD_INFO_HEADER
# include OPENRCT2_BUILD_INFO_HEADER
#endif
const char gVersionInfoTag[] =
#ifdef OPENRCT2_VERSION_TAG
OPENRCT2_VERSION_TAG
#else
"v" OPENRCT2_VERSION
#endif
;
const char gVersionInfoFull[] = OPENRCT2_NAME ", "
#ifdef OPENRCT2_VERSION_TAG
OPENRCT2_VERSION_TAG
@@ -39,3 +52,57 @@ const char gVersionInfoFull[] = OPENRCT2_NAME ", "
" provided by " OPENRCT2_BUILD_SERVER
#endif
;
NewVersionInfo get_latest_version()
{
// If the check doesn't succeed, provide current version so we don't bother user
// with invalid data.
std::string tag = gVersionInfoTag;
NewVersionInfo verinfo{ tag, "", "", "" };
#ifndef DISABLE_HTTP
auto now = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
auto then = gConfigGeneral.last_version_check_time;
if (then < now - 24 * 60 * 60)
{
Http::Request request;
request.url = "https://api.github.com/repos/OpenRCT2/OpenRCT2/releases/latest";
request.method = Http::Method::GET;
Http::Response res;
try
{
res = Do(request);
if (res.status != Http::Status::OK)
throw std::runtime_error("bad http status");
}
catch (std::exception& e)
{
Console::Error::WriteLine("Failed to download '%s', cause %s", request.url.c_str(), e.what());
return {};
}
json_t* root = Json::FromString(res.body);
auto get_as_string = [root](std::string name) {
std::string value;
json_t* json_value = json_object_get(root, name.c_str());
if (json_is_string(json_value))
{
value = (json_string_value(json_value));
}
return value;
};
verinfo.tag = get_as_string("tag_name");
verinfo.name = get_as_string("name");
verinfo.changelog = get_as_string("body");
verinfo.url = get_as_string("html_url");
json_decref(root);
gConfigGeneral.last_version_check_time = now;
config_save_default();
}
#endif
return verinfo;
}

View File

@@ -11,6 +11,8 @@
#include "common.h"
#include <string>
#define OPENRCT2_NAME "OpenRCT2"
#define OPENRCT2_VERSION "0.2.6"
@@ -77,3 +79,13 @@
#endif
extern const char gVersionInfoFull[];
extern const char gVersionInfoTag[];
struct NewVersionInfo
{
std::string tag;
std::string name;
std::string changelog;
std::string url;
};
NewVersionInfo get_latest_version();

View File

@@ -213,6 +213,7 @@ namespace Config
model->show_real_names_of_guests = reader->GetBoolean("show_real_names_of_guests", true);
model->allow_early_completion = reader->GetBoolean("allow_early_completion", false);
model->transparent_screenshot = reader->GetBoolean("transparent_screenshot", true);
model->last_version_check_time = reader->GetInt64("last_version_check_time", 0);
}
}
@@ -288,6 +289,7 @@ namespace Config
writer->WriteBoolean("allow_early_completion", model->allow_early_completion);
writer->WriteEnum<int32_t>("virtual_floor_style", model->virtual_floor_style, Enum_VirtualFloorStyle);
writer->WriteBoolean("transparent_screenshot", model->transparent_screenshot);
writer->WriteInt64("last_version_check_time", model->last_version_check_time);
}
static void ReadInterface(IIniReader* reader)

View File

@@ -101,6 +101,7 @@ struct GeneralConfiguration
utf8* last_save_track_directory;
utf8* last_run_version;
bool use_native_browse_dialog;
int64_t last_version_check_time;
};
struct InterfaceConfiguration

View File

@@ -482,6 +482,7 @@ enum
WC_VIEW_CLIPPING = 131,
WC_OBJECT_LOAD_ERROR = 132,
WC_NETWORK = 133,
WC_NEW_VERSION = 134,
// Only used for colour schemes
WC_STAFF = 220,

View File

@@ -3878,6 +3878,11 @@ enum
STR_MULTIPLAYER_RECEIVED_INVALID_DATA = 6379,
STR_UPDATE_AVAILABLE = 6380,
STR_JOIN_DISCORD = 6381,
STR_NEW_RELEASE_VERSION_INFO = 6382,
STR_NEW_RELEASE_DOWNLOAD_PAGE = 6383,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
/* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings
};