diff --git a/meson.build b/meson.build index 457c2fa2e..344b52082 100644 --- a/meson.build +++ b/meson.build @@ -314,6 +314,10 @@ else ident_platform = 'UNKNOWN' endif +install_check = get_option('install_check') +if host_platform == 'darwin' or host_platform == 'android' + install_check = false +endif app_exe = get_option('app_exe') app_id = get_option('app_id') mod_id = get_option('mod_id') @@ -328,7 +332,7 @@ conf_data.set('WIN', host_platform == 'windows') conf_data.set('MACOSX', host_platform == 'darwin') conf_data.set('X86', is_x86 ? 'true' : 'false') conf_data.set('BETA', is_beta ? 'true' : 'false') -conf_data.set('INSTALL_CHECK', get_option('install_check') ? 'true' : 'false') +conf_data.set('INSTALL_CHECK', install_check ? 'true' : 'false') conf_data.set('IGNORE_UPDATES', get_option('ignore_updates') ? 'true' : 'false') conf_data.set('MOD_ID', mod_id) conf_data.set('DEBUG', is_debug ? 'true' : 'false') diff --git a/src/Config.template.h b/src/Config.template.h index cdd7792b1..c29a832ce 100644 --- a/src/Config.template.h +++ b/src/Config.template.h @@ -41,7 +41,6 @@ constexpr char PATH_SEP[] = "/"; constexpr char PATH_SEP_CHAR = '/'; #endif -//VersionInfoStart constexpr int SAVE_VERSION = 97; constexpr int MINOR_VERSION = 0; constexpr int BUILD_NUM = 352; @@ -49,7 +48,6 @@ constexpr int SNAPSHOT_ID = @SNAPSHOT_ID@; constexpr int MOD_ID = @MOD_ID@; constexpr int FUTURE_SAVE_VERSION = 97; constexpr int FUTURE_MINOR_VERSION = 0; -//VersionInfoEnd constexpr char IDENT_RELTYPE = SNAPSHOT ? 'S' : (BETA ? 'B' : 'R'); diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 826518cba..d180e7393 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -13,33 +13,6 @@ #include #include -#ifdef MACOSX -# include -# include -#endif - -#ifdef LIN -# include "icon_cps.png.h" -# include "icon_exe.png.h" -# include "save.xml.h" -# include "powder.desktop.h" -#endif - -#ifdef WIN -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include -# include -# include -# include -# include -# include "resource.h" -#else -# include -# include -#endif - #include "ClientListener.h" #include "Config.h" #include "Format.h" @@ -1120,144 +1093,6 @@ void Client::SaveAuthorInfo(Json::Value *saveInto) } } -bool Client::DoInstallation() -{ - bool ok = true; -#if defined(WIN) - auto deleteKey = [](ByteString path) { - RegDeleteKeyW(HKEY_CURRENT_USER, Platform::WinWiden(path).c_str()); - }; - auto createKey = [](ByteString path, ByteString value, ByteString extraKey = {}, ByteString extraValue = {}) { - auto ok = true; - auto wPath = Platform::WinWiden(path); - auto wValue = Platform::WinWiden(value); - auto wExtraKey = Platform::WinWiden(extraKey); - auto wExtraValue = Platform::WinWiden(extraValue); - HKEY k; - ok = ok && RegCreateKeyExW(HKEY_CURRENT_USER, wPath.c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &k, NULL) == ERROR_SUCCESS; - ok = ok && RegSetValueExW(k, NULL, 0, REG_SZ, reinterpret_cast(wValue.c_str()), (wValue.size() + 1) * 2) == ERROR_SUCCESS; - if (wExtraKey.size()) - { - ok = ok && RegSetValueExW(k, wExtraKey.c_str(), 0, REG_SZ, reinterpret_cast(wExtraValue.c_str()), (wExtraValue.size() + 1) * 2) == ERROR_SUCCESS; - } - RegCloseKey(k); - return ok; - }; - - CoInitializeEx(NULL, COINIT_MULTITHREADED); - auto exe = Platform::ExecutableName(); - auto icon = ByteString::Build(exe, ",-", IDI_DOC_ICON); - auto path = Platform::GetCwd(); - auto open = ByteString::Build("\"", exe, "\" ddir \"", path, "\" \"file://%1\""); - auto ptsave = ByteString::Build("\"", exe, "\" ddir \"", path, "\" \"%1\""); - deleteKey("Software\\Classes\\ptsave"); - deleteKey("Software\\Classes\\.cps"); - deleteKey("Software\\Classes\\.stm"); - deleteKey("Software\\Classes\\PowderToySave"); - ok = ok && createKey("Software\\Classes\\ptsave", "Powder Toy Save", "URL Protocol", ""); - ok = ok && createKey("Software\\Classes\\ptsave\\DefaultIcon", icon); - ok = ok && createKey("Software\\Classes\\ptsave\\shell\\open\\command", ptsave); - ok = ok && createKey("Software\\Classes\\.cps", "PowderToySave"); - ok = ok && createKey("Software\\Classes\\.stm", "PowderToySave"); - ok = ok && createKey("Software\\Classes\\PowderToySave", "Powder Toy Save"); - ok = ok && createKey("Software\\Classes\\PowderToySave\\DefaultIcon", icon); - ok = ok && createKey("Software\\Classes\\PowderToySave\\shell\\open\\command", open); - IShellLinkW *shellLink = NULL; - IPersistFile *shellLinkPersist = NULL; - wchar_t programsPath[MAX_PATH]; - ok = ok && SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, programsPath) == S_OK; - ok = ok && CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&shellLink) == S_OK; - ok = ok && shellLink->SetPath(Platform::WinWiden(exe).c_str()) == S_OK; - ok = ok && shellLink->SetWorkingDirectory(Platform::WinWiden(path).c_str()) == S_OK; - ok = ok && shellLink->SetDescription(Platform::WinWiden(APPNAME).c_str()) == S_OK; - ok = ok && shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&shellLinkPersist) == S_OK; - ok = ok && shellLinkPersist->Save(Platform::WinWiden(ByteString::Build(Platform::WinNarrow(programsPath), "\\", APPNAME, ".lnk")).c_str(), TRUE) == S_OK; - if (shellLinkPersist) - { - shellLinkPersist->Release(); - } - if (shellLink) - { - shellLink->Release(); - } - CoUninitialize(); -#elif defined(LIN) - auto desktopEscapeString = [](ByteString str) { - ByteString escaped; - for (auto ch : str) - { - auto from = " " "\n" "\t" "\r" "\\"; - auto to = "s" "n" "t" "r" "\\"; - if (auto off = strchr(from, ch)) - { - escaped.append(1, '\\'); - escaped.append(1, to[off - from]); - } - else - { - escaped.append(1, ch); - } - } - return escaped; - }; - auto desktopEscapeExec = [](ByteString str) { - ByteString escaped; - for (auto ch : str) - { - if (strchr(" \t\n\"\'\\><~|&;$*?#()`", ch)) - { - escaped.append(1, '\\'); - } - escaped.append(1, ch); - } - return escaped; - }; - - if (ok) - { - ByteString desktopData(powder_desktop, powder_desktop + powder_desktop_size); - auto exe = Platform::ExecutableName(); - auto path = exe.SplitFromEndBy('/').Before(); - desktopData = desktopData.Substitute("Exec=" + ByteString(APPEXE), "Exec=" + desktopEscapeString(desktopEscapeExec(exe))); - desktopData += ByteString::Build("Path=", desktopEscapeString(path), "\n"); - ByteString file = ByteString::Build(APPVENDOR, "-", APPID, ".desktop"); - ok = ok && Platform::WriteFile(std::vector(desktopData.begin(), desktopData.end()), file); - ok = ok && !system(ByteString::Build("xdg-desktop-menu install ", file).c_str()); - ok = ok && !system(ByteString::Build("xdg-mime default ", file, " application/vnd.powdertoy.save").c_str()); - ok = ok && !system(ByteString::Build("xdg-mime default ", file, " x-scheme-handler/ptsave").c_str()); - Platform::RemoveFile(file); - } - if (ok) - { - ByteString file = ByteString(APPVENDOR) + "-save.xml"; - ok = ok && Platform::WriteFile(std::vector(save_xml, save_xml + save_xml_size), file); - ok = ok && !system(ByteString::Build("xdg-mime install ", file).c_str()); - Platform::RemoveFile(file); - } - if (ok) - { - ByteString file = ByteString(APPVENDOR) + "-cps.png"; - ok = ok && Platform::WriteFile(std::vector(icon_cps_png, icon_cps_png + icon_cps_png_size), file); - ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --context mimetypes --size 64 ", file, " application-vnd.powdertoy.save").c_str()); - Platform::RemoveFile(file); - } - if (ok) - { - ByteString file = ByteString(APPVENDOR) + "-exe.png"; - ok = ok && Platform::WriteFile(std::vector(icon_exe_png, icon_exe_png + icon_exe_png_size), file); - ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --size 64 ", file, " ", APPVENDOR, "-", APPEXE).c_str()); - Platform::RemoveFile(file); - } - if (ok) - { - ok = ok && !system("xdg-icon-resource forceupdate"); - } -#else - ok = false; -#endif - return ok; -} - bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor) { auto &prefs = GlobalPrefs::Ref(); @@ -1408,7 +1243,7 @@ String Client::DoMigration(ByteString fromDir, ByteString toDir) } // chdir into the new directory - chdir(toDir.c_str()); + Platform::ChangeDir(toDir); if (scripts.size()) RescanStamps(); diff --git a/src/client/Client.h b/src/client/Client.h index 3df2ab4b5..c5e4d9990 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -97,8 +97,6 @@ public: ByteString FileOpenDialogue(); //std::string FileSaveDialogue(); - bool DoInstallation(); - void AddServerNotification(std::pair notification); std::vector > GetServerNotifications(); diff --git a/src/client/http/RequestManagerHttp.cpp b/src/client/http/RequestManagerHttp.cpp index cd1bce45f..574215725 100644 --- a/src/client/http/RequestManagerHttp.cpp +++ b/src/client/http/RequestManagerHttp.cpp @@ -444,8 +444,6 @@ namespace http HandleCURLcode(curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT)); #elif defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 44, 0) HandleCURLcode(curl_easy_setopt(easy, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE)); -#elif defined(WIN) -# error "That's unfortunate." #endif } } diff --git a/src/common/Platform.cpp b/src/common/Platform.cpp index bcf980d86..2aa776376 100644 --- a/src/common/Platform.cpp +++ b/src/common/Platform.cpp @@ -1,4 +1,5 @@ #include "Platform.h" +#include "resource.h" #include #include #include @@ -23,6 +24,13 @@ #ifdef MACOSX # include # include +# include +#endif +#ifdef LIN +# include "icon_cps.png.h" +# include "icon_exe.png.h" +# include "save.xml.h" +# include "powder.desktop.h" #endif namespace Platform @@ -205,6 +213,15 @@ bool MakeDirectory(ByteString dir) #endif } +bool ChangeDir(ByteString toDir) +{ +#ifdef WIN + return _wchdir(WinWiden(toDir).c_str()) == 0; +#else + return chdir(toDir.c_str()) == 0; +#endif +} + // Returns a list of all files in a directory matching a search // search - list of search terms. extensions - list of extensions to also match std::vector DirectorySearch(ByteString directory, ByteString search, std::vector extensions) @@ -409,4 +426,160 @@ void DoRestart() } exit(-1); } + +bool CanUpdate() +{ +#ifdef MACOSX + return false; +#else + return true; +#endif +} + +bool CanInstall() +{ + return INSTALL_CHECK; +} + +bool Install() +{ + bool ok = true; +#if defined(WIN) + auto deleteKey = [](ByteString path) { + RegDeleteKeyW(HKEY_CURRENT_USER, Platform::WinWiden(path).c_str()); + }; + auto createKey = [](ByteString path, ByteString value, ByteString extraKey = {}, ByteString extraValue = {}) { + auto ok = true; + auto wPath = Platform::WinWiden(path); + auto wValue = Platform::WinWiden(value); + auto wExtraKey = Platform::WinWiden(extraKey); + auto wExtraValue = Platform::WinWiden(extraValue); + HKEY k; + ok = ok && RegCreateKeyExW(HKEY_CURRENT_USER, wPath.c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &k, NULL) == ERROR_SUCCESS; + ok = ok && RegSetValueExW(k, NULL, 0, REG_SZ, reinterpret_cast(wValue.c_str()), (wValue.size() + 1) * 2) == ERROR_SUCCESS; + if (wExtraKey.size()) + { + ok = ok && RegSetValueExW(k, wExtraKey.c_str(), 0, REG_SZ, reinterpret_cast(wExtraValue.c_str()), (wExtraValue.size() + 1) * 2) == ERROR_SUCCESS; + } + RegCloseKey(k); + return ok; + }; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + auto exe = Platform::ExecutableName(); +#ifndef IDI_DOC_ICON + // make this fail so I don't remove #include "resource.h" again and get away with it +# error where muh IDI_DOC_ICON D: +#endif + auto icon = ByteString::Build(exe, ",-", IDI_DOC_ICON); + auto path = Platform::GetCwd(); + auto open = ByteString::Build("\"", exe, "\" ddir \"", path, "\" \"file://%1\""); + auto ptsave = ByteString::Build("\"", exe, "\" ddir \"", path, "\" \"%1\""); + deleteKey("Software\\Classes\\ptsave"); + deleteKey("Software\\Classes\\.cps"); + deleteKey("Software\\Classes\\.stm"); + deleteKey("Software\\Classes\\PowderToySave"); + ok = ok && createKey("Software\\Classes\\ptsave", "Powder Toy Save", "URL Protocol", ""); + ok = ok && createKey("Software\\Classes\\ptsave\\DefaultIcon", icon); + ok = ok && createKey("Software\\Classes\\ptsave\\shell\\open\\command", ptsave); + ok = ok && createKey("Software\\Classes\\.cps", "PowderToySave"); + ok = ok && createKey("Software\\Classes\\.stm", "PowderToySave"); + ok = ok && createKey("Software\\Classes\\PowderToySave", "Powder Toy Save"); + ok = ok && createKey("Software\\Classes\\PowderToySave\\DefaultIcon", icon); + ok = ok && createKey("Software\\Classes\\PowderToySave\\shell\\open\\command", open); + IShellLinkW *shellLink = NULL; + IPersistFile *shellLinkPersist = NULL; + wchar_t programsPath[MAX_PATH]; + ok = ok && SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, programsPath) == S_OK; + ok = ok && CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&shellLink) == S_OK; + ok = ok && shellLink->SetPath(Platform::WinWiden(exe).c_str()) == S_OK; + ok = ok && shellLink->SetWorkingDirectory(Platform::WinWiden(path).c_str()) == S_OK; + ok = ok && shellLink->SetDescription(Platform::WinWiden(APPNAME).c_str()) == S_OK; + ok = ok && shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&shellLinkPersist) == S_OK; + ok = ok && shellLinkPersist->Save(Platform::WinWiden(ByteString::Build(Platform::WinNarrow(programsPath), "\\", APPNAME, ".lnk")).c_str(), TRUE) == S_OK; + if (shellLinkPersist) + { + shellLinkPersist->Release(); + } + if (shellLink) + { + shellLink->Release(); + } + CoUninitialize(); +#elif defined(LIN) + auto desktopEscapeString = [](ByteString str) { + ByteString escaped; + for (auto ch : str) + { + auto from = " " "\n" "\t" "\r" "\\"; + auto to = "s" "n" "t" "r" "\\"; + if (auto off = strchr(from, ch)) + { + escaped.append(1, '\\'); + escaped.append(1, to[off - from]); + } + else + { + escaped.append(1, ch); + } + } + return escaped; + }; + auto desktopEscapeExec = [](ByteString str) { + ByteString escaped; + for (auto ch : str) + { + if (strchr(" \t\n\"\'\\><~|&;$*?#()`", ch)) + { + escaped.append(1, '\\'); + } + escaped.append(1, ch); + } + return escaped; + }; + + if (ok) + { + ByteString desktopData(powder_desktop, powder_desktop + powder_desktop_size); + auto exe = Platform::ExecutableName(); + auto path = exe.SplitFromEndBy('/').Before(); + desktopData = desktopData.Substitute("Exec=" + ByteString(APPEXE), "Exec=" + desktopEscapeString(desktopEscapeExec(exe))); + desktopData += ByteString::Build("Path=", desktopEscapeString(path), "\n"); + ByteString file = ByteString::Build(APPVENDOR, "-", APPID, ".desktop"); + ok = ok && Platform::WriteFile(std::vector(desktopData.begin(), desktopData.end()), file); + ok = ok && !system(ByteString::Build("xdg-desktop-menu install ", file).c_str()); + ok = ok && !system(ByteString::Build("xdg-mime default ", file, " application/vnd.powdertoy.save").c_str()); + ok = ok && !system(ByteString::Build("xdg-mime default ", file, " x-scheme-handler/ptsave").c_str()); + Platform::RemoveFile(file); + } + if (ok) + { + ByteString file = ByteString(APPVENDOR) + "-save.xml"; + ok = ok && Platform::WriteFile(std::vector(save_xml, save_xml + save_xml_size), file); + ok = ok && !system(ByteString::Build("xdg-mime install ", file).c_str()); + Platform::RemoveFile(file); + } + if (ok) + { + ByteString file = ByteString(APPVENDOR) + "-cps.png"; + ok = ok && Platform::WriteFile(std::vector(icon_cps_png, icon_cps_png + icon_cps_png_size), file); + ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --context mimetypes --size 64 ", file, " application-vnd.powdertoy.save").c_str()); + Platform::RemoveFile(file); + } + if (ok) + { + ByteString file = ByteString(APPVENDOR) + "-exe.png"; + ok = ok && Platform::WriteFile(std::vector(icon_exe_png, icon_exe_png + icon_exe_png_size), file); + ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --size 64 ", file, " ", APPVENDOR, "-", APPEXE).c_str()); + Platform::RemoveFile(file); + } + if (ok) + { + ok = ok && !system("xdg-icon-resource forceupdate"); + } +#else + ok = false; +#endif + return ok; +} } diff --git a/src/common/Platform.h b/src/common/Platform.h index 09ff770fd..878c829db 100644 --- a/src/common/Platform.h +++ b/src/common/Platform.h @@ -1,11 +1,7 @@ #pragma once #include "Config.h" - #include "common/String.h" - -#ifdef WIN -# include -#endif +#include namespace Platform { @@ -41,11 +37,16 @@ namespace Platform bool ReadFile(std::vector &fileData, ByteString filename); bool WriteFile(std::vector fileData, ByteString filename, bool replaceAtomically = false); // TODO: Revisit call sites, remove default. -#ifdef WIN ByteString WinNarrow(const std::wstring &source); std::wstring WinWiden(const ByteString &source); -#endif extern std::string originalCwd; extern std::string sharedCwd; + + bool CanUpdate(); + + bool CanInstall(); + bool Install(); + + bool ChangeDir(ByteString toDir); } diff --git a/src/common/tpt-compat.h b/src/common/tpt-compat.h index baba17912..52356c231 100644 --- a/src/common/tpt-compat.h +++ b/src/common/tpt-compat.h @@ -22,11 +22,6 @@ #define _USE_MATH_DEFINES #include -//some compatibility stuff for non-standard compilers -#if defined(WIN) && !defined(strcasecmp) -#define strcasecmp stricmp -#endif - #ifdef M_PI constexpr float TPT_PI_FLT = float(M_PI); constexpr double TPT_PI_DBL = double(M_PI); diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index c77e1d8b5..e70798aa6 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -773,21 +773,10 @@ bool VideoBuffer::WritePNG(const ByteString &path) const { rowPointers[y] = (png_const_bytep)&Buffer[y * Width]; } -#ifdef WIN - FILE *f = _wfopen(Platform::WinWiden(path).c_str(), L"wb"); -#else - FILE *f = fopen(path.c_str(), "wb"); -#endif - if (!f) - { - std::cerr << "WritePNG: fopen failed" << std::endl; - return false; - } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { std::cerr << "WritePNG: png_create_write_struct failed" << std::endl; - fclose(f); return false; } png_infop info = png_create_info_struct(png); @@ -795,7 +784,6 @@ bool VideoBuffer::WritePNG(const ByteString &path) const { std::cerr << "WritePNG: png_create_info_struct failed" << std::endl; png_destroy_write_struct(&png, (png_infopp)NULL); - fclose(f); return false; } if (setjmp(png_jmpbuf(png))) @@ -803,10 +791,17 @@ bool VideoBuffer::WritePNG(const ByteString &path) const // libpng longjmp'd here in its infinite widsom, clean up and return std::cerr << "WritePNG: longjmp from within libpng" << std::endl; png_destroy_write_struct(&png, &info); - fclose(f); return false; } - png_init_io(png, f); + struct InMemoryFile + { + std::vector data; + } imf; + png_set_write_fn(png, (png_voidp)&imf, [](png_structp png, png_bytep data, size_t length) -> void { + auto ud = png_get_io_ptr(png); + auto &imf = *(InMemoryFile *)ud; + imf.data.insert(imf.data.end(), data, data + length); + }, NULL); png_set_IHDR(png, info, Width, Height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png, info); png_set_filler(png, 0, PNG_FILLER_AFTER); @@ -814,8 +809,7 @@ bool VideoBuffer::WritePNG(const ByteString &path) const png_write_image(png, (png_bytepp)&rowPointers[0]); png_write_end(png, NULL); png_destroy_write_struct(&png, &info); - fclose(f); - return true; + return Platform::WriteFile(imf.data, path); } bool PngDataToPixels(std::vector &imageData, int &imgw, int &imgh, const char *pngData, size_t pngDataSize, bool addBackground) diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index 47813a9ff..90faf8191 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -252,22 +252,23 @@ void GameController::PlaceSave(ui::Point position) void GameController::Install() { -#if defined(MACOSX) - new InformationMessage("No installation necessary", "You don't need to install " + String(APPNAME) + " on OS X", false); -#elif defined(WIN) || defined(LIN) - new ConfirmPrompt("Install " + String(APPNAME), "Do you wish to install " + String(APPNAME) + " on this computer?\nThis allows you to open save files and saves directly from the website.", { [] { - if (Client::Ref().DoInstallation()) - { - new InformationMessage("Success", "Installation completed", false); - } - else - { - new ErrorMessage("Could not install", "The installation did not complete due to an error"); - } - } }); -#else - new ErrorMessage("Cannot install", "You cannot install " + String(APPNAME) + " on this platform"); -#endif + if (Platform::CanInstall()) + { + new ConfirmPrompt("Install " + String(APPNAME), "Do you wish to install " + String(APPNAME) + " on this computer?\nThis allows you to open save files and saves directly from the website.", { [] { + if (Platform::Install()) + { + new InformationMessage("Success", "Installation completed", false); + } + else + { + new ErrorMessage("Could not install", "The installation did not complete due to an error"); + } + } }); + } + else + { + new InformationMessage("No installation necessary", "You don't need to install " + String(APPNAME) + " on this platform", false); + } } void GameController::AdjustGridSize(int direction) @@ -727,7 +728,6 @@ void GameController::Tick() if(firstTick) { commandInterface->Init(); -#if !defined(MACOSX) if constexpr (INSTALL_CHECK) { if (Client::Ref().IsFirstRun()) @@ -735,7 +735,6 @@ void GameController::Tick() Install(); } } -#endif firstTick = false; } if (gameModel->SelectNextIdentifier.length()) @@ -1593,11 +1592,14 @@ void GameController::NotifyUpdateAvailable(Client * sender) { UpdateInfo info = Client::Ref().GetUpdateInfo(); StringBuilder updateMessage; -#ifndef MACOSX - updateMessage << "Are you sure you want to run the updater? Please save any changes before updating.\n\nCurrent version:\n "; -#else - updateMessage << "Click \"Continue\" to download the latest version from our website.\n\nCurrent version:\n "; -#endif + if (Platform::CanUpdate()) + { + updateMessage << "Are you sure you want to run the updater? Please save any changes before updating.\n\nCurrent version:\n "; + } + else + { + updateMessage << "Click \"Continue\" to download the latest version from our website.\n\nCurrent version:\n "; + } if constexpr (SNAPSHOT) { @@ -1672,21 +1674,24 @@ void GameController::RemoveNotification(Notification * notification) void GameController::RunUpdater() { -#ifndef MACOSX - Exit(); - new UpdateActivity(); -#else - ByteString file; - if constexpr (USE_UPDATESERVER) + if (Platform::CanUpdate()) { - file = ByteString::Build(SCHEME, UPDATESERVER, Client::Ref().GetUpdateInfo().File); + Exit(); + new UpdateActivity(); } else { - file = ByteString::Build(SCHEME, SERVER, Client::Ref().GetUpdateInfo().File); + ByteString file; + if constexpr (USE_UPDATESERVER) + { + file = ByteString::Build(SCHEME, UPDATESERVER, Client::Ref().GetUpdateInfo().File); + } + else + { + file = ByteString::Build(SCHEME, SERVER, Client::Ref().GetUpdateInfo().File); + } + Platform::OpenURI(file); } - Platform::OpenURI(file); -#endif // MACOSX } bool GameController::GetMouseClickRequired() diff --git a/src/gui/update/UpdateActivity.cpp b/src/gui/update/UpdateActivity.cpp index 9c2341afd..3ef0cd7dc 100644 --- a/src/gui/update/UpdateActivity.cpp +++ b/src/gui/update/UpdateActivity.cpp @@ -151,4 +151,3 @@ void UpdateActivity::NotifyError(Task * sender) UpdateActivity::~UpdateActivity() { } - diff --git a/src/gui/update/UpdateActivity.h b/src/gui/update/UpdateActivity.h index 7ee6a9221..227c1b4bb 100644 --- a/src/gui/update/UpdateActivity.h +++ b/src/gui/update/UpdateActivity.h @@ -1,4 +1,5 @@ #pragma once +#include "Config.h" class Task; class TaskWindow; class UpdateActivity diff --git a/src/lua/CommandInterface.cpp b/src/lua/CommandInterface.cpp index 77ce44f79..f2d6a47fc 100644 --- a/src/lua/CommandInterface.cpp +++ b/src/lua/CommandInterface.cpp @@ -3,9 +3,6 @@ #include #include #include -#if !defined(WIN) || defined(__GNUC__) -#include -#endif #include "Misc.h" #include "gui/game/GameModel.h" diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 7a3f5049e..d8f5b2fc5 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -52,17 +52,6 @@ #include "gui/game/Tool.h" #include "gui/game/Brush.h" -#ifndef WIN -#include -#endif - -extern "C" -{ -#ifdef WIN -#include -#endif -#include -} #include "eventcompat.lua.h" // idea from mniip, makes things much simpler diff --git a/src/lua/LuaSocket.cpp b/src/lua/LuaSocket.cpp index 07cd5378f..9083968b3 100644 --- a/src/lua/LuaSocket.cpp +++ b/src/lua/LuaSocket.cpp @@ -1,61 +1,17 @@ #include "LuaSocket.h" - -#include -#include -#ifdef WIN -# include -# include -#else -# include -# include -#endif - #include "LuaScriptInterface.h" #include "Misc.h" +#include +#include namespace LuaSocket { - double Now() - { -#ifdef WIN - FILETIME rt; - GetSystemTimeAsFileTime(&rt); - return (rt.dwLowDateTime + (uint64_t(rt.dwHighDateTime) << 32) - uint64_t(116444736000000000ULL)) / 1e7; -#else - struct timeval rt; - gettimeofday(&rt, (struct timezone *)NULL); - return rt.tv_sec + rt.tv_usec / 1e6; -#endif - } - static int GetTime(lua_State *l) { lua_pushnumber(l, Now()); return 1; } - void Timeout(double timeout) - { -#ifdef WIN - if (timeout < 0.0) timeout = 0.0; - if (timeout < DBL_MAX / 1000.0) timeout *= 1000.0; - if (timeout > INT_MAX) timeout = INT_MAX; - ::Sleep(int(timeout)); -#else - struct timespec req, rem; - if (timeout < 0.0) timeout = 0.0; - if (timeout > INT_MAX) timeout = INT_MAX; - req.tv_sec = int(timeout); - req.tv_nsec = int((timeout - req.tv_sec) * 1000000000); - if (req.tv_nsec > 999999999) req.tv_nsec = 999999999; - while (nanosleep(&req, &rem)) - { - req.tv_sec = rem.tv_sec; - req.tv_nsec = rem.tv_nsec; - } -#endif - } - static int Sleep(lua_State *l) { Timeout(luaL_checknumber(l, 1)); diff --git a/src/lua/LuaSocketDefault.cpp b/src/lua/LuaSocketDefault.cpp new file mode 100644 index 000000000..6c4723425 --- /dev/null +++ b/src/lua/LuaSocketDefault.cpp @@ -0,0 +1,32 @@ +#include "LuaSocket.h" +#include "LuaScriptInterface.h" +#include "Misc.h" +#include +#include +#include +#include + +namespace LuaSocket +{ + double Now() + { + struct timeval rt; + gettimeofday(&rt, (struct timezone *)NULL); + return rt.tv_sec + rt.tv_usec / 1e6; + } + + void Timeout(double timeout) + { + struct timespec req, rem; + if (timeout < 0.0) timeout = 0.0; + if (timeout > INT_MAX) timeout = INT_MAX; + req.tv_sec = int(timeout); + req.tv_nsec = int((timeout - req.tv_sec) * 1000000000); + if (req.tv_nsec > 999999999) req.tv_nsec = 999999999; + while (nanosleep(&req, &rem)) + { + req.tv_sec = rem.tv_sec; + req.tv_nsec = rem.tv_nsec; + } + } +} diff --git a/src/lua/LuaSocketTCPHttp.cpp b/src/lua/LuaSocketTCPHttp.cpp index 29cf3c131..baec28f93 100644 --- a/src/lua/LuaSocketTCPHttp.cpp +++ b/src/lua/LuaSocketTCPHttp.cpp @@ -7,13 +7,6 @@ #include #include #include -#ifdef WIN -# include -# include -#else -# include -# include -#endif #include "LuaScriptInterface.h" #include "client/http/RequestManager.h" diff --git a/src/lua/LuaSocketWindows.cpp b/src/lua/LuaSocketWindows.cpp new file mode 100644 index 000000000..0679febd5 --- /dev/null +++ b/src/lua/LuaSocketWindows.cpp @@ -0,0 +1,25 @@ +#include "LuaSocket.h" +#include "LuaScriptInterface.h" +#include "Misc.h" +#include +#include +#include +#include + +namespace LuaSocket +{ + double Now() + { + FILETIME rt; + GetSystemTimeAsFileTime(&rt); + return (rt.dwLowDateTime + (uint64_t(rt.dwHighDateTime) << 32) - uint64_t(116444736000000000ULL)) / 1e7; + } + + void Timeout(double timeout) + { + if (timeout < 0.0) timeout = 0.0; + if (timeout < DBL_MAX / 1000.0) timeout *= 1000.0; + if (timeout > INT_MAX) timeout = INT_MAX; + ::Sleep(int(timeout)); + } +} diff --git a/src/lua/TPTScriptInterface.cpp b/src/lua/TPTScriptInterface.cpp index 3a05e5666..e2f122f7c 100644 --- a/src/lua/TPTScriptInterface.cpp +++ b/src/lua/TPTScriptInterface.cpp @@ -1,9 +1,6 @@ #include "TPTScriptInterface.h" #include -#ifdef MACOSX -#include -#endif #include #include @@ -314,7 +311,7 @@ AnyType TPTScriptInterface::tptS_set(std::deque * words) if (newValue < 0 || newValue >= PT_NUM) { // TODO: add element CAKE to invalidate this - if (!strcasecmp(((StringType)value).Value().ToUtf8().c_str(),"cake")) + if (((StringType)value).Value().ToUpper() == "CAKE") throw GeneralException("Cake is a lie, not an element"); throw GeneralException("Invalid element"); } diff --git a/src/lua/meson.build b/src/lua/meson.build index e87124233..137466f0b 100644 --- a/src/lua/meson.build +++ b/src/lua/meson.build @@ -10,11 +10,16 @@ luaconsole_files = files( 'LuaProgressBar.cpp', 'LuaScriptInterface.cpp', 'LuaSlider.cpp', + 'LuaSocket.cpp', 'LuaSmartRef.cpp', 'LuaTextbox.cpp', 'LuaWindow.cpp', - 'LuaSocket.cpp', ) +if host_platform == 'windows' + luaconsole_files += files('LuaSocketWindows.cpp') +else + luaconsole_files += files('LuaSocketDefault.cpp') +endif if enable_http luaconsole_files += files('LuaSocketTCPHttp.cpp') else