mirror of
https://github.com/UltimMC/Launcher.git
synced 2025-12-13 12:12:14 +00:00
Compare commits
1 Commits
0.6.14
...
feature/li
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bdf63b0ee |
5
.arcconfig
Normal file
5
.arcconfig
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"project_id": "MultiMC5",
|
||||||
|
"conduit_uri": "http://ph.multimc.org"
|
||||||
|
}
|
||||||
|
|
||||||
25
.clang-format
Normal file
25
.clang-format
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
UseTab: false
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentFunctionDeclarationAfterType: false
|
||||||
|
NamespaceIndentation: None
|
||||||
|
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
ColumnLimit: 160
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
|
||||||
|
Standard: Cpp11
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpaceAfterControlStatementKeyword: true
|
||||||
|
|
||||||
|
AlignTrailingComments: true
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
51
.github/ISSUE_TEMPLATE.md
vendored
Normal file
51
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<!--
|
||||||
|
Before submitting this issue, please make sure you have:
|
||||||
|
|
||||||
|
1. Filled out this form completely, the only optional field is "additional info".
|
||||||
|
- Use as many details as possible and state the problem clearly.
|
||||||
|
2. Proof-read your ENTIRE issue report.
|
||||||
|
- Grammar and spelling mistakes make issue reports harder to understand.
|
||||||
|
3. Made sure your problem is not caused by an issue in your own modpack.
|
||||||
|
- We provide support for MultiMC, not your modpack. Problems with your modpack will be ignored.
|
||||||
|
4. Given the issue a descriptive title.
|
||||||
|
- A good title includes a brief summary of the issue and avoids things such as "Help" and "What?!".
|
||||||
|
Use of UPPERCASE is discouraged, as it reads like someone is screaming.
|
||||||
|
5. Place all information below the ---- of lines.
|
||||||
|
- It makes the issue look pretty
|
||||||
|
|
||||||
|
If you believe your issue to be a bug, please make sure you check the wiki page: https://github.com/MultiMC/MultiMC5/wiki/Report-a-Bug
|
||||||
|
-->
|
||||||
|
|
||||||
|
System Information
|
||||||
|
-----------------------------
|
||||||
|
MultiMC version:
|
||||||
|
|
||||||
|
Operating System:
|
||||||
|
|
||||||
|
Summary of the issue or suggestion:
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
What should happen:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Steps to reproduce the issue (Add more if needed):
|
||||||
|
-------------------------------------------------------------
|
||||||
|
1.
|
||||||
|
|
||||||
|
2.
|
||||||
|
|
||||||
|
3.
|
||||||
|
|
||||||
|
Suspected cause:
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Logs/Screenshots:
|
||||||
|
----------------------------
|
||||||
|
[//]: # (Please refer to https://github.com/MultiMC/MultiMC5/wiki/Log-Upload for instructions on how to attach your logs.)
|
||||||
|
|
||||||
|
|
||||||
|
Additional Info:
|
||||||
|
---------------------------
|
||||||
51
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
51
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,51 +0,0 @@
|
|||||||
name: Bug Report
|
|
||||||
description: File a bug report
|
|
||||||
labels: [bug, needs-triage]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
If you need help with running Minecraft, please visit us [on our Discord](https://discord.gg/multimc) before making a bug report.
|
|
||||||
|
|
||||||
Before submitting a bug report, please make sure you have read this *entire* form, and that:
|
|
||||||
* You have read the [FAQ](https://github.com/MultiMC/Launcher/wiki/FAQ) and it has not answered your question
|
|
||||||
* Your bug is not caused by Minecraft or any mods you have installed.
|
|
||||||
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/MultiMC/Launcher/issues)
|
|
||||||
|
|
||||||
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Operating System
|
|
||||||
description: If you know this bug occurs on multiple operating systems, select all you have tested.
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Windows
|
|
||||||
- macOS
|
|
||||||
- Linux
|
|
||||||
- Other
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Description of bug
|
|
||||||
description: What did you expect to happen, what happened, and why is it incorrect?
|
|
||||||
placeholder: The cat button should show a cat, but it showed a dog instead!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce
|
|
||||||
description: A bulleted list, or an exported instance if relevant.
|
|
||||||
placeholder: "* Press the cat button"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Suspected cause
|
|
||||||
description: If you know what could be causing this bug, describe it here.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: This issue is unique
|
|
||||||
options:
|
|
||||||
- label: I have searched the issue tracker and did not find an issue describing my bug.
|
|
||||||
required: true
|
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +0,0 @@
|
|||||||
blank_issues_enabled: true
|
|
||||||
contact_links:
|
|
||||||
- name: MultiMC Discord
|
|
||||||
url: https://discord.gg/multimc
|
|
||||||
about: Please ask for support here before opening an issue.
|
|
||||||
38
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
38
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@@ -1,38 +0,0 @@
|
|||||||
name: Suggestion
|
|
||||||
description: Make a suggestion
|
|
||||||
labels: [idea, needs-triage]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
### Use this form to suggest a feature for MultiMC.
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Role
|
|
||||||
description: In what way do you use MultiMC that needs this feature?
|
|
||||||
placeholder: I play modded Minecraft.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Suggestion
|
|
||||||
description: What do you want MultiMC to do?
|
|
||||||
placeholder: I want the cat button to meow.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Benefit
|
|
||||||
description: Why do you need MultiMC to do this?
|
|
||||||
placeholder: so that I can always hear a cat when I need to.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: This suggestion is unique
|
|
||||||
options:
|
|
||||||
- label: I have searched the issue tracker and did not find an issue describing my suggestion, especially not one that has been rejected.
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: You may use the editor below to elaborate further.
|
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,21 +1,22 @@
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
*.kdev4
|
.kdev4
|
||||||
.user
|
.user
|
||||||
.directory
|
.directory
|
||||||
resources/CMakeFiles
|
resources/CMakeFiles
|
||||||
|
resources/MultiMCLauncher.jar
|
||||||
*~
|
*~
|
||||||
*.swp
|
*.swp
|
||||||
html/
|
html/
|
||||||
|
|
||||||
# Project Files
|
# Project Files
|
||||||
*.pro.user
|
MultiMC5.kdev4
|
||||||
|
MultiMC.pro.user
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
CMakeLists.txt.user.*
|
CMakeLists.txt.user.*
|
||||||
/.project
|
/.project
|
||||||
/.settings
|
/.settings
|
||||||
/.idea
|
/.idea
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Debug
|
|
||||||
|
|
||||||
# Build dirs
|
# Build dirs
|
||||||
build
|
build
|
||||||
@@ -29,7 +30,3 @@ tags
|
|||||||
|
|
||||||
#OSX Stuff
|
#OSX Stuff
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
branding/
|
|
||||||
secrets/
|
|
||||||
run/
|
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,8 +1,6 @@
|
|||||||
[submodule "depends/libnbtplusplus"]
|
[submodule "depends/libnbtplusplus"]
|
||||||
path = libraries/libnbtplusplus
|
path = libraries/libnbtplusplus
|
||||||
url = https://github.com/MultiMC/libnbtplusplus.git
|
url = https://github.com/MultiMC/libnbtplusplus.git
|
||||||
pushurl = git@github.com:MultiMC/libnbtplusplus.git
|
|
||||||
[submodule "libraries/quazip"]
|
[submodule "libraries/quazip"]
|
||||||
path = libraries/quazip
|
path = libraries/quazip
|
||||||
url = https://github.com/MultiMC/quazip.git
|
url = https://github.com/MultiMC/quazip.git
|
||||||
pushurl = git@github.com:MultiMC/quazip.git
|
|
||||||
|
|||||||
38
.travis.yml
Normal file
38
.travis.yml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# General set up
|
||||||
|
language: cpp
|
||||||
|
cache: apt
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
dist: precise
|
||||||
|
sudo: required
|
||||||
|
compiler: gcc
|
||||||
|
env: TRAVIS_DIST=precise QT_VERSION=5.4.2
|
||||||
|
- os: linux
|
||||||
|
dist: precise
|
||||||
|
sudo: required
|
||||||
|
compiler: gcc
|
||||||
|
env: TRAVIS_DIST=precise QT_VERSION=5.6.2
|
||||||
|
- os: linux
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
compiler: gcc
|
||||||
|
env: TRAVIS_DIST=trusty QT_VERSION=5.4.2
|
||||||
|
- os: linux
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
compiler: gcc
|
||||||
|
env: TRAVIS_DIST=trusty QT_VERSION=5.6.2
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
install:
|
||||||
|
- source travis/prepare.sh # installs qt and cmake. need to source because some env vars are set from there
|
||||||
|
|
||||||
|
# Actual work
|
||||||
|
before_script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH ..
|
||||||
|
script:
|
||||||
|
- make -j4 && make test ARGS="-V"
|
||||||
90
BUILD.md
90
BUILD.md
@@ -7,15 +7,14 @@ Build Instructions
|
|||||||
* [Getting the source](#source)
|
* [Getting the source](#source)
|
||||||
* [Linux](#linux)
|
* [Linux](#linux)
|
||||||
* [Windows](#windows)
|
* [Windows](#windows)
|
||||||
* [macOS](#macos)
|
* [OS X](#os-x)
|
||||||
|
|
||||||
# Note
|
# Note
|
||||||
|
|
||||||
MultiMC is a portable application and is not supposed to be installed into any system folders.
|
MultiMC is a portable application and is not supposed to be installed into any system folders.
|
||||||
That would be anything outside your home folder. Before running `make install`, make sure
|
That would be anything outside your home folder. Before runing `make install`, make sure
|
||||||
you set the install path to something you have write access to. Never build this under
|
you set the install path to something you have write access to. Never build this under
|
||||||
an administrator/root level account. Don't use `sudo`. It won't work and it's not supposed to work.
|
an administrator/root level account. Don't use `sudo`. It won't work and it's not supposed to work.
|
||||||
Also note that this guide is for development purposes only. No support is given for building your own fork or special build for any reason whatsoever.
|
|
||||||
|
|
||||||
|
|
||||||
# Getting the source
|
# Getting the source
|
||||||
@@ -23,7 +22,7 @@ Also note that this guide is for development purposes only. No support is given
|
|||||||
Clone the source code using git and grab all the submodules:
|
Clone the source code using git and grab all the submodules:
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/MultiMC/Launcher.git
|
git clone git@github.com:MultiMC/MultiMC5.git
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update
|
git submodule update
|
||||||
```
|
```
|
||||||
@@ -51,7 +50,7 @@ mkdir ~/MultiMC && cd ~/MultiMC
|
|||||||
mkdir build
|
mkdir build
|
||||||
mkdir install
|
mkdir install
|
||||||
# clone the complete source
|
# clone the complete source
|
||||||
git clone --recursive https://github.com/MultiMC/Launcher.git src
|
git clone --recursive git@github.com:MultiMC/MultiMC5.git src
|
||||||
# configure the project
|
# configure the project
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
|
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
|
||||||
@@ -75,7 +74,7 @@ You can use IDEs like KDevelop or QtCreator to open the CMake project if you wan
|
|||||||
### Loading the project in Qt Creator (optional)
|
### Loading the project in Qt Creator (optional)
|
||||||
1. Open Qt Creator.
|
1. Open Qt Creator.
|
||||||
2. Choose `File->Open File or Project`.
|
2. Choose `File->Open File or Project`.
|
||||||
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt.
|
3. Navigate to the MultiMC5 source folder you cloned and choose CMakeLists.txt.
|
||||||
4. Read the instructions that just popped up about a build location and choose one.
|
4. Read the instructions that just popped up about a build location and choose one.
|
||||||
5. You should see "Run CMake" in the window.
|
5. You should see "Run CMake" in the window.
|
||||||
- Make sure that Generator is set to "Unix Generator (Desktop Qt 5.6.x GCC 64bit)".
|
- Make sure that Generator is set to "Unix Generator (Desktop Qt 5.6.x GCC 64bit)".
|
||||||
@@ -83,7 +82,7 @@ You can use IDEs like KDevelop or QtCreator to open the CMake project if you wan
|
|||||||
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
||||||
- Hit "Finish" if CMake ran successfully.
|
- Hit "Finish" if CMake ran successfully.
|
||||||
6. Cross your fingers and press the Run button (bottom left of Qt Creator).
|
6. Cross your fingers and press the Run button (bottom left of Qt Creator).
|
||||||
- If the project builds successfully it will run and the Launcher window will pop up.
|
- If the project builds successfully it will run and the MultiMC5 window will pop up.
|
||||||
|
|
||||||
**If this doesn't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!**
|
**If this doesn't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!**
|
||||||
|
|
||||||
@@ -93,19 +92,14 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
* [Qt 5.6+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows
|
* [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
|
* [OpenSSL](http://slproweb.com/products/Win32OpenSSL.html) -- Newest Win32 OpenSSL Light
|
||||||
- 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.
|
- 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.
|
- 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
|
* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine
|
||||||
* [Java JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
|
* [Java JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
|
||||||
* [CMake](http://www.cmake.org/cmake/resources/software.html) -- Windows (Win32 Installer)
|
* [CMake](http://www.cmake.org/cmake/resources/software.html) -- Windows (Win32 Installer)
|
||||||
|
|
||||||
Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
Put it somewhere on the `PATH`, so that it is accessible from the console.
|
||||||
|
|
||||||
## Getting set up
|
## Getting set up
|
||||||
|
|
||||||
@@ -121,8 +115,9 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
|||||||
- Installation can take a very long time, go grab a cup of tea or something and let it work.
|
- Installation can take a very long time, go grab a cup of tea or something and let it work.
|
||||||
|
|
||||||
### Installing OpenSSL
|
### Installing OpenSSL
|
||||||
1. Download .zip file from the link above.
|
1. Run the OpenSSL installer,
|
||||||
2. Unzip and add the directory to PATH, so CMake can find it.
|
2. It's best to choose the option to copy OpenSSL DLLs to the `/bin` directory
|
||||||
|
- If you do this you'll need to add that directory (the default being `C:\OpenSSL-Win32\bin`) to your PATH system variable (Google how to do this, or use this guide for Java: http://www.java.com/en/download/help/path.xml).
|
||||||
|
|
||||||
### Installing CMake
|
### Installing CMake
|
||||||
1. Run the CMake installer,
|
1. Run the CMake installer,
|
||||||
@@ -132,7 +127,7 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
|||||||
### Loading the project
|
### Loading the project
|
||||||
1. Open Qt Creator,
|
1. Open Qt Creator,
|
||||||
2. Choose File->Open File or Project,
|
2. Choose File->Open File or Project,
|
||||||
3. Navigate to the Launcher source folder you cloned and choose CMakeLists.txt,
|
3. Navigate to the MultiMC5 source folder you cloned and choose CMakeLists.txt,
|
||||||
4. Read the instructions that just popped up about a build location and choose one,
|
4. Read the instructions that just popped up about a build location and choose one,
|
||||||
5. If you chose not to add CMake to the system PATH, tell Qt Creator where you installed it,
|
5. If you chose not to add CMake to the system PATH, tell Qt Creator where you installed it,
|
||||||
- Otherwise you can skip this step.
|
- Otherwise you can skip this step.
|
||||||
@@ -142,66 +137,49 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
|||||||
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
- You'll see warnings and it might not be clear that it succeeded until you scroll to the bottom of the window.
|
||||||
- Hit "Finish" if CMake ran successfully.
|
- Hit "Finish" if CMake ran successfully.
|
||||||
7. Cross your fingers and press the Run button (bottom left of Qt Creator)!
|
7. Cross your fingers and press the Run button (bottom left of Qt Creator)!
|
||||||
- If the project builds successfully it will run and the Launcher window will pop up,
|
- If the project builds successfully it will run and the MultiMC5 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.
|
- 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))!**
|
**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
|
### 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.
|
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.
|
2. Once that is open, change into your user directory, and clone MultiMC by doing `git clone --recursive https://github.com/MultiMC/MultiMC5.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. 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.
|
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.
|
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.
|
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.
|
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
|
# OS X
|
||||||
|
|
||||||
### Install prerequisites:
|
### Install prerequisites:
|
||||||
- Install XCode and set it up to the point where you can build things from a terminal
|
* install homebrew
|
||||||
- Install the official build of CMake (https://cmake.org/download/)
|
* then:
|
||||||
- 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/)
|
```
|
||||||
|
brew install qt5
|
||||||
|
brew tap homebrew/versions
|
||||||
|
brew install gcc48
|
||||||
|
brew install cmake
|
||||||
|
```
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
Pick an installation path - this is where the final `.app` will be constructed when you run `make install`. Supply it as the `CMAKE_INSTALL_PREFIX` argument during CMake configuration.
|
Pick an installation path - this is where the final `.app` will be constructed when you run `make install`. Supply it as the `CMAKE_INSTALL_PREFIX` argument during CMake configuration.
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone --recursive https://github.com/MultiMC/Launcher.git
|
git clone https://github.com/MultiMC/MultiMC5.git
|
||||||
cd Launcher
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
cd MultiMC5
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake \
|
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5
|
||||||
-DCMAKE_C_COMPILER=/usr/bin/clang \
|
export CC=/usr/local/bin/gcc-4.8
|
||||||
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
export CXX=/usr/local/bin/g++-4.8
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/Users/YOU/some/path/that/makes/sense/
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH="$(dirname $PWD)/dist/" \
|
make
|
||||||
-DCMAKE_PREFIX_PATH="/path/to/Qt5.6/" \
|
|
||||||
-DQt5_DIR="/path/to/Qt5.6/" \
|
|
||||||
-DLauncher_LAYOUT=mac-bundle \
|
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
|
|
||||||
..
|
|
||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** The final app bundle may not run due to code signing issues, which
|
**These build instructions were taken and adapted from https://gist.github.com/number5/7250865 If they don't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!**
|
||||||
need to be fixed with `codesign -fs -`.
|
|
||||||
|
|||||||
187
CMakeLists.txt
187
CMakeLists.txt
@@ -1,27 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
|
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
||||||
|
if(IS_IN_SOURCE_BUILD)
|
||||||
|
message(AUTHOR_WARNING "You are building MultiMC in-source. This is NOT recommended!")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
# In Qt 5.1+ we have our own main() function, don't autolink to qtmain on Windows
|
||||||
cmake_policy(SET CMP0020 OLD)
|
cmake_policy(SET CMP0020 OLD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Launcher)
|
project(MultiMC)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
|
|
||||||
if(IS_IN_SOURCE_BUILD)
|
|
||||||
message(FATAL_ERROR "You are building the Launcher in-source. Please separate the build tree from the source tree.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
if(CMAKE_HOST_SYSTEM_VERSION MATCHES ".*[Mm]icrosoft.*" OR
|
|
||||||
CMAKE_HOST_SYSTEM_VERSION MATCHES ".*WSL.*"
|
|
||||||
)
|
|
||||||
message(FATAL_ERROR "Building the Launcher is not supported in Linux-on-Windows distributions.")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
##################################### Set CMake options #####################################
|
##################################### Set CMake options #####################################
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
@@ -41,7 +32,7 @@ set(CMAKE_C_STANDARD_REQUIRED true)
|
|||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
set(CMAKE_CXX_FLAGS " -Wall -pedantic -Werror -Wno-deprecated-declarations -D_GLIBCXX_USE_CXX11_ABI=0 -fstack-protector-strong --param=ssp-buffer-size=4 -O3 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS " -Wall -pedantic -Werror -D_GLIBCXX_USE_CXX11_ABI=0 -fstack-protector-strong --param=ssp-buffer-size=4 -O3 -D_FORTIFY_SOURCE=2 ${CMAKE_CXX_FLAGS}")
|
||||||
if(UNIX AND APPLE)
|
if(UNIX AND APPLE)
|
||||||
set(CMAKE_CXX_FLAGS " -stdlib=libc++ ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS " -stdlib=libc++ ${CMAKE_CXX_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
@@ -50,61 +41,42 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror=return-type")
|
|||||||
##################################### Set Application options #####################################
|
##################################### Set Application options #####################################
|
||||||
|
|
||||||
######## Set URLs ########
|
######## Set URLs ########
|
||||||
set(Launcher_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetch Launcher's news RSS feed from.")
|
set(MultiMC_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetch MultiMC's news RSS feed from.")
|
||||||
|
|
||||||
######## Set version numbers ########
|
######## Set version numbers ########
|
||||||
set(Launcher_VERSION_MAJOR 0)
|
set(MultiMC_VERSION_MAJOR 0)
|
||||||
set(Launcher_VERSION_MINOR 6)
|
set(MultiMC_VERSION_MINOR 6)
|
||||||
set(Launcher_VERSION_HOTFIX 14)
|
set(MultiMC_VERSION_HOTFIX 5)
|
||||||
|
|
||||||
# Build number
|
# Build number
|
||||||
set(Launcher_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||||
|
|
||||||
# Build platform.
|
# Build platform.
|
||||||
set(Launcher_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
set(MultiMC_BUILD_PLATFORM "" CACHE STRING "A short string identifying the platform that this build was built for. Only used by the notification system and to display in the about dialog.")
|
||||||
|
|
||||||
# Channel list URL
|
# Channel list URL
|
||||||
set(Launcher_UPDATER_BASE "" CACHE STRING "Base URL for the updater.")
|
set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
|
||||||
|
|
||||||
# Notification URL
|
# Notification URL
|
||||||
set(Launcher_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
||||||
|
|
||||||
# The metadata server
|
|
||||||
set(Launcher_META_URL "https://meta.multimc.org/v1/" CACHE STRING "URL to fetch Launcher's meta files from.")
|
|
||||||
|
|
||||||
# paste.ee API key
|
# paste.ee API key
|
||||||
set(Launcher_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE STRING "API key you can get from paste.ee when you register an account")
|
set(MultiMC_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE STRING "API key you can get from paste.ee when you register an account")
|
||||||
|
|
||||||
# Imgur API Client ID
|
|
||||||
set(Launcher_IMGUR_CLIENT_ID "5b97b0713fba4a3" CACHE STRING "Client ID you can get from Imgur when you register an application")
|
|
||||||
|
|
||||||
# Google analytics ID
|
# Google analytics ID
|
||||||
set(Launcher_ANALYTICS_ID "UA-87731965-2" CACHE STRING "ID you can get from Google analytics")
|
set(MultiMC_ANALYTICS_ID "UA-87731965-2" CACHE STRING "ID you can get from Google analytics")
|
||||||
|
|
||||||
# Bug tracker URL
|
|
||||||
set(Launcher_BUG_TRACKER_URL "" CACHE STRING "URL for the bug tracker.")
|
|
||||||
|
|
||||||
# Discord URL
|
|
||||||
set(Launcher_DISCORD_URL "" CACHE STRING "URL for the Discord guild.")
|
|
||||||
|
|
||||||
# Subreddit URL
|
|
||||||
set(Launcher_SUBREDDIT_URL "" CACHE STRING "URL for the subreddit.")
|
|
||||||
|
|
||||||
# Use the secrets library or a public stub?
|
|
||||||
option(Launcher_EMBED_SECRETS "Determines whether to embed secrets. Secrets are separate and non-public." OFF)
|
|
||||||
|
|
||||||
#### Check the current Git commit and branch
|
#### Check the current Git commit and branch
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
get_git_head_revision(Launcher_GIT_REFSPEC Launcher_GIT_COMMIT)
|
get_git_head_revision(MultiMC_GIT_REFSPEC MultiMC_GIT_COMMIT)
|
||||||
|
|
||||||
message(STATUS "Git commit: ${Launcher_GIT_COMMIT}")
|
message(STATUS "Git commit: ${MultiMC_GIT_COMMIT}")
|
||||||
message(STATUS "Git refspec: ${Launcher_GIT_REFSPEC}")
|
message(STATUS "Git refspec: ${MultiMC_GIT_REFSPEC}")
|
||||||
|
|
||||||
set(Launcher_RELEASE_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}")
|
set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}")
|
||||||
|
|
||||||
#### Custom target to just print the version.
|
#### Custom target to just print the version.
|
||||||
add_custom_target(version echo "Version: ${Launcher_RELEASE_VERSION_NAME}")
|
add_custom_target(version echo "Version: ${MultiMC_RELEASE_VERSION_NAME}")
|
||||||
add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.LAUNCHER_VERSION\\' value=\\'${Launcher_RELEASE_VERSION_NAME}\\']")
|
|
||||||
|
|
||||||
################################ 3rd Party Libs ################################
|
################################ 3rd Party Libs ################################
|
||||||
|
|
||||||
@@ -129,55 +101,47 @@ if (Qt5_POSITION_INDEPENDENT_CODE)
|
|||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
####################################### Secrets #######################################
|
|
||||||
|
|
||||||
if(Launcher_EMBED_SECRETS)
|
|
||||||
add_subdirectory(secrets)
|
|
||||||
else()
|
|
||||||
add_subdirectory(notsecrets)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
####################################### Install layout #######################################
|
####################################### Install layout #######################################
|
||||||
|
|
||||||
# How to install the build results
|
# How to install the build results
|
||||||
set(Launcher_LAYOUT "auto" CACHE STRING "The layout for the launcher installation (auto, win-bundle, lin-nodeps, mac-bundle)")
|
set(MultiMC_LAYOUT "auto" CACHE STRING "The layout for MultiMC installation (auto, win-bundle, lin-bundle, lin-nodeps, lin-system, mac-bundle)")
|
||||||
set_property(CACHE Launcher_LAYOUT PROPERTY STRINGS auto win-bundle lin-nodeps mac-bundle)
|
set_property(CACHE MultiMC_LAYOUT PROPERTY STRINGS auto win-bundle lin-bundle lin-nodeps lin-system mac-bundle)
|
||||||
|
|
||||||
if(Launcher_LAYOUT STREQUAL "auto")
|
if(MultiMC_LAYOUT STREQUAL "auto")
|
||||||
if(UNIX AND APPLE)
|
if(UNIX AND APPLE)
|
||||||
set(Launcher_LAYOUT_REAL "mac-bundle")
|
set(MultiMC_LAYOUT_REAL "mac-bundle")
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(Launcher_LAYOUT_REAL "lin-nodeps")
|
set(MultiMC_LAYOUT_REAL "lin-nodeps")
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(Launcher_LAYOUT_REAL "win-bundle")
|
set(MultiMC_LAYOUT_REAL "win-bundle")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Cannot choose a sensible install layout for your platform.")
|
message(FATAL_ERROR "Cannot choose a sensible install layout for your platform.")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
set(Launcher_LAYOUT_REAL ${Launcher_LAYOUT})
|
set(MultiMC_LAYOUT_REAL ${MultiMC_LAYOUT})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
|
if(MultiMC_LAYOUT_REAL STREQUAL "mac-bundle")
|
||||||
set(BINARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(BINARY_DEST_DIR "MultiMC.app/Contents/MacOS")
|
||||||
set(LIBRARY_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(LIBRARY_DEST_DIR "MultiMC.app/Contents/MacOS")
|
||||||
set(PLUGIN_DEST_DIR "${Launcher_Name}.app/Contents/MacOS")
|
set(PLUGIN_DEST_DIR "MultiMC.app/Contents/MacOS")
|
||||||
set(RESOURCES_DEST_DIR "${Launcher_Name}.app/Contents/Resources")
|
set(RESOURCES_DEST_DIR "MultiMC.app/Contents/Resources")
|
||||||
set(JARS_DEST_DIR "${Launcher_Name}.app/Contents/MacOS/jars")
|
set(JARS_DEST_DIR "MultiMC.app/Contents/MacOS/jars")
|
||||||
|
|
||||||
set(BUNDLE_DEST_DIR ".")
|
set(BUNDLE_DEST_DIR ".")
|
||||||
|
|
||||||
# Apps to bundle
|
# Apps to bundle
|
||||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.app")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app")
|
||||||
|
|
||||||
# Mac bundle settings
|
# Mac bundle settings
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${Launcher_Name}")
|
set(MACOSX_BUNDLE_BUNDLE_NAME "MultiMC")
|
||||||
set(MACOSX_BUNDLE_INFO_STRING "${Launcher_Name}: Minecraft launcher and management utility.")
|
set(MACOSX_BUNDLE_INFO_STRING "MultiMC Minecraft launcher and management utility.")
|
||||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.${Launcher_Name}")
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.multimc.MultiMC5")
|
||||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_BUNDLE_VERSION "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}.${Launcher_VERSION_HOTFIX}.${Launcher_VERSION_BUILD}")
|
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_VERSION_BUILD}")
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${Launcher_Name}.icns)
|
set(MACOSX_BUNDLE_ICON_FILE MultiMC.icns)
|
||||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2021 ${Launcher_Copyright}")
|
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2019 MultiMC Contributors")
|
||||||
|
|
||||||
# directories to look for dependencies
|
# directories to look for dependencies
|
||||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
@@ -186,9 +150,32 @@ if(Launcher_LAYOUT_REAL STREQUAL "mac-bundle")
|
|||||||
set(INSTALL_BUNDLE "full")
|
set(INSTALL_BUNDLE "full")
|
||||||
|
|
||||||
# Add the icon
|
# Add the icon
|
||||||
install(FILES ${Launcher_Branding_ICNS} DESTINATION ${RESOURCES_DEST_DIR} RENAME ${Launcher_Name}.icns)
|
install(FILES application/resources/MultiMC.icns DESTINATION ${RESOURCES_DEST_DIR})
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
|
elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-bundle")
|
||||||
|
set(BINARY_DEST_DIR "bin")
|
||||||
|
set(LIBRARY_DEST_DIR "bin")
|
||||||
|
set(PLUGIN_DEST_DIR "plugins")
|
||||||
|
set(BUNDLE_DEST_DIR ".")
|
||||||
|
set(RESOURCES_DEST_DIR ".")
|
||||||
|
set(JARS_DEST_DIR "bin/jars")
|
||||||
|
|
||||||
|
# Apps to bundle
|
||||||
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/MultiMC")
|
||||||
|
|
||||||
|
# directories to look for dependencies
|
||||||
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
|
|
||||||
|
# install as bundle
|
||||||
|
set(INSTALL_BUNDLE "full")
|
||||||
|
|
||||||
|
# Set RPATH
|
||||||
|
SET(MultiMC_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
|
# Install basic runner script
|
||||||
|
install(PROGRAMS application/package/linux/MultiMC DESTINATION ${BUNDLE_DEST_DIR})
|
||||||
|
|
||||||
|
elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-nodeps")
|
||||||
set(BINARY_DEST_DIR "bin")
|
set(BINARY_DEST_DIR "bin")
|
||||||
set(LIBRARY_DEST_DIR "bin")
|
set(LIBRARY_DEST_DIR "bin")
|
||||||
set(PLUGIN_DEST_DIR "plugins")
|
set(PLUGIN_DEST_DIR "plugins")
|
||||||
@@ -200,13 +187,28 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "lin-nodeps")
|
|||||||
set(INSTALL_BUNDLE "nodeps")
|
set(INSTALL_BUNDLE "nodeps")
|
||||||
|
|
||||||
# Set RPATH
|
# Set RPATH
|
||||||
SET(Launcher_BINARY_RPATH "$ORIGIN/")
|
SET(MultiMC_BINARY_RPATH "$ORIGIN/")
|
||||||
|
|
||||||
# Install basic runner script
|
# Install basic runner script
|
||||||
configure_file(launcher/Launcher.in "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" @ONLY)
|
install(PROGRAMS application/package/linux/MultiMC DESTINATION ${BUNDLE_DEST_DIR})
|
||||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/LauncherScript" DESTINATION ${BUNDLE_DEST_DIR} RENAME ${Launcher_Name})
|
|
||||||
|
|
||||||
elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
|
elseif(MultiMC_LAYOUT_REAL STREQUAL "lin-system")
|
||||||
|
set(MultiMC_APP_BINARY_NAME "multimc" CACHE STRING "Name of the MultiMC binary")
|
||||||
|
set(MultiMC_BINARY_DEST_DIR "bin" CACHE STRING "Path to the binary directory")
|
||||||
|
set(MultiMC_LIBRARY_DEST_DIR "lib${LIB_SUFFIX}" CACHE STRING "Path to the library directory")
|
||||||
|
set(MultiMC_SHARE_DEST_DIR "share/multimc" CACHE STRING "Path to the shared data directory")
|
||||||
|
set(JARS_DEST_DIR "${MultiMC_SHARE_DEST_DIR}/jars")
|
||||||
|
|
||||||
|
set(BINARY_DEST_DIR ${MultiMC_BINARY_DEST_DIR})
|
||||||
|
set(LIBRARY_DEST_DIR ${MultiMC_LIBRARY_DEST_DIR})
|
||||||
|
|
||||||
|
MESSAGE(STATUS "Compiling for linux system with ${MultiMC_SHARE_DEST_DIR} and MULTIMC_LINUX_DATADIR")
|
||||||
|
SET(MultiMC_APP_BINARY_DEFS "-DMULTIMC_JARS_LOCATION=${CMAKE_INSTALL_PREFIX}/${JARS_DEST_DIR}" "-DMULTIMC_LINUX_DATADIR")
|
||||||
|
|
||||||
|
# install as bundle with no dependencies included
|
||||||
|
set(INSTALL_BUNDLE "nodeps")
|
||||||
|
|
||||||
|
elseif(MultiMC_LAYOUT_REAL STREQUAL "win-bundle")
|
||||||
set(BINARY_DEST_DIR ".")
|
set(BINARY_DEST_DIR ".")
|
||||||
set(LIBRARY_DEST_DIR ".")
|
set(LIBRARY_DEST_DIR ".")
|
||||||
set(PLUGIN_DEST_DIR ".")
|
set(PLUGIN_DEST_DIR ".")
|
||||||
@@ -215,7 +217,7 @@ elseif(Launcher_LAYOUT_REAL STREQUAL "win-bundle")
|
|||||||
set(JARS_DEST_DIR "jars")
|
set(JARS_DEST_DIR "jars")
|
||||||
|
|
||||||
# Apps to bundle
|
# Apps to bundle
|
||||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/${Launcher_Name}.exe")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.exe")
|
||||||
|
|
||||||
# directories to look for dependencies
|
# directories to look for dependencies
|
||||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
@@ -234,7 +236,7 @@ set_directory_properties(PROPERTIES EP_BASE External)
|
|||||||
option(NBT_BUILD_SHARED "Build NBT shared library" ON)
|
option(NBT_BUILD_SHARED "Build NBT shared library" ON)
|
||||||
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
|
option(NBT_USE_ZLIB "Build NBT library with zlib support" OFF)
|
||||||
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
option(NBT_BUILD_TESTS "Build NBT library tests" OFF) #FIXME: fix unit tests.
|
||||||
set(NBT_NAME Launcher_nbt++)
|
set(NBT_NAME MultiMC_nbt++)
|
||||||
set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
|
set(NBT_DEST_DIR ${LIBRARY_DEST_DIR})
|
||||||
add_subdirectory(libraries/libnbtplusplus)
|
add_subdirectory(libraries/libnbtplusplus)
|
||||||
|
|
||||||
@@ -245,17 +247,16 @@ add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
|||||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||||
add_subdirectory(libraries/xz-embedded) # xz compression
|
add_subdirectory(libraries/xz-embedded) # xz compression
|
||||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||||
|
add_subdirectory(libraries/pack200) # java pack200 compression
|
||||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
||||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||||
add_subdirectory(libraries/classparser) # google analytics library
|
add_subdirectory(libraries/classparser) # google analytics library
|
||||||
add_subdirectory(libraries/optional-bare)
|
|
||||||
add_subdirectory(libraries/tomlc99) # toml parser
|
|
||||||
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
|
||||||
|
|
||||||
############################### Built Artifacts ###############################
|
############################### Built Artifacts ###############################
|
||||||
|
|
||||||
add_subdirectory(buildconfig)
|
add_subdirectory(api/logic)
|
||||||
|
add_subdirectory(api/gui)
|
||||||
|
|
||||||
# NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order.
|
# NOTE: this must always be last to appease the CMake deity of quirky install command evaluation order.
|
||||||
add_subdirectory(launcher)
|
add_subdirectory(application)
|
||||||
|
|||||||
110
COPYING.md
110
COPYING.md
@@ -1,6 +1,6 @@
|
|||||||
# MultiMC
|
# MultiMC
|
||||||
|
|
||||||
Copyright 2012-2021 MultiMC Contributors
|
Copyright 2012-2019 MultiMC Contributors
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
@@ -128,6 +128,35 @@
|
|||||||
This license is copied below, and is also available with a FAQ at:
|
This license is copied below, and is also available with a FAQ at:
|
||||||
http://scripts.sil.org/OFL
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
# Pack200
|
||||||
|
|
||||||
|
The GNU General Public License (GPL)
|
||||||
|
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
+ "CLASSPATH" EXCEPTION TO THE GPL
|
||||||
|
|
||||||
|
Certain source files distributed by Oracle America and/or its affiliates are
|
||||||
|
subject to the following clarification and special exception to the GPL, but
|
||||||
|
only where Oracle has expressly included in the particular source file's header
|
||||||
|
the words "Oracle designates this particular file as subject to the "Classpath"
|
||||||
|
exception as provided by Oracle in the LICENSE file that accompanied this code."
|
||||||
|
|
||||||
|
Linking this library statically or dynamically with other modules is making
|
||||||
|
a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
the GNU General Public License cover the whole combination.
|
||||||
|
|
||||||
|
As a special exception, the copyright holders of this library give you
|
||||||
|
permission to link this library with independent modules to produce an
|
||||||
|
executable, regardless of the license terms of these independent modules,
|
||||||
|
and to copy and distribute the resulting executable under terms of your
|
||||||
|
choice, provided that you also meet, for each linked independent module,
|
||||||
|
the terms and conditions of the license of that module. An independent
|
||||||
|
module is a module which is not derived from or based on this library. If
|
||||||
|
you modify this library, you may extend this exception to your version of
|
||||||
|
the library, but you are not obligated to do so. If you do not wish to do
|
||||||
|
so, delete this exception statement from your version.
|
||||||
|
|
||||||
# Quazip
|
# Quazip
|
||||||
|
|
||||||
Copyright (C) 2005-2011 Sergey A. Tachenov
|
Copyright (C) 2005-2011 Sergey A. Tachenov
|
||||||
@@ -223,82 +252,3 @@
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
# optional-bare
|
|
||||||
|
|
||||||
Code from https://github.com/martinmoene/optional-bare/
|
|
||||||
|
|
||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
# tomlc99
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 CK Tan
|
|
||||||
https://github.com/cktan/tomlc99
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
# O2 (Katabasis fork)
|
|
||||||
|
|
||||||
Copyright (c) 2012, Akos Polster
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|||||||
63
README.md
63
README.md
@@ -5,76 +5,41 @@
|
|||||||
MultiMC 5
|
MultiMC 5
|
||||||
=========
|
=========
|
||||||
|
|
||||||
MultiMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
|
MultiMC is a custom launcher for Minecraft that allows you to easily manage multiple installations of Minecraft at once. It also allows you to easily install and remove mods by simply dragging and dropping. Here are the current [features](https://github.com/MultiMC/MultiMC5/wiki#features) of MultiMC.
|
||||||
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
If you want to contribute, talk to us on [Discord](https://discord.gg/multimc) first.
|
The project uses C++ and Qt5 as the language and base framework. This might seem odd in the Minecraft community, but allows using 25MB of RAM, where other tools use an excessive amount of resources for no reason.
|
||||||
|
|
||||||
While blindly submitting PRs is definitely possible, they're not necessarily going to get accepted.
|
We can do more, with less, on worse hardware and leave more resources for the game while keeping the launcher running and providing extra features.
|
||||||
|
|
||||||
We aren't looking for flashy features, but expanding upon the existing feature set without distruption or endangering future viability of the project is OK.
|
If you want to contribute, either talk to us on [Discord](https://discord.gg/0k2zsXGNHs0fE4Wm), [IRC](http://webchat.esper.net/?nick=&channels=MultiMC)(esper.net/#MultiMC) or pick up some item from [workflowy](https://workflowy.com/s/2EyDMcp7CU) - there are many.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
If you want to build MultiMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
If you want to build MultiMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
||||||
|
|
||||||
### Code formatting
|
The ci server is running at [ci.multimc.org](http://ci.multimc.org), where you can watch the builds happen in (or very close to) real time. It can also serve as a nice reference on how to set up the build environment on your end.
|
||||||
Just follow the existing formatting.
|
|
||||||
|
|
||||||
In general, in order of importance:
|
According to travis.ci, the builds are currently [](https://travis-ci.org/MultiMC/MultiMC5)
|
||||||
* Make sure your IDE is not messing up line endings or whitespace and avoid using linters.
|
|
||||||
* Prefer readability over dogma.
|
### Code formatting
|
||||||
* Keep to the existing formatting.
|
We use [Clang Format](http://clang.llvm.org/docs/ClangFormat.html) to format the project. We highly recommend setting it up so the project stays well formatted.
|
||||||
* Indent with 4 space unless it's in a submodule.
|
|
||||||
* Keep lists (of arguments, parameters, initializers...) as lists, not paragraphs. It should either read from top to bottom, or left to right. Not both.
|
|
||||||
|
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
Translations can be done [on crowdin](https://translate.multimc.org). Please avoid making direct pull requests to the translations repository.
|
Translations can be done either directly in the [translations repository](https://github.com/MultiMC/MultiMC5). For more details, see: [Translating-MultiMC](https://github.com/MultiMC/MultiMC5/wiki/Translating-MultiMC).
|
||||||
|
|
||||||
## Forking/Redistributing/Custom builds policy
|
## Forking/Redistributing
|
||||||
We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.
|
We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.
|
||||||
|
|
||||||
Part of the reason for using the Apache license is that we don't want people using the "MultiMC" name when redistributing the project. This means people must take the time to go through the source code and remove all references to "MultiMC", including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).
|
Part of the reason for using the Apache license is we don't want people using the "MultiMC" name when redistributing the project. This means people must take the time to go through the source code and remove all references to "MultiMC", including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).
|
||||||
|
|
||||||
Apache covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork *without* implying that you have our blessing.
|
Apache covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork *without* implying that you have our blessing.
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Copyright © 2013-2021 MultiMC Contributors
|
Copyright © 2013-2019 MultiMC Contributors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
## Build status
|
|
||||||
### Linux (Intel32)
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Linux32_Build&guest=1">
|
|
||||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Linux32_Build)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Linux32_Deploy&guest=1">
|
|
||||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Linux32_Deploy)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### Linux (AMD64)
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Linux64_Build&guest=1">
|
|
||||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Linux64_Build)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Linux64_Deploy&guest=1">
|
|
||||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Linux64_Deploy)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### macOS (AMD64)
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_MacOS_Build&guest=1">
|
|
||||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_MacOS_Build)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_MacOS_Deploy&guest=1">
|
|
||||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_MacOS_Deploy)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### Windows (Intel32)
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Windows_Build&guest=1">
|
|
||||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Windows_Build)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=Launcher_Launcher_Windows_Deploy&guest=1">
|
|
||||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:Launcher_Launcher_Windows_Deploy)/statusIcon"/>
|
|
||||||
</a>
|
|
||||||
|
|||||||
34
api/gui/CMakeLists.txt
Normal file
34
api/gui/CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
project(MultiMC_gui LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(GUI_SOURCES
|
||||||
|
DesktopServices.h
|
||||||
|
DesktopServices.cpp
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
icons/MMCIcon.h
|
||||||
|
icons/MMCIcon.cpp
|
||||||
|
icons/IconList.h
|
||||||
|
icons/IconList.cpp
|
||||||
|
|
||||||
|
SkinUtils.cpp
|
||||||
|
SkinUtils.h
|
||||||
|
)
|
||||||
|
################################ COMPILE ################################
|
||||||
|
|
||||||
|
add_library(MultiMC_gui SHARED ${GUI_SOURCES})
|
||||||
|
set_target_properties(MultiMC_gui PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
|
||||||
|
|
||||||
|
generate_export_header(MultiMC_gui)
|
||||||
|
|
||||||
|
# Link
|
||||||
|
target_link_libraries(MultiMC_gui MultiMC_iconfix MultiMC_logic Qt5::Gui)
|
||||||
|
|
||||||
|
# Mark and export headers
|
||||||
|
target_include_directories(MultiMC_gui PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
# Install it
|
||||||
|
install(
|
||||||
|
TARGETS MultiMC_gui
|
||||||
|
RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
|
||||||
|
LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
|
||||||
|
)
|
||||||
37
api/gui/DesktopServices.h
Normal file
37
api/gui/DesktopServices.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QString>
|
||||||
|
#include "multimc_gui_export.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This wraps around QDesktopServices and adds workarounds where needed
|
||||||
|
* Use this instead of QDesktopServices!
|
||||||
|
*/
|
||||||
|
namespace DesktopServices
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Open a file in whatever application is applicable
|
||||||
|
*/
|
||||||
|
MULTIMC_GUI_EXPORT bool openFile(const QString &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a file in the specified application
|
||||||
|
*/
|
||||||
|
MULTIMC_GUI_EXPORT bool openFile(const QString &application, const QString &path, const QString & workingDirectory = QString(), qint64 *pid = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run an application
|
||||||
|
*/
|
||||||
|
MULTIMC_GUI_EXPORT bool run(const QString &application,const QStringList &args, const QString & workingDirectory = QString(), qint64 *pid = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a directory
|
||||||
|
*/
|
||||||
|
MULTIMC_GUI_EXPORT bool openDirectory(const QString &path, bool ensureExists = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the URL, most likely in a browser. Maybe.
|
||||||
|
*/
|
||||||
|
MULTIMC_GUI_EXPORT bool openUrl(const QUrl &url);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,10 +15,9 @@
|
|||||||
|
|
||||||
#include "SkinUtils.h"
|
#include "SkinUtils.h"
|
||||||
#include "net/HttpMetaCache.h"
|
#include "net/HttpMetaCache.h"
|
||||||
#include "Application.h"
|
#include "Env.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QPainter>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@@ -30,18 +29,16 @@ namespace SkinUtils
|
|||||||
*/
|
*/
|
||||||
QPixmap getFaceFromCache(QString username, int height, int width)
|
QPixmap getFaceFromCache(QString username, int height, int width)
|
||||||
{
|
{
|
||||||
QFile fskin(APPLICATION->metacache()->resolveEntry("skins", username + ".png")->getFullPath());
|
QFile fskin(ENV.metacache()
|
||||||
|
->resolveEntry("skins", username + ".png")
|
||||||
|
->getFullPath());
|
||||||
|
|
||||||
if (fskin.exists())
|
if (fskin.exists())
|
||||||
{
|
{
|
||||||
QPixmap skinTexture(fskin.fileName());
|
QPixmap skin(fskin.fileName());
|
||||||
if(!skinTexture.isNull())
|
if(!skin.isNull())
|
||||||
{
|
{
|
||||||
QPixmap skin = QPixmap(8, 8);
|
return skin.copy(8, 8, 8, 8).scaled(height, width, Qt::KeepAspectRatio);
|
||||||
QPainter painter(&skin);
|
|
||||||
painter.drawPixmap(0, 0, skinTexture.copy(8, 8, 8, 8));
|
|
||||||
painter.drawPixmap(0, 0, skinTexture.copy(40, 8, 8, 8));
|
|
||||||
return skin.scaled(height, width, Qt::KeepAspectRatio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
|
#include "multimc_gui_export.h"
|
||||||
|
|
||||||
namespace SkinUtils
|
namespace SkinUtils
|
||||||
{
|
{
|
||||||
QPixmap getFaceFromCache(QString id, int height = 64, int width = 64);
|
QPixmap MULTIMC_GUI_EXPORT getFaceFromCache(QString id, int height = 64, int width = 64);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -395,7 +395,7 @@ QIcon IconList::getIcon(const QString &key) const
|
|||||||
return icons[icon_index].icon();
|
return icons[icon_index].icon();
|
||||||
|
|
||||||
// Fallback for icons that don't exist.
|
// Fallback for icons that don't exist.
|
||||||
icon_index = getIconIndex("grass");
|
icon_index = getIconIndex("infinity");
|
||||||
|
|
||||||
if (icon_index != -1)
|
if (icon_index != -1)
|
||||||
return icons[icon_index].icon();
|
return icons[icon_index].icon();
|
||||||
@@ -404,7 +404,7 @@ QIcon IconList::getIcon(const QString &key) const
|
|||||||
|
|
||||||
int IconList::getIconIndex(const QString &key) const
|
int IconList::getIconIndex(const QString &key) const
|
||||||
{
|
{
|
||||||
auto iter = name_index.find(key == "default" ? "grass" : key);
|
auto iter = name_index.find(key == "default" ? "infinity" : key);
|
||||||
if (iter != name_index.end())
|
if (iter != name_index.end())
|
||||||
return *iter;
|
return *iter;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,15 +21,16 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "MMCIcon.h"
|
#include "MMCIcon.h"
|
||||||
#include "settings/Setting.h"
|
#include "settings/Setting.h"
|
||||||
|
#include "Env.h" // there is a global icon list inside Env.
|
||||||
|
#include <icons/IIconList.h>
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "multimc_gui_export.h"
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
|
|
||||||
class IconList : public QAbstractListModel
|
class MULTIMC_GUI_EXPORT IconList : public QAbstractListModel, public IIconList
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -43,19 +44,19 @@ public:
|
|||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
bool addThemeIcon(const QString &key);
|
||||||
|
bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type) override;
|
||||||
|
void saveIcon(const QString &key, const QString &path, const char * format) const override;
|
||||||
|
bool deleteIcon(const QString &key) override;
|
||||||
|
bool iconFileExists(const QString &key) const override;
|
||||||
|
|
||||||
virtual QStringList mimeTypes() const override;
|
virtual QStringList mimeTypes() const override;
|
||||||
virtual Qt::DropActions supportedDropActions() const override;
|
virtual Qt::DropActions supportedDropActions() const override;
|
||||||
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
bool addThemeIcon(const QString &key);
|
void installIcons(const QStringList &iconFiles) override;
|
||||||
bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type);
|
void installIcon(const QString &file, const QString &name) override;
|
||||||
void saveIcon(const QString &key, const QString &path, const char * format) const;
|
|
||||||
bool deleteIcon(const QString &key);
|
|
||||||
bool iconFileExists(const QString &key) const;
|
|
||||||
|
|
||||||
void installIcons(const QStringList &iconFiles);
|
|
||||||
void installIcon(const QString &file, const QString &name);
|
|
||||||
|
|
||||||
const MMCIcon * icon(const QString &key) const;
|
const MMCIcon * icon(const QString &key) const;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,17 +17,11 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <icons/IIconList.h>
|
||||||
|
|
||||||
enum IconType : unsigned
|
#include "multimc_gui_export.h"
|
||||||
{
|
|
||||||
Builtin,
|
|
||||||
Transient,
|
|
||||||
FileBased,
|
|
||||||
ICONS_TOTAL,
|
|
||||||
ToBeDeleted
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MMCImage
|
struct MULTIMC_GUI_EXPORT MMCImage
|
||||||
{
|
{
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
QString key;
|
QString key;
|
||||||
@@ -38,7 +32,7 @@ struct MMCImage
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MMCIcon
|
struct MULTIMC_GUI_EXPORT MMCIcon
|
||||||
{
|
{
|
||||||
QString m_key;
|
QString m_key;
|
||||||
QString m_name;
|
QString m_name;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
class MinecraftInstance;
|
class MinecraftInstance;
|
||||||
class QDir;
|
class QDir;
|
||||||
class QString;
|
class QString;
|
||||||
@@ -25,7 +27,7 @@ class Task;
|
|||||||
class BaseVersion;
|
class BaseVersion;
|
||||||
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
|
||||||
|
|
||||||
class BaseInstaller
|
class MULTIMC_LOGIC_EXPORT BaseInstaller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BaseInstaller();
|
BaseInstaller();
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "Commandline.h"
|
#include "Commandline.h"
|
||||||
#include "BuildConfig.h"
|
|
||||||
|
|
||||||
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
|
BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
|
||||||
: QObject()
|
: QObject()
|
||||||
@@ -38,7 +37,6 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s
|
|||||||
m_settings->registerSetting("notes", "");
|
m_settings->registerSetting("notes", "");
|
||||||
m_settings->registerSetting("lastLaunchTime", 0);
|
m_settings->registerSetting("lastLaunchTime", 0);
|
||||||
m_settings->registerSetting("totalTimePlayed", 0);
|
m_settings->registerSetting("totalTimePlayed", 0);
|
||||||
m_settings->registerSetting("lastTimePlayed", 0);
|
|
||||||
|
|
||||||
// Custom Commands
|
// Custom Commands
|
||||||
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
||||||
@@ -136,24 +134,15 @@ void BaseInstance::setRunning(bool running)
|
|||||||
|
|
||||||
m_isRunning = running;
|
m_isRunning = running;
|
||||||
|
|
||||||
if(!m_settings->get("RecordGameTime").toBool())
|
|
||||||
{
|
|
||||||
emit runningStatusChanged(running);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(running)
|
if(running)
|
||||||
{
|
{
|
||||||
m_timeStarted = QDateTime::currentDateTime();
|
m_timeStarted = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QDateTime timeEnded = QDateTime::currentDateTime();
|
|
||||||
|
|
||||||
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
qint64 current = settings()->get("totalTimePlayed").toLongLong();
|
||||||
|
QDateTime timeEnded = QDateTime::currentDateTime();
|
||||||
settings()->set("totalTimePlayed", current + m_timeStarted.secsTo(timeEnded));
|
settings()->set("totalTimePlayed", current + m_timeStarted.secsTo(timeEnded));
|
||||||
settings()->set("lastTimePlayed", m_timeStarted.secsTo(timeEnded));
|
|
||||||
|
|
||||||
emit propertiesChanged(this);
|
emit propertiesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,20 +160,9 @@ int64_t BaseInstance::totalTimePlayed() const
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t BaseInstance::lastTimePlayed() const
|
|
||||||
{
|
|
||||||
if(m_isRunning)
|
|
||||||
{
|
|
||||||
QDateTime timeNow = QDateTime::currentDateTime();
|
|
||||||
return m_timeStarted.secsTo(timeNow);
|
|
||||||
}
|
|
||||||
return settings()->get("lastTimePlayed").toLongLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstance::resetTimePlayed()
|
void BaseInstance::resetTimePlayed()
|
||||||
{
|
{
|
||||||
settings()->reset("totalTimePlayed");
|
settings()->reset("totalTimePlayed");
|
||||||
settings()->reset("lastTimePlayed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BaseInstance::instanceType() const
|
QString BaseInstance::instanceType() const
|
||||||
@@ -261,7 +239,7 @@ QString BaseInstance::name() const
|
|||||||
|
|
||||||
QString BaseInstance::windowTitle() const
|
QString BaseInstance::windowTitle() const
|
||||||
{
|
{
|
||||||
return BuildConfig.LAUNCHER_NAME + ": " + name().replace(QRegExp("[ \n\r\t]+"), " ");
|
return "MultiMC: " + name().replace(QRegExp("[ \n\r\t]+"), " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: why is this here? move it to MinecraftInstance!!!
|
// FIXME: why is this here? move it to MinecraftInstance!!!
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,13 +26,13 @@
|
|||||||
|
|
||||||
#include "settings/INIFile.h"
|
#include "settings/INIFile.h"
|
||||||
#include "BaseVersionList.h"
|
#include "BaseVersionList.h"
|
||||||
#include "minecraft/auth/MinecraftAccount.h"
|
#include "minecraft/auth/MojangAccount.h"
|
||||||
#include "MessageLevel.h"
|
#include "MessageLevel.h"
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
|
||||||
#include "net/Mode.h"
|
#include "net/Mode.h"
|
||||||
|
|
||||||
#include "minecraft/launch/MinecraftServerTarget.h"
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
class QDir;
|
class QDir;
|
||||||
class Task;
|
class Task;
|
||||||
@@ -50,7 +50,7 @@ typedef std::shared_ptr<BaseInstance> InstancePtr;
|
|||||||
* To create a new instance type, create a new class inheriting from this class
|
* To create a new instance type, create a new class inheriting from this class
|
||||||
* and implement the pure virtual functions.
|
* and implement the pure virtual functions.
|
||||||
*/
|
*/
|
||||||
class BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance>
|
class MULTIMC_LOGIC_EXPORT BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance>
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
@@ -71,21 +71,20 @@ public:
|
|||||||
virtual void saveNow() = 0;
|
virtual void saveNow() = 0;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* the instance has been invalidated - it is no longer tracked by the launcher for some reason,
|
* the instance has been invalidated - it is no longer tracked by MultiMC for some reason,
|
||||||
* but it has not necessarily been deleted.
|
* but it has not necessarily been deleted.
|
||||||
*
|
*
|
||||||
* Happens when the instance folder changes to some other location, or the instance is removed by external means.
|
* Happens when the instance folder changes to some other location, or the instance is removed by external means.
|
||||||
*/
|
*/
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
|
||||||
/// The instance's ID. The ID SHALL be determined by LAUNCHER internally. The ID IS guaranteed to
|
/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
|
||||||
/// be unique.
|
/// be unique.
|
||||||
virtual QString id() const;
|
virtual QString id() const;
|
||||||
|
|
||||||
void setRunning(bool running);
|
void setRunning(bool running);
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
int64_t totalTimePlayed() const;
|
int64_t totalTimePlayed() const;
|
||||||
int64_t lastTimePlayed() const;
|
|
||||||
void resetTimePlayed();
|
void resetTimePlayed();
|
||||||
|
|
||||||
/// get the type of this instance
|
/// get the type of this instance
|
||||||
@@ -143,11 +142,10 @@ public:
|
|||||||
virtual SettingsObjectPtr settings() const;
|
virtual SettingsObjectPtr settings() const;
|
||||||
|
|
||||||
/// returns a valid update task
|
/// returns a valid update task
|
||||||
virtual Task::Ptr createUpdateTask(Net::Mode mode) = 0;
|
virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0;
|
||||||
|
|
||||||
/// returns a valid launcher (task container)
|
/// returns a valid launcher (task container)
|
||||||
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(
|
virtual shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
|
||||||
AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) = 0;
|
|
||||||
|
|
||||||
/// returns the current launch task (if any)
|
/// returns the current launch task (if any)
|
||||||
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
shared_qobject_ptr<LaunchTask> getLaunchTask();
|
||||||
@@ -223,9 +221,9 @@ public:
|
|||||||
bool reloadSettings();
|
bool reloadSettings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'print' a verbose description of the instance into a QStringList
|
* 'print' a verbose desription of the instance into a QStringList
|
||||||
*/
|
*/
|
||||||
virtual QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) = 0;
|
virtual QStringList verboseDescription(AuthSessionPtr session) = 0;
|
||||||
|
|
||||||
Status currentStatus() const;
|
Status currentStatus() const;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "BaseVersion.h"
|
#include "BaseVersion.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
* all have a default implementation, but they can be overridden by plugins to
|
* all have a default implementation, but they can be overridden by plugins to
|
||||||
* change the behavior of the list.
|
* change the behavior of the list.
|
||||||
*/
|
*/
|
||||||
class BaseVersionList : public QAbstractListModel
|
class MULTIMC_LOGIC_EXPORT BaseVersionList : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -63,7 +64,7 @@ public:
|
|||||||
* The task returned by this function should reset the model when it's done.
|
* The task returned by this function should reset the model when it's done.
|
||||||
* \return A pointer to a task that reloads the version list.
|
* \return A pointer to a task that reloads the version list.
|
||||||
*/
|
*/
|
||||||
virtual Task::Ptr getLoadTask() = 0;
|
virtual shared_qobject_ptr<Task> getLoadTask() = 0;
|
||||||
|
|
||||||
//! Checks whether or not the list is loaded. If this returns false, the list should be
|
//! Checks whether or not the list is loaded. If this returns false, the list should be
|
||||||
//loaded.
|
//loaded.
|
||||||
499
api/logic/CMakeLists.txt
Normal file
499
api/logic/CMakeLists.txt
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
project(MultiMC_logic)
|
||||||
|
|
||||||
|
include (UnitTest)
|
||||||
|
|
||||||
|
set(CORE_SOURCES
|
||||||
|
# LOGIC - Base classes and infrastructure
|
||||||
|
BaseInstaller.h
|
||||||
|
BaseInstaller.cpp
|
||||||
|
BaseVersionList.h
|
||||||
|
BaseVersionList.cpp
|
||||||
|
InstanceList.h
|
||||||
|
InstanceList.cpp
|
||||||
|
InstanceTask.h
|
||||||
|
InstanceTask.cpp
|
||||||
|
LoggedProcess.h
|
||||||
|
LoggedProcess.cpp
|
||||||
|
MessageLevel.cpp
|
||||||
|
MessageLevel.h
|
||||||
|
BaseVersion.h
|
||||||
|
BaseInstance.h
|
||||||
|
BaseInstance.cpp
|
||||||
|
NullInstance.h
|
||||||
|
MMCZip.h
|
||||||
|
MMCZip.cpp
|
||||||
|
MMCStrings.h
|
||||||
|
MMCStrings.cpp
|
||||||
|
|
||||||
|
# Basic instance manipulation tasks (derived from InstanceTask)
|
||||||
|
InstanceCreationTask.h
|
||||||
|
InstanceCreationTask.cpp
|
||||||
|
InstanceCopyTask.h
|
||||||
|
InstanceCopyTask.cpp
|
||||||
|
InstanceImportTask.h
|
||||||
|
InstanceImportTask.cpp
|
||||||
|
|
||||||
|
# Use tracking separate from memory management
|
||||||
|
Usable.h
|
||||||
|
|
||||||
|
# Prefix tree where node names are strings between separators
|
||||||
|
SeparatorPrefixTree.h
|
||||||
|
|
||||||
|
# WARNING: globals live here
|
||||||
|
Env.h
|
||||||
|
Env.cpp
|
||||||
|
|
||||||
|
# String filters
|
||||||
|
Filter.h
|
||||||
|
Filter.cpp
|
||||||
|
|
||||||
|
# JSON parsing helpers
|
||||||
|
Json.h
|
||||||
|
Json.cpp
|
||||||
|
|
||||||
|
FileSystem.h
|
||||||
|
FileSystem.cpp
|
||||||
|
|
||||||
|
Exception.h
|
||||||
|
|
||||||
|
# RW lock protected map
|
||||||
|
RWStorage.h
|
||||||
|
|
||||||
|
# A variable that has an implicit default value and keeps track of changes
|
||||||
|
DefaultVariable.h
|
||||||
|
|
||||||
|
# a smart pointer wrapper intended for safer use with Qt signal/slot mechanisms
|
||||||
|
QObjectPtr.h
|
||||||
|
|
||||||
|
# Compression support
|
||||||
|
GZip.h
|
||||||
|
GZip.cpp
|
||||||
|
|
||||||
|
# Command line parameter parsing
|
||||||
|
Commandline.h
|
||||||
|
Commandline.cpp
|
||||||
|
|
||||||
|
# Version number string support
|
||||||
|
Version.h
|
||||||
|
Version.cpp
|
||||||
|
|
||||||
|
# A Recursive file system watcher
|
||||||
|
RecursiveFileSystemWatcher.h
|
||||||
|
RecursiveFileSystemWatcher.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(FileSystem
|
||||||
|
SOURCES FileSystem_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
DATA testdata
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(GZip
|
||||||
|
SOURCES GZip_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PATHMATCHER_SOURCES
|
||||||
|
# Path matchers
|
||||||
|
pathmatcher/FSTreeMatcher.h
|
||||||
|
pathmatcher/IPathMatcher.h
|
||||||
|
pathmatcher/MultiMatcher.h
|
||||||
|
pathmatcher/RegexpMatcher.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(NET_SOURCES
|
||||||
|
# network stuffs
|
||||||
|
net/ByteArraySink.h
|
||||||
|
net/ChecksumValidator.h
|
||||||
|
net/Download.cpp
|
||||||
|
net/Download.h
|
||||||
|
net/FileSink.cpp
|
||||||
|
net/FileSink.h
|
||||||
|
net/HttpMetaCache.cpp
|
||||||
|
net/HttpMetaCache.h
|
||||||
|
net/MetaCacheSink.cpp
|
||||||
|
net/MetaCacheSink.h
|
||||||
|
net/NetAction.h
|
||||||
|
net/NetJob.cpp
|
||||||
|
net/NetJob.h
|
||||||
|
net/PasteUpload.cpp
|
||||||
|
net/PasteUpload.h
|
||||||
|
net/Sink.h
|
||||||
|
net/URLConstants.cpp
|
||||||
|
net/URLConstants.h
|
||||||
|
net/Validator.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# Game launch logic
|
||||||
|
set(LAUNCH_SOURCES
|
||||||
|
launch/steps/PostLaunchCommand.cpp
|
||||||
|
launch/steps/PostLaunchCommand.h
|
||||||
|
launch/steps/PreLaunchCommand.cpp
|
||||||
|
launch/steps/PreLaunchCommand.h
|
||||||
|
launch/steps/TextPrint.cpp
|
||||||
|
launch/steps/TextPrint.h
|
||||||
|
launch/steps/Update.cpp
|
||||||
|
launch/steps/Update.h
|
||||||
|
launch/LaunchStep.cpp
|
||||||
|
launch/LaunchStep.h
|
||||||
|
launch/LaunchTask.cpp
|
||||||
|
launch/LaunchTask.h
|
||||||
|
launch/LogModel.cpp
|
||||||
|
launch/LogModel.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# Old update system
|
||||||
|
set(UPDATE_SOURCES
|
||||||
|
updater/GoUpdate.h
|
||||||
|
updater/GoUpdate.cpp
|
||||||
|
updater/UpdateChecker.h
|
||||||
|
updater/UpdateChecker.cpp
|
||||||
|
updater/DownloadTask.h
|
||||||
|
updater/DownloadTask.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(UpdateChecker
|
||||||
|
SOURCES updater/UpdateChecker_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
DATA updater/testdata
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(DownloadTask
|
||||||
|
SOURCES updater/DownloadTask_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
DATA updater/testdata
|
||||||
|
)
|
||||||
|
|
||||||
|
# Rarely used notifications
|
||||||
|
set(NOTIFICATIONS_SOURCES
|
||||||
|
# Notifications - short warning messages
|
||||||
|
notifications/NotificationChecker.h
|
||||||
|
notifications/NotificationChecker.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Backend for the news bar... there's usually no news.
|
||||||
|
set(NEWS_SOURCES
|
||||||
|
# News System
|
||||||
|
news/NewsChecker.h
|
||||||
|
news/NewsChecker.cpp
|
||||||
|
news/NewsEntry.h
|
||||||
|
news/NewsEntry.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Icon interface
|
||||||
|
set(ICONS_SOURCES
|
||||||
|
# Icons System and related code
|
||||||
|
icons/IIconList.h
|
||||||
|
icons/IIconList.cpp
|
||||||
|
icons/IconUtils.h
|
||||||
|
icons/IconUtils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Minecraft services status checker
|
||||||
|
set(STATUS_SOURCES
|
||||||
|
# Status system
|
||||||
|
status/StatusChecker.h
|
||||||
|
status/StatusChecker.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Support for Minecraft instances and launch
|
||||||
|
set(MINECRAFT_SOURCES
|
||||||
|
# Minecraft support
|
||||||
|
minecraft/auth/AuthSession.h
|
||||||
|
minecraft/auth/AuthSession.cpp
|
||||||
|
minecraft/auth/MojangAccountList.h
|
||||||
|
minecraft/auth/MojangAccountList.cpp
|
||||||
|
minecraft/auth/MojangAccount.h
|
||||||
|
minecraft/auth/MojangAccount.cpp
|
||||||
|
minecraft/auth/YggdrasilTask.h
|
||||||
|
minecraft/auth/YggdrasilTask.cpp
|
||||||
|
minecraft/auth/flows/AuthenticateTask.h
|
||||||
|
minecraft/auth/flows/AuthenticateTask.cpp
|
||||||
|
minecraft/auth/flows/RefreshTask.cpp
|
||||||
|
minecraft/auth/flows/RefreshTask.cpp
|
||||||
|
minecraft/auth/flows/ValidateTask.h
|
||||||
|
minecraft/auth/flows/ValidateTask.cpp
|
||||||
|
minecraft/gameoptions/GameOptions.h
|
||||||
|
minecraft/gameoptions/GameOptions.cpp
|
||||||
|
minecraft/update/AssetUpdateTask.h
|
||||||
|
minecraft/update/AssetUpdateTask.cpp
|
||||||
|
minecraft/update/FMLLibrariesTask.cpp
|
||||||
|
minecraft/update/FMLLibrariesTask.h
|
||||||
|
minecraft/update/FoldersTask.cpp
|
||||||
|
minecraft/update/FoldersTask.h
|
||||||
|
minecraft/update/LibrariesTask.cpp
|
||||||
|
minecraft/update/LibrariesTask.h
|
||||||
|
minecraft/launch/ClaimAccount.cpp
|
||||||
|
minecraft/launch/ClaimAccount.h
|
||||||
|
minecraft/launch/CreateServerResourcePacksFolder.cpp
|
||||||
|
minecraft/launch/CreateServerResourcePacksFolder.h
|
||||||
|
minecraft/launch/ModMinecraftJar.cpp
|
||||||
|
minecraft/launch/ModMinecraftJar.h
|
||||||
|
minecraft/launch/DirectJavaLaunch.cpp
|
||||||
|
minecraft/launch/DirectJavaLaunch.h
|
||||||
|
minecraft/launch/ExtractNatives.cpp
|
||||||
|
minecraft/launch/ExtractNatives.h
|
||||||
|
minecraft/launch/LauncherPartLaunch.cpp
|
||||||
|
minecraft/launch/LauncherPartLaunch.h
|
||||||
|
minecraft/launch/PrintInstanceInfo.cpp
|
||||||
|
minecraft/launch/PrintInstanceInfo.h
|
||||||
|
minecraft/launch/ReconstructAssets.cpp
|
||||||
|
minecraft/launch/ReconstructAssets.h
|
||||||
|
minecraft/legacy/LegacyModList.h
|
||||||
|
minecraft/legacy/LegacyModList.cpp
|
||||||
|
minecraft/legacy/LegacyInstance.h
|
||||||
|
minecraft/legacy/LegacyInstance.cpp
|
||||||
|
minecraft/legacy/LegacyUpgradeTask.h
|
||||||
|
minecraft/legacy/LegacyUpgradeTask.cpp
|
||||||
|
minecraft/GradleSpecifier.h
|
||||||
|
minecraft/MinecraftInstance.cpp
|
||||||
|
minecraft/MinecraftInstance.h
|
||||||
|
minecraft/LaunchProfile.cpp
|
||||||
|
minecraft/LaunchProfile.h
|
||||||
|
minecraft/Component.cpp
|
||||||
|
minecraft/Component.h
|
||||||
|
minecraft/ComponentList.cpp
|
||||||
|
minecraft/ComponentList.h
|
||||||
|
minecraft/ComponentUpdateTask.cpp
|
||||||
|
minecraft/ComponentUpdateTask.h
|
||||||
|
minecraft/MinecraftLoadAndCheck.h
|
||||||
|
minecraft/MinecraftLoadAndCheck.cpp
|
||||||
|
minecraft/MinecraftUpdate.h
|
||||||
|
minecraft/MinecraftUpdate.cpp
|
||||||
|
minecraft/MojangVersionFormat.cpp
|
||||||
|
minecraft/MojangVersionFormat.h
|
||||||
|
minecraft/Rule.cpp
|
||||||
|
minecraft/Rule.h
|
||||||
|
minecraft/OneSixVersionFormat.cpp
|
||||||
|
minecraft/OneSixVersionFormat.h
|
||||||
|
minecraft/OpSys.cpp
|
||||||
|
minecraft/OpSys.h
|
||||||
|
minecraft/ParseUtils.cpp
|
||||||
|
minecraft/ParseUtils.h
|
||||||
|
minecraft/ProfileUtils.cpp
|
||||||
|
minecraft/ProfileUtils.h
|
||||||
|
minecraft/Library.cpp
|
||||||
|
minecraft/Library.h
|
||||||
|
minecraft/MojangDownloadInfo.h
|
||||||
|
minecraft/VersionFile.cpp
|
||||||
|
minecraft/VersionFile.h
|
||||||
|
minecraft/VersionFilterData.h
|
||||||
|
minecraft/VersionFilterData.cpp
|
||||||
|
minecraft/Mod.h
|
||||||
|
minecraft/Mod.cpp
|
||||||
|
minecraft/SimpleModList.h
|
||||||
|
minecraft/SimpleModList.cpp
|
||||||
|
minecraft/World.h
|
||||||
|
minecraft/World.cpp
|
||||||
|
minecraft/WorldList.h
|
||||||
|
minecraft/WorldList.cpp
|
||||||
|
|
||||||
|
# Assets
|
||||||
|
minecraft/AssetsUtils.h
|
||||||
|
minecraft/AssetsUtils.cpp
|
||||||
|
|
||||||
|
# Forge and all things forge related
|
||||||
|
minecraft/forge/ForgeXzDownload.h
|
||||||
|
minecraft/forge/ForgeXzDownload.cpp
|
||||||
|
|
||||||
|
# Skin upload utilities
|
||||||
|
minecraft/SkinUpload.cpp
|
||||||
|
minecraft/SkinUpload.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(GradleSpecifier
|
||||||
|
SOURCES minecraft/GradleSpecifier_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(MojangVersionFormat
|
||||||
|
SOURCES minecraft/MojangVersionFormat_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
DATA minecraft/testdata
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(Library
|
||||||
|
SOURCES minecraft/Library_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
# FIXME: shares data with FileSystem test
|
||||||
|
add_unit_test(SimpleModList
|
||||||
|
SOURCES minecraft/SimpleModList_test.cpp
|
||||||
|
DATA testdata
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(ParseUtils
|
||||||
|
SOURCES minecraft/ParseUtils_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
# the screenshots feature
|
||||||
|
set(SCREENSHOTS_SOURCES
|
||||||
|
screenshots/Screenshot.h
|
||||||
|
screenshots/ImgurUpload.h
|
||||||
|
screenshots/ImgurUpload.cpp
|
||||||
|
screenshots/ImgurAlbumCreation.h
|
||||||
|
screenshots/ImgurAlbumCreation.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TASKS_SOURCES
|
||||||
|
# Tasks
|
||||||
|
tasks/Task.h
|
||||||
|
tasks/Task.cpp
|
||||||
|
tasks/SequentialTask.h
|
||||||
|
tasks/SequentialTask.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SETTINGS_SOURCES
|
||||||
|
# Settings
|
||||||
|
settings/INIFile.cpp
|
||||||
|
settings/INIFile.h
|
||||||
|
settings/INISettingsObject.cpp
|
||||||
|
settings/INISettingsObject.h
|
||||||
|
settings/OverrideSetting.cpp
|
||||||
|
settings/OverrideSetting.h
|
||||||
|
settings/PassthroughSetting.cpp
|
||||||
|
settings/PassthroughSetting.h
|
||||||
|
settings/Setting.cpp
|
||||||
|
settings/Setting.h
|
||||||
|
settings/SettingsObject.cpp
|
||||||
|
settings/SettingsObject.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(INIFile
|
||||||
|
SOURCES settings/INIFile_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
set(JAVA_SOURCES
|
||||||
|
# Java related code
|
||||||
|
java/launch/CheckJava.cpp
|
||||||
|
java/launch/CheckJava.h
|
||||||
|
java/JavaChecker.h
|
||||||
|
java/JavaChecker.cpp
|
||||||
|
java/JavaCheckerJob.h
|
||||||
|
java/JavaCheckerJob.cpp
|
||||||
|
java/JavaInstall.h
|
||||||
|
java/JavaInstall.cpp
|
||||||
|
java/JavaInstallList.h
|
||||||
|
java/JavaInstallList.cpp
|
||||||
|
java/JavaUtils.h
|
||||||
|
java/JavaUtils.cpp
|
||||||
|
java/JavaVersion.h
|
||||||
|
java/JavaVersion.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(JavaVersion
|
||||||
|
SOURCES java/JavaVersion_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TRANSLATIONS_SOURCES
|
||||||
|
translations/TranslationsModel.h
|
||||||
|
translations/TranslationsModel.cpp
|
||||||
|
translations/POTranslator.h
|
||||||
|
translations/POTranslator.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TOOLS_SOURCES
|
||||||
|
# Tools
|
||||||
|
tools/BaseExternalTool.cpp
|
||||||
|
tools/BaseExternalTool.h
|
||||||
|
tools/BaseProfiler.cpp
|
||||||
|
tools/BaseProfiler.h
|
||||||
|
tools/JProfiler.cpp
|
||||||
|
tools/JProfiler.h
|
||||||
|
tools/JVisualVM.cpp
|
||||||
|
tools/JVisualVM.h
|
||||||
|
tools/MCEditTool.cpp
|
||||||
|
tools/MCEditTool.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(META_SOURCES
|
||||||
|
# Metadata sources
|
||||||
|
meta/JsonFormat.cpp
|
||||||
|
meta/JsonFormat.h
|
||||||
|
meta/BaseEntity.cpp
|
||||||
|
meta/BaseEntity.h
|
||||||
|
meta/VersionList.cpp
|
||||||
|
meta/VersionList.h
|
||||||
|
meta/Version.cpp
|
||||||
|
meta/Version.h
|
||||||
|
meta/Index.cpp
|
||||||
|
meta/Index.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FTB_SOURCES
|
||||||
|
modplatform/ftb/FtbPackFetchTask.h
|
||||||
|
modplatform/ftb/FtbPackFetchTask.cpp
|
||||||
|
modplatform/ftb/FtbPackInstallTask.h
|
||||||
|
modplatform/ftb/FtbPackInstallTask.cpp
|
||||||
|
|
||||||
|
modplatform/ftb/FtbPrivatePackManager.h
|
||||||
|
modplatform/ftb/FtbPrivatePackManager.cpp
|
||||||
|
|
||||||
|
modplatform/ftb/PackHelpers.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FLAME_SOURCES
|
||||||
|
# Flame
|
||||||
|
modplatform/flame/PackManifest.h
|
||||||
|
modplatform/flame/PackManifest.cpp
|
||||||
|
modplatform/flame/FileResolvingTask.h
|
||||||
|
modplatform/flame/FileResolvingTask.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_unit_test(Index
|
||||||
|
SOURCES meta/Index_test.cpp
|
||||||
|
LIBS MultiMC_logic
|
||||||
|
)
|
||||||
|
|
||||||
|
################################ COMPILE ################################
|
||||||
|
|
||||||
|
# we need zlib
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
|
set(LOGIC_SOURCES
|
||||||
|
${CORE_SOURCES}
|
||||||
|
${PATHMATCHER_SOURCES}
|
||||||
|
${NET_SOURCES}
|
||||||
|
${LAUNCH_SOURCES}
|
||||||
|
${UPDATE_SOURCES}
|
||||||
|
${NOTIFICATIONS_SOURCES}
|
||||||
|
${NEWS_SOURCES}
|
||||||
|
${STATUS_SOURCES}
|
||||||
|
${MINECRAFT_SOURCES}
|
||||||
|
${SCREENSHOTS_SOURCES}
|
||||||
|
${TASKS_SOURCES}
|
||||||
|
${SETTINGS_SOURCES}
|
||||||
|
${JAVA_SOURCES}
|
||||||
|
${TRANSLATIONS_SOURCES}
|
||||||
|
${TOOLS_SOURCES}
|
||||||
|
${META_SOURCES}
|
||||||
|
${ICONS_SOURCES}
|
||||||
|
${FTB_SOURCES}
|
||||||
|
${FLAME_SOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
|
message(STATUS "FOO! ${LOGIC_SOURCES}")
|
||||||
|
|
||||||
|
add_library(MultiMC_logic SHARED ${LOGIC_SOURCES})
|
||||||
|
set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
|
||||||
|
|
||||||
|
generate_export_header(MultiMC_logic)
|
||||||
|
|
||||||
|
# Link
|
||||||
|
target_link_libraries(MultiMC_logic xz-embedded MultiMC_unpack200 systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
|
||||||
|
target_link_libraries(MultiMC_logic Qt5::Core Qt5::Xml Qt5::Network Qt5::Concurrent)
|
||||||
|
|
||||||
|
# Mark and export headers
|
||||||
|
target_include_directories(MultiMC_logic PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" PRIVATE "${ZLIB_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
# Install it
|
||||||
|
install(
|
||||||
|
TARGETS MultiMC_logic
|
||||||
|
RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
|
||||||
|
LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file libutil/include/cmdutils.h
|
* @file libutil/include/cmdutils.h
|
||||||
* @brief commandline parsing and processing utilities
|
* @brief commandline parsing and processing utilities
|
||||||
@@ -38,7 +40,7 @@ namespace Commandline
|
|||||||
* @param args the argument string
|
* @param args the argument string
|
||||||
* @return a QStringList containing all arguments
|
* @return a QStringList containing all arguments
|
||||||
*/
|
*/
|
||||||
QStringList splitArgs(QString args);
|
MULTIMC_LOGIC_EXPORT QStringList splitArgs(QString args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The FlagStyle enum
|
* @brief The FlagStyle enum
|
||||||
@@ -67,8 +69,8 @@ namespace ArgumentStyle
|
|||||||
{
|
{
|
||||||
enum Enum
|
enum Enum
|
||||||
{
|
{
|
||||||
Space, /**< --option value */
|
Space, /**< --option=value */
|
||||||
Equals, /**< --option=value */
|
Equals, /**< --option value */
|
||||||
SpaceAndEquals, /**< --option[= ]value */
|
SpaceAndEquals, /**< --option[= ]value */
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
Default = Equals
|
Default = Equals
|
||||||
@@ -81,7 +83,7 @@ enum Enum
|
|||||||
/**
|
/**
|
||||||
* @brief The ParsingError class
|
* @brief The ParsingError class
|
||||||
*/
|
*/
|
||||||
class ParsingError : public std::runtime_error
|
class MULTIMC_LOGIC_EXPORT ParsingError : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParsingError(const QString &what);
|
ParsingError(const QString &what);
|
||||||
@@ -90,7 +92,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief The Parser class
|
* @brief The Parser class
|
||||||
*/
|
*/
|
||||||
class Parser
|
class MULTIMC_LOGIC_EXPORT Parser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
209
api/logic/Env.cpp
Normal file
209
api/logic/Env.cpp
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
#include "Env.h"
|
||||||
|
#include "net/HttpMetaCache.h"
|
||||||
|
#include "BaseVersion.h"
|
||||||
|
#include "BaseVersionList.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QNetworkProxy>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
#include "meta/Index.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
struct Env::Private
|
||||||
|
{
|
||||||
|
QNetworkAccessManager m_qnam;
|
||||||
|
shared_qobject_ptr<HttpMetaCache> m_metacache;
|
||||||
|
std::shared_ptr<IIconList> m_iconlist;
|
||||||
|
shared_qobject_ptr<Meta::Index> m_metadataIndex;
|
||||||
|
QString m_jarsPath;
|
||||||
|
QSet<QString> m_features;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Env * instance;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The *NEW* global rat nest of an object. Handle with care.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Env::Env()
|
||||||
|
{
|
||||||
|
d = new Private();
|
||||||
|
}
|
||||||
|
|
||||||
|
Env::~Env()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
Env& Env::Env::getInstance()
|
||||||
|
{
|
||||||
|
if(!instance)
|
||||||
|
{
|
||||||
|
instance = new Env();
|
||||||
|
}
|
||||||
|
return *instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::dispose()
|
||||||
|
{
|
||||||
|
delete instance;
|
||||||
|
instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_qobject_ptr< HttpMetaCache > Env::metacache()
|
||||||
|
{
|
||||||
|
return d->m_metacache;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager& Env::qnam() const
|
||||||
|
{
|
||||||
|
return d->m_qnam;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<IIconList> Env::icons()
|
||||||
|
{
|
||||||
|
return d->m_iconlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::registerIconList(std::shared_ptr<IIconList> iconlist)
|
||||||
|
{
|
||||||
|
d->m_iconlist = iconlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_qobject_ptr<Meta::Index> Env::metadataIndex()
|
||||||
|
{
|
||||||
|
if (!d->m_metadataIndex)
|
||||||
|
{
|
||||||
|
d->m_metadataIndex.reset(new Meta::Index());
|
||||||
|
}
|
||||||
|
return d->m_metadataIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Env::initHttpMetaCache()
|
||||||
|
{
|
||||||
|
auto &m_metacache = d->m_metacache;
|
||||||
|
m_metacache.reset(new HttpMetaCache("metacache"));
|
||||||
|
m_metacache->addBase("asset_indexes", QDir("assets/indexes").absolutePath());
|
||||||
|
m_metacache->addBase("asset_objects", QDir("assets/objects").absolutePath());
|
||||||
|
m_metacache->addBase("versions", QDir("versions").absolutePath());
|
||||||
|
m_metacache->addBase("libraries", QDir("libraries").absolutePath());
|
||||||
|
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
|
||||||
|
m_metacache->addBase("fmllibs", QDir("mods/minecraftforge/libs").absolutePath());
|
||||||
|
m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
|
||||||
|
m_metacache->addBase("general", QDir("cache").absolutePath());
|
||||||
|
m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
|
||||||
|
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
|
||||||
|
m_metacache->addBase("root", QDir::currentPath());
|
||||||
|
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
||||||
|
m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
|
||||||
|
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
||||||
|
m_metacache->Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password)
|
||||||
|
{
|
||||||
|
// Set the application proxy settings.
|
||||||
|
if (proxyTypeStr == "SOCKS5")
|
||||||
|
{
|
||||||
|
QNetworkProxy::setApplicationProxy(
|
||||||
|
QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password));
|
||||||
|
}
|
||||||
|
else if (proxyTypeStr == "HTTP")
|
||||||
|
{
|
||||||
|
QNetworkProxy::setApplicationProxy(
|
||||||
|
QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password));
|
||||||
|
}
|
||||||
|
else if (proxyTypeStr == "None")
|
||||||
|
{
|
||||||
|
// If we have no proxy set, set no proxy and return.
|
||||||
|
QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we have "Default" selected, set Qt to use the system proxy settings.
|
||||||
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Detecting proxy settings...";
|
||||||
|
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
|
||||||
|
d->m_qnam.setProxy(proxy);
|
||||||
|
QString proxyDesc;
|
||||||
|
if (proxy.type() == QNetworkProxy::NoProxy)
|
||||||
|
{
|
||||||
|
qDebug() << "Using no proxy is an option!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (proxy.type())
|
||||||
|
{
|
||||||
|
case QNetworkProxy::DefaultProxy:
|
||||||
|
proxyDesc = "Default proxy: ";
|
||||||
|
break;
|
||||||
|
case QNetworkProxy::Socks5Proxy:
|
||||||
|
proxyDesc = "Socks5 proxy: ";
|
||||||
|
break;
|
||||||
|
case QNetworkProxy::HttpProxy:
|
||||||
|
proxyDesc = "HTTP proxy: ";
|
||||||
|
break;
|
||||||
|
case QNetworkProxy::HttpCachingProxy:
|
||||||
|
proxyDesc = "HTTP caching: ";
|
||||||
|
break;
|
||||||
|
case QNetworkProxy::FtpCachingProxy:
|
||||||
|
proxyDesc = "FTP caching: ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
proxyDesc = "DERP proxy: ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
proxyDesc += QString("%3@%1:%2 pass %4")
|
||||||
|
.arg(proxy.hostName())
|
||||||
|
.arg(proxy.port())
|
||||||
|
.arg(proxy.user())
|
||||||
|
.arg(proxy.password());
|
||||||
|
qDebug() << proxyDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Env::getJarsPath()
|
||||||
|
{
|
||||||
|
if(d->m_jarsPath.isEmpty())
|
||||||
|
{
|
||||||
|
return FS::PathCombine(QCoreApplication::applicationDirPath(), "jars");
|
||||||
|
}
|
||||||
|
return d->m_jarsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::setJarsPath(const QString& path)
|
||||||
|
{
|
||||||
|
d->m_jarsPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::enableFeature(const QString& featureName, bool state)
|
||||||
|
{
|
||||||
|
if(state)
|
||||||
|
{
|
||||||
|
d->m_features.insert(featureName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d->m_features.remove(featureName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Env::isFeatureEnabled(const QString& featureName) const
|
||||||
|
{
|
||||||
|
return d->m_features.contains(featureName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::getEnabledFeatures(QSet<QString>& features) const
|
||||||
|
{
|
||||||
|
features = d->m_features;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Env::setEnabledFeatures(const QSet<QString>& features) const
|
||||||
|
{
|
||||||
|
d->m_features = features;
|
||||||
|
}
|
||||||
65
api/logic/Env.h
Normal file
65
api/logic/Env.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "icons/IIconList.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class HttpMetaCache;
|
||||||
|
class BaseVersionList;
|
||||||
|
class BaseVersion;
|
||||||
|
|
||||||
|
namespace Meta
|
||||||
|
{
|
||||||
|
class Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ENV)
|
||||||
|
#undef ENV
|
||||||
|
#endif
|
||||||
|
#define ENV (Env::getInstance())
|
||||||
|
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT Env
|
||||||
|
{
|
||||||
|
friend class MultiMC;
|
||||||
|
private:
|
||||||
|
struct Private;
|
||||||
|
Env();
|
||||||
|
~Env();
|
||||||
|
static void dispose();
|
||||||
|
public:
|
||||||
|
static Env& getInstance();
|
||||||
|
|
||||||
|
QNetworkAccessManager &qnam() const;
|
||||||
|
|
||||||
|
shared_qobject_ptr<HttpMetaCache> metacache();
|
||||||
|
|
||||||
|
std::shared_ptr<IIconList> icons();
|
||||||
|
|
||||||
|
/// init the cache. FIXME: possible future hook point
|
||||||
|
void initHttpMetaCache();
|
||||||
|
|
||||||
|
/// Updates the application proxy settings from the settings object.
|
||||||
|
void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
|
||||||
|
|
||||||
|
void registerIconList(std::shared_ptr<IIconList> iconlist);
|
||||||
|
|
||||||
|
shared_qobject_ptr<Meta::Index> metadataIndex();
|
||||||
|
|
||||||
|
QString getJarsPath();
|
||||||
|
void setJarsPath(const QString & path);
|
||||||
|
|
||||||
|
bool isFeatureEnabled(const QString & featureName) const;
|
||||||
|
void enableFeature(const QString & featureName, bool state = true);
|
||||||
|
void getEnabledFeatures(QSet<QString> & features) const;
|
||||||
|
void setEnabledFeatures(const QSet<QString> & features) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Private * d;
|
||||||
|
};
|
||||||
@@ -6,7 +6,9 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
class Exception : public std::exception
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT Exception : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Exception(const QString &message) : std::exception(), m_message(message)
|
Exception(const QString &message) : std::exception(), m_message(message)
|
||||||
@@ -174,11 +174,6 @@ bool copy::operator()(const QString &offset)
|
|||||||
bool deletePath(QString path)
|
bool deletePath(QString path)
|
||||||
{
|
{
|
||||||
bool OK = true;
|
bool OK = true;
|
||||||
QFileInfo finfo(path);
|
|
||||||
if(finfo.isFile()) {
|
|
||||||
return QFile::remove(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
|
|
||||||
if (!dir.exists())
|
if (!dir.exists())
|
||||||
@@ -299,7 +294,7 @@ QString NormalizePath(QString path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString badFilenameChars = "\"\\/?<>:;*|!+\r\n";
|
QString badFilenameChars = "\"\\/?<>:*|!+\r\n";
|
||||||
|
|
||||||
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
|
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
|
||||||
{
|
{
|
||||||
@@ -309,6 +304,10 @@ QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
|
|||||||
{
|
{
|
||||||
string[i] = replaceWith;
|
string[i] = replaceWith;
|
||||||
}
|
}
|
||||||
|
else if(string[i] > 127) // non ASCII
|
||||||
|
{
|
||||||
|
string[i] = replaceWith;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,14 @@
|
|||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFlags>
|
#include <QFlags>
|
||||||
|
|
||||||
namespace FS
|
namespace FS
|
||||||
{
|
{
|
||||||
|
|
||||||
class FileSystemException : public ::Exception
|
class MULTIMC_LOGIC_EXPORT FileSystemException : public ::Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileSystemException(const QString &message) : Exception(message) {}
|
FileSystemException(const QString &message) : Exception(message) {}
|
||||||
@@ -20,31 +21,31 @@ public:
|
|||||||
/**
|
/**
|
||||||
* write data to a file safely
|
* write data to a file safely
|
||||||
*/
|
*/
|
||||||
void write(const QString &filename, const QByteArray &data);
|
MULTIMC_LOGIC_EXPORT void write(const QString &filename, const QByteArray &data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read data from a file safely\
|
* read data from a file safely\
|
||||||
*/
|
*/
|
||||||
QByteArray read(const QString &filename);
|
MULTIMC_LOGIC_EXPORT QByteArray read(const QString &filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the last changed timestamp of an existing file
|
* Update the last changed timestamp of an existing file
|
||||||
*/
|
*/
|
||||||
bool updateTimestamp(const QString & filename);
|
MULTIMC_LOGIC_EXPORT bool updateTimestamp(const QString & filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates all the folders in a path for the specified path
|
* Creates all the folders in a path for the specified path
|
||||||
* last segment of the path is treated as a file name and is ignored!
|
* last segment of the path is treated as a file name and is ignored!
|
||||||
*/
|
*/
|
||||||
bool ensureFilePathExists(QString filenamepath);
|
MULTIMC_LOGIC_EXPORT bool ensureFilePathExists(QString filenamepath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates all the folders in a path for the specified path
|
* Creates all the folders in a path for the specified path
|
||||||
* last segment of the path is treated as a folder name and is created!
|
* last segment of the path is treated as a folder name and is created!
|
||||||
*/
|
*/
|
||||||
bool ensureFolderPathExists(QString filenamepath);
|
MULTIMC_LOGIC_EXPORT bool ensureFolderPathExists(QString filenamepath);
|
||||||
|
|
||||||
class copy
|
class MULTIMC_LOGIC_EXPORT copy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
copy(const QString & src, const QString & dst)
|
copy(const QString & src, const QString & dst)
|
||||||
@@ -80,13 +81,13 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Delete a folder recursively
|
* Delete a folder recursively
|
||||||
*/
|
*/
|
||||||
bool deletePath(QString path);
|
MULTIMC_LOGIC_EXPORT bool deletePath(QString path);
|
||||||
|
|
||||||
QString PathCombine(const QString &path1, const QString &path2);
|
MULTIMC_LOGIC_EXPORT QString PathCombine(const QString &path1, const QString &path2);
|
||||||
QString PathCombine(const QString &path1, const QString &path2, const QString &path3);
|
MULTIMC_LOGIC_EXPORT QString PathCombine(const QString &path1, const QString &path2, const QString &path3);
|
||||||
QString PathCombine(const QString &path1, const QString &path2, const QString &path3, const QString &path4);
|
MULTIMC_LOGIC_EXPORT QString PathCombine(const QString &path1, const QString &path2, const QString &path3, const QString &path4);
|
||||||
|
|
||||||
QString AbsolutePath(QString path);
|
MULTIMC_LOGIC_EXPORT QString AbsolutePath(QString path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve an executable
|
* Resolve an executable
|
||||||
@@ -98,7 +99,7 @@ QString AbsolutePath(QString path);
|
|||||||
*
|
*
|
||||||
* @return absolute path to executable or null string
|
* @return absolute path to executable or null string
|
||||||
*/
|
*/
|
||||||
QString ResolveExecutable(QString path);
|
MULTIMC_LOGIC_EXPORT QString ResolveExecutable(QString path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize path
|
* Normalize path
|
||||||
@@ -108,20 +109,20 @@ QString ResolveExecutable(QString path);
|
|||||||
*
|
*
|
||||||
* Returns false if the path logic somehow filed (and normalizedPath in invalid)
|
* Returns false if the path logic somehow filed (and normalizedPath in invalid)
|
||||||
*/
|
*/
|
||||||
QString NormalizePath(QString path);
|
MULTIMC_LOGIC_EXPORT QString NormalizePath(QString path);
|
||||||
|
|
||||||
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith = '-');
|
MULTIMC_LOGIC_EXPORT QString RemoveInvalidFilenameChars(QString string, QChar replaceWith = '-');
|
||||||
|
|
||||||
QString DirNameFromString(QString string, QString inDir = ".");
|
MULTIMC_LOGIC_EXPORT QString DirNameFromString(QString string, QString inDir = ".");
|
||||||
|
|
||||||
/// Checks if the a given Path contains "!"
|
/// Checks if the a given Path contains "!"
|
||||||
bool checkProblemticPathJava(QDir folder);
|
MULTIMC_LOGIC_EXPORT bool checkProblemticPathJava(QDir folder);
|
||||||
|
|
||||||
// Get the Directory representing the User's Desktop
|
// Get the Directory representing the User's Desktop
|
||||||
QString getDesktopDir();
|
MULTIMC_LOGIC_EXPORT QString getDesktopDir();
|
||||||
|
|
||||||
// Create a shortcut at *location*, pointing to *dest* called with the arguments *args*
|
// Create a shortcut at *location*, pointing to *dest* called with the arguments *args*
|
||||||
// call it *name* and assign it the icon *icon*
|
// call it *name* and assign it the icon *icon*
|
||||||
// return true if operation succeeded
|
// return true if operation succeeded
|
||||||
bool createShortCut(QString location, QString dest, QStringList args, QString name, QString iconLocation);
|
MULTIMC_LOGIC_EXPORT bool createShortCut(QString location, QString dest, QStringList args, QString name, QString iconLocation);
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ slots:
|
|||||||
<< "asdf"
|
<< "asdf"
|
||||||
<< QString()
|
<< QString()
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
<< GET_TEST_FILE("data/FileSystem-test_createShortcut-unix")
|
<< MULTIMC_GET_TEST_FILE("data/FileSystem-test_createShortcut-unix")
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
<< QByteArray()
|
<< QByteArray()
|
||||||
#endif
|
#endif
|
||||||
@@ -3,14 +3,16 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
class Filter
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Filter();
|
virtual ~Filter();
|
||||||
virtual bool accepts(const QString & value) = 0;
|
virtual bool accepts(const QString & value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContainsFilter: public Filter
|
class MULTIMC_LOGIC_EXPORT ContainsFilter: public Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContainsFilter(const QString &pattern);
|
ContainsFilter(const QString &pattern);
|
||||||
@@ -20,7 +22,7 @@ private:
|
|||||||
QString pattern;
|
QString pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExactFilter: public Filter
|
class MULTIMC_LOGIC_EXPORT ExactFilter: public Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExactFilter(const QString &pattern);
|
ExactFilter(const QString &pattern);
|
||||||
@@ -30,7 +32,7 @@ private:
|
|||||||
QString pattern;
|
QString pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegexpFilter: public Filter
|
class MULTIMC_LOGIC_EXPORT RegexpFilter: public Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RegexpFilter(const QString ®exp, bool invert);
|
RegexpFilter(const QString ®exp, bool invert);
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
class GZip
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT GZip
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
|
static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
|
||||||
@@ -5,10 +5,9 @@
|
|||||||
#include "pathmatcher/RegexpMatcher.h"
|
#include "pathmatcher/RegexpMatcher.h"
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
|
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves)
|
||||||
{
|
{
|
||||||
m_origInstance = origInstance;
|
m_origInstance = origInstance;
|
||||||
m_keepPlaytime = keepPlaytime;
|
|
||||||
|
|
||||||
if(!copySaves)
|
if(!copySaves)
|
||||||
{
|
{
|
||||||
@@ -47,9 +46,6 @@ void InstanceCopyTask::copyFinished()
|
|||||||
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
||||||
inst->setName(m_instName);
|
inst->setName(m_instName);
|
||||||
inst->setIconKey(m_instIcon);
|
inst->setIconKey(m_instIcon);
|
||||||
if(!m_keepPlaytime) {
|
|
||||||
inst->resetTimePlayed();
|
|
||||||
}
|
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include "net/NetJob.h"
|
#include "net/NetJob.h"
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
@@ -10,11 +11,11 @@
|
|||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
#include "InstanceTask.h"
|
#include "InstanceTask.h"
|
||||||
|
|
||||||
class InstanceCopyTask : public InstanceTask
|
class MULTIMC_LOGIC_EXPORT InstanceCopyTask : public InstanceTask
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
|
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Entry point for tasks.
|
//! Entry point for tasks.
|
||||||
@@ -27,5 +28,4 @@ private: /* data */
|
|||||||
QFuture<bool> m_copyFuture;
|
QFuture<bool> m_copyFuture;
|
||||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||||
std::unique_ptr<IPathMatcher> m_matcher;
|
std::unique_ptr<IPathMatcher> m_matcher;
|
||||||
bool m_keepPlaytime;
|
|
||||||
};
|
};
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
//FIXME: remove this
|
//FIXME: remove this
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/ComponentList.h"
|
||||||
|
|
||||||
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
|
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
|
||||||
{
|
{
|
||||||
@@ -20,7 +20,7 @@ void InstanceCreationTask::executeTask()
|
|||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
instanceSettings->registerSetting("InstanceType", "Legacy");
|
||||||
instanceSettings->set("InstanceType", "OneSix");
|
instanceSettings->set("InstanceType", "OneSix");
|
||||||
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
|
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
|
||||||
auto components = inst.getPackProfile();
|
auto components = inst.getComponentList();
|
||||||
components->buildingFromScratch();
|
components->buildingFromScratch();
|
||||||
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
||||||
inst.setName(m_instName);
|
inst.setName(m_instName);
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include "net/NetJob.h"
|
#include "net/NetJob.h"
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
#include "BaseVersion.h"
|
#include "BaseVersion.h"
|
||||||
#include "InstanceTask.h"
|
#include "InstanceTask.h"
|
||||||
|
|
||||||
class InstanceCreationTask : public InstanceTask
|
class MULTIMC_LOGIC_EXPORT InstanceCreationTask : public InstanceTask
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -1,39 +1,20 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "InstanceImportTask.h"
|
#include "InstanceImportTask.h"
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "Application.h"
|
#include "Env.h"
|
||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "NullInstance.h"
|
#include "NullInstance.h"
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
|
#include "icons/IIconList.h"
|
||||||
#include "icons/IconUtils.h"
|
#include "icons/IconUtils.h"
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
// FIXME: this does not belong here, it's Minecraft/Flame specific
|
// FIXME: this does not belong here, it's Minecraft/Flame specific
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/ComponentList.h"
|
||||||
#include "modplatform/flame/FileResolvingTask.h"
|
#include "modplatform/flame/FileResolvingTask.h"
|
||||||
#include "modplatform/flame/PackManifest.h"
|
#include "modplatform/flame/PackManifest.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include <quazipdir.h>
|
|
||||||
#include "modplatform/technic/TechnicPackProcessor.h"
|
|
||||||
|
|
||||||
#include "icons/IconList.h"
|
|
||||||
#include "Application.h"
|
|
||||||
|
|
||||||
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
||||||
{
|
{
|
||||||
@@ -42,6 +23,8 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
|||||||
|
|
||||||
void InstanceImportTask::executeTask()
|
void InstanceImportTask::executeTask()
|
||||||
{
|
{
|
||||||
|
InstancePtr newInstance;
|
||||||
|
|
||||||
if (m_sourceUrl.isLocalFile())
|
if (m_sourceUrl.isLocalFile())
|
||||||
{
|
{
|
||||||
m_archivePath = m_sourceUrl.toLocalFile();
|
m_archivePath = m_sourceUrl.toLocalFile();
|
||||||
@@ -53,7 +36,7 @@ void InstanceImportTask::executeTask()
|
|||||||
m_downloadRequired = true;
|
m_downloadRequired = true;
|
||||||
|
|
||||||
const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path();
|
const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path();
|
||||||
auto entry = APPLICATION->metacache()->resolveEntry("general", path);
|
auto entry = ENV.metacache()->resolveEntry("general", path);
|
||||||
entry->setStale(true);
|
entry->setStale(true);
|
||||||
m_filesNetJob.reset(new NetJob(tr("Modpack download")));
|
m_filesNetJob.reset(new NetJob(tr("Modpack download")));
|
||||||
m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
|
m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
|
||||||
@@ -62,7 +45,7 @@ void InstanceImportTask::executeTask()
|
|||||||
connect(job, &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
|
connect(job, &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
|
||||||
connect(job, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
|
connect(job, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
|
||||||
connect(job, &NetJob::failed, this, &InstanceImportTask::downloadFailed);
|
connect(job, &NetJob::failed, this, &InstanceImportTask::downloadFailed);
|
||||||
m_filesNetJob->start(APPLICATION->network());
|
m_filesNetJob->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +82,6 @@ void InstanceImportTask::processZipPack()
|
|||||||
|
|
||||||
QStringList blacklist = {"instance.cfg", "manifest.json"};
|
QStringList blacklist = {"instance.cfg", "manifest.json"};
|
||||||
QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
|
QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
|
||||||
bool technicFound = QuaZipDir(m_packZip.get()).exists("/bin/modpack.jar") || QuaZipDir(m_packZip.get()).exists("/bin/version.json");
|
|
||||||
QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
|
QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
|
||||||
QString root;
|
QString root;
|
||||||
if(!mmcFound.isNull())
|
if(!mmcFound.isNull())
|
||||||
@@ -109,14 +91,6 @@ void InstanceImportTask::processZipPack()
|
|||||||
root = mmcFound;
|
root = mmcFound;
|
||||||
m_modpackType = ModpackType::MultiMC;
|
m_modpackType = ModpackType::MultiMC;
|
||||||
}
|
}
|
||||||
else if (technicFound)
|
|
||||||
{
|
|
||||||
// process as Technic pack
|
|
||||||
qDebug() << "Technic:" << technicFound;
|
|
||||||
extractDir.mkpath(".minecraft");
|
|
||||||
extractDir.cd(".minecraft");
|
|
||||||
m_modpackType = ModpackType::Technic;
|
|
||||||
}
|
|
||||||
else if(!flameFound.isNull())
|
else if(!flameFound.isNull())
|
||||||
{
|
{
|
||||||
// process as Flame pack
|
// process as Flame pack
|
||||||
@@ -124,6 +98,7 @@ void InstanceImportTask::processZipPack()
|
|||||||
root = flameFound;
|
root = flameFound;
|
||||||
m_modpackType = ModpackType::Flame;
|
m_modpackType = ModpackType::Flame;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_modpackType == ModpackType::Unknown)
|
if(m_modpackType == ModpackType::Unknown)
|
||||||
{
|
{
|
||||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||||
@@ -140,7 +115,7 @@ void InstanceImportTask::processZipPack()
|
|||||||
void InstanceImportTask::extractFinished()
|
void InstanceImportTask::extractFinished()
|
||||||
{
|
{
|
||||||
m_packZip.reset();
|
m_packZip.reset();
|
||||||
if (!m_extractFuture.result())
|
if (m_extractFuture.result().isEmpty())
|
||||||
{
|
{
|
||||||
emitFailed(tr("Failed to extract modpack"));
|
emitFailed(tr("Failed to extract modpack"));
|
||||||
return;
|
return;
|
||||||
@@ -186,9 +161,6 @@ void InstanceImportTask::extractFinished()
|
|||||||
case ModpackType::MultiMC:
|
case ModpackType::MultiMC:
|
||||||
processMultiMC();
|
processMultiMC();
|
||||||
return;
|
return;
|
||||||
case ModpackType::Technic:
|
|
||||||
processTechnic();
|
|
||||||
return;
|
|
||||||
case ModpackType::Unknown:
|
case ModpackType::Unknown:
|
||||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||||
return;
|
return;
|
||||||
@@ -240,7 +212,6 @@ void InstanceImportTask::processFlame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString forgeVersion;
|
QString forgeVersion;
|
||||||
QString fabricVersion;
|
|
||||||
for(auto &loader: pack.minecraft.modLoaders)
|
for(auto &loader: pack.minecraft.modLoaders)
|
||||||
{
|
{
|
||||||
auto id = loader.id;
|
auto id = loader.id;
|
||||||
@@ -250,12 +221,6 @@ void InstanceImportTask::processFlame()
|
|||||||
forgeVersion = id;
|
forgeVersion = id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(id.startsWith("fabric-"))
|
|
||||||
{
|
|
||||||
id.remove("fabric-");
|
|
||||||
fabricVersion = id;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
|
logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +236,7 @@ void InstanceImportTask::processFlame()
|
|||||||
mcVersion.remove(QRegExp("[.]+$"));
|
mcVersion.remove(QRegExp("[.]+$"));
|
||||||
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
|
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
|
||||||
}
|
}
|
||||||
auto components = instance.getPackProfile();
|
auto components = instance.getComponentList();
|
||||||
components->buildingFromScratch();
|
components->buildingFromScratch();
|
||||||
components->setComponentVersion("net.minecraft", mcVersion, true);
|
components->setComponentVersion("net.minecraft", mcVersion, true);
|
||||||
if(!forgeVersion.isEmpty())
|
if(!forgeVersion.isEmpty())
|
||||||
@@ -290,10 +255,6 @@ void InstanceImportTask::processFlame()
|
|||||||
}
|
}
|
||||||
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
||||||
}
|
}
|
||||||
if(!fabricVersion.isEmpty())
|
|
||||||
{
|
|
||||||
components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
|
|
||||||
}
|
|
||||||
if (m_instIcon != "default")
|
if (m_instIcon != "default")
|
||||||
{
|
{
|
||||||
instance.setIconKey(m_instIcon);
|
instance.setIconKey(m_instIcon);
|
||||||
@@ -327,13 +288,13 @@ void InstanceImportTask::processFlame()
|
|||||||
qDebug() << info.fileName();
|
qDebug() << info.fileName();
|
||||||
jarMods.push_back(info.absoluteFilePath());
|
jarMods.push_back(info.absoluteFilePath());
|
||||||
}
|
}
|
||||||
auto profile = instance.getPackProfile();
|
auto profile = instance.getComponentList();
|
||||||
profile->installJarMods(jarMods);
|
profile->installJarMods(jarMods);
|
||||||
// nuke the original files
|
// nuke the original files
|
||||||
FS::deletePath(jarmodsPath);
|
FS::deletePath(jarmodsPath);
|
||||||
}
|
}
|
||||||
instance.setName(m_instName);
|
instance.setName(m_instName);
|
||||||
m_modIdResolver = new Flame::FileResolvingTask(APPLICATION->network(), pack);
|
m_modIdResolver.reset(new Flame::FileResolvingTask(pack));
|
||||||
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
|
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
|
||||||
{
|
{
|
||||||
auto results = m_modIdResolver->getResults();
|
auto results = m_modIdResolver->getResults();
|
||||||
@@ -391,7 +352,7 @@ void InstanceImportTask::processFlame()
|
|||||||
setProgress(current, total);
|
setProgress(current, total);
|
||||||
});
|
});
|
||||||
setStatus(tr("Downloading mods..."));
|
setStatus(tr("Downloading mods..."));
|
||||||
m_filesNetJob->start(APPLICATION->network());
|
m_filesNetJob->start();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
|
connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
|
||||||
@@ -410,16 +371,9 @@ void InstanceImportTask::processFlame()
|
|||||||
m_modIdResolver->start();
|
m_modIdResolver->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceImportTask::processTechnic()
|
|
||||||
{
|
|
||||||
shared_qobject_ptr<Technic::TechnicPackProcessor> packProcessor = new Technic::TechnicPackProcessor();
|
|
||||||
connect(packProcessor.get(), &Technic::TechnicPackProcessor::succeeded, this, &InstanceImportTask::emitSucceeded);
|
|
||||||
connect(packProcessor.get(), &Technic::TechnicPackProcessor::failed, this, &InstanceImportTask::emitFailed);
|
|
||||||
packProcessor->run(m_globalSettings, m_instName, m_instIcon, m_stagingPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceImportTask::processMultiMC()
|
void InstanceImportTask::processMultiMC()
|
||||||
{
|
{
|
||||||
|
// FIXME: copy from FolderInstanceProvider!!! FIX IT!!!
|
||||||
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
||||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
instanceSettings->registerSetting("InstanceType", "Legacy");
|
||||||
@@ -445,7 +399,7 @@ void InstanceImportTask::processMultiMC()
|
|||||||
if (!importIconPath.isNull() && QFile::exists(importIconPath))
|
if (!importIconPath.isNull() && QFile::exists(importIconPath))
|
||||||
{
|
{
|
||||||
// import icon
|
// import icon
|
||||||
auto iconList = APPLICATION->icons();
|
auto iconList = ENV.icons();
|
||||||
if (iconList->iconFileExists(m_instIcon))
|
if (iconList->iconFileExists(m_instIcon))
|
||||||
{
|
{
|
||||||
iconList->deleteIcon(m_instIcon);
|
iconList->deleteIcon(m_instIcon);
|
||||||
@@ -1,21 +1,7 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "InstanceTask.h"
|
#include "InstanceTask.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include "net/NetJob.h"
|
#include "net/NetJob.h"
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
@@ -23,15 +9,13 @@
|
|||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
#include <nonstd/optional>
|
|
||||||
|
|
||||||
class QuaZip;
|
class QuaZip;
|
||||||
namespace Flame
|
namespace Flame
|
||||||
{
|
{
|
||||||
class FileResolvingTask;
|
class FileResolvingTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstanceImportTask : public InstanceTask
|
class MULTIMC_LOGIC_EXPORT InstanceImportTask : public InstanceTask
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -45,7 +29,6 @@ private:
|
|||||||
void processZipPack();
|
void processZipPack();
|
||||||
void processMultiMC();
|
void processMultiMC();
|
||||||
void processFlame();
|
void processFlame();
|
||||||
void processTechnic();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void downloadSucceeded();
|
void downloadSucceeded();
|
||||||
@@ -55,18 +38,17 @@ private slots:
|
|||||||
void extractAborted();
|
void extractAborted();
|
||||||
|
|
||||||
private: /* data */
|
private: /* data */
|
||||||
NetJob::Ptr m_filesNetJob;
|
NetJobPtr m_filesNetJob;
|
||||||
shared_qobject_ptr<Flame::FileResolvingTask> m_modIdResolver;
|
shared_qobject_ptr<Flame::FileResolvingTask> m_modIdResolver;
|
||||||
QUrl m_sourceUrl;
|
QUrl m_sourceUrl;
|
||||||
QString m_archivePath;
|
QString m_archivePath;
|
||||||
bool m_downloadRequired = false;
|
bool m_downloadRequired = false;
|
||||||
std::unique_ptr<QuaZip> m_packZip;
|
std::unique_ptr<QuaZip> m_packZip;
|
||||||
QFuture<nonstd::optional<QStringList>> m_extractFuture;
|
QFuture<QStringList> m_extractFuture;
|
||||||
QFutureWatcher<nonstd::optional<QStringList>> m_extractFutureWatcher;
|
QFutureWatcher<QStringList> m_extractFutureWatcher;
|
||||||
enum class ModpackType{
|
enum class ModpackType{
|
||||||
Unknown,
|
Unknown,
|
||||||
MultiMC,
|
MultiMC,
|
||||||
Flame,
|
Flame
|
||||||
Technic
|
|
||||||
} m_modpackType = ModpackType::Unknown;
|
} m_modpackType = ModpackType::Unknown;
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QMimeData>
|
|
||||||
|
|
||||||
#include "InstanceList.h"
|
#include "InstanceList.h"
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
@@ -64,50 +63,6 @@ InstanceList::~InstanceList()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::DropActions InstanceList::supportedDragActions() const
|
|
||||||
{
|
|
||||||
return Qt::MoveAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::DropActions InstanceList::supportedDropActions() const
|
|
||||||
{
|
|
||||||
return Qt::MoveAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceList::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const
|
|
||||||
{
|
|
||||||
if(data && data->hasFormat("application/x-instanceid")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstanceList::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
|
|
||||||
{
|
|
||||||
if(data && data->hasFormat("application/x-instanceid")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList InstanceList::mimeTypes() const
|
|
||||||
{
|
|
||||||
auto types = QAbstractListModel::mimeTypes();
|
|
||||||
types.push_back("application/x-instanceid");
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMimeData * InstanceList::mimeData(const QModelIndexList& indexes) const
|
|
||||||
{
|
|
||||||
auto mimeData = QAbstractListModel::mimeData(indexes);
|
|
||||||
if(indexes.size() == 1) {
|
|
||||||
auto instanceId = data(indexes[0], InstanceIDRole).toString();
|
|
||||||
mimeData->setData("application/x-instanceid", instanceId.toUtf8());
|
|
||||||
}
|
|
||||||
return mimeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int InstanceList::rowCount(const QModelIndex &parent) const
|
int InstanceList::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
@@ -145,10 +100,6 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
return pdata->name();
|
return pdata->name();
|
||||||
}
|
}
|
||||||
case Qt::AccessibleTextRole:
|
|
||||||
{
|
|
||||||
return tr("%1 Instance").arg(pdata->name());
|
|
||||||
}
|
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
{
|
{
|
||||||
return pdata->instanceRoot();
|
return pdata->instanceRoot();
|
||||||
@@ -157,7 +108,7 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
return pdata->iconKey();
|
return pdata->iconKey();
|
||||||
}
|
}
|
||||||
// HACK: see InstanceView.h in gui!
|
// HACK: see GroupView.h in gui!
|
||||||
case GroupRole:
|
case GroupRole:
|
||||||
{
|
{
|
||||||
return getInstanceGroup(pdata->id());
|
return getInstanceGroup(pdata->id());
|
||||||
@@ -205,8 +156,8 @@ GroupId InstanceList::getInstanceGroup(const InstanceId& id) const
|
|||||||
{
|
{
|
||||||
return GroupId();
|
return GroupId();
|
||||||
}
|
}
|
||||||
auto iter = m_instanceGroupIndex.find(inst->id());
|
auto iter = m_groupMap.find(inst->id());
|
||||||
if(iter != m_instanceGroupIndex.end())
|
if(iter != m_groupMap.end())
|
||||||
{
|
{
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
@@ -223,8 +174,8 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
auto iter = m_instanceGroupIndex.find(inst->id());
|
auto iter = m_groupMap.find(inst->id());
|
||||||
if(iter != m_instanceGroupIndex.end())
|
if(iter != m_groupMap.end())
|
||||||
{
|
{
|
||||||
if(*iter != name)
|
if(*iter != name)
|
||||||
{
|
{
|
||||||
@@ -235,12 +186,12 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
m_instanceGroupIndex[id] = name;
|
m_groupMap[id] = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(changed)
|
if(changed)
|
||||||
{
|
{
|
||||||
m_groupNameCache.insert(name);
|
m_groups.insert(name);
|
||||||
auto idx = getInstIndex(inst.get());
|
auto idx = getInstIndex(inst.get());
|
||||||
emit dataChanged(index(idx), index(idx), {GroupRole});
|
emit dataChanged(index(idx), index(idx), {GroupRole});
|
||||||
saveGroupList();
|
saveGroupList();
|
||||||
@@ -249,7 +200,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
|||||||
|
|
||||||
QStringList InstanceList::getGroups()
|
QStringList InstanceList::getGroups()
|
||||||
{
|
{
|
||||||
return m_groupNameCache.toList();
|
return m_groups.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceList::deleteGroup(const QString& name)
|
void InstanceList::deleteGroup(const QString& name)
|
||||||
@@ -262,7 +213,7 @@ void InstanceList::deleteGroup(const QString& name)
|
|||||||
auto instGroupName = getInstanceGroup(instID);
|
auto instGroupName = getInstanceGroup(instID);
|
||||||
if(instGroupName == name)
|
if(instGroupName == name)
|
||||||
{
|
{
|
||||||
m_instanceGroupIndex.remove(instID);
|
m_groupMap.remove(instID);
|
||||||
qDebug() << "Remove" << instID << "from group" << name;
|
qDebug() << "Remove" << instID << "from group" << name;
|
||||||
removed = true;
|
removed = true;
|
||||||
auto idx = getInstIndex(instance.get());
|
auto idx = getInstIndex(instance.get());
|
||||||
@@ -278,21 +229,16 @@ void InstanceList::deleteGroup(const QString& name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceList::isGroupCollapsed(const QString& group)
|
|
||||||
{
|
|
||||||
return m_collapsedGroups.contains(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceList::deleteInstance(const InstanceId& id)
|
void InstanceList::deleteInstance(const InstanceId& id)
|
||||||
{
|
{
|
||||||
auto inst = getInstanceById(id);
|
auto inst = getInstanceById(id);
|
||||||
if(!inst)
|
if(!inst)
|
||||||
{
|
{
|
||||||
qDebug() << "Cannot delete instance" << id << ". No such instance is present (deleted externally?).";
|
qDebug() << "Cannot delete instance" << id << " No such instance is present.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_instanceGroupIndex.remove(id))
|
if(m_groupMap.remove(id))
|
||||||
{
|
{
|
||||||
saveGroupList();
|
saveGroupList();
|
||||||
}
|
}
|
||||||
@@ -304,7 +250,7 @@ void InstanceList::deleteInstance(const InstanceId& id)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Instance" << id << "has been deleted by the launcher.";
|
qDebug() << "Instance" << id << "has been deleted by MultiMC.";
|
||||||
}
|
}
|
||||||
|
|
||||||
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr> &list)
|
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr> &list)
|
||||||
@@ -432,19 +378,9 @@ InstanceList::InstListError InstanceList::loadList()
|
|||||||
add(newList);
|
add(newList);
|
||||||
}
|
}
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
updateTotalPlayTime();
|
|
||||||
return NoError;
|
return NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceList::updateTotalPlayTime()
|
|
||||||
{
|
|
||||||
totalPlayTime = 0;
|
|
||||||
for(auto const& itr : m_instances)
|
|
||||||
{
|
|
||||||
totalPlayTime += itr.get()->totalTimePlayed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstanceList::saveNow()
|
void InstanceList::saveNow()
|
||||||
{
|
{
|
||||||
for(auto & item: m_instances)
|
for(auto & item: m_instances)
|
||||||
@@ -530,7 +466,6 @@ void InstanceList::propertiesChanged(BaseInstance *inst)
|
|||||||
if (i != -1)
|
if (i != -1)
|
||||||
{
|
{
|
||||||
emit dataChanged(index(i), index(i));
|
emit dataChanged(index(i), index(i));
|
||||||
updateTotalPlayTime();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +511,7 @@ void InstanceList::saveGroupList()
|
|||||||
WatchLock foo(m_watcher, m_instDir);
|
WatchLock foo(m_watcher, m_instDir);
|
||||||
QString groupFileName = m_instDir + "/instgroups.json";
|
QString groupFileName = m_instDir + "/instgroups.json";
|
||||||
QMap<QString, QSet<QString>> reverseGroupMap;
|
QMap<QString, QSet<QString>> reverseGroupMap;
|
||||||
for (auto iter = m_instanceGroupIndex.begin(); iter != m_instanceGroupIndex.end(); iter++)
|
for (auto iter = m_groupMap.begin(); iter != m_groupMap.end(); iter++)
|
||||||
{
|
{
|
||||||
QString id = iter.key();
|
QString id = iter.key();
|
||||||
QString group = iter.value();
|
QString group = iter.value();
|
||||||
@@ -609,7 +544,7 @@ void InstanceList::saveGroupList()
|
|||||||
auto name = iter.key();
|
auto name = iter.key();
|
||||||
QJsonObject groupObj;
|
QJsonObject groupObj;
|
||||||
QJsonArray instanceArr;
|
QJsonArray instanceArr;
|
||||||
groupObj.insert("hidden", QJsonValue(m_collapsedGroups.contains(name)));
|
groupObj.insert("hidden", QJsonValue(QString("false")));
|
||||||
for (auto item : list)
|
for (auto item : list)
|
||||||
{
|
{
|
||||||
instanceArr.append(QJsonValue(item));
|
instanceArr.append(QJsonValue(item));
|
||||||
@@ -633,6 +568,7 @@ void InstanceList::saveGroupList()
|
|||||||
void InstanceList::loadGroupList()
|
void InstanceList::loadGroupList()
|
||||||
{
|
{
|
||||||
qDebug() << "Will load group list now.";
|
qDebug() << "Will load group list now.";
|
||||||
|
QSet<QString> groupSet;
|
||||||
|
|
||||||
QString groupFileName = m_instDir + "/instgroups.json";
|
QString groupFileName = m_instDir + "/instgroups.json";
|
||||||
|
|
||||||
@@ -683,8 +619,7 @@ void InstanceList::loadGroupList()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> groupSet;
|
m_groupMap.clear();
|
||||||
m_instanceGroupIndex.clear();
|
|
||||||
|
|
||||||
// Iterate through all the groups.
|
// Iterate through all the groups.
|
||||||
QJsonObject groupMapping = rootObj.value("groups").toObject();
|
QJsonObject groupMapping = rootObj.value("groups").toObject();
|
||||||
@@ -695,35 +630,37 @@ void InstanceList::loadGroupList()
|
|||||||
// If not an object, complain and skip to the next one.
|
// If not an object, complain and skip to the next one.
|
||||||
if (!iter.value().isObject())
|
if (!iter.value().isObject())
|
||||||
{
|
{
|
||||||
qWarning() << QString("Group '%1' in the group list should be an object.").arg(groupName).toUtf8();
|
qWarning() << QString("Group '%1' in the group list should "
|
||||||
|
"be an object.")
|
||||||
|
.arg(groupName)
|
||||||
|
.toUtf8();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject groupObj = iter.value().toObject();
|
QJsonObject groupObj = iter.value().toObject();
|
||||||
if (!groupObj.value("instances").isArray())
|
if (!groupObj.value("instances").isArray())
|
||||||
{
|
{
|
||||||
qWarning() << QString("Group '%1' in the group list is invalid. It should contain an array called 'instances'.").arg(groupName).toUtf8();
|
qWarning() << QString("Group '%1' in the group list is invalid. "
|
||||||
|
"It should contain an array "
|
||||||
|
"called 'instances'.")
|
||||||
|
.arg(groupName)
|
||||||
|
.toUtf8();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep a list/set of groups for choosing
|
// keep a list/set of groups for choosing
|
||||||
groupSet.insert(groupName);
|
groupSet.insert(groupName);
|
||||||
|
|
||||||
auto hidden = groupObj.value("hidden").toBool(false);
|
|
||||||
if(hidden) {
|
|
||||||
m_collapsedGroups.insert(groupName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through the list of instances in the group.
|
// Iterate through the list of instances in the group.
|
||||||
QJsonArray instancesArray = groupObj.value("instances").toArray();
|
QJsonArray instancesArray = groupObj.value("instances").toArray();
|
||||||
|
|
||||||
for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end(); iter2++)
|
for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end(); iter2++)
|
||||||
{
|
{
|
||||||
m_instanceGroupIndex[(*iter2).toString()] = groupName;
|
m_groupMap[(*iter2).toString()] = groupName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_groupsLoaded = true;
|
m_groupsLoaded = true;
|
||||||
m_groupNameCache.unite(groupSet);
|
m_groups.unite(groupSet);
|
||||||
qDebug() << "Group list loaded.";
|
qDebug() << "Group list loaded.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,17 +685,6 @@ void InstanceList::on_InstFolderChanged(const Setting &setting, QVariant value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceList::on_GroupStateChanged(const QString& group, bool collapsed)
|
|
||||||
{
|
|
||||||
qDebug() << "Group" << group << (collapsed ? "collapsed" : "expanded");
|
|
||||||
if(collapsed) {
|
|
||||||
m_collapsedGroups.insert(group);
|
|
||||||
} else {
|
|
||||||
m_collapsedGroups.remove(group);
|
|
||||||
}
|
|
||||||
saveGroupList();
|
|
||||||
}
|
|
||||||
|
|
||||||
class InstanceStaging : public Task
|
class InstanceStaging : public Task
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -844,7 +770,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
* WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows.
|
* WHY: the whole reason why this uses an exponential backoff retry scheme is antivirus on Windows.
|
||||||
* Basically, it starts messing things up while the launcher is extracting/creating instances
|
* Basically, it starts messing things up while MultiMC is extracting/creating instances
|
||||||
* and causes that horrible failure that is NTFS to lock files in place because they are open.
|
* and causes that horrible failure that is NTFS to lock files in place because they are open.
|
||||||
*/
|
*/
|
||||||
ExponentialSeries backoff;
|
ExponentialSeries backoff;
|
||||||
@@ -867,7 +793,7 @@ Task * InstanceList::wrapInstanceTask(InstanceTask * task)
|
|||||||
QString InstanceList::getStagedInstancePath()
|
QString InstanceList::getStagedInstancePath()
|
||||||
{
|
{
|
||||||
QString key = QUuid::createUuid().toString();
|
QString key = QUuid::createUuid().toString();
|
||||||
QString relPath = FS::PathCombine("_LAUNCHER_TEMP/" , key);
|
QString relPath = FS::PathCombine("_MMC_TEMP/" , key);
|
||||||
QDir rootPath(m_instDir);
|
QDir rootPath(m_instDir);
|
||||||
auto path = FS::PathCombine(m_instDir, relPath);
|
auto path = FS::PathCombine(m_instDir, relPath);
|
||||||
if(!rootPath.mkpath(relPath))
|
if(!rootPath.mkpath(relPath))
|
||||||
@@ -889,11 +815,10 @@ bool InstanceList::commitStagedInstance(const QString& path, const QString& inst
|
|||||||
qWarning() << "Failed to move" << path << "to" << destination;
|
qWarning() << "Failed to move" << path << "to" << destination;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_instanceGroupIndex[instID] = groupName;
|
m_groupMap[instID] = groupName;
|
||||||
instanceSet.insert(instID);
|
instanceSet.insert(instID);
|
||||||
m_groupNameCache.insert(groupName);
|
m_groups.insert(groupName);
|
||||||
emit instancesChanged();
|
emit instancesChanged();
|
||||||
emit instanceSelectRequest(instID);
|
|
||||||
}
|
}
|
||||||
saveGroupList();
|
saveGroupList();
|
||||||
return true;
|
return true;
|
||||||
@@ -904,9 +829,4 @@ bool InstanceList::destroyStagingPath(const QString& keyPath)
|
|||||||
return FS::deletePath(keyPath);
|
return FS::deletePath(keyPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceList::getTotalPlayTime() {
|
|
||||||
updateTotalPlayTime();
|
|
||||||
return totalPlayTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "InstanceList.moc"
|
#include "InstanceList.moc"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
@@ -47,7 +49,7 @@ enum class GroupsState
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class InstanceList : public QAbstractListModel
|
class MULTIMC_LOGIC_EXPORT InstanceList : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -93,11 +95,10 @@ public:
|
|||||||
InstListError loadList();
|
InstListError loadList();
|
||||||
void saveNow();
|
void saveNow();
|
||||||
|
|
||||||
|
|
||||||
InstancePtr getInstanceById(QString id) const;
|
InstancePtr getInstanceById(QString id) const;
|
||||||
QModelIndex getInstanceIndexById(const QString &id) const;
|
QModelIndex getInstanceIndexById(const QString &id) const;
|
||||||
QStringList getGroups();
|
QStringList getGroups();
|
||||||
bool isGroupCollapsed(const QString &groupName);
|
|
||||||
|
|
||||||
GroupId getInstanceGroup(const InstanceId & id) const;
|
GroupId getInstanceGroup(const InstanceId & id) const;
|
||||||
void setInstanceGroup(const InstanceId & id, const GroupId& name);
|
void setInstanceGroup(const InstanceId & id, const GroupId& name);
|
||||||
|
|
||||||
@@ -125,28 +126,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool destroyStagingPath(const QString & keyPath);
|
bool destroyStagingPath(const QString & keyPath);
|
||||||
|
|
||||||
int getTotalPlayTime();
|
|
||||||
|
|
||||||
Qt::DropActions supportedDragActions() const override;
|
|
||||||
|
|
||||||
Qt::DropActions supportedDropActions() const override;
|
|
||||||
|
|
||||||
bool canDropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) const override;
|
|
||||||
|
|
||||||
bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
|
|
||||||
|
|
||||||
QStringList mimeTypes() const override;
|
|
||||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataIsInvalid();
|
void dataIsInvalid();
|
||||||
void instancesChanged();
|
void instancesChanged();
|
||||||
void instanceSelectRequest(QString instanceId);
|
|
||||||
void groupsChanged(QSet<QString> groups);
|
void groupsChanged(QSet<QString> groups);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void on_InstFolderChanged(const Setting &setting, QVariant value);
|
void on_InstFolderChanged(const Setting &setting, QVariant value);
|
||||||
void on_GroupStateChanged(const QString &group, bool collapsed);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void propertiesChanged(BaseInstance *inst);
|
void propertiesChanged(BaseInstance *inst);
|
||||||
@@ -155,7 +141,6 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int getInstIndex(BaseInstance *inst) const;
|
int getInstIndex(BaseInstance *inst) const;
|
||||||
void updateTotalPlayTime();
|
|
||||||
void suspendWatch();
|
void suspendWatch();
|
||||||
void resumeWatch();
|
void resumeWatch();
|
||||||
void add(const QList<InstancePtr> &list);
|
void add(const QList<InstancePtr> &list);
|
||||||
@@ -166,17 +151,14 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int m_watchLevel = 0;
|
int m_watchLevel = 0;
|
||||||
int totalPlayTime = 0;
|
|
||||||
bool m_dirty = false;
|
bool m_dirty = false;
|
||||||
QList<InstancePtr> m_instances;
|
QList<InstancePtr> m_instances;
|
||||||
QSet<QString> m_groupNameCache;
|
QSet<QString> m_groups;
|
||||||
|
|
||||||
SettingsObjectPtr m_globalSettings;
|
SettingsObjectPtr m_globalSettings;
|
||||||
QString m_instDir;
|
QString m_instDir;
|
||||||
QFileSystemWatcher * m_watcher;
|
QFileSystemWatcher * m_watcher;
|
||||||
// FIXME: this is so inefficient that looking at it is almost painful.
|
QMap<InstanceId, GroupId> m_groupMap;
|
||||||
QSet<QString> m_collapsedGroups;
|
|
||||||
QMap<InstanceId, GroupId> m_instanceGroupIndex;
|
|
||||||
QSet<InstanceId> instanceSet;
|
QSet<InstanceId> instanceSet;
|
||||||
bool m_groupsLoaded = false;
|
bool m_groupsLoaded = false;
|
||||||
bool m_instancesProbed = false;
|
bool m_instancesProbed = false;
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include "settings/SettingsObject.h"
|
#include "settings/SettingsObject.h"
|
||||||
|
|
||||||
class InstanceTask : public Task
|
class MULTIMC_LOGIC_EXPORT InstanceTask : public Task
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -16,32 +16,32 @@
|
|||||||
|
|
||||||
namespace Json
|
namespace Json
|
||||||
{
|
{
|
||||||
class JsonException : public ::Exception
|
class MULTIMC_LOGIC_EXPORT JsonException : public ::Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JsonException(const QString &message) : Exception(message) {}
|
JsonException(const QString &message) : Exception(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @throw FileSystemException
|
/// @throw FileSystemException
|
||||||
void write(const QJsonDocument &doc, const QString &filename);
|
MULTIMC_LOGIC_EXPORT void write(const QJsonDocument &doc, const QString &filename);
|
||||||
/// @throw FileSystemException
|
/// @throw FileSystemException
|
||||||
void write(const QJsonObject &object, const QString &filename);
|
MULTIMC_LOGIC_EXPORT void write(const QJsonObject &object, const QString &filename);
|
||||||
/// @throw FileSystemException
|
/// @throw FileSystemException
|
||||||
void write(const QJsonArray &array, const QString &filename);
|
MULTIMC_LOGIC_EXPORT void write(const QJsonArray &array, const QString &filename);
|
||||||
|
|
||||||
QByteArray toBinary(const QJsonObject &obj);
|
MULTIMC_LOGIC_EXPORT QByteArray toBinary(const QJsonObject &obj);
|
||||||
QByteArray toBinary(const QJsonArray &array);
|
MULTIMC_LOGIC_EXPORT QByteArray toBinary(const QJsonArray &array);
|
||||||
QByteArray toText(const QJsonObject &obj);
|
MULTIMC_LOGIC_EXPORT QByteArray toText(const QJsonObject &obj);
|
||||||
QByteArray toText(const QJsonArray &array);
|
MULTIMC_LOGIC_EXPORT QByteArray toText(const QJsonArray &array);
|
||||||
|
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
QJsonDocument requireDocument(const QByteArray &data, const QString &what = "Document");
|
MULTIMC_LOGIC_EXPORT QJsonDocument requireDocument(const QByteArray &data, const QString &what = "Document");
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
QJsonDocument requireDocument(const QString &filename, const QString &what = "Document");
|
MULTIMC_LOGIC_EXPORT QJsonDocument requireDocument(const QString &filename, const QString &what = "Document");
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
QJsonObject requireObject(const QJsonDocument &doc, const QString &what = "Document");
|
MULTIMC_LOGIC_EXPORT QJsonObject requireObject(const QJsonDocument &doc, const QString &what = "Document");
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
QJsonArray requireArray(const QJsonDocument &doc, const QString &what = "Document");
|
MULTIMC_LOGIC_EXPORT QJsonArray requireArray(const QJsonDocument &doc, const QString &what = "Document");
|
||||||
|
|
||||||
/////////////////// WRITING ////////////////////
|
/////////////////// WRITING ////////////////////
|
||||||
|
|
||||||
@@ -84,31 +84,31 @@ template <typename T>
|
|||||||
T requireIsType(const QJsonValue &value, const QString &what = "Value");
|
T requireIsType(const QJsonValue &value, const QString &what = "Value");
|
||||||
|
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> double requireIsType<double>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT double requireIsType<double>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> bool requireIsType<bool>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT bool requireIsType<bool>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> int requireIsType<int>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT int requireIsType<int>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QJsonObject requireIsType<QJsonObject>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QJsonObject requireIsType<QJsonObject>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QJsonArray requireIsType<QJsonArray>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QJsonArray requireIsType<QJsonArray>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QJsonValue requireIsType<QJsonValue>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QJsonValue requireIsType<QJsonValue>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QByteArray requireIsType<QByteArray>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QByteArray requireIsType<QByteArray>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QDateTime requireIsType<QDateTime>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QDateTime requireIsType<QDateTime>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QVariant requireIsType<QVariant>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QVariant requireIsType<QVariant>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QString requireIsType<QString>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QString requireIsType<QString>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QDir requireIsType<QDir>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QDir requireIsType<QDir>(const QJsonValue &value, const QString &what);
|
||||||
/// @throw JsonException
|
/// @throw JsonException
|
||||||
template<> QUrl requireIsType<QUrl>(const QJsonValue &value, const QString &what);
|
template<> MULTIMC_LOGIC_EXPORT QUrl requireIsType<QUrl>(const QJsonValue &value, const QString &what);
|
||||||
|
|
||||||
// the following functions are higher level functions, that make use of the above functions for
|
// the following functions are higher level functions, that make use of the above functions for
|
||||||
// type conversion
|
// type conversion
|
||||||
@@ -65,16 +65,16 @@ void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status)
|
|||||||
if (status == QProcess::NormalExit)
|
if (status == QProcess::NormalExit)
|
||||||
{
|
{
|
||||||
//: Message displayed on instance exit
|
//: Message displayed on instance exit
|
||||||
emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::Launcher);
|
emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::MultiMC);
|
||||||
changeState(LoggedProcess::Finished);
|
changeState(LoggedProcess::Finished);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//: Message displayed on instance crashed
|
//: Message displayed on instance crashed
|
||||||
if(exit_code == -1)
|
if(exit_code == -1)
|
||||||
emit log({tr("Process crashed.")}, MessageLevel::Launcher);
|
emit log({tr("Process crashed.")}, MessageLevel::MultiMC);
|
||||||
else
|
else
|
||||||
emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::Launcher);
|
emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::MultiMC);
|
||||||
changeState(LoggedProcess::Crashed);
|
changeState(LoggedProcess::Crashed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include "MessageLevel.h"
|
#include "MessageLevel.h"
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a basic process.
|
* This is a basic process.
|
||||||
* It has line-based logging support and hides some of the nasty bits.
|
* It has line-based logging support and hides some of the nasty bits.
|
||||||
*/
|
*/
|
||||||
class LoggedProcess : public QProcess
|
class MULTIMC_LOGIC_EXPORT LoggedProcess : public QProcess
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
10
api/logic/MMCStrings.h
Normal file
10
api/logic/MMCStrings.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
namespace Strings
|
||||||
|
{
|
||||||
|
int MULTIMC_LOGIC_EXPORT naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -208,27 +208,16 @@ bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & re
|
|||||||
|
|
||||||
|
|
||||||
// ours
|
// ours
|
||||||
nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
|
QStringList MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
|
||||||
{
|
{
|
||||||
QDir directory(target);
|
QDir directory(target);
|
||||||
QStringList extracted;
|
QStringList extracted;
|
||||||
|
|
||||||
qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
|
qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
|
||||||
auto numEntries = zip->getEntriesCount();
|
if (!zip->goToFirstFile())
|
||||||
if(numEntries < 0) {
|
|
||||||
qWarning() << "Failed to enumerate files in archive";
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
else if(numEntries == 0) {
|
|
||||||
qDebug() << "Extracting empty archives seems odd...";
|
|
||||||
return extracted;
|
|
||||||
}
|
|
||||||
else if (!zip->goToFirstFile())
|
|
||||||
{
|
{
|
||||||
qWarning() << "Failed to seek to first file in zip";
|
qWarning() << "Failed to seek to first file in zip";
|
||||||
return nonstd::nullopt;
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
QString name = zip->getCurrentFileName();
|
QString name = zip->getCurrentFileName();
|
||||||
@@ -246,7 +235,7 @@ nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString &
|
|||||||
{
|
{
|
||||||
qWarning() << "Failed to extract file" << name << "to" << absFilePath;
|
qWarning() << "Failed to extract file" << name << "to" << absFilePath;
|
||||||
JlCompress::removeFile(extracted);
|
JlCompress::removeFile(extracted);
|
||||||
return nonstd::nullopt;
|
return QStringList();
|
||||||
}
|
}
|
||||||
extracted.append(absFilePath);
|
extracted.append(absFilePath);
|
||||||
qDebug() << "Extracted file" << name;
|
qDebug() << "Extracted file" << name;
|
||||||
@@ -255,58 +244,12 @@ nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString &
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ours
|
// ours
|
||||||
bool MMCZip::extractRelFile(QuaZip *zip, const QString &file, const QString &target)
|
QStringList MMCZip::extractDir(QString fileCompressed, QString dir)
|
||||||
{
|
|
||||||
return JlCompress::extractFile(zip, file, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ours
|
|
||||||
nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString dir)
|
|
||||||
{
|
{
|
||||||
QuaZip zip(fileCompressed);
|
QuaZip zip(fileCompressed);
|
||||||
if (!zip.open(QuaZip::mdUnzip))
|
if (!zip.open(QuaZip::mdUnzip))
|
||||||
{
|
{
|
||||||
// check if this is a minimum size empty zip file...
|
return {};
|
||||||
QFileInfo fileInfo(fileCompressed);
|
|
||||||
if(fileInfo.size() == 22) {
|
|
||||||
return QStringList();
|
|
||||||
}
|
|
||||||
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();;
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
}
|
||||||
return MMCZip::extractSubDir(&zip, "", dir);
|
return MMCZip::extractSubDir(&zip, "", dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ours
|
|
||||||
nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString subdir, QString dir)
|
|
||||||
{
|
|
||||||
QuaZip zip(fileCompressed);
|
|
||||||
if (!zip.open(QuaZip::mdUnzip))
|
|
||||||
{
|
|
||||||
// check if this is a minimum size empty zip file...
|
|
||||||
QFileInfo fileInfo(fileCompressed);
|
|
||||||
if(fileInfo.size() == 22) {
|
|
||||||
return QStringList();
|
|
||||||
}
|
|
||||||
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();;
|
|
||||||
return nonstd::nullopt;
|
|
||||||
}
|
|
||||||
return MMCZip::extractSubDir(&zip, subdir, dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ours
|
|
||||||
bool MMCZip::extractFile(QString fileCompressed, QString file, QString target)
|
|
||||||
{
|
|
||||||
QuaZip zip(fileCompressed);
|
|
||||||
if (!zip.open(QuaZip::mdUnzip))
|
|
||||||
{
|
|
||||||
// check if this is a minimum size empty zip file...
|
|
||||||
QFileInfo fileInfo(fileCompressed);
|
|
||||||
if(fileInfo.size() == 22) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
qWarning() << "Could not open archive for unzipping:" << fileCompressed << "Error:" << zip.getZipError();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return MMCZip::extractRelFile(&zip, file, target);
|
|
||||||
}
|
|
||||||
71
api/logic/MMCZip.h
Normal file
71
api/logic/MMCZip.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QSet>
|
||||||
|
#include "minecraft/Mod.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
#include <JlCompress.h>
|
||||||
|
|
||||||
|
namespace MMCZip
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge two zip files, using a filter function
|
||||||
|
*/
|
||||||
|
bool MULTIMC_LOGIC_EXPORT mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
|
||||||
|
const JlCompress::FilterFunction filter = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* take a source jar, add mods to it, resulting in target jar
|
||||||
|
*/
|
||||||
|
bool MULTIMC_LOGIC_EXPORT createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a single file in archive by file name (not path)
|
||||||
|
*
|
||||||
|
* \return the path prefix where the file is
|
||||||
|
*/
|
||||||
|
QString MULTIMC_LOGIC_EXPORT findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString(""));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a multiple files of the same name in archive by file name
|
||||||
|
* If a file is found in a path, no deeper paths are searched
|
||||||
|
*
|
||||||
|
* \return true if anything was found
|
||||||
|
*/
|
||||||
|
bool MULTIMC_LOGIC_EXPORT findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root = QString());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a subdirectory from an archive
|
||||||
|
*/
|
||||||
|
QStringList MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a whole archive.
|
||||||
|
*
|
||||||
|
* \param fileCompressed The name of the archive.
|
||||||
|
* \param dir The directory to extract to, the current directory if left empty.
|
||||||
|
* \return The list of the full paths of the files extracted, empty on failure.
|
||||||
|
*/
|
||||||
|
QStringList MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
MessageLevel::Enum MessageLevel::getLevel(const QString& levelName)
|
MessageLevel::Enum MessageLevel::getLevel(const QString& levelName)
|
||||||
{
|
{
|
||||||
if (levelName == "Launcher")
|
if (levelName == "MultiMC")
|
||||||
return MessageLevel::Launcher;
|
return MessageLevel::MultiMC;
|
||||||
else if (levelName == "Debug")
|
else if (levelName == "Debug")
|
||||||
return MessageLevel::Debug;
|
return MessageLevel::Debug;
|
||||||
else if (levelName == "Info")
|
else if (levelName == "Info")
|
||||||
@@ -13,7 +13,7 @@ enum Enum
|
|||||||
Unknown, /**< No idea what this is or where it came from */
|
Unknown, /**< No idea what this is or where it came from */
|
||||||
StdOut, /**< Undetermined stderr messages */
|
StdOut, /**< Undetermined stderr messages */
|
||||||
StdErr, /**< Undetermined stdout messages */
|
StdErr, /**< Undetermined stdout messages */
|
||||||
Launcher, /**< Launcher Messages */
|
MultiMC, /**< MultiMC Messages */
|
||||||
Debug, /**< Debug Messages */
|
Debug, /**< Debug Messages */
|
||||||
Info, /**< Info Messages */
|
Info, /**< Info Messages */
|
||||||
Message, /**< Standard Messages */
|
Message, /**< Standard Messages */
|
||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
{
|
{
|
||||||
return instanceRoot();
|
return instanceRoot();
|
||||||
};
|
};
|
||||||
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr, MinecraftServerTargetPtr) override
|
shared_qobject_ptr<LaunchTask> createLaunchTask(AuthSessionPtr) override
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override
|
QStringList verboseDescription(AuthSessionPtr session) override
|
||||||
{
|
{
|
||||||
QStringList out;
|
QStringList out;
|
||||||
out << "Null instance - placeholder.";
|
out << "Null instance - placeholder.";
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
enum class ProblemSeverity
|
enum class ProblemSeverity
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
@@ -13,7 +15,7 @@ struct PatchProblem
|
|||||||
QString m_description;
|
QString m_description;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProblemProvider
|
class MULTIMC_LOGIC_EXPORT ProblemProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ProblemProvider() {};
|
virtual ~ProblemProvider() {};
|
||||||
@@ -21,7 +23,7 @@ public:
|
|||||||
virtual ProblemSeverity getProblemSeverity() const = 0;
|
virtual ProblemSeverity getProblemSeverity() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProblemContainer : public ProblemProvider
|
class MULTIMC_LOGIC_EXPORT ProblemContainer : public ProblemProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const QList<PatchProblem> getProblems() const override
|
const QList<PatchProblem> getProblems() const override
|
||||||
@@ -77,12 +77,6 @@ public:
|
|||||||
{
|
{
|
||||||
return m_ptr;
|
return m_ptr;
|
||||||
}
|
}
|
||||||
bool operator==(const shared_qobject_ptr<T>& other) {
|
|
||||||
return m_ptr == other.m_ptr;
|
|
||||||
}
|
|
||||||
bool operator!=(const shared_qobject_ptr<T>& other) {
|
|
||||||
return m_ptr != other.m_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr <T> m_ptr;
|
std::shared_ptr <T> m_ptr;
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QWriteLocker>
|
#include <QWriteLocker>
|
||||||
#include <QReadLocker>
|
#include <QReadLocker>
|
||||||
#include <QMap>
|
|
||||||
#include <QSet>
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
class RWStorage
|
class RWStorage
|
||||||
{
|
{
|
||||||
@@ -4,7 +4,9 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include "pathmatcher/IPathMatcher.h"
|
#include "pathmatcher/IPathMatcher.h"
|
||||||
|
|
||||||
class RecursiveFileSystemWatcher : public QObject
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT RecursiveFileSystemWatcher : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -3,8 +3,6 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "QObjectPtr.h"
|
|
||||||
|
|
||||||
class Usable;
|
class Usable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,11 +14,11 @@ class Usable
|
|||||||
{
|
{
|
||||||
friend class UseLock;
|
friend class UseLock;
|
||||||
public:
|
public:
|
||||||
std::size_t useCount() const
|
std::size_t useCount()
|
||||||
{
|
{
|
||||||
return m_useCount;
|
return m_useCount;
|
||||||
}
|
}
|
||||||
bool isInUse() const
|
bool isInUse()
|
||||||
{
|
{
|
||||||
return m_useCount > 0;
|
return m_useCount > 0;
|
||||||
}
|
}
|
||||||
@@ -45,7 +43,7 @@ private:
|
|||||||
class UseLock
|
class UseLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UseLock(shared_qobject_ptr<Usable> usable)
|
UseLock(std::shared_ptr<Usable> usable)
|
||||||
: m_usable(usable)
|
: m_usable(usable)
|
||||||
{
|
{
|
||||||
// this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate.
|
// this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate.
|
||||||
@@ -56,5 +54,5 @@ public:
|
|||||||
m_usable->decrementUses();
|
m_usable->decrementUses();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
shared_qobject_ptr<Usable> m_usable;
|
std::shared_ptr<Usable> m_usable;
|
||||||
};
|
};
|
||||||
@@ -78,7 +78,7 @@ void Version::parse()
|
|||||||
// FIXME: this is bad. versions can contain a lot more separators...
|
// FIXME: this is bad. versions can contain a lot more separators...
|
||||||
QStringList parts = m_string.split('.');
|
QStringList parts = m_string.split('.');
|
||||||
|
|
||||||
for (const auto &part : parts)
|
for (const auto part : parts)
|
||||||
{
|
{
|
||||||
m_sections.append(Section(part));
|
m_sections.append(Section(part));
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,11 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
class QUrl;
|
class QUrl;
|
||||||
|
|
||||||
class Version
|
class MULTIMC_LOGIC_EXPORT Version
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Version(const QString &str);
|
Version(const QString &str);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
7
api/logic/icons/IIconList.cpp
Normal file
7
api/logic/icons/IIconList.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include "IIconList.h"
|
||||||
|
|
||||||
|
// blargh
|
||||||
|
IIconList::~IIconList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
26
api/logic/icons/IIconList.h
Normal file
26
api/logic/icons/IIconList.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
enum IconType : unsigned
|
||||||
|
{
|
||||||
|
Builtin,
|
||||||
|
Transient,
|
||||||
|
FileBased,
|
||||||
|
ICONS_TOTAL,
|
||||||
|
ToBeDeleted
|
||||||
|
};
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT IIconList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IIconList();
|
||||||
|
virtual bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type) = 0;
|
||||||
|
virtual bool deleteIcon(const QString &key) = 0;
|
||||||
|
virtual void saveIcon(const QString &key, const QString &path, const char * format) const = 0;
|
||||||
|
virtual bool iconFileExists(const QString &key) const = 0;
|
||||||
|
virtual void installIcons(const QStringList &iconFiles) = 0;
|
||||||
|
virtual void installIcon(const QString &file, const QString &name) = 0;
|
||||||
|
};
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
namespace IconUtils {
|
namespace IconUtils {
|
||||||
|
|
||||||
// Given a folder and an icon key, find 'best' of the icons with the given key in there and return its path
|
// Given a folder and an icon key, find 'best' of the icons with the given key in there and return its path
|
||||||
QString findBestIconIn(const QString &folder, const QString & iconKey);
|
MULTIMC_LOGIC_EXPORT QString findBestIconIn(const QString &folder, const QString & iconKey);
|
||||||
|
|
||||||
// Get icon file type filter for file browser dialogs
|
// Get icon file type filter for file browser dialogs
|
||||||
QString getIconFilter();
|
MULTIMC_LOGIC_EXPORT QString getIconFilter();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "JavaChecker.h"
|
#include "JavaChecker.h"
|
||||||
|
#include "JavaUtils.h"
|
||||||
|
#include <FileSystem.h>
|
||||||
|
#include <Commandline.h>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "JavaUtils.h"
|
#include "Env.h"
|
||||||
#include "FileSystem.h"
|
|
||||||
#include "Commandline.h"
|
|
||||||
#include "Application.h"
|
|
||||||
|
|
||||||
JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
|
JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
|
|||||||
|
|
||||||
void JavaChecker::performCheck()
|
void JavaChecker::performCheck()
|
||||||
{
|
{
|
||||||
QString checkerJar = FS::PathCombine(APPLICATION->getJarsPath(), "JavaCheck.jar");
|
QString checkerJar = FS::PathCombine(ENV.getJarsPath(), "JavaCheck.jar");
|
||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success)
|
if(!results.contains("os.arch") || !results.contains("java.version") || !success)
|
||||||
{
|
{
|
||||||
result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
|
result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
|
||||||
emit checkFinished(result);
|
emit checkFinished(result);
|
||||||
@@ -124,7 +124,6 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
|
|
||||||
auto os_arch = results["os.arch"];
|
auto os_arch = results["os.arch"];
|
||||||
auto java_version = results["java.version"];
|
auto java_version = results["java.version"];
|
||||||
auto java_vendor = results["java.vendor"];
|
|
||||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
|
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
|
||||||
|
|
||||||
|
|
||||||
@@ -133,7 +132,6 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
|||||||
result.mojangPlatform = is_64 ? "64" : "32";
|
result.mojangPlatform = is_64 ? "64" : "32";
|
||||||
result.realPlatform = os_arch;
|
result.realPlatform = os_arch;
|
||||||
result.javaVersion = java_version;
|
result.javaVersion = java_version;
|
||||||
result.javaVendor = java_vendor;
|
|
||||||
qDebug() << "Java checker succeeded.";
|
qDebug() << "Java checker succeeded.";
|
||||||
emit checkFinished(result);
|
emit checkFinished(result);
|
||||||
}
|
}
|
||||||
@@ -142,12 +140,8 @@ void JavaChecker::error(QProcess::ProcessError err)
|
|||||||
{
|
{
|
||||||
if(err == QProcess::FailedToStart)
|
if(err == QProcess::FailedToStart)
|
||||||
{
|
{
|
||||||
qDebug() << "Java checker has failed to start.";
|
|
||||||
qDebug() << "Process environment:";
|
|
||||||
qDebug() << process->environment();
|
|
||||||
qDebug() << "Native environment:";
|
|
||||||
qDebug() << QProcessEnvironment::systemEnvironment().toStringList();
|
|
||||||
killTimer.stop();
|
killTimer.stop();
|
||||||
|
qDebug() << "Java checker has failed to start.";
|
||||||
JavaCheckResult result;
|
JavaCheckResult result;
|
||||||
{
|
{
|
||||||
result.path = m_path;
|
result.path = m_path;
|
||||||
@@ -5,17 +5,18 @@
|
|||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
#include "JavaVersion.h"
|
#include "JavaVersion.h"
|
||||||
|
|
||||||
class JavaChecker;
|
class JavaChecker;
|
||||||
|
|
||||||
struct JavaCheckResult
|
struct MULTIMC_LOGIC_EXPORT JavaCheckResult
|
||||||
{
|
{
|
||||||
QString path;
|
QString path;
|
||||||
QString mojangPlatform;
|
QString mojangPlatform;
|
||||||
QString realPlatform;
|
QString realPlatform;
|
||||||
JavaVersion javaVersion;
|
JavaVersion javaVersion;
|
||||||
QString javaVendor;
|
|
||||||
QString outLog;
|
QString outLog;
|
||||||
QString errorLog;
|
QString errorLog;
|
||||||
bool is_64bit = false;
|
bool is_64bit = false;
|
||||||
@@ -30,7 +31,7 @@ struct JavaCheckResult
|
|||||||
|
|
||||||
typedef shared_qobject_ptr<QProcess> QProcessPtr;
|
typedef shared_qobject_ptr<QProcess> QProcessPtr;
|
||||||
typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr;
|
typedef shared_qobject_ptr<JavaChecker> JavaCheckerPtr;
|
||||||
class JavaChecker : public QObject
|
class MULTIMC_LOGIC_EXPORT JavaChecker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -29,13 +29,13 @@ JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Ptr JavaInstallList::getLoadTask()
|
shared_qobject_ptr<Task> JavaInstallList::getLoadTask()
|
||||||
{
|
{
|
||||||
load();
|
load();
|
||||||
return getCurrentTask();
|
return getCurrentTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Ptr JavaInstallList::getCurrentTask()
|
shared_qobject_ptr<Task> JavaInstallList::getCurrentTask()
|
||||||
{
|
{
|
||||||
if(m_status == Status::InProgress)
|
if(m_status == Status::InProgress)
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,9 +26,11 @@
|
|||||||
|
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
class JavaListLoadTask;
|
class JavaListLoadTask;
|
||||||
|
|
||||||
class JavaInstallList : public BaseVersionList
|
class MULTIMC_LOGIC_EXPORT JavaInstallList : public BaseVersionList
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
enum class Status
|
enum class Status
|
||||||
@@ -40,7 +42,7 @@ class JavaInstallList : public BaseVersionList
|
|||||||
public:
|
public:
|
||||||
explicit JavaInstallList(QObject *parent = 0);
|
explicit JavaInstallList(QObject *parent = 0);
|
||||||
|
|
||||||
Task::Ptr getLoadTask() override;
|
shared_qobject_ptr<Task> getLoadTask() override;
|
||||||
bool isLoaded() override;
|
bool isLoaded() override;
|
||||||
const BaseVersionPtr at(int i) const override;
|
const BaseVersionPtr at(int i) const override;
|
||||||
int count() const override;
|
int count() const override;
|
||||||
@@ -54,7 +56,7 @@ public slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void load();
|
void load();
|
||||||
Task::Ptr getCurrentTask();
|
shared_qobject_ptr<Task> getCurrentTask();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Status m_status = Status::NotDone;
|
Status m_status = Status::NotDone;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -150,7 +150,7 @@ JavaInstallPtr JavaUtils::GetDefaultJava()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN32)
|
#if defined(Q_OS_WIN32)
|
||||||
QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName, QString keyJavaDir, QString subkeySuffix)
|
QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName)
|
||||||
{
|
{
|
||||||
QList<JavaInstallPtr> javas;
|
QList<JavaInstallPtr> javas;
|
||||||
|
|
||||||
@@ -175,6 +175,8 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString
|
|||||||
RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz);
|
RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString recommended = value;
|
||||||
|
|
||||||
TCHAR subKeyName[255];
|
TCHAR subKeyName[255];
|
||||||
DWORD subKeyNameSize, numSubKeys, retCode;
|
DWORD subKeyNameSize, numSubKeys, retCode;
|
||||||
|
|
||||||
@@ -193,7 +195,7 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString
|
|||||||
if (retCode == ERROR_SUCCESS)
|
if (retCode == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
// Now open the registry key for the version that we just got.
|
// Now open the registry key for the version that we just got.
|
||||||
QString newKeyName = keyName + "\\" + subKeyName + subkeySuffix;
|
QString newKeyName = keyName + "\\" + subKeyName;
|
||||||
|
|
||||||
HKEY newKey;
|
HKEY newKey;
|
||||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0,
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0,
|
||||||
@@ -202,11 +204,11 @@ QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString
|
|||||||
// Read the JavaHome value to find where Java is installed.
|
// Read the JavaHome value to find where Java is installed.
|
||||||
value = new char[0];
|
value = new char[0];
|
||||||
valueSz = 0;
|
valueSz = 0;
|
||||||
if (RegQueryValueEx(newKey, keyJavaDir.toStdString().c_str(), NULL, NULL, (BYTE *)value,
|
if (RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
|
||||||
&valueSz) == ERROR_MORE_DATA)
|
&valueSz) == ERROR_MORE_DATA)
|
||||||
{
|
{
|
||||||
value = new char[valueSz];
|
value = new char[valueSz];
|
||||||
RegQueryValueEx(newKey, keyJavaDir.toStdString().c_str(), NULL, NULL, (BYTE *)value,
|
RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
|
||||||
&valueSz);
|
&valueSz);
|
||||||
|
|
||||||
// Now, we construct the version object and add it to the list.
|
// Now, we construct the version object and add it to the list.
|
||||||
@@ -235,94 +237,25 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
{
|
{
|
||||||
QList<JavaInstallPtr> java_candidates;
|
QList<JavaInstallPtr> java_candidates;
|
||||||
|
|
||||||
// Oracle
|
|
||||||
QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome");
|
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
|
||||||
QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome");
|
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
|
||||||
QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment", "JavaHome");
|
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
|
||||||
QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey(
|
QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey(
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit", "JavaHome");
|
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
|
||||||
|
|
||||||
// Oracle for Java 9 and newer
|
|
||||||
QList<JavaInstallPtr> NEWJRE64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome");
|
|
||||||
QList<JavaInstallPtr> NEWJDK64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome");
|
|
||||||
QList<JavaInstallPtr> NEWJRE32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JRE", "JavaHome");
|
|
||||||
QList<JavaInstallPtr> NEWJDK32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\JDK", "JavaHome");
|
|
||||||
|
|
||||||
// AdoptOpenJDK
|
|
||||||
QList<JavaInstallPtr> ADOPTOPENJRE32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI");
|
|
||||||
QList<JavaInstallPtr> ADOPTOPENJRE64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JRE", "Path", "\\hotspot\\MSI");
|
|
||||||
QList<JavaInstallPtr> ADOPTOPENJDK32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
QList<JavaInstallPtr> ADOPTOPENJDK64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\AdoptOpenJDK\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
|
|
||||||
// Foundation (Eclipse)
|
|
||||||
QList<JavaInstallPtr> FOUNDATIONJDK32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
QList<JavaInstallPtr> FOUNDATIONJDK64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Foundation\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
|
|
||||||
// Adoptium (Eclipse)
|
|
||||||
QList<JavaInstallPtr> ADOPTIUMJDK32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
QList<JavaInstallPtr> ADOPTIUMJDK64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\Eclipse Adoptium\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
|
|
||||||
// Microsoft
|
|
||||||
QList<JavaInstallPtr> MICROSOFTJDK64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\Microsoft\\JDK", "Path", "\\hotspot\\MSI");
|
|
||||||
|
|
||||||
// Azul Zulu
|
|
||||||
QList<JavaInstallPtr> ZULU64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
|
||||||
QList<JavaInstallPtr> ZULU32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\Azul Systems\\Zulu", "InstallationPath");
|
|
||||||
|
|
||||||
// BellSoft Liberica
|
|
||||||
QList<JavaInstallPtr> LIBERICA64s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_64KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath");
|
|
||||||
QList<JavaInstallPtr> LIBERICA32s = this->FindJavaFromRegistryKey(
|
|
||||||
KEY_WOW64_32KEY, "SOFTWARE\\BellSoft\\Liberica", "InstallationPath");
|
|
||||||
|
|
||||||
// List x64 before x86
|
|
||||||
java_candidates.append(JRE64s);
|
java_candidates.append(JRE64s);
|
||||||
java_candidates.append(NEWJRE64s);
|
|
||||||
java_candidates.append(ADOPTOPENJRE64s);
|
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre8/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre8/bin/javaw.exe"));
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre7/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre7/bin/javaw.exe"));
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre6/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre6/bin/javaw.exe"));
|
||||||
java_candidates.append(JDK64s);
|
java_candidates.append(JDK64s);
|
||||||
java_candidates.append(NEWJDK64s);
|
|
||||||
java_candidates.append(ADOPTOPENJDK64s);
|
|
||||||
java_candidates.append(FOUNDATIONJDK64s);
|
|
||||||
java_candidates.append(ADOPTIUMJDK64s);
|
|
||||||
java_candidates.append(MICROSOFTJDK64s);
|
|
||||||
java_candidates.append(ZULU64s);
|
|
||||||
java_candidates.append(LIBERICA64s);
|
|
||||||
|
|
||||||
java_candidates.append(JRE32s);
|
java_candidates.append(JRE32s);
|
||||||
java_candidates.append(NEWJRE32s);
|
|
||||||
java_candidates.append(ADOPTOPENJRE32s);
|
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre8/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre8/bin/javaw.exe"));
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre7/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre7/bin/javaw.exe"));
|
||||||
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre6/bin/javaw.exe"));
|
java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre6/bin/javaw.exe"));
|
||||||
java_candidates.append(JDK32s);
|
java_candidates.append(JDK32s);
|
||||||
java_candidates.append(NEWJDK32s);
|
|
||||||
java_candidates.append(ADOPTOPENJDK32s);
|
|
||||||
java_candidates.append(FOUNDATIONJDK32s);
|
|
||||||
java_candidates.append(ADOPTIUMJDK32s);
|
|
||||||
java_candidates.append(ZULU32s);
|
|
||||||
java_candidates.append(LIBERICA32s);
|
|
||||||
|
|
||||||
java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
|
java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
|
||||||
|
|
||||||
QList<QString> candidates;
|
QList<QString> candidates;
|
||||||
@@ -394,13 +327,9 @@ QList<QString> JavaUtils::FindJavaPaths()
|
|||||||
scanJavaDir("/usr/java");
|
scanJavaDir("/usr/java");
|
||||||
// general locations used by distro packaging
|
// general locations used by distro packaging
|
||||||
scanJavaDir("/usr/lib/jvm");
|
scanJavaDir("/usr/lib/jvm");
|
||||||
scanJavaDir("/usr/lib64/jvm");
|
|
||||||
scanJavaDir("/usr/lib32/jvm");
|
scanJavaDir("/usr/lib32/jvm");
|
||||||
// javas stored in MultiMC's folder
|
// javas stored in MultiMC's folder
|
||||||
scanJavaDir("java");
|
scanJavaDir("java");
|
||||||
// manually installed JDKs in /opt
|
|
||||||
scanJavaDir("/opt/jdk");
|
|
||||||
scanJavaDir("/opt/jdks");
|
|
||||||
return javas;
|
return javas;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,9 +24,11 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
QProcessEnvironment CleanEnviroment();
|
QProcessEnvironment CleanEnviroment();
|
||||||
|
|
||||||
class JavaUtils : public QObject
|
class MULTIMC_LOGIC_EXPORT JavaUtils : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -37,6 +39,6 @@ public:
|
|||||||
JavaInstallPtr GetDefaultJava();
|
JavaInstallPtr GetDefaultJava();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QList<JavaInstallPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName, QString keyJavaDir, QString subkeySuffix = "");
|
QList<JavaInstallPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
// NOTE: apparently the GNU C library pollutes the global namespace with these... undef them.
|
// NOTE: apparently the GNU C library pollutes the global namespace with these... undef them.
|
||||||
@@ -10,7 +11,7 @@
|
|||||||
#undef minor
|
#undef minor
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class JavaVersion
|
class MULTIMC_LOGIC_EXPORT JavaVersion
|
||||||
{
|
{
|
||||||
friend class JavaVersionTest;
|
friend class JavaVersionTest;
|
||||||
public:
|
public:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -33,22 +33,22 @@ void CheckJava::executeTask()
|
|||||||
if (perInstance)
|
if (perInstance)
|
||||||
{
|
{
|
||||||
emit logLine(
|
emit logLine(
|
||||||
QString("The java binary \"%1\" couldn't be found. Please fix the java path "
|
tr("The java binary \"%1\" couldn't be found. Please fix the java path "
|
||||||
"override in the instance's settings or disable it.").arg(m_javaPath),
|
"override in the instance's settings or disable it.").arg(m_javaPath),
|
||||||
MessageLevel::Warning);
|
MessageLevel::Warning);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in "
|
emit logLine(tr("The java binary \"%1\" couldn't be found. Please set up java in "
|
||||||
"the settings.").arg(m_javaPath),
|
"the settings.").arg(m_javaPath),
|
||||||
MessageLevel::Warning);
|
MessageLevel::Warning);
|
||||||
}
|
}
|
||||||
emitFailed(QString("Java path is not valid."));
|
emitFailed(tr("Java path is not valid."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::Launcher);
|
emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::MultiMC);
|
||||||
}
|
}
|
||||||
|
|
||||||
QFileInfo javaInfo(realJavaPath);
|
QFileInfo javaInfo(realJavaPath);
|
||||||
@@ -56,13 +56,12 @@ void CheckJava::executeTask()
|
|||||||
auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
|
auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
|
||||||
auto storedArchitecture = settings->get("JavaArchitecture").toString();
|
auto storedArchitecture = settings->get("JavaArchitecture").toString();
|
||||||
auto storedVersion = settings->get("JavaVersion").toString();
|
auto storedVersion = settings->get("JavaVersion").toString();
|
||||||
auto storedVendor = settings->get("JavaVendor").toString();
|
|
||||||
m_javaUnixTime = javaUnixTime;
|
m_javaUnixTime = javaUnixTime;
|
||||||
// if timestamps are not the same, or something is missing, check!
|
// if timestamps are not the same, or something is missing, check!
|
||||||
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedVendor.size() == 0)
|
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0)
|
||||||
{
|
{
|
||||||
m_JavaChecker = new JavaChecker();
|
m_JavaChecker = new JavaChecker();
|
||||||
emit logLine(QString("Checking Java version..."), MessageLevel::Launcher);
|
emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
|
||||||
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
||||||
m_JavaChecker->m_path = realJavaPath;
|
m_JavaChecker->m_path = realJavaPath;
|
||||||
m_JavaChecker->performCheck();
|
m_JavaChecker->performCheck();
|
||||||
@@ -72,8 +71,7 @@ void CheckJava::executeTask()
|
|||||||
{
|
{
|
||||||
auto verString = instance->settings()->get("JavaVersion").toString();
|
auto verString = instance->settings()->get("JavaVersion").toString();
|
||||||
auto archString = instance->settings()->get("JavaArchitecture").toString();
|
auto archString = instance->settings()->get("JavaArchitecture").toString();
|
||||||
auto vendorString = instance->settings()->get("JavaVendor").toString();
|
printJavaInfo(verString, archString);
|
||||||
printJavaInfo(verString, archString, vendorString);
|
|
||||||
}
|
}
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
@@ -85,18 +83,18 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
case JavaCheckResult::Validity::Errored:
|
case JavaCheckResult::Validity::Errored:
|
||||||
{
|
{
|
||||||
// Error message displayed if java can't start
|
// Error message displayed if java can't start
|
||||||
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
emit logLine(tr("Could not start java:"), MessageLevel::Error);
|
||||||
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
||||||
emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::Launcher);
|
emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
|
||||||
printSystemInfo(false, false);
|
printSystemInfo(false, false);
|
||||||
emitFailed(QString("Could not start java!"));
|
emitFailed(tr("Could not start java!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case JavaCheckResult::Validity::ReturnedInvalidData:
|
case JavaCheckResult::Validity::ReturnedInvalidData:
|
||||||
{
|
{
|
||||||
emit logLine(QString("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
|
emit logLine(tr("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
|
||||||
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
||||||
emit logLine("\nMinecraft might not start properly.", MessageLevel::Launcher);
|
emit logLine("\nMinecraft might not start properly.", MessageLevel::MultiMC);
|
||||||
printSystemInfo(false, false);
|
printSystemInfo(false, false);
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
@@ -104,10 +102,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
case JavaCheckResult::Validity::Valid:
|
case JavaCheckResult::Validity::Valid:
|
||||||
{
|
{
|
||||||
auto instance = m_parent->instance();
|
auto instance = m_parent->instance();
|
||||||
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.javaVendor);
|
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform);
|
||||||
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
||||||
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
||||||
instance->settings()->set("JavaVendor", result.javaVendor);
|
|
||||||
instance->settings()->set("JavaTimestamp", m_javaUnixTime);
|
instance->settings()->set("JavaTimestamp", m_javaUnixTime);
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
return;
|
return;
|
||||||
@@ -115,9 +112,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor)
|
void CheckJava::printJavaInfo(const QString& version, const QString& architecture)
|
||||||
{
|
{
|
||||||
emit logLine(QString("Java is version %1, using %2-bit architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::Launcher);
|
emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
|
||||||
printSystemInfo(true, architecture == "64");
|
printSystemInfo(true, architecture == "64");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,13 +124,13 @@ void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
|
|||||||
auto system64 = Sys::isSystem64bit();
|
auto system64 = Sys::isSystem64bit();
|
||||||
if(cpu64 != system64)
|
if(cpu64 != system64)
|
||||||
{
|
{
|
||||||
emit logLine(QString("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
|
emit logLine(tr("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
|
||||||
}
|
}
|
||||||
if(javaIsKnown)
|
if(javaIsKnown)
|
||||||
{
|
{
|
||||||
if(javaIs64bit != system64)
|
if(javaIs64bit != system64)
|
||||||
{
|
{
|
||||||
emit logLine(QString("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
|
emit logLine(tr("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -35,7 +35,7 @@ private slots:
|
|||||||
void checkJavaFinished(JavaCheckResult result);
|
void checkJavaFinished(JavaCheckResult result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printJavaInfo(const QString & version, const QString & architecture, const QString & vendor);
|
void printJavaInfo(const QString & version, const QString & architecture);
|
||||||
void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
|
void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2013-2021 MultiMC Contributors
|
/* Copyright 2013-2019 MultiMC Contributors
|
||||||
*
|
*
|
||||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||||
*
|
*
|
||||||
@@ -24,7 +24,9 @@
|
|||||||
#include "LoggedProcess.h"
|
#include "LoggedProcess.h"
|
||||||
#include "LaunchStep.h"
|
#include "LaunchStep.h"
|
||||||
|
|
||||||
class LaunchTask: public Task
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
class MULTIMC_LOGIC_EXPORT LaunchTask: public Task
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
@@ -103,8 +105,8 @@ signals:
|
|||||||
void requestLogging();
|
void requestLogging();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::Launcher);
|
void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
|
||||||
void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::Launcher);
|
void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
|
||||||
void onReadyForLaunch();
|
void onReadyForLaunch();
|
||||||
void onStepFinished();
|
void onStepFinished();
|
||||||
void onProgressReportingRequested();
|
void onProgressReportingRequested();
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user