diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3804f1eb..d2684228 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,8 @@ name: CI on: push: branches: [ "6" ] - pull-request: + + pull_request: branches: [ "6" ] jobs: diff --git a/BUILD.md b/BUILD.md index 585b088c..0d0afaff 100644 --- a/BUILD.md +++ b/BUILD.md @@ -39,10 +39,9 @@ git submodule update Getting the project to build and run on Linux is easy if you use any modern and up-to-date linux distribution. ## Build dependencies -* A C++ compiler capable of building C++11 code. -* Qt 5.6+ Development tools (http://qt-project.org/downloads) ("Qt Online Installer for Linux (64 bit)") or the equivalent from your package manager. It is always better to use the Qt from your distribution, as long as it has a new enough version. (for example, `qttools5-dev`) -* cmake 3.1 or newer -* zlib (for example, `zlib1g-dev`) +* A C++ compiler capable of building C++17 code. +* Qt 6.2+ Development tools (http://qt-project.org/downloads) ("Qt Online Installer for Linux (64 bit)") or the equivalent from your package manager. It is always better to use the Qt from your distribution, as long as it has a new enough version. +* cmake 3.22 or newer * Java JDK 8 (for example, `openjdk-8-jdk`) * GL headers (for example, `libgl1-mesa-dev`) @@ -71,8 +70,9 @@ You can use IDEs like KDevelop or QtCreator to open the CMake project if you wan 1. Run the Qt installer. 2. Choose a place to install Qt. 3. Choose the components you want to install. - - You need Qt 5.6.x 64-bit ticked. + - You need Qt 6.5.x 64-bit ticked. - You need Tools/Qt Creator ticked. + - You need The extra Core5Compat library ticked. - Other components are selected by default, you can untick them if you don't need them. 4. Accept the license agreements. 5. Double check the install details and then click "Install". @@ -98,20 +98,11 @@ You can use IDEs like KDevelop or QtCreator to open the CMake project if you wan Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt Creator. The project will simply not compile using Microsoft build tools, because that's not something we do. If it does compile, it is by chance only. ## Dependencies -* [Qt 5.6+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows - - http://download.qt.io/new_archive/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe - - Download the MinGW version (MSVC version does not work). -* [OpenSSL](https://github.com/IndySockets/OpenSSL-Binaries/tree/master/Archive/) -- Win32 OpenSSL, version 1.0.2g (from 2016) - - https://github.com/IndySockets/OpenSSL-Binaries/raw/master/Archive/openssl-1.0.2g-i386-win32.zip - - the usual OpenSSL for Windows (http://slproweb.com/products/Win32OpenSSL.html) only provides the newest version of OpenSSL, and we need the 1.0.2g version - - **Download the 32-bit version, not 64-bit.** - - Microsoft Visual C++ 2008 Redist is required for this, there's a link on the OpenSSL download page above next to the main download. - - We use a custom build of OpenSSL that doesn't have this dependency. For normal development, the custom build is not necessary though. -* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine +* [Qt 6.5+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows * [Java JDK 8](https://adoptium.net/releases.html?variant=openjdk8) - Use the MSI installer. * [CMake](http://www.cmake.org/cmake/resources/software.html) -- Windows (Win32 Installer) -Ensure that OpenSSL, zlib, Java and CMake are on `PATH`. +Ensure that Java and CMake are on `PATH`. ## Getting set up @@ -119,17 +110,14 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`. 1. Run the Qt installer 2. Choose a place to install Qt (C:\Qt is the default), 3. Choose the components you want to install - - You need Qt 5.6 (32 bit) ticked, - - You need Tools/Qt Creator ticked, + - You need Qt 6.5 ticked. + - You need Tools/Qt Creator ticked. + - You need The extra Core5Compat library ticked. - Other components are selected by default, you can untick them if you don't need them. 4. Accept the license agreements, 5. Double check the install details and then click "Install" - Installation can take a very long time, go grab a cup of tea or something and let it work. -### Installing OpenSSL -1. Download .zip file from the link above. -2. Unzip and add the directory to PATH, so CMake can find it. - ### Installing CMake 1. Run the CMake installer, 2. It's easiest if you choose to add CMake to the PATH for all users, @@ -151,41 +139,13 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`. - If the project builds successfully it will run and the Launcher window will pop up, - Test OpenSSL by making an instance and trying to log in. If Qt Creator couldn't find OpenSSL during the CMake stage, login will fail and you'll get an error. -The following .dlls are needed for the app to run (copy them to build directory if you want to be able to move the build to another pc): -``` -platforms/qwindows.dll -libeay32.dll -libgcc_s_dw2-1.dll -libssp-0.dll -libstdc++-6.dll -libwinpthread-1.dll -Qt5Core.dll -Qt5Gui.dll -Qt5Network.dll -Qt5Svg.dll -Qt5Widgets.dll -Qt5Xml.dll -ssleay32.dll -zlib1.dll -``` - -**These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!** -### Compile from command line on Windows -1. If you installed Qt with the web installer, there should be a shortcut called `Qt 5.4 for Desktop (MinGW 4.9 32-bit)` in the Start menu on Windows 7 and 10. Best way to find it is to search for it. Do note you cannot just use cmd.exe, you have to use the shortcut, otherwise the proper MinGW software will not be on the PATH. -2. Once that is open, change into your user directory, and clone MultiMC by doing `git clone --recursive https://github.com/MultiMC/Launcher.git`, and change directory to the folder you cloned to. -3. Make a build directory, and change directory to the directory and do `cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=C:\Path\that\makes\sense\for\you`. By default, it will install to C:\Program Files (x86), which you might not want, if you want a local installation. If you want to install it to that directory, make sure to run the command window as administrator. -3. Do `mingw32-make -jX`, where X is the number of cores your CPU has plus one. -4. Now to wait for it to compile. This could take some time. Hopefully it compiles properly. -5. Run the command `mingw32-make install`, and it should install MultiMC, to whatever the `-DCMAKE_INSTALL_PREFIX` was. -6. In most cases, whenever compiling, the OpenSSL dll's aren't put into the directory to where MultiMC installs, meaning you cannot log in. The best way to fix this is just to do `copy C:\OpenSSL-Win32\*.dll C:\Where\you\installed\MultiMC\to`. This should copy the required OpenSSL dll's to log in. - # macOS ### Install prerequisites: - Install XCode Command Line tools - Install the official build of CMake (https://cmake.org/download/) - Install JDK 8 (https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html) -- Get Qt 5.6 and install it (https://download.qt.io/new_archive/qt/5.6/5.6.3/) +- Get Qt 6.5 and install it ### XCode Command Line tools @@ -209,10 +169,7 @@ cmake \ -DCMAKE_CXX_COMPILER=/usr/bin/clang++ \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX:PATH="$(dirname $PWD)/dist/" \ - -DCMAKE_PREFIX_PATH="/path/to/Qt5.6/" \ - -DQt5_DIR="/path/to/Qt5.6/" \ - -DLauncher_LAYOUT=mac-bundle \ - -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \ + -DCMAKE_PREFIX_PATH="/path/to/Qt6.5/" \ .. make install ``` diff --git a/launcher/UpdateController.cpp b/launcher/UpdateController.cpp index f9b7d349..de7a02dc 100644 --- a/launcher/UpdateController.cpp +++ b/launcher/UpdateController.cpp @@ -116,7 +116,6 @@ void UpdateController::installUpdates() return; } - bool useXPHack = false; QString exePath; QString exeOrigin; QString exeBackup; @@ -138,20 +137,7 @@ void UpdateController::installUpdates() } #endif QFileInfo destination (FS::PathCombine(m_root, op.destination)); -#ifdef Q_OS_WIN32 - if(QSysInfo::windowsVersion() < QSysInfo::WV_VISTA) - { - if(destination.fileName() == windowsExeName) - { - QDir rootDir(m_root); - exeOrigin = rootDir.relativeFilePath(op.source); - exePath = rootDir.relativeFilePath(op.destination); - exeBackup = rootDir.relativeFilePath(FS::PathCombine(backupPath, destination.fileName())); - useXPHack = true; - continue; - } - } -#endif + if(destination.exists()) { QString backupName = op.destination; @@ -224,38 +210,6 @@ void UpdateController::installUpdates() args = qApp->arguments(); args.removeFirst(); - // on old Windows, do insane things... no error checking here, this is just to have something. - if(useXPHack) - { - QString script; - auto nativePath = QDir::toNativeSeparators(exePath); - auto nativeOriginPath = QDir::toNativeSeparators(exeOrigin); - auto nativeBackupPath = QDir::toNativeSeparators(exeBackup); - - // so we write this vbscript thing... - QTextStream out(&script); - out << "WScript.Sleep 1000\n"; - out << "Set fso=CreateObject(\"Scripting.FileSystemObject\")\n"; - out << "Set shell=CreateObject(\"WScript.Shell\")\n"; - out << "fso.MoveFile \"" << nativePath << "\", \"" << nativeBackupPath << "\"\n"; - out << "fso.MoveFile \"" << nativeOriginPath << "\", \"" << nativePath << "\"\n"; - out << "shell.Run \"" << nativePath << "\"\n"; - - QString scriptPath = FS::PathCombine(m_root, "update", "update.vbs"); - - // we save it - QFile scriptFile(scriptPath); - scriptFile.open(QIODevice::WriteOnly); - scriptFile.write(script.toLocal8Bit().replace("\n", "\r\n")); - scriptFile.close(); - - // we run it - started = QProcess::startDetached("wscript", {scriptPath}, m_root); - - // and we quit. conscious thought. - qApp->quit(); - return; - } bool doLiveCheck = true; bool startFailed = false; diff --git a/launcher/java/JavaUtils.cpp b/launcher/java/JavaUtils.cpp index fd7e43e9..d413c422 100644 --- a/launcher/java/JavaUtils.cpp +++ b/launcher/java/JavaUtils.cpp @@ -154,6 +154,10 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString { QList javas; + auto wKeyName = keyName.toStdWString(); + auto wKeyJavaDir = keyJavaDir.toStdWString(); + auto wSubkeySuffix = subkeySuffix.toStdWString(); + QString archType = "unknown"; if (keyType == KEY_WOW64_64KEY) archType = "64"; @@ -161,26 +165,24 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString archType = "32"; HKEY jreKey; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName.toStdString().c_str(), 0, - KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wKeyName.c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) { // Read the current type version from the registry. // This will be used to find any key that contains the JavaHome value. char *value = new char[0]; DWORD valueSz = 0; - if (RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz) == + if (RegQueryValueExW(jreKey, L"CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz) == ERROR_MORE_DATA) { value = new char[valueSz]; - RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz); + RegQueryValueExW(jreKey, L"CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz); } - TCHAR subKeyName[255]; + wchar_t subKeyName[255]; DWORD subKeyNameSize, numSubKeys, retCode; // Get the number of subkeys - RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); + RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); // Iterate until RegEnumKeyEx fails if (numSubKeys > 0) @@ -188,34 +190,29 @@ QList JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString for (DWORD i = 0; i < numSubKeys; i++) { subKeyNameSize = 255; - retCode = RegEnumKeyEx(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, - NULL); + retCode = RegEnumKeyExW(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); if (retCode == ERROR_SUCCESS) { // Now open the registry key for the version that we just got. - QString newKeyName = keyName + "\\" + subKeyName + subkeySuffix; + std::wstring newKeyName = wKeyName + L"\\" + subKeyName + wSubkeySuffix; HKEY newKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0, - KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) { // Read the JavaHome value to find where Java is installed. value = new char[0]; valueSz = 0; - if (RegQueryValueEx(newKey, keyJavaDir.toStdString().c_str(), NULL, NULL, (BYTE *)value, - &valueSz) == ERROR_MORE_DATA) + if (RegQueryValueExW(newKey, wKeyJavaDir.c_str(), NULL, NULL, (BYTE *)value, &valueSz) == ERROR_MORE_DATA) { value = new char[valueSz]; - RegQueryValueEx(newKey, keyJavaDir.toStdString().c_str(), NULL, NULL, (BYTE *)value, - &valueSz); + RegQueryValueExW(newKey, wKeyJavaDir.c_str(), NULL, NULL, (BYTE *)value, &valueSz); // Now, we construct the version object and add it to the list. JavaInstallPtr javaVersion(new JavaInstall()); - javaVersion->id = subKeyName; + javaVersion->id = QString::fromWCharArray(subKeyName, valueSz); javaVersion->arch = archType; - javaVersion->path = - QDir(FS::PathCombine(value, "bin")).absoluteFilePath("javaw.exe"); + javaVersion->path = QDir(FS::PathCombine(value, "bin")).absoluteFilePath("javaw.exe"); javas.append(javaVersion); } diff --git a/launcher/main.cpp b/launcher/main.cpp index aabb5a06..448e9fc1 100644 --- a/launcher/main.cpp +++ b/launcher/main.cpp @@ -24,11 +24,6 @@ int main(int argc, char *argv[]) return 42; #endif -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); -#endif - // initialize Qt Application app(argc, argv); @@ -56,4 +51,5 @@ int main(int argc, char *argv[]) case Application::Succeeded: return 0; } + return 1; } diff --git a/launcher/ui/dialogs/CreateShortcutDialog.cpp b/launcher/ui/dialogs/CreateShortcutDialog.cpp index 44844b97..436500c6 100644 --- a/launcher/ui/dialogs/CreateShortcutDialog.cpp +++ b/launcher/ui/dialogs/CreateShortcutDialog.cpp @@ -21,6 +21,43 @@ #ifdef Q_OS_WIN #include #include + +static void createWindowsLink(QString target, QString workingDir, QString args, QString filename, QString desc, QString iconPath) +{ + HRESULT result; + IShellLink *link; + + CoInitialize(nullptr); + result = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &link); + if (SUCCEEDED(result)) + { + IPersistFile *file; + + auto wTarget = target.toStdWString(); + auto wWorkingDir = workingDir.toStdWString(); + auto wArgs = args.toStdWString(); + auto wDesc = desc.toStdWString(); + auto wIconPath = iconPath.toStdWString(); + + link->SetPath(wTarget.c_str()); + link->SetWorkingDirectory(wWorkingDir.c_str()); + link->SetArguments(wArgs.c_str()); + link->SetDescription(wDesc.c_str()); + link->SetIconLocation(wIconPath.c_str(), 0); + + result = link->QueryInterface(IID_IPersistFile, (LPVOID *) &file); + + if (SUCCEEDED(result)) + { + auto wFilename = filename.toStdWString(); + wchar_t path[MAX_PATH]; + file->Save(path, TRUE); + file->Release(); + } + link->Release(); + } + CoUninitialize(); +} #endif CreateShortcutDialog::CreateShortcutDialog(QWidget *parent, InstancePtr instance) @@ -218,8 +255,7 @@ void CreateShortcutDialog::createShortcut() { QTextStream stream(&shortcutFile); stream << shortcutText; - shortcutFile.setPermissions(QFile::ReadOwner | QFile::ReadGroup | QFile::ReadOther - | QFile::WriteOwner | QFile::ExeOwner | QFile::ExeGroup); + shortcutFile.setPermissions(QFile::ReadOwner | QFile::ReadGroup | QFile::ReadOther | QFile::WriteOwner | QFile::ExeOwner | QFile::ExeGroup); shortcutFile.close(); } #ifdef Q_OS_WIN @@ -232,48 +268,14 @@ void CreateShortcutDialog::createShortcut() iconPixmap.save(QDir::currentPath() + "/icons/shortcut-icon.ico"); } - createWindowsLink(QDir::toNativeSeparators(QCoreApplication::applicationFilePath()).toStdString().c_str(), - QDir::toNativeSeparators(QDir::currentPath()).toStdString().c_str(), - getLaunchArgs().toStdString().c_str(), - ui->shortcutPath->text().toStdString().c_str(), - (m_instance->name() + " - " + BuildConfig.LAUNCHER_DISPLAYNAME).toStdString().c_str(), - QDir::toNativeSeparators(QDir::currentPath() + "/icons/shortcut-icon.ico").toStdString().c_str() - ); + createWindowsLink( + QDir::toNativeSeparators(QCoreApplication::applicationFilePath()), + QDir::toNativeSeparators(QDir::currentPath()), + getLaunchArgs(), + ui->shortcutPath->text(), + (m_instance->name() + " - " + BuildConfig.LAUNCHER_DISPLAYNAME), + QDir::toNativeSeparators(QDir::currentPath() + "/icons/shortcut-icon.ico") + ); } #endif } - -#ifdef Q_OS_WIN -void CreateShortcutDialog::createWindowsLink(LPCSTR target, LPCSTR workingDir, LPCSTR args, LPCSTR filename, - LPCSTR desc, LPCSTR iconPath) -{ - HRESULT result; - IShellLink *link; - - CoInitialize(nullptr); - result = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &link); - if (SUCCEEDED(result)) - { - IPersistFile *file; - - link->SetPath(target); - link->SetWorkingDirectory(workingDir); - link->SetArguments(args); - link->SetDescription(desc); - link->SetIconLocation(iconPath, 0); - - result = link->QueryInterface(IID_IPersistFile, (LPVOID *) &file); - - if (SUCCEEDED(result)) - { - WCHAR path[MAX_PATH]; - MultiByteToWideChar(CP_ACP, 0, filename, -1, path, MAX_PATH); - - file->Save(path, TRUE); - file->Release(); - } - link->Release(); - } - CoUninitialize(); -} -#endif diff --git a/launcher/ui/dialogs/CreateShortcutDialog.h b/launcher/ui/dialogs/CreateShortcutDialog.h index 4714253b..cf8b045a 100644 --- a/launcher/ui/dialogs/CreateShortcutDialog.h +++ b/launcher/ui/dialogs/CreateShortcutDialog.h @@ -43,8 +43,4 @@ private: QString getLaunchArgs(bool escapeQuotesTwice = false); void createShortcut(); - -#ifdef Q_OS_WIN - void createWindowsLink(LPCSTR target, LPCSTR workingDir, LPCSTR args, LPCSTR filename, LPCSTR desc, LPCSTR iconPath); -#endif }; \ No newline at end of file