GOG installer extraction for POSIX

This commit is contained in:
Keith Stellyes 2020-10-21 10:53:22 -07:00 committed by Gymnasiast
parent 6fb7921dbd
commit 268e39d12a
No known key found for this signature in database
GPG Key ID: DBFFF47AB2CA3EDD
14 changed files with 229 additions and 2 deletions

View File

@ -3651,6 +3651,15 @@ STR_6396 :Disable screensaver and monitor power saving
STR_6397 :If checked, screensaver and other monitor power saving features will be inhibited while OpenRCT2 is running.
STR_6398 :File contains unsupported ride types. Please update to a newer version of OpenRCT2.
STR_6399 :OpenRCT2 needs files from the original RollerCoaster Tycoon 2 in order to work. Please set the “game_path” variable in config.ini to the directory where you installed RollerCoaster Tycoon 2, then restart OpenRCT2.
STR_6400 :I have the GOG installer for RollerCoaster Tycoon 2 downloaded, but it is not installed
STR_6401 :I have RollerCoaster Tycoon 2 installed already
STR_6402 :OpenRCT2 Data Setup
STR_6403 :Select which applies best to you
STR_6404 :Please select GOG RollerCoaster Tycoon 2 installer
STR_6405 :Select GOG Installer
STR_6406 :GOG RollerCoaster Tycoon 2 Installer
STR_6407 :This may take a few minutes
STR_6408 :Please install innoextract to extract GOG Installer
#############
# Scenarios #

1
debian/control vendored
View File

@ -12,6 +12,7 @@ Homepage: https://openrct2.io/
Vcs-Browser: https://github.com/OpenRCT2/OpenRCT2
Vcs-Git: https://github.com/OpenRCT2/OpenRCT2
Depends: ${shlibs:Depends}, ${misc:Depends}
Recommends: innoextract
Description: An open source re-implementation of Roller Coaster Tycoon 2.
An open source clone of RollerCoaster Tycoon 2 built by decompiling the
original game one bit at a time.

View File

@ -36,6 +36,7 @@
0.3.2 (2020-11-01)
------------------------------------------------------------------------
- Feature: [#12307] For Linux users, allow extraction of GOG installer via innoextract.
- Feature: [#12110] Add Hybrid Coaster (Rocky Mountain Construction I-Box) track type.
- Feature: [#12999] .sea (RCT Classic) scenarios are now listed in the “New Scenario” dialog.
- Feature: [#13000] objective_options command for console.

View File

@ -116,6 +116,7 @@ The program can also be built as a command line program using CMake. This type o
- gl (commonly provided by Mesa or GPU vendors; only for UI client, can be disabled)
- duktape (unless scripting is disabled)
- cmake
- innoextract (optional runtime dependency; used for GOG installer extraction during setup)
Refer to https://github.com/OpenRCT2/OpenRCT2/wiki/Building-OpenRCT2-on-Linux#required-packages-general for more information about installing the packages.

View File

@ -40,6 +40,17 @@ namespace OpenRCT2::Ui
return false;
}
bool HasMenuSupport() override
{
return false;
}
int32_t ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
return -1;
}
void ShowMessageBox(SDL_Window* window, const std::string& message) override
{
log_verbose(message.c_str());

View File

@ -16,6 +16,7 @@
# include <openrct2/common.h>
# include <openrct2/core/Path.hpp>
# include <openrct2/core/String.hpp>
# include <openrct2/core/StringBuilder.h>
# include <openrct2/localisation/Localisation.h>
# include <openrct2/platform/Platform2.h>
# include <openrct2/ui/UiContext.h>
@ -256,6 +257,74 @@ namespace OpenRCT2::Ui
return GetDialogApp(&dummy) != DIALOG_TYPE::NONE;
}
bool HasMenuSupport() override
{
std::string executablePath;
DIALOG_TYPE dtype = GetDialogApp(&executablePath);
return dtype != DIALOG_TYPE::NONE;
}
int32_t ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
std::string executablePath;
DIALOG_TYPE dtype = GetDialogApp(&executablePath);
size_t longest_string = 0;
for (const auto& option : options)
{
if (option.size() > longest_string)
{
longest_string = option.size();
}
}
// zenity and kdialog don't support automatic scaling, this is an approximation
int width = (longest_string + 1) * 8;
int height = (options.size() + 1) * 8;
switch (dtype)
{
case DIALOG_TYPE::ZENITY:
{
auto sb = StringBuilder();
sb.Append(reinterpret_cast<utf8*>(
String::Format("zenity --list --column '' --width=%d --height=%d", width, height)));
for (const auto& option : options)
{
sb.Append(reinterpret_cast<utf8*>(String::Format(" '%s'", option.c_str())));
}
sb.Append(
reinterpret_cast<utf8*>(String::Format(" --title '%s' --text '%s'", title.c_str(), text.c_str())));
std::string buff;
Platform::Execute(sb.GetBuffer(), &buff);
return std::find(options.begin(), options.end(), buff) - options.begin();
}
case DIALOG_TYPE::KDIALOG:
{
auto sb = StringBuilder();
sb.Append(reinterpret_cast<utf8*>(
String::Format("kdialog --geometry %dx%d --title '%s' --menu ", width, height, title.c_str())));
sb.Append(reinterpret_cast<utf8*>(String::Format(" '%s'", text.c_str())));
for (const auto& option : options)
{
sb.Append(reinterpret_cast<utf8*>(String::Format(" '%s' '%s'", option.c_str(), option.c_str())));
}
std::string buff;
Platform::Execute(sb.GetBuffer(), &buff);
return std::find(options.begin(), options.end(), buff) - options.begin();
}
default:
{
break;
}
}
return options.size();
}
private:
static DIALOG_TYPE GetDialogApp(std::string* executablePath)
{

View File

@ -95,6 +95,17 @@ namespace OpenRCT2::Ui
MessageBoxW(hwnd, messageW.c_str(), L"OpenRCT2", MB_OK);
}
bool HasMenuSupport() override
{
return false;
}
int32_t ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
return -1;
}
void OpenFolder(const std::string& path) override
{
std::wstring pathW = String::ToWideChar(path);

View File

@ -604,6 +604,16 @@ public:
_platformUiContext->ShowMessageBox(_window, message);
}
bool HasMenuSupport() override
{
return _platformUiContext->HasMenuSupport();
}
int32_t ShowMenuDialog(const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
return _platformUiContext->ShowMenuDialog(options, title, text);
}
void OpenFolder(const std::string& path) override
{
_platformUiContext->OpenFolder(path);

View File

@ -12,6 +12,7 @@
#include <memory>
#include <openrct2/common.h>
#include <string>
#include <vector>
struct SDL_Window;
@ -33,6 +34,9 @@ namespace OpenRCT2
virtual bool IsSteamOverlayAttached() abstract;
virtual void ShowMessageBox(SDL_Window* window, const std::string& message) abstract;
virtual bool HasMenuSupport() abstract;
virtual int ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) abstract;
virtual void OpenFolder(const std::string& path) abstract;
virtual void OpenURL(const std::string& url) abstract;

View File

@ -64,6 +64,17 @@ namespace OpenRCT2::Ui
}
}
bool HasMenuSupport() override
{
return false;
}
int32_t ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
return -1;
}
void OpenFolder(const std::string& path) override
{
@autoreleasepool

View File

@ -11,6 +11,7 @@
#include "../Context.h"
#include "../OpenRCT2.h"
#include "../PlatformEnvironment.h"
#include "../core/Console.hpp"
#include "../core/File.h"
#include "../core/FileStream.h"
@ -721,6 +722,21 @@ namespace Config
}
return std::string();
}
static bool ExtractGogInstaller(const utf8* installerPath, const utf8* targetPath)
{
std::string path;
std::string output;
if (!Platform::FindApp("innoextract", &path))
{
GetContext()->GetUiContext()->ShowMessageBox(format_string(STR_INSTALL_INNOEXTRACT, nullptr));
return false;
}
int32_t exit_status = Platform::Execute(
String::Format("%s '%s' --exclude-temp --output-dir '%s'", path.c_str(), installerPath, targetPath), &output);
return exit_status == 0;
}
} // namespace Config
GeneralConfiguration gConfigGeneral;
@ -816,13 +832,71 @@ bool config_find_or_browse_install_directory()
while (true)
{
uiContext->ShowMessageBox(format_string(STR_NEEDS_RCT2_FILES, nullptr));
std::string gog = language_get_string(STR_OWN_ON_GOG);
std::string hdd = language_get_string(STR_INSTALLED_ON_HDD);
std::string installPath = uiContext->ShowDirectoryDialog(format_string(STR_PICK_RCT2_DIR, nullptr));
std::vector<std::string> options;
std::string chosenOption;
if (uiContext->HasMenuSupport())
{
options.push_back(hdd);
options.push_back(gog);
int optionIndex = uiContext->ShowMenuDialog(
options, language_get_string(STR_OPENRCT2_SETUP), language_get_string(STR_WHICH_APPLIES_BEST));
if (optionIndex < 0 || static_cast<uint32_t>(optionIndex) >= options.size())
{
// graceful fallback if app errors or user exits out of window
chosenOption = hdd;
}
else
{
chosenOption = options[optionIndex];
}
}
chosenOption = hdd;
std::string installPath;
if (chosenOption == hdd)
{
installPath = uiContext->ShowDirectoryDialog(language_get_string(STR_PICK_RCT2_DIR));
}
else if (chosenOption == gog)
{
uiContext->ShowMessageBox(language_get_string(STR_PLEASE_SELECT_GOG_INSTALLER));
utf8 gogPath[4096];
std::string dest = Path::Combine(
GetContext()->GetPlatformEnvironment()->GetDirectoryPath(DIRBASE::CONFIG), "rct2");
file_dialog_desc desc;
memset(&desc, 0, sizeof(desc));
desc.type = FileDialogType::Open;
desc.title = language_get_string(STR_SELECT_GOG_INSTALLER);
desc.filters[0].name = language_get_string(STR_GOG_INSTALLER);
desc.filters[0].pattern = "*.exe";
desc.filters[1].name = language_get_string(STR_ALL_FILES);
desc.filters[1].pattern = "*";
desc.filters[2].name = nullptr;
desc.initial_directory = Platform::GetFolderPath(SPECIAL_FOLDER::USER_HOME).c_str();
if (!platform_open_common_file_dialog(gogPath, &desc, 4096))
{
return false;
}
uiContext->ShowMessageBox(language_get_string(STR_THIS_WILL_TAKE_A_FEW_MINUTES));
if (!Config::ExtractGogInstaller(gogPath, dest.c_str()))
{
return false;
}
installPath = Path::Combine(dest, "app");
}
if (installPath.empty())
{
return false;
}
Memory::Free(gConfigGeneral.rct2_path);
gConfigGeneral.rct2_path = String::Duplicate(installPath.c_str());

View File

@ -3905,6 +3905,16 @@ enum
STR_NEEDS_RCT2_FILES_MANUAL = 6399,
STR_OWN_ON_GOG = 6400,
STR_INSTALLED_ON_HDD = 6401,
STR_OPENRCT2_SETUP = 6402,
STR_WHICH_APPLIES_BEST = 6403,
STR_PLEASE_SELECT_GOG_INSTALLER = 6404,
STR_SELECT_GOG_INSTALLER = 6405,
STR_GOG_INSTALLER = 6406,
STR_THIS_WILL_TAKE_A_FEW_MINUTES = 6407,
STR_INSTALL_INNOEXTRACT = 6408,
// 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
};

View File

@ -90,6 +90,16 @@ namespace OpenRCT2::Ui
void ShowMessageBox(const std::string& /*message*/) override
{
}
bool HasMenuSupport() override
{
return false;
}
int32_t ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) override
{
return options.size();
}
void OpenFolder(const std::string& /*path*/) override
{
}

View File

@ -113,6 +113,11 @@ namespace OpenRCT2
virtual void TriggerResize() abstract;
virtual void ShowMessageBox(const std::string& message) abstract;
virtual bool HasMenuSupport() abstract;
// Creates a menu with a series of options, returns the index of the selected option
virtual int ShowMenuDialog(
const std::vector<std::string>& options, const std::string& title, const std::string& text) abstract;
virtual void OpenFolder(const std::string& path) abstract;
virtual void OpenURL(const std::string& url) abstract;
virtual std::string ShowFileDialog(const FileDialogDesc& desc) abstract;