mirror of
https://github.com/UltimMC/Launcher.git
synced 2025-12-13 12:12:14 +00:00
Compare commits
5 Commits
0.6.12
...
feature/ar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75edfc8d08 | ||
|
|
0272d6d7f7 | ||
|
|
406203e76b | ||
|
|
2bcd255909 | ||
|
|
d5d710b89e |
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:
|
||||
---------------------------
|
||||
52
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
52
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,52 +0,0 @@
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
labels: [bug, needs-triage]
|
||||
issue_body: false
|
||||
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/MultiMC5/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/MultiMC5/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.
|
||||
41
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
41
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Suggestion
|
||||
description: Make a suggestion
|
||||
labels: [idea, needs-triage]
|
||||
issue_body: true
|
||||
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: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### You may use the editor below to elaborate further.
|
||||
# The issue_body: true up there makes the standard WYSIWYG editor for issues show up down here.
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
Thumbs.db
|
||||
*.kdev4
|
||||
.kdev4
|
||||
.user
|
||||
.directory
|
||||
resources/CMakeFiles
|
||||
@@ -9,7 +9,8 @@ resources/MultiMCLauncher.jar
|
||||
html/
|
||||
|
||||
# Project Files
|
||||
*.pro.user
|
||||
MultiMC5.kdev4
|
||||
MultiMC.pro.user
|
||||
CMakeLists.txt.user
|
||||
CMakeLists.txt.user.*
|
||||
/.project
|
||||
|
||||
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"
|
||||
72
BUILD.md
72
BUILD.md
@@ -7,7 +7,7 @@ Build Instructions
|
||||
* [Getting the source](#source)
|
||||
* [Linux](#linux)
|
||||
* [Windows](#windows)
|
||||
* [macOS](#macos)
|
||||
* [OS X](#os-x)
|
||||
|
||||
# Note
|
||||
|
||||
@@ -50,7 +50,7 @@ mkdir ~/MultiMC && cd ~/MultiMC
|
||||
mkdir build
|
||||
mkdir install
|
||||
# clone the complete source
|
||||
git clone --recursive https://github.com/MultiMC/MultiMC5.git src
|
||||
git clone --recursive git@github.com:MultiMC/MultiMC5.git src
|
||||
# configure the project
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
|
||||
@@ -92,19 +92,14 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt
|
||||
|
||||
## Dependencies
|
||||
* [Qt 5.6+ Development tools](http://qt-project.org/downloads) -- Qt Online Installer for Windows
|
||||
- http://download.qt.io/new_archive/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe
|
||||
- Download the MinGW version (MSVC version does not work).
|
||||
* [OpenSSL](https://github.com/IndySockets/OpenSSL-Binaries/tree/master/Archive/) -- Win32 OpenSSL, version 1.0.2g (from 2016)
|
||||
- https://github.com/IndySockets/OpenSSL-Binaries/raw/master/Archive/openssl-1.0.2g-i386-win32.zip
|
||||
- the usual OpenSSL for Windows (http://slproweb.com/products/Win32OpenSSL.html) only provides the newest version of OpenSSL, and we need the 1.0.2g version
|
||||
- **Download the 32-bit version, not 64-bit.**
|
||||
* [OpenSSL](http://slproweb.com/products/Win32OpenSSL.html) -- Newest Win32 OpenSSL Light
|
||||
- Microsoft Visual C++ 2008 Redist is required for this, there's a link on the OpenSSL download page above next to the main download.
|
||||
- We use a custom build of OpenSSL that doesn't have this dependency. For normal development, the custom build is not necessary though.
|
||||
* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine
|
||||
* [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)
|
||||
|
||||
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
|
||||
|
||||
@@ -120,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.
|
||||
|
||||
### Installing OpenSSL
|
||||
1. Download .zip file from the link above.
|
||||
2. Unzip and add the directory to PATH, so CMake can find it.
|
||||
1. Run the OpenSSL installer,
|
||||
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
|
||||
1. Run the CMake installer,
|
||||
@@ -144,24 +140,6 @@ Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
|
||||
- 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.
|
||||
|
||||
The following .dlls are needed for the app to run (copy them to build directory if you want to be able to move the build to another pc):
|
||||
```
|
||||
platforms/qwindows.dll
|
||||
libeay32.dll
|
||||
libgcc_s_dw2-1.dll
|
||||
libssp-0.dll
|
||||
libstdc++-6.dll
|
||||
libwinpthread-1.dll
|
||||
Qt5Core.dll
|
||||
Qt5Gui.dll
|
||||
Qt5Network.dll
|
||||
Qt5Svg.dll
|
||||
Qt5Widgets.dll
|
||||
Qt5Xml.dll
|
||||
ssleay32.dll
|
||||
zlib1.dll
|
||||
```
|
||||
|
||||
**These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!**
|
||||
### Compile from command line on Windows
|
||||
1. If you installed Qt with the web installer, there should be a shortcut called `Qt 5.4 for Desktop (MinGW 4.9 32-bit)` in the Start menu on Windows 7 and 10. Best way to find it is to search for it. Do note you cannot just use cmd.exe, you have to use the shortcut, otherwise the proper MinGW software will not be on the PATH.
|
||||
@@ -172,32 +150,36 @@ zlib1.dll
|
||||
5. Run the command `mingw32-make install`, and it should install MultiMC, to whatever the `-DCMAKE_INSTALL_PREFIX` was.
|
||||
6. In most cases, whenever compiling, the OpenSSL dll's aren't put into the directory to where MultiMC installs, meaning you cannot log in. The best way to fix this is just to do `copy C:\OpenSSL-Win32\*.dll C:\Where\you\installed\MultiMC\to`. This should copy the required OpenSSL dll's to log in.
|
||||
|
||||
# macOS
|
||||
# OS X
|
||||
|
||||
### Install prerequisites:
|
||||
- Install XCode and set it up to the point where you can build things from a terminal
|
||||
- Install the official build of CMake (https://cmake.org/download/)
|
||||
- Install JDK 8 (https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html)
|
||||
- Get Qt 5.6 and install it (https://download.qt.io/new_archive/qt/5.6/5.6.3/)
|
||||
* install homebrew
|
||||
* then:
|
||||
|
||||
```
|
||||
brew install qt5
|
||||
brew tap homebrew/versions
|
||||
brew install gcc48
|
||||
brew install cmake
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/MultiMC/MultiMC5.git
|
||||
git clone https://github.com/MultiMC/MultiMC5.git
|
||||
git submodule init
|
||||
git submodule update
|
||||
cd MultiMC5
|
||||
mkdir build
|
||||
cd build
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER=/usr/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH="../dist/" \
|
||||
-DCMAKE_PREFIX_PATH="/path/to/Qt5.6/" \
|
||||
-DQt5_DIR="/path/to/Qt5.6/" \
|
||||
-DMultiMC_LAYOUT=mac-bundle \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 \
|
||||
..
|
||||
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5
|
||||
export CC=/usr/local/bin/gcc-4.8
|
||||
export CXX=/usr/local/bin/g++-4.8
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/Users/YOU/some/path/that/makes/sense/
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
**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))!**
|
||||
|
||||
@@ -2,15 +2,7 @@ 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(FATAL_ERROR "You are building MultiMC 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 MultiMC is not supported in Linux-on-Windows distributions.")
|
||||
endif()
|
||||
message(AUTHOR_WARNING "You are building MultiMC in-source. This is NOT recommended!")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
@@ -21,7 +13,6 @@ endif()
|
||||
project(MultiMC)
|
||||
enable_testing()
|
||||
|
||||
|
||||
##################################### Set CMake options #####################################
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
@@ -55,7 +46,7 @@ set(MultiMC_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetc
|
||||
######## Set version numbers ########
|
||||
set(MultiMC_VERSION_MAJOR 0)
|
||||
set(MultiMC_VERSION_MINOR 6)
|
||||
set(MultiMC_VERSION_HOTFIX 12)
|
||||
set(MultiMC_VERSION_HOTFIX 7)
|
||||
|
||||
# Build number
|
||||
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
|
||||
@@ -69,9 +60,6 @@ set(MultiMC_CHANLIST_URL "" CACHE STRING "URL for the channel list.")
|
||||
# Notification URL
|
||||
set(MultiMC_NOTIFICATION_URL "" CACHE STRING "URL for checking for notifications.")
|
||||
|
||||
# The metadata server
|
||||
set(MultiMC_META_URL "https://meta.multimc.org/v1/" CACHE STRING "URL to fetch MultiMC's meta files from.")
|
||||
|
||||
# paste.ee API key
|
||||
set(MultiMC_PASTE_EE_API_KEY "utLvciUouSURFzfjPxLBf5W4ISsUX4pwBDF7N1AfZ" CACHE STRING "API key you can get from paste.ee when you register an account")
|
||||
|
||||
@@ -89,7 +77,6 @@ set(MultiMC_RELEASE_VERSION_NAME "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MIN
|
||||
|
||||
#### Custom target to just print the version.
|
||||
add_custom_target(version echo "Version: ${MultiMC_RELEASE_VERSION_NAME}")
|
||||
add_custom_target(tcversion echo "\\#\\#teamcity[setParameter name=\\'env.MULTIMC_VERSION\\' value=\\'${MultiMC_RELEASE_VERSION_NAME}\\']")
|
||||
|
||||
################################ 3rd Party Libs ################################
|
||||
|
||||
@@ -154,7 +141,7 @@ if(MultiMC_LAYOUT_REAL STREQUAL "mac-bundle")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${MultiMC_VERSION_MAJOR}.${MultiMC_VERSION_MINOR}.${MultiMC_VERSION_HOTFIX}.${MultiMC_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 MultiMC.icns)
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2021 MultiMC Contributors")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2019 MultiMC Contributors")
|
||||
|
||||
# directories to look for dependencies
|
||||
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
@@ -260,15 +247,14 @@ add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||
add_subdirectory(libraries/xz-embedded) # xz compression
|
||||
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/iconfix) # fork of Qt's QIcon loader
|
||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||
add_subdirectory(libraries/classparser) # google analytics library
|
||||
add_subdirectory(libraries/optional-bare)
|
||||
|
||||
############################### Built Artifacts ###############################
|
||||
|
||||
add_subdirectory(buildconfig)
|
||||
add_subdirectory(api/logic)
|
||||
add_subdirectory(api/gui)
|
||||
|
||||
|
||||
59
COPYING.md
59
COPYING.md
@@ -1,6 +1,6 @@
|
||||
# MultiMC
|
||||
|
||||
Copyright 2012-2021 MultiMC Contributors
|
||||
Copyright 2012-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
|
||||
@@ -128,6 +128,35 @@
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
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
|
||||
|
||||
Copyright (C) 2005-2011 Sergey A. Tachenov
|
||||
@@ -223,31 +252,3 @@
|
||||
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.
|
||||
|
||||
# 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.
|
||||
|
||||
50
README.md
50
README.md
@@ -13,22 +13,21 @@ The project uses C++ and Qt5 as the language and base framework. This might seem
|
||||
|
||||
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.
|
||||
|
||||
If you want to contribute, either talk to us on [Discord](https://discord.gg/multimc), [IRC](http://webchat.esper.net/?nick=&channels=MultiMC)(esper.net/#MultiMC) or pick up some item from the github issues [workflowy](https://github.com/MultiMC/MultiMC5/issues) - there is always plenty of ideas around.
|
||||
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
|
||||
If you want to build MultiMC yourself, check [BUILD.md](BUILD.md) for build instructions.
|
||||
|
||||
### Code formatting
|
||||
Just follow the existing 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.
|
||||
|
||||
In general:
|
||||
* Indent with 4 space unless it's in a submodule
|
||||
* Keep lists (of arguments, parameters, initializators...) as lists, not paragraphs.
|
||||
* Prefer readability over dogma.
|
||||
According to travis.ci, the builds are currently [](https://travis-ci.org/MultiMC/MultiMC5)
|
||||
|
||||
### Code 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.
|
||||
|
||||
|
||||
## Translations
|
||||
Translations can be done [on crowdin](https://translate.multimc.org).
|
||||
Translations can be done either directly in the [translations repository](https://github.com/MultiMC/MultiMC5-translate). For more details, see: [Translating-MultiMC](https://github.com/MultiMC/MultiMC5/wiki/Translating-MultiMC).
|
||||
|
||||
## 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.
|
||||
@@ -39,41 +38,8 @@ Apache covers reasonable use for the name - a mention of the project's origins i
|
||||
|
||||
|
||||
## 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).
|
||||
|
||||
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=MultiMC_Launcher_Linux32_Build&guest=1">
|
||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux32_Build)/statusIcon"/>
|
||||
</a>
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux32_Deploy&guest=1">
|
||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux32_Deploy)/statusIcon"/>
|
||||
</a>
|
||||
|
||||
### Linux (AMD64)
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux64_Build&guest=1">
|
||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux64_Build)/statusIcon"/>
|
||||
</a>
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux64_Deploy&guest=1">
|
||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux64_Deploy)/statusIcon"/>
|
||||
</a>
|
||||
|
||||
### macOS (AMD64)
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_MacOS_Build&guest=1">
|
||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_MacOS_Build)/statusIcon"/>
|
||||
</a>
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_MacOS_Deploy&guest=1">
|
||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_MacOS_Deploy)/statusIcon"/>
|
||||
</a>
|
||||
|
||||
### Windows (Intel32)
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Windows_Build&guest=1">
|
||||
Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Windows_Build)/statusIcon"/>
|
||||
</a>
|
||||
<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Windows_Deploy&guest=1">
|
||||
Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Windows_Deploy)/statusIcon"/>
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "Env.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
@@ -36,14 +35,10 @@ QPixmap getFaceFromCache(QString username, int height, int width)
|
||||
|
||||
if (fskin.exists())
|
||||
{
|
||||
QPixmap skinTexture(fskin.fileName());
|
||||
if(!skinTexture.isNull())
|
||||
QPixmap skin(fskin.fileName());
|
||||
if(!skin.isNull())
|
||||
{
|
||||
QPixmap skin = QPixmap(8, 8);
|
||||
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);
|
||||
return skin.copy(8, 8, 8, 8).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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -119,6 +119,8 @@ set(NET_SOURCES
|
||||
net/PasteUpload.cpp
|
||||
net/PasteUpload.h
|
||||
net/Sink.h
|
||||
net/URLConstants.cpp
|
||||
net/URLConstants.h
|
||||
net/Validator.h
|
||||
)
|
||||
|
||||
@@ -226,8 +228,8 @@ set(MINECRAFT_SOURCES
|
||||
|
||||
minecraft/launch/ClaimAccount.cpp
|
||||
minecraft/launch/ClaimAccount.h
|
||||
minecraft/launch/CreateGameFolders.cpp
|
||||
minecraft/launch/CreateGameFolders.h
|
||||
minecraft/launch/CreateServerResourcePacksFolder.cpp
|
||||
minecraft/launch/CreateServerResourcePacksFolder.h
|
||||
minecraft/launch/ModMinecraftJar.cpp
|
||||
minecraft/launch/ModMinecraftJar.h
|
||||
minecraft/launch/DirectJavaLaunch.cpp
|
||||
@@ -257,16 +259,14 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/LaunchProfile.h
|
||||
minecraft/Component.cpp
|
||||
minecraft/Component.h
|
||||
minecraft/PackProfile.cpp
|
||||
minecraft/PackProfile.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
|
||||
@@ -303,14 +303,13 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/AssetsUtils.h
|
||||
minecraft/AssetsUtils.cpp
|
||||
|
||||
# Minecraft services
|
||||
minecraft/services/SkinUpload.cpp
|
||||
minecraft/services/SkinUpload.h
|
||||
minecraft/services/SkinDelete.cpp
|
||||
minecraft/services/SkinDelete.h
|
||||
# Forge and all things forge related
|
||||
minecraft/forge/ForgeXzDownload.h
|
||||
minecraft/forge/ForgeXzDownload.cpp
|
||||
|
||||
mojang/PackageManifest.h
|
||||
mojang/PackageManifest.cpp
|
||||
# Skin upload utilities
|
||||
minecraft/SkinUpload.cpp
|
||||
minecraft/SkinUpload.h
|
||||
)
|
||||
|
||||
add_unit_test(GradleSpecifier
|
||||
@@ -318,28 +317,6 @@ add_unit_test(GradleSpecifier
|
||||
LIBS MultiMC_logic
|
||||
)
|
||||
|
||||
add_executable(PackageManifest
|
||||
mojang/PackageManifest_test.cpp
|
||||
)
|
||||
target_link_libraries(PackageManifest
|
||||
MultiMC_logic
|
||||
Qt5::Test
|
||||
)
|
||||
target_include_directories(PackageManifest
|
||||
PRIVATE ../../cmake/UnitTest/
|
||||
)
|
||||
add_test(
|
||||
NAME PackageManifest
|
||||
COMMAND PackageManifest
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
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
|
||||
@@ -454,14 +431,15 @@ set(META_SOURCES
|
||||
)
|
||||
|
||||
set(FTB_SOURCES
|
||||
modplatform/legacy_ftb/PackFetchTask.h
|
||||
modplatform/legacy_ftb/PackFetchTask.cpp
|
||||
modplatform/legacy_ftb/PackInstallTask.h
|
||||
modplatform/legacy_ftb/PackInstallTask.cpp
|
||||
modplatform/legacy_ftb/PrivatePackManager.h
|
||||
modplatform/legacy_ftb/PrivatePackManager.cpp
|
||||
modplatform/ftb/FtbPackFetchTask.h
|
||||
modplatform/ftb/FtbPackFetchTask.cpp
|
||||
modplatform/ftb/FtbPackInstallTask.h
|
||||
modplatform/ftb/FtbPackInstallTask.cpp
|
||||
|
||||
modplatform/legacy_ftb/PackHelpers.h
|
||||
modplatform/ftb/FtbPrivatePackManager.h
|
||||
modplatform/ftb/FtbPrivatePackManager.cpp
|
||||
|
||||
modplatform/ftb/PackHelpers.h
|
||||
)
|
||||
|
||||
set(FLAME_SOURCES
|
||||
@@ -470,31 +448,8 @@ set(FLAME_SOURCES
|
||||
modplatform/flame/PackManifest.cpp
|
||||
modplatform/flame/FileResolvingTask.h
|
||||
modplatform/flame/FileResolvingTask.cpp
|
||||
)
|
||||
|
||||
set(MODPACKSCH_SOURCES
|
||||
modplatform/modpacksch/FTBPackInstallTask.h
|
||||
modplatform/modpacksch/FTBPackInstallTask.cpp
|
||||
modplatform/modpacksch/FTBPackManifest.h
|
||||
modplatform/modpacksch/FTBPackManifest.cpp
|
||||
)
|
||||
|
||||
set(TECHNIC_SOURCES
|
||||
modplatform/technic/SingleZipPackInstallTask.h
|
||||
modplatform/technic/SingleZipPackInstallTask.cpp
|
||||
modplatform/technic/SolderPackInstallTask.h
|
||||
modplatform/technic/SolderPackInstallTask.cpp
|
||||
modplatform/technic/TechnicPackProcessor.h
|
||||
modplatform/technic/TechnicPackProcessor.cpp
|
||||
)
|
||||
|
||||
set(ATLAUNCHER_SOURCES
|
||||
modplatform/atlauncher/ATLPackIndex.cpp
|
||||
modplatform/atlauncher/ATLPackIndex.h
|
||||
modplatform/atlauncher/ATLPackInstallTask.cpp
|
||||
modplatform/atlauncher/ATLPackInstallTask.h
|
||||
modplatform/atlauncher/ATLPackManifest.cpp
|
||||
modplatform/atlauncher/ATLPackManifest.h
|
||||
modplatform/flame/UrlResolvingTask.h
|
||||
modplatform/flame/UrlResolvingTask.cpp
|
||||
)
|
||||
|
||||
add_unit_test(Index
|
||||
@@ -527,9 +482,6 @@ set(LOGIC_SOURCES
|
||||
${ICONS_SOURCES}
|
||||
${FTB_SOURCES}
|
||||
${FLAME_SOURCES}
|
||||
${MODPACKSCH_SOURCES}
|
||||
${TECHNIC_SOURCES}
|
||||
${ATLAUNCHER_SOURCES}
|
||||
)
|
||||
|
||||
add_library(MultiMC_logic SHARED ${LOGIC_SOURCES})
|
||||
@@ -538,7 +490,7 @@ set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISI
|
||||
generate_export_header(MultiMC_logic)
|
||||
|
||||
# Link
|
||||
target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES} optional-bare BuildConfig)
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
/* Copyright 2013-2019 MultiMC Contributors
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
@@ -69,8 +69,8 @@ namespace ArgumentStyle
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
Space, /**< --option value */
|
||||
Equals, /**< --option=value */
|
||||
Space, /**< --option=value */
|
||||
Equals, /**< --option value */
|
||||
SpaceAndEquals, /**< --option[= ]value */
|
||||
#ifdef Q_OS_WIN32
|
||||
Default = Equals
|
||||
|
||||
@@ -96,11 +96,7 @@ void Env::initHttpMetaCache()
|
||||
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("ATLauncherPacks", QDir("cache/ATLauncherPacks").absolutePath());
|
||||
m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
|
||||
m_metacache->addBase("ModpacksCHPacks", QDir("cache/ModpacksCHPacks").absolutePath());
|
||||
m_metacache->addBase("TechnicPacks", QDir("cache/TechnicPacks").absolutePath());
|
||||
m_metacache->addBase("TwitchPacks", QDir("cache/TwitchPacks").absolutePath());
|
||||
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
|
||||
m_metacache->addBase("root", QDir::currentPath());
|
||||
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
||||
@@ -163,9 +159,11 @@ void Env::updateProxySettings(QString proxyTypeStr, QString addr, int port, QStr
|
||||
proxyDesc = "DERP proxy: ";
|
||||
break;
|
||||
}
|
||||
proxyDesc += QString("%1:%2")
|
||||
proxyDesc += QString("%3@%1:%2 pass %4")
|
||||
.arg(proxy.hostName())
|
||||
.arg(proxy.port());
|
||||
.arg(proxy.port())
|
||||
.arg(proxy.user())
|
||||
.arg(proxy.password());
|
||||
qDebug() << proxyDesc;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ QString NormalizePath(QString path)
|
||||
}
|
||||
}
|
||||
|
||||
QString badFilenameChars = "\"\\/?<>:;*|!+\r\n";
|
||||
QString badFilenameChars = "\"\\/?<>:*|!+\r\n";
|
||||
|
||||
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
|
||||
{
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
#include "pathmatcher/RegexpMatcher.h"
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
|
||||
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves)
|
||||
{
|
||||
m_origInstance = origInstance;
|
||||
m_keepPlaytime = keepPlaytime;
|
||||
|
||||
if(!copySaves)
|
||||
{
|
||||
@@ -47,9 +46,6 @@ void InstanceCopyTask::copyFinished()
|
||||
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
|
||||
inst->setName(m_instName);
|
||||
inst->setIconKey(m_instIcon);
|
||||
if(!m_keepPlaytime) {
|
||||
inst->resetTimePlayed();
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class MULTIMC_LOGIC_EXPORT InstanceCopyTask : public InstanceTask
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
|
||||
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves);
|
||||
|
||||
protected:
|
||||
//! Entry point for tasks.
|
||||
@@ -28,5 +28,4 @@ private: /* data */
|
||||
QFuture<bool> m_copyFuture;
|
||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||
std::unique_ptr<IPathMatcher> m_matcher;
|
||||
bool m_keepPlaytime;
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
//FIXME: remove this
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/ComponentList.h"
|
||||
|
||||
InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
|
||||
{
|
||||
@@ -20,7 +20,7 @@ void InstanceCreationTask::executeTask()
|
||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
||||
instanceSettings->set("InstanceType", "OneSix");
|
||||
MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
|
||||
auto components = inst.getPackProfile();
|
||||
auto components = inst.getComponentList();
|
||||
components->buildingFromScratch();
|
||||
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
|
||||
inst.setName(m_instName);
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/* 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 "BaseInstance.h"
|
||||
#include "FileSystem.h"
|
||||
@@ -26,12 +11,10 @@
|
||||
|
||||
// FIXME: this does not belong here, it's Minecraft/Flame specific
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/ComponentList.h"
|
||||
#include "modplatform/flame/FileResolvingTask.h"
|
||||
#include "modplatform/flame/PackManifest.h"
|
||||
#include "Json.h"
|
||||
#include <quazipdir.h>
|
||||
#include "modplatform/technic/TechnicPackProcessor.h"
|
||||
|
||||
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
||||
{
|
||||
@@ -40,6 +23,8 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
|
||||
|
||||
void InstanceImportTask::executeTask()
|
||||
{
|
||||
InstancePtr newInstance;
|
||||
|
||||
if (m_sourceUrl.isLocalFile())
|
||||
{
|
||||
m_archivePath = m_sourceUrl.toLocalFile();
|
||||
@@ -97,7 +82,6 @@ void InstanceImportTask::processZipPack()
|
||||
|
||||
QStringList blacklist = {"instance.cfg", "manifest.json"};
|
||||
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 root;
|
||||
if(!mmcFound.isNull())
|
||||
@@ -107,14 +91,6 @@ void InstanceImportTask::processZipPack()
|
||||
root = mmcFound;
|
||||
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())
|
||||
{
|
||||
// process as Flame pack
|
||||
@@ -122,6 +98,7 @@ void InstanceImportTask::processZipPack()
|
||||
root = flameFound;
|
||||
m_modpackType = ModpackType::Flame;
|
||||
}
|
||||
|
||||
if(m_modpackType == ModpackType::Unknown)
|
||||
{
|
||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||
@@ -138,7 +115,7 @@ void InstanceImportTask::processZipPack()
|
||||
void InstanceImportTask::extractFinished()
|
||||
{
|
||||
m_packZip.reset();
|
||||
if (!m_extractFuture.result())
|
||||
if (m_extractFuture.result().isEmpty())
|
||||
{
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
@@ -184,9 +161,6 @@ void InstanceImportTask::extractFinished()
|
||||
case ModpackType::MultiMC:
|
||||
processMultiMC();
|
||||
return;
|
||||
case ModpackType::Technic:
|
||||
processTechnic();
|
||||
return;
|
||||
case ModpackType::Unknown:
|
||||
emitFailed(tr("Archive does not contain a recognized modpack type."));
|
||||
return;
|
||||
@@ -262,7 +236,7 @@ void InstanceImportTask::processFlame()
|
||||
mcVersion.remove(QRegExp("[.]+$"));
|
||||
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
|
||||
}
|
||||
auto components = instance.getPackProfile();
|
||||
auto components = instance.getComponentList();
|
||||
components->buildingFromScratch();
|
||||
components->setComponentVersion("net.minecraft", mcVersion, true);
|
||||
if(!forgeVersion.isEmpty())
|
||||
@@ -314,7 +288,7 @@ void InstanceImportTask::processFlame()
|
||||
qDebug() << info.fileName();
|
||||
jarMods.push_back(info.absoluteFilePath());
|
||||
}
|
||||
auto profile = instance.getPackProfile();
|
||||
auto profile = instance.getComponentList();
|
||||
profile->installJarMods(jarMods);
|
||||
// nuke the original files
|
||||
FS::deletePath(jarmodsPath);
|
||||
@@ -397,14 +371,6 @@ void InstanceImportTask::processFlame()
|
||||
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()
|
||||
{
|
||||
// FIXME: copy from FolderInstanceProvider!!! FIX IT!!!
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
/* 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
|
||||
|
||||
#include "InstanceTask.h"
|
||||
@@ -24,8 +9,6 @@
|
||||
#include "settings/SettingsObject.h"
|
||||
#include "QObjectPtr.h"
|
||||
|
||||
#include <nonstd/optional>
|
||||
|
||||
class QuaZip;
|
||||
namespace Flame
|
||||
{
|
||||
@@ -46,7 +29,6 @@ private:
|
||||
void processZipPack();
|
||||
void processMultiMC();
|
||||
void processFlame();
|
||||
void processTechnic();
|
||||
|
||||
private slots:
|
||||
void downloadSucceeded();
|
||||
@@ -62,12 +44,11 @@ private: /* data */
|
||||
QString m_archivePath;
|
||||
bool m_downloadRequired = false;
|
||||
std::unique_ptr<QuaZip> m_packZip;
|
||||
QFuture<nonstd::optional<QStringList>> m_extractFuture;
|
||||
QFutureWatcher<nonstd::optional<QStringList>> m_extractFutureWatcher;
|
||||
QFuture<QStringList> m_extractFuture;
|
||||
QFutureWatcher<QStringList> m_extractFutureWatcher;
|
||||
enum class ModpackType{
|
||||
Unknown,
|
||||
MultiMC,
|
||||
Flame,
|
||||
Technic
|
||||
Flame
|
||||
} 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -160,8 +160,8 @@ GroupId InstanceList::getInstanceGroup(const InstanceId& id) const
|
||||
{
|
||||
return GroupId();
|
||||
}
|
||||
auto iter = m_instanceGroupIndex.find(inst->id());
|
||||
if(iter != m_instanceGroupIndex.end())
|
||||
auto iter = m_groupMap.find(inst->id());
|
||||
if(iter != m_groupMap.end())
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
@@ -178,8 +178,8 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
auto iter = m_instanceGroupIndex.find(inst->id());
|
||||
if(iter != m_instanceGroupIndex.end())
|
||||
auto iter = m_groupMap.find(inst->id());
|
||||
if(iter != m_groupMap.end())
|
||||
{
|
||||
if(*iter != name)
|
||||
{
|
||||
@@ -190,12 +190,12 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
else
|
||||
{
|
||||
changed = true;
|
||||
m_instanceGroupIndex[id] = name;
|
||||
m_groupMap[id] = name;
|
||||
}
|
||||
|
||||
if(changed)
|
||||
{
|
||||
m_groupNameCache.insert(name);
|
||||
m_groups.insert(name);
|
||||
auto idx = getInstIndex(inst.get());
|
||||
emit dataChanged(index(idx), index(idx), {GroupRole});
|
||||
saveGroupList();
|
||||
@@ -204,7 +204,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
|
||||
|
||||
QStringList InstanceList::getGroups()
|
||||
{
|
||||
return m_groupNameCache.toList();
|
||||
return m_groups.toList();
|
||||
}
|
||||
|
||||
void InstanceList::deleteGroup(const QString& name)
|
||||
@@ -217,7 +217,7 @@ void InstanceList::deleteGroup(const QString& name)
|
||||
auto instGroupName = getInstanceGroup(instID);
|
||||
if(instGroupName == name)
|
||||
{
|
||||
m_instanceGroupIndex.remove(instID);
|
||||
m_groupMap.remove(instID);
|
||||
qDebug() << "Remove" << instID << "from group" << name;
|
||||
removed = true;
|
||||
auto idx = getInstIndex(instance.get());
|
||||
@@ -233,11 +233,6 @@ void InstanceList::deleteGroup(const QString& name)
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceList::isGroupCollapsed(const QString& group)
|
||||
{
|
||||
return m_collapsedGroups.contains(group);
|
||||
}
|
||||
|
||||
void InstanceList::deleteInstance(const InstanceId& id)
|
||||
{
|
||||
auto inst = getInstanceById(id);
|
||||
@@ -247,7 +242,7 @@ void InstanceList::deleteInstance(const InstanceId& id)
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_instanceGroupIndex.remove(id))
|
||||
if(m_groupMap.remove(id))
|
||||
{
|
||||
saveGroupList();
|
||||
}
|
||||
@@ -520,7 +515,7 @@ void InstanceList::saveGroupList()
|
||||
WatchLock foo(m_watcher, m_instDir);
|
||||
QString groupFileName = m_instDir + "/instgroups.json";
|
||||
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 group = iter.value();
|
||||
@@ -553,7 +548,7 @@ void InstanceList::saveGroupList()
|
||||
auto name = iter.key();
|
||||
QJsonObject groupObj;
|
||||
QJsonArray instanceArr;
|
||||
groupObj.insert("hidden", QJsonValue(m_collapsedGroups.contains(name)));
|
||||
groupObj.insert("hidden", QJsonValue(QString("false")));
|
||||
for (auto item : list)
|
||||
{
|
||||
instanceArr.append(QJsonValue(item));
|
||||
@@ -577,6 +572,7 @@ void InstanceList::saveGroupList()
|
||||
void InstanceList::loadGroupList()
|
||||
{
|
||||
qDebug() << "Will load group list now.";
|
||||
QSet<QString> groupSet;
|
||||
|
||||
QString groupFileName = m_instDir + "/instgroups.json";
|
||||
|
||||
@@ -627,8 +623,7 @@ void InstanceList::loadGroupList()
|
||||
return;
|
||||
}
|
||||
|
||||
QSet<QString> groupSet;
|
||||
m_instanceGroupIndex.clear();
|
||||
m_groupMap.clear();
|
||||
|
||||
// Iterate through all the groups.
|
||||
QJsonObject groupMapping = rootObj.value("groups").toObject();
|
||||
@@ -639,35 +634,37 @@ void InstanceList::loadGroupList()
|
||||
// If not an object, complain and skip to the next one.
|
||||
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;
|
||||
}
|
||||
|
||||
QJsonObject groupObj = iter.value().toObject();
|
||||
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;
|
||||
}
|
||||
|
||||
// keep a list/set of groups for choosing
|
||||
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.
|
||||
QJsonArray instancesArray = groupObj.value("instances").toArray();
|
||||
|
||||
for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end(); iter2++)
|
||||
{
|
||||
m_instanceGroupIndex[(*iter2).toString()] = groupName;
|
||||
m_groupMap[(*iter2).toString()] = groupName;
|
||||
}
|
||||
}
|
||||
m_groupsLoaded = true;
|
||||
m_groupNameCache.unite(groupSet);
|
||||
m_groups.unite(groupSet);
|
||||
qDebug() << "Group list loaded.";
|
||||
}
|
||||
|
||||
@@ -692,17 +689,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
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -833,9 +819,9 @@ bool InstanceList::commitStagedInstance(const QString& path, const QString& inst
|
||||
qWarning() << "Failed to move" << path << "to" << destination;
|
||||
return false;
|
||||
}
|
||||
m_instanceGroupIndex[instID] = groupName;
|
||||
m_groupMap[instID] = groupName;
|
||||
instanceSet.insert(instID);
|
||||
m_groupNameCache.insert(groupName);
|
||||
m_groups.insert(groupName);
|
||||
emit instancesChanged();
|
||||
emit instanceSelectRequest(instID);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -99,8 +99,6 @@ public:
|
||||
InstancePtr getInstanceById(QString id) const;
|
||||
QModelIndex getInstanceIndexById(const QString &id) const;
|
||||
QStringList getGroups();
|
||||
bool isGroupCollapsed(const QString &groupName);
|
||||
|
||||
GroupId getInstanceGroup(const InstanceId & id) const;
|
||||
void setInstanceGroup(const InstanceId & id, const GroupId& name);
|
||||
|
||||
@@ -136,7 +134,6 @@ signals:
|
||||
|
||||
public slots:
|
||||
void on_InstFolderChanged(const Setting &setting, QVariant value);
|
||||
void on_GroupStateChanged(const QString &group, bool collapsed);
|
||||
|
||||
private slots:
|
||||
void propertiesChanged(BaseInstance *inst);
|
||||
@@ -157,14 +154,12 @@ private:
|
||||
int m_watchLevel = 0;
|
||||
bool m_dirty = false;
|
||||
QList<InstancePtr> m_instances;
|
||||
QSet<QString> m_groupNameCache;
|
||||
QSet<QString> m_groups;
|
||||
|
||||
SettingsObjectPtr m_globalSettings;
|
||||
QString m_instDir;
|
||||
QFileSystemWatcher * m_watcher;
|
||||
// FIXME: this is so inefficient that looking at it is almost painful.
|
||||
QSet<QString> m_collapsedGroups;
|
||||
QMap<InstanceId, GroupId> m_instanceGroupIndex;
|
||||
QMap<InstanceId, GroupId> m_groupMap;
|
||||
QSet<InstanceId> instanceSet;
|
||||
bool m_groupsLoaded = false;
|
||||
bool m_instancesProbed = false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 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");
|
||||
* 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
|
||||
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);
|
||||
QStringList extracted;
|
||||
|
||||
qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
|
||||
auto numEntries = zip->getEntriesCount();
|
||||
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())
|
||||
if (!zip->goToFirstFile())
|
||||
{
|
||||
qWarning() << "Failed to seek to first file in zip";
|
||||
return nonstd::nullopt;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
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;
|
||||
JlCompress::removeFile(extracted);
|
||||
return nonstd::nullopt;
|
||||
return QStringList();
|
||||
}
|
||||
extracted.append(absFilePath);
|
||||
qDebug() << "Extracted file" << name;
|
||||
@@ -255,58 +244,12 @@ nonstd::optional<QStringList> MMCZip::extractSubDir(QuaZip *zip, const QString &
|
||||
}
|
||||
|
||||
// ours
|
||||
bool MMCZip::extractRelFile(QuaZip *zip, const QString &file, const QString &target)
|
||||
{
|
||||
return JlCompress::extractFile(zip, file, target);
|
||||
}
|
||||
|
||||
// ours
|
||||
nonstd::optional<QStringList> MMCZip::extractDir(QString fileCompressed, QString dir)
|
||||
QStringList MMCZip::extractDir(QString fileCompressed, 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 {};
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
#include <JlCompress.h>
|
||||
#include <nonstd/optional>
|
||||
|
||||
namespace MMCZip
|
||||
{
|
||||
@@ -58,9 +57,7 @@ namespace MMCZip
|
||||
/**
|
||||
* Extract a subdirectory from an archive
|
||||
*/
|
||||
nonstd::optional<QStringList> MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
|
||||
|
||||
bool MULTIMC_LOGIC_EXPORT extractRelFile(QuaZip *zip, const QString & file, const QString &target);
|
||||
QStringList MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
|
||||
|
||||
/**
|
||||
* Extract a whole archive.
|
||||
@@ -69,26 +66,6 @@ namespace MMCZip
|
||||
* \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.
|
||||
*/
|
||||
nonstd::optional<QStringList> MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
|
||||
|
||||
/**
|
||||
* Extract a subdirectory from an archive
|
||||
*
|
||||
* \param fileCompressed The name of the archive.
|
||||
* \param subdir The directory within the archive to extract
|
||||
* \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.
|
||||
*/
|
||||
nonstd::optional<QStringList> MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString subdir, QString dir);
|
||||
|
||||
/**
|
||||
* Extract a single file from an archive into a directory
|
||||
*
|
||||
* \param fileCompressed The name of the archive.
|
||||
* \param file The file within the archive to extract
|
||||
* \param dir The directory to extract to, the current directory if left empty.
|
||||
* \return true for success or false for failure
|
||||
*/
|
||||
bool MULTIMC_LOGIC_EXPORT extractFile(QString fileCompressed, QString file, QString dir);
|
||||
QStringList MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
|
||||
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ void Version::parse()
|
||||
// FIXME: this is bad. versions can contain a lot more separators...
|
||||
QStringList parts = m_string.split('.');
|
||||
|
||||
for (const auto &part : parts)
|
||||
for (const auto part : parts)
|
||||
{
|
||||
m_sections.append(Section(part));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
|
||||
@@ -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;
|
||||
emit checkFinished(result);
|
||||
@@ -124,7 +124,6 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
|
||||
auto os_arch = results["os.arch"];
|
||||
auto java_version = results["java.version"];
|
||||
auto java_vendor = results["java.vendor"];
|
||||
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.realPlatform = os_arch;
|
||||
result.javaVersion = java_version;
|
||||
result.javaVendor = java_vendor;
|
||||
qDebug() << "Java checker succeeded.";
|
||||
emit checkFinished(result);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ struct MULTIMC_LOGIC_EXPORT JavaCheckResult
|
||||
QString mojangPlatform;
|
||||
QString realPlatform;
|
||||
JavaVersion javaVersion;
|
||||
QString javaVendor;
|
||||
QString outLog;
|
||||
QString errorLog;
|
||||
bool is_64bit = false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,17 +33,17 @@ void CheckJava::executeTask()
|
||||
if (perInstance)
|
||||
{
|
||||
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),
|
||||
MessageLevel::Warning);
|
||||
}
|
||||
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),
|
||||
MessageLevel::Warning);
|
||||
}
|
||||
emitFailed(QString("Java path is not valid."));
|
||||
emitFailed(tr("Java path is not valid."));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -56,13 +56,12 @@ void CheckJava::executeTask()
|
||||
auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
|
||||
auto storedArchitecture = settings->get("JavaArchitecture").toString();
|
||||
auto storedVersion = settings->get("JavaVersion").toString();
|
||||
auto storedVendor = settings->get("JavaVendor").toString();
|
||||
m_javaUnixTime = javaUnixTime;
|
||||
// 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();
|
||||
emit logLine(QString("Checking Java version..."), MessageLevel::MultiMC);
|
||||
emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
|
||||
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
||||
m_JavaChecker->m_path = realJavaPath;
|
||||
m_JavaChecker->performCheck();
|
||||
@@ -72,8 +71,7 @@ void CheckJava::executeTask()
|
||||
{
|
||||
auto verString = instance->settings()->get("JavaVersion").toString();
|
||||
auto archString = instance->settings()->get("JavaArchitecture").toString();
|
||||
auto vendorString = instance->settings()->get("JavaVendor").toString();
|
||||
printJavaInfo(verString, archString, vendorString);
|
||||
printJavaInfo(verString, archString);
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
@@ -85,16 +83,16 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
case JavaCheckResult::Validity::Errored:
|
||||
{
|
||||
// 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 logLine("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
|
||||
printSystemInfo(false, false);
|
||||
emitFailed(QString("Could not start java!"));
|
||||
emitFailed(tr("Could not start java!"));
|
||||
return;
|
||||
}
|
||||
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 logLine("\nMinecraft might not start properly.", MessageLevel::MultiMC);
|
||||
printSystemInfo(false, false);
|
||||
@@ -104,10 +102,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
case JavaCheckResult::Validity::Valid:
|
||||
{
|
||||
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("JavaArchitecture", result.mojangPlatform);
|
||||
instance->settings()->set("JavaVendor", result.javaVendor);
|
||||
instance->settings()->set("JavaTimestamp", m_javaUnixTime);
|
||||
emitSucceeded();
|
||||
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::MultiMC);
|
||||
emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
|
||||
printSystemInfo(true, architecture == "64");
|
||||
}
|
||||
|
||||
@@ -127,13 +124,13 @@ void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
|
||||
auto system64 = Sys::isSystem64bit();
|
||||
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(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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ private slots:
|
||||
void checkJavaFinished(JavaCheckResult result);
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
* 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");
|
||||
* 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>
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
/* Copyright 2013-2019 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "Env.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include "BuildConfig.h"
|
||||
|
||||
class ParsingValidator : public Net::Validator
|
||||
{
|
||||
public: /* con/des */
|
||||
@@ -55,9 +53,7 @@ public: /* methods */
|
||||
auto fname = m_entity->localFilename();
|
||||
try
|
||||
{
|
||||
auto doc = Json::requireDocument(data, fname);
|
||||
auto obj = Json::requireObject(doc, fname);
|
||||
m_entity->parse(obj);
|
||||
m_entity->parse(Json::requireObject(Json::requireDocument(data, fname), fname));
|
||||
return true;
|
||||
}
|
||||
catch (const Exception &e)
|
||||
@@ -78,7 +74,7 @@ Meta::BaseEntity::~BaseEntity()
|
||||
|
||||
QUrl Meta::BaseEntity::url() const
|
||||
{
|
||||
return QUrl(BuildConfig.META_URL).resolved(localFilename());
|
||||
return QUrl("https://meta.multimc.org/v1/").resolved(localFilename());
|
||||
}
|
||||
|
||||
bool Meta::BaseEntity::loadLocalFile()
|
||||
@@ -91,9 +87,7 @@ bool Meta::BaseEntity::loadLocalFile()
|
||||
// TODO: check if the file has the expected checksum
|
||||
try
|
||||
{
|
||||
auto doc = Json::requireDocument(fname, fname);
|
||||
auto obj = Json::requireObject(doc, fname);
|
||||
parse(obj);
|
||||
parse(Json::requireObject(Json::requireDocument(fname, fname), fname));
|
||||
return true;
|
||||
}
|
||||
catch (const Exception &e)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <QDateTime>
|
||||
|
||||
#include "JsonFormat.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/ComponentList.h"
|
||||
|
||||
Meta::Version::Version(const QString &uid, const QString &version)
|
||||
: BaseVersion(), m_uid(uid), m_version(version)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2015-2021 MultiMC Contributors
|
||||
/* Copyright 2015-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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "FileSystem.h"
|
||||
#include "net/Download.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "net/URLConstants.h"
|
||||
|
||||
namespace {
|
||||
QSet<QString> collectPathsFromDir(QString dirPath)
|
||||
@@ -308,7 +308,7 @@ QString AssetObject::getLocalPath()
|
||||
|
||||
QUrl AssetObject::getUrl()
|
||||
{
|
||||
return BuildConfig.RESOURCE_BASE + getRelPath();
|
||||
return URLConstants::RESOURCE_BASE + getRelPath();
|
||||
}
|
||||
|
||||
QString AssetObject::getRelPath()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
#include "meta/Version.h"
|
||||
#include "VersionFile.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/ComponentList.h"
|
||||
#include <FileSystem.h>
|
||||
#include <QSaveFile>
|
||||
#include "OneSixVersionFormat.h"
|
||||
#include <assert.h>
|
||||
|
||||
Component::Component(PackProfile * parent, const QString& uid)
|
||||
Component::Component(ComponentList * parent, const QString& uid)
|
||||
{
|
||||
assert(parent);
|
||||
m_parent = parent;
|
||||
@@ -19,7 +19,7 @@ Component::Component(PackProfile * parent, const QString& uid)
|
||||
m_uid = uid;
|
||||
}
|
||||
|
||||
Component::Component(PackProfile * parent, std::shared_ptr<Meta::Version> version)
|
||||
Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> version)
|
||||
{
|
||||
assert(parent);
|
||||
m_parent = parent;
|
||||
@@ -31,7 +31,7 @@ Component::Component(PackProfile * parent, std::shared_ptr<Meta::Version> versio
|
||||
m_loaded = version->isLoaded();
|
||||
}
|
||||
|
||||
Component::Component(PackProfile * parent, const QString& uid, std::shared_ptr<VersionFile> file)
|
||||
Component::Component(ComponentList * parent, const QString& uid, std::shared_ptr<VersionFile> file)
|
||||
{
|
||||
assert(parent);
|
||||
m_parent = parent;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "QObjectPtr.h"
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
class PackProfile;
|
||||
class ComponentList;
|
||||
class LaunchProfile;
|
||||
namespace Meta
|
||||
{
|
||||
@@ -22,11 +22,11 @@ class MULTIMC_LOGIC_EXPORT Component : public QObject, public ProblemProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Component(PackProfile * parent, const QString &uid);
|
||||
Component(ComponentList * parent, const QString &uid);
|
||||
|
||||
// DEPRECATED: remove these constructors?
|
||||
Component(PackProfile * parent, std::shared_ptr<Meta::Version> version);
|
||||
Component(PackProfile * parent, const QString & uid, std::shared_ptr<VersionFile> file);
|
||||
Component(ComponentList * parent, std::shared_ptr<Meta::Version> version);
|
||||
Component(ComponentList * parent, const QString & uid, std::shared_ptr<VersionFile> file);
|
||||
|
||||
virtual ~Component(){};
|
||||
void applyTo(LaunchProfile *profile);
|
||||
@@ -73,7 +73,7 @@ signals:
|
||||
void dataChanged();
|
||||
|
||||
public: /* data */
|
||||
PackProfile * m_parent;
|
||||
ComponentList * m_parent;
|
||||
|
||||
// BEGIN: persistent component list properties
|
||||
/// ID of the component
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -32,23 +32,23 @@
|
||||
#include <QTimer>
|
||||
#include <Json.h>
|
||||
|
||||
#include "PackProfile.h"
|
||||
#include "PackProfile_p.h"
|
||||
#include "ComponentList.h"
|
||||
#include "ComponentList_p.h"
|
||||
#include "ComponentUpdateTask.h"
|
||||
|
||||
PackProfile::PackProfile(MinecraftInstance * instance)
|
||||
ComponentList::ComponentList(MinecraftInstance * instance)
|
||||
: QAbstractListModel()
|
||||
{
|
||||
d.reset(new PackProfileData);
|
||||
d.reset(new ComponentListData);
|
||||
d->m_instance = instance;
|
||||
d->m_saveTimer.setSingleShot(true);
|
||||
d->m_saveTimer.setInterval(5000);
|
||||
d->interactionDisabled = instance->isRunning();
|
||||
connect(d->m_instance, &BaseInstance::runningStatusChanged, this, &PackProfile::disableInteraction);
|
||||
connect(&d->m_saveTimer, &QTimer::timeout, this, &PackProfile::save_internal);
|
||||
connect(d->m_instance, &BaseInstance::runningStatusChanged, this, &ComponentList::disableInteraction);
|
||||
connect(&d->m_saveTimer, &QTimer::timeout, this, &ComponentList::save_internal);
|
||||
}
|
||||
|
||||
PackProfile::~PackProfile()
|
||||
ComponentList::~ComponentList()
|
||||
{
|
||||
saveNow();
|
||||
}
|
||||
@@ -97,7 +97,7 @@ static QJsonObject componentToJsonV1(ComponentPtr component)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static ComponentPtr componentFromJsonV1(PackProfile * parent, const QString & componentJsonPattern, const QJsonObject &obj)
|
||||
static ComponentPtr componentFromJsonV1(ComponentList * parent, const QString & componentJsonPattern, const QJsonObject &obj)
|
||||
{
|
||||
// critical
|
||||
auto uid = Json::requireString(obj.value("uid"));
|
||||
@@ -120,7 +120,7 @@ static ComponentPtr componentFromJsonV1(PackProfile * parent, const QString & co
|
||||
}
|
||||
|
||||
// Save the given component container data to a file
|
||||
static bool savePackProfile(const QString & filename, const ComponentContainer & container)
|
||||
static bool saveComponentList(const QString & filename, const ComponentContainer & container)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("formatVersion", currentComponentsFileVersion);
|
||||
@@ -153,7 +153,7 @@ static bool savePackProfile(const QString & filename, const ComponentContainer &
|
||||
}
|
||||
|
||||
// Read the given file into component containers
|
||||
static bool loadPackProfile(PackProfile * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container)
|
||||
static bool loadComponentList(ComponentList * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container)
|
||||
{
|
||||
QFile componentsFile(filename);
|
||||
if (!componentsFile.exists())
|
||||
@@ -210,7 +210,7 @@ static bool loadPackProfile(PackProfile * parent, const QString & filename, cons
|
||||
|
||||
// BEGIN: save/load logic
|
||||
|
||||
void PackProfile::saveNow()
|
||||
void ComponentList::saveNow()
|
||||
{
|
||||
if(saveIsScheduled())
|
||||
{
|
||||
@@ -219,18 +219,18 @@ void PackProfile::saveNow()
|
||||
}
|
||||
}
|
||||
|
||||
bool PackProfile::saveIsScheduled() const
|
||||
bool ComponentList::saveIsScheduled() const
|
||||
{
|
||||
return d->dirty;
|
||||
}
|
||||
|
||||
void PackProfile::buildingFromScratch()
|
||||
void ComponentList::buildingFromScratch()
|
||||
{
|
||||
d->loaded = true;
|
||||
d->dirty = true;
|
||||
}
|
||||
|
||||
void PackProfile::scheduleSave()
|
||||
void ComponentList::scheduleSave()
|
||||
{
|
||||
if(!d->loaded)
|
||||
{
|
||||
@@ -245,30 +245,30 @@ void PackProfile::scheduleSave()
|
||||
d->m_saveTimer.start();
|
||||
}
|
||||
|
||||
QString PackProfile::componentsFilePath() const
|
||||
QString ComponentList::componentsFilePath() const
|
||||
{
|
||||
return FS::PathCombine(d->m_instance->instanceRoot(), "mmc-pack.json");
|
||||
}
|
||||
|
||||
QString PackProfile::patchesPattern() const
|
||||
QString ComponentList::patchesPattern() const
|
||||
{
|
||||
return FS::PathCombine(d->m_instance->instanceRoot(), "patches", "%1.json");
|
||||
}
|
||||
|
||||
QString PackProfile::patchFilePathForUid(const QString& uid) const
|
||||
QString ComponentList::patchFilePathForUid(const QString& uid) const
|
||||
{
|
||||
return patchesPattern().arg(uid);
|
||||
}
|
||||
|
||||
void PackProfile::save_internal()
|
||||
void ComponentList::save_internal()
|
||||
{
|
||||
qDebug() << "Component list save performed now for" << d->m_instance->name();
|
||||
auto filename = componentsFilePath();
|
||||
savePackProfile(filename, d->components);
|
||||
saveComponentList(filename, d->components);
|
||||
d->dirty = false;
|
||||
}
|
||||
|
||||
bool PackProfile::load()
|
||||
bool ComponentList::load()
|
||||
{
|
||||
auto filename = componentsFilePath();
|
||||
QFile componentsFile(filename);
|
||||
@@ -286,7 +286,7 @@ bool PackProfile::load()
|
||||
|
||||
// load the new component list and swap it with the current one...
|
||||
ComponentContainer newComponents;
|
||||
if(!loadPackProfile(this, filename, patchesPattern(), newComponents))
|
||||
if(!loadComponentList(this, filename, patchesPattern(), newComponents))
|
||||
{
|
||||
qCritical() << "Failed to load the component config for instance" << d->m_instance->name();
|
||||
return false;
|
||||
@@ -298,7 +298,7 @@ bool PackProfile::load()
|
||||
// disconnect all the old components
|
||||
for(auto component: d->components)
|
||||
{
|
||||
disconnect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
|
||||
disconnect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
|
||||
}
|
||||
d->components.clear();
|
||||
d->componentIndex.clear();
|
||||
@@ -309,7 +309,7 @@ bool PackProfile::load()
|
||||
qWarning() << "Ignoring duplicate component entry" << component->m_uid;
|
||||
continue;
|
||||
}
|
||||
connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
|
||||
connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
|
||||
d->components.append(component);
|
||||
d->componentIndex[component->m_uid] = component;
|
||||
}
|
||||
@@ -319,7 +319,7 @@ bool PackProfile::load()
|
||||
}
|
||||
}
|
||||
|
||||
void PackProfile::reload(Net::Mode netmode)
|
||||
void ComponentList::reload(Net::Mode netmode)
|
||||
{
|
||||
// Do not reload when the update/resolve task is running. It is in control.
|
||||
if(d->m_updateTask)
|
||||
@@ -339,29 +339,29 @@ void PackProfile::reload(Net::Mode netmode)
|
||||
}
|
||||
}
|
||||
|
||||
shared_qobject_ptr<Task> PackProfile::getCurrentTask()
|
||||
shared_qobject_ptr<Task> ComponentList::getCurrentTask()
|
||||
{
|
||||
return d->m_updateTask;
|
||||
}
|
||||
|
||||
void PackProfile::resolve(Net::Mode netmode)
|
||||
void ComponentList::resolve(Net::Mode netmode)
|
||||
{
|
||||
auto updateTask = new ComponentUpdateTask(ComponentUpdateTask::Mode::Resolution, netmode, this);
|
||||
d->m_updateTask.reset(updateTask);
|
||||
connect(updateTask, &ComponentUpdateTask::succeeded, this, &PackProfile::updateSucceeded);
|
||||
connect(updateTask, &ComponentUpdateTask::failed, this, &PackProfile::updateFailed);
|
||||
connect(updateTask, &ComponentUpdateTask::succeeded, this, &ComponentList::updateSucceeded);
|
||||
connect(updateTask, &ComponentUpdateTask::failed, this, &ComponentList::updateFailed);
|
||||
d->m_updateTask->start();
|
||||
}
|
||||
|
||||
|
||||
void PackProfile::updateSucceeded()
|
||||
void ComponentList::updateSucceeded()
|
||||
{
|
||||
qDebug() << "Component list update/resolve task succeeded for" << d->m_instance->name();
|
||||
d->m_updateTask.reset();
|
||||
invalidateLaunchProfile();
|
||||
}
|
||||
|
||||
void PackProfile::updateFailed(const QString& error)
|
||||
void ComponentList::updateFailed(const QString& error)
|
||||
{
|
||||
qDebug() << "Component list update/resolve task failed for" << d->m_instance->name() << "Reason:" << error;
|
||||
d->m_updateTask.reset();
|
||||
@@ -431,7 +431,7 @@ static void upgradeDeprecatedFiles(QString root, QString instanceName)
|
||||
* - Part is taken from the old order.json file.
|
||||
* - Part is loaded from loose json files in the instance's `patches` directory.
|
||||
*/
|
||||
bool PackProfile::migratePreComponentConfig()
|
||||
bool ComponentList::migratePreComponentConfig()
|
||||
{
|
||||
// upgrade the very old files from the beginnings of MultiMC 5
|
||||
upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
|
||||
@@ -598,17 +598,17 @@ bool PackProfile::migratePreComponentConfig()
|
||||
}
|
||||
}
|
||||
// new we have a complete list of components...
|
||||
return savePackProfile(componentsFilePath(), components);
|
||||
return saveComponentList(componentsFilePath(), components);
|
||||
}
|
||||
|
||||
// END: save/load
|
||||
|
||||
void PackProfile::appendComponent(ComponentPtr component)
|
||||
void ComponentList::appendComponent(ComponentPtr component)
|
||||
{
|
||||
insertComponent(d->components.size(), component);
|
||||
}
|
||||
|
||||
void PackProfile::insertComponent(size_t index, ComponentPtr component)
|
||||
void ComponentList::insertComponent(size_t index, ComponentPtr component)
|
||||
{
|
||||
auto id = component->getID();
|
||||
if(id.isEmpty())
|
||||
@@ -625,16 +625,16 @@ void PackProfile::insertComponent(size_t index, ComponentPtr component)
|
||||
d->components.insert(index, component);
|
||||
d->componentIndex[id] = component;
|
||||
endInsertRows();
|
||||
connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
|
||||
connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
|
||||
scheduleSave();
|
||||
}
|
||||
|
||||
void PackProfile::componentDataChanged()
|
||||
void ComponentList::componentDataChanged()
|
||||
{
|
||||
auto objPtr = qobject_cast<Component *>(sender());
|
||||
if(!objPtr)
|
||||
{
|
||||
qWarning() << "PackProfile got dataChenged signal from a non-Component!";
|
||||
qWarning() << "ComponentList got dataChenged signal from a non-Component!";
|
||||
return;
|
||||
}
|
||||
if(objPtr->getID() == "net.minecraft") {
|
||||
@@ -652,10 +652,10 @@ void PackProfile::componentDataChanged()
|
||||
}
|
||||
index++;
|
||||
}
|
||||
qWarning() << "PackProfile got dataChenged signal from a Component which does not belong to it!";
|
||||
qWarning() << "ComponentList got dataChenged signal from a Component which does not belong to it!";
|
||||
}
|
||||
|
||||
bool PackProfile::remove(const int index)
|
||||
bool ComponentList::remove(const int index)
|
||||
{
|
||||
auto patch = getComponent(index);
|
||||
if (!patch->isRemovable())
|
||||
@@ -679,7 +679,7 @@ bool PackProfile::remove(const int index)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackProfile::remove(const QString id)
|
||||
bool ComponentList::remove(const QString id)
|
||||
{
|
||||
int i = 0;
|
||||
for (auto patch : d->components)
|
||||
@@ -693,7 +693,7 @@ bool PackProfile::remove(const QString id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PackProfile::customize(int index)
|
||||
bool ComponentList::customize(int index)
|
||||
{
|
||||
auto patch = getComponent(index);
|
||||
if (!patch->isCustomizable())
|
||||
@@ -711,7 +711,7 @@ bool PackProfile::customize(int index)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackProfile::revertToBase(int index)
|
||||
bool ComponentList::revertToBase(int index)
|
||||
{
|
||||
auto patch = getComponent(index);
|
||||
if (!patch->isRevertible())
|
||||
@@ -729,7 +729,7 @@ bool PackProfile::revertToBase(int index)
|
||||
return true;
|
||||
}
|
||||
|
||||
Component * PackProfile::getComponent(const QString &id)
|
||||
Component * ComponentList::getComponent(const QString &id)
|
||||
{
|
||||
auto iter = d->componentIndex.find(id);
|
||||
if (iter == d->componentIndex.end())
|
||||
@@ -739,7 +739,7 @@ Component * PackProfile::getComponent(const QString &id)
|
||||
return (*iter).get();
|
||||
}
|
||||
|
||||
Component * PackProfile::getComponent(int index)
|
||||
Component * ComponentList::getComponent(int index)
|
||||
{
|
||||
if(index < 0 || index >= d->components.size())
|
||||
{
|
||||
@@ -748,7 +748,7 @@ Component * PackProfile::getComponent(int index)
|
||||
return d->components[index].get();
|
||||
}
|
||||
|
||||
QVariant PackProfile::data(const QModelIndex &index, int role) const
|
||||
QVariant ComponentList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
@@ -822,7 +822,7 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
bool ComponentList::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
|
||||
{
|
||||
@@ -840,7 +840,7 @@ bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int r
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
QVariant ComponentList::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
@@ -861,7 +861,7 @@ QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int r
|
||||
}
|
||||
|
||||
// FIXME: zero precision mess
|
||||
Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const
|
||||
Qt::ItemFlags ComponentList::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return Qt::NoItemFlags;
|
||||
@@ -884,17 +884,17 @@ Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const
|
||||
return outFlags;
|
||||
}
|
||||
|
||||
int PackProfile::rowCount(const QModelIndex &parent) const
|
||||
int ComponentList::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return d->components.size();
|
||||
}
|
||||
|
||||
int PackProfile::columnCount(const QModelIndex &parent) const
|
||||
int ComponentList::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return NUM_COLUMNS;
|
||||
}
|
||||
|
||||
void PackProfile::move(const int index, const MoveDirection direction)
|
||||
void ComponentList::move(const int index, const MoveDirection direction)
|
||||
{
|
||||
int theirIndex;
|
||||
if (direction == MoveUp)
|
||||
@@ -930,22 +930,22 @@ void PackProfile::move(const int index, const MoveDirection direction)
|
||||
scheduleSave();
|
||||
}
|
||||
|
||||
void PackProfile::invalidateLaunchProfile()
|
||||
void ComponentList::invalidateLaunchProfile()
|
||||
{
|
||||
d->m_profile.reset();
|
||||
}
|
||||
|
||||
void PackProfile::installJarMods(QStringList selectedFiles)
|
||||
void ComponentList::installJarMods(QStringList selectedFiles)
|
||||
{
|
||||
installJarMods_internal(selectedFiles);
|
||||
}
|
||||
|
||||
void PackProfile::installCustomJar(QString selectedFile)
|
||||
void ComponentList::installCustomJar(QString selectedFile)
|
||||
{
|
||||
installCustomJar_internal(selectedFile);
|
||||
}
|
||||
|
||||
bool PackProfile::installEmpty(const QString& uid, const QString& name)
|
||||
bool ComponentList::installEmpty(const QString& uid, const QString& name)
|
||||
{
|
||||
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
||||
if(!FS::ensureFolderPathExists(patchDir))
|
||||
@@ -973,7 +973,7 @@ bool PackProfile::installEmpty(const QString& uid, const QString& name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackProfile::removeComponent_internal(ComponentPtr patch)
|
||||
bool ComponentList::removeComponent_internal(ComponentPtr patch)
|
||||
{
|
||||
bool ok = true;
|
||||
// first, remove the patch file. this ensures it's not used anymore
|
||||
@@ -991,7 +991,7 @@ bool PackProfile::removeComponent_internal(ComponentPtr patch)
|
||||
// FIXME: we need a generic way of removing local resources, not just jar mods...
|
||||
auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool
|
||||
{
|
||||
if (!jarMod->isLocal())
|
||||
if (!jarMod->isInstanceLocal())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1023,7 +1023,7 @@ bool PackProfile::removeComponent_internal(ComponentPtr patch)
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool PackProfile::installJarMods_internal(QStringList filepaths)
|
||||
bool ComponentList::installJarMods_internal(QStringList filepaths)
|
||||
{
|
||||
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
||||
if(!FS::ensureFolderPathExists(patchDir))
|
||||
@@ -1085,7 +1085,7 @@ bool PackProfile::installJarMods_internal(QStringList filepaths)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackProfile::installCustomJar_internal(QString filepath)
|
||||
bool ComponentList::installCustomJar_internal(QString filepath)
|
||||
{
|
||||
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
|
||||
if(!FS::ensureFolderPathExists(patchDir))
|
||||
@@ -1146,7 +1146,7 @@ bool PackProfile::installCustomJar_internal(QString filepath)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
|
||||
std::shared_ptr<LaunchProfile> ComponentList::getProfile() const
|
||||
{
|
||||
if(!d->m_profile)
|
||||
{
|
||||
@@ -1168,7 +1168,7 @@ std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
|
||||
return d->m_profile;
|
||||
}
|
||||
|
||||
void PackProfile::setOldConfigVersion(const QString& uid, const QString& version)
|
||||
void ComponentList::setOldConfigVersion(const QString& uid, const QString& version)
|
||||
{
|
||||
if(version.isEmpty())
|
||||
{
|
||||
@@ -1177,7 +1177,7 @@ void PackProfile::setOldConfigVersion(const QString& uid, const QString& version
|
||||
d->m_oldConfigVersions[uid] = version;
|
||||
}
|
||||
|
||||
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
|
||||
bool ComponentList::setComponentVersion(const QString& uid, const QString& version, bool important)
|
||||
{
|
||||
auto iter = d->componentIndex.find(uid);
|
||||
if(iter != d->componentIndex.end())
|
||||
@@ -1203,7 +1203,7 @@ bool PackProfile::setComponentVersion(const QString& uid, const QString& version
|
||||
}
|
||||
}
|
||||
|
||||
QString PackProfile::getComponentVersion(const QString& uid) const
|
||||
QString ComponentList::getComponentVersion(const QString& uid) const
|
||||
{
|
||||
const auto iter = d->componentIndex.find(uid);
|
||||
if (iter != d->componentIndex.end())
|
||||
@@ -1213,7 +1213,7 @@ QString PackProfile::getComponentVersion(const QString& uid) const
|
||||
return QString();
|
||||
}
|
||||
|
||||
void PackProfile::disableInteraction(bool disable)
|
||||
void ComponentList::disableInteraction(bool disable)
|
||||
{
|
||||
if(d->interactionDisabled != disable) {
|
||||
d->interactionDisabled = disable;
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
@@ -31,10 +31,10 @@
|
||||
#include "net/Mode.h"
|
||||
|
||||
class MinecraftInstance;
|
||||
struct PackProfileData;
|
||||
struct ComponentListData;
|
||||
class ComponentUpdateTask;
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT PackProfile : public QAbstractListModel
|
||||
class MULTIMC_LOGIC_EXPORT ComponentList : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
friend ComponentUpdateTask;
|
||||
@@ -46,8 +46,8 @@ public:
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
explicit PackProfile(MinecraftInstance * instance);
|
||||
virtual ~PackProfile();
|
||||
explicit ComponentList(MinecraftInstance * instance);
|
||||
virtual ~ComponentList();
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
@@ -114,10 +114,6 @@ public:
|
||||
/// get the profile component by index
|
||||
Component * getComponent(int index);
|
||||
|
||||
/// Add the component to the internal list of patches
|
||||
// todo(merged): is this the best approach
|
||||
void appendComponent(ComponentPtr component);
|
||||
|
||||
private:
|
||||
void scheduleSave();
|
||||
bool saveIsScheduled() const;
|
||||
@@ -125,6 +121,8 @@ private:
|
||||
/// apply the component patches. Catches all the errors and returns true/false for success/failure
|
||||
void invalidateLaunchProfile();
|
||||
|
||||
/// Add the component to the internal list of patches
|
||||
void appendComponent(ComponentPtr component);
|
||||
/// insert component so that its index is ideally the specified one (returns real index)
|
||||
void insertComponent(size_t index, ComponentPtr component);
|
||||
|
||||
@@ -148,5 +146,5 @@ private:
|
||||
|
||||
private: /* data */
|
||||
|
||||
std::unique_ptr<PackProfileData> d;
|
||||
std::unique_ptr<ComponentListData> d;
|
||||
};
|
||||
@@ -9,8 +9,9 @@
|
||||
class MinecraftInstance;
|
||||
using ComponentContainer = QList<ComponentPtr>;
|
||||
using ComponentIndex = QMap<QString, ComponentPtr>;
|
||||
using ConnectionList = QList<QMetaObject::Connection>;
|
||||
|
||||
struct PackProfileData
|
||||
struct ComponentListData
|
||||
{
|
||||
// the instance this belongs to
|
||||
MinecraftInstance *m_instance;
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "ComponentUpdateTask.h"
|
||||
|
||||
#include "PackProfile_p.h"
|
||||
#include "PackProfile.h"
|
||||
#include "ComponentList_p.h"
|
||||
#include "ComponentList.h"
|
||||
#include "Component.h"
|
||||
#include <Env.h>
|
||||
#include <meta/Index.h>
|
||||
@@ -22,16 +22,16 @@
|
||||
* Really, it should be a reactor/state machine that receives input from the application
|
||||
* and dynamically adapts to changing requirements...
|
||||
*
|
||||
* The reactor should be the only entry into manipulating the PackProfile.
|
||||
* The reactor should be the only entry into manipulating the ComponentList.
|
||||
* See: https://en.wikipedia.org/wiki/Reactor_pattern
|
||||
*/
|
||||
|
||||
/*
|
||||
* Or make this operate on a snapshot of the PackProfile state, then merge results in as long as the snapshot and PackProfile didn't change?
|
||||
* Or make this operate on a snapshot of the ComponentList state, then merge results in as long as the snapshot and ComponentList didn't change?
|
||||
* If the component list changes, start over.
|
||||
*/
|
||||
|
||||
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* list, QObject* parent)
|
||||
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList* list, QObject* parent)
|
||||
: Task(parent)
|
||||
{
|
||||
d.reset(new ComponentUpdateTaskData);
|
||||
@@ -126,7 +126,7 @@ static LoadResult loadComponent(ComponentPtr component, shared_qobject_ptr<Task>
|
||||
|
||||
// FIXME: dead code. determine if this can still be useful?
|
||||
/*
|
||||
static LoadResult loadPackProfile(ComponentPtr component, shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
|
||||
static LoadResult loadComponentList(ComponentPtr component, shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
|
||||
{
|
||||
if(component->m_loaded)
|
||||
{
|
||||
@@ -217,7 +217,7 @@ void ComponentUpdateTask::loadComponents()
|
||||
}
|
||||
case Mode::Resolution:
|
||||
{
|
||||
singleResult = loadPackProfile(component, loadTask, d->netmode);
|
||||
singleResult = loadComponentList(component, loadTask, d->netmode);
|
||||
loadType = RemoteLoadStatus::Type::List;
|
||||
break;
|
||||
}
|
||||
@@ -244,7 +244,7 @@ void ComponentUpdateTask::loadComponents()
|
||||
});
|
||||
RemoteLoadStatus status;
|
||||
status.type = loadType;
|
||||
status.PackProfileIndex = componentIndex;
|
||||
status.componentListIndex = componentIndex;
|
||||
d->remoteLoadStatusList.append(status);
|
||||
taskIndex++;
|
||||
}
|
||||
@@ -451,17 +451,13 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
|
||||
auto & comp = (*compIter);
|
||||
if(comp->getVersion() != req.equalsVersion)
|
||||
{
|
||||
if(comp->isCustom()) {
|
||||
if(comp->m_dependencyOnly)
|
||||
{
|
||||
decision = Decision::VersionNotSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
decision = Decision::LockedVersionNotSame;
|
||||
} else {
|
||||
if(comp->m_dependencyOnly)
|
||||
{
|
||||
decision = Decision::VersionNotSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
decision = Decision::LockedVersionNotSame;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -495,7 +491,7 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
|
||||
}
|
||||
|
||||
// FIXME, TODO: decouple dependency resolution from loading
|
||||
// FIXME: This works directly with the PackProfile internals. It shouldn't! It needs richer data types than PackProfile uses.
|
||||
// FIXME: This works directly with the ComponentList internals. It shouldn't! It needs richer data types than ComponentList uses.
|
||||
// FIXME: throw all this away and use a graph
|
||||
void ComponentUpdateTask::resolveDependencies(bool checkOnly)
|
||||
{
|
||||
@@ -648,7 +644,7 @@ void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex)
|
||||
// update the cached data of the component from the downloaded version file.
|
||||
if (taskSlot.type == RemoteLoadStatus::Type::Version)
|
||||
{
|
||||
auto component = d->m_list->getComponent(taskSlot.PackProfileIndex);
|
||||
auto component = d->m_list->getComponent(taskSlot.componentListIndex);
|
||||
component->m_loaded = true;
|
||||
component->updateCachedData();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "net/Mode.h"
|
||||
|
||||
#include <memory>
|
||||
class PackProfile;
|
||||
class ComponentList;
|
||||
struct ComponentUpdateTaskData;
|
||||
|
||||
class ComponentUpdateTask : public Task
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile * list, QObject *parent = 0);
|
||||
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList * list, QObject *parent = 0);
|
||||
virtual ~ComponentUpdateTask();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <QList>
|
||||
#include "net/Mode.h"
|
||||
|
||||
class PackProfile;
|
||||
class ComponentList;
|
||||
|
||||
struct RemoteLoadStatus
|
||||
{
|
||||
@@ -15,7 +15,7 @@ struct RemoteLoadStatus
|
||||
List,
|
||||
Version
|
||||
} type = Type::Version;
|
||||
size_t PackProfileIndex = 0;
|
||||
size_t componentListIndex = 0;
|
||||
bool finished = false;
|
||||
bool succeeded = false;
|
||||
QString error;
|
||||
@@ -23,7 +23,7 @@ struct RemoteLoadStatus
|
||||
|
||||
struct ComponentUpdateTaskData
|
||||
{
|
||||
PackProfile * m_list = nullptr;
|
||||
ComponentList * m_list = nullptr;
|
||||
QList<RemoteLoadStatus> remoteLoadStatusList;
|
||||
bool remoteLoadSuccessful = true;
|
||||
size_t remoteTasksInProgress = 0;
|
||||
|
||||
@@ -117,7 +117,7 @@ struct GradleSpecifier
|
||||
}
|
||||
bool matchName(const GradleSpecifier & other) const
|
||||
{
|
||||
return other.artifactId() == artifactId() && other.groupId() == groupId();
|
||||
return other.artifactId() == artifactId() && other.groupId() == groupId() && other.classifier() == classifier();
|
||||
}
|
||||
bool operator==(const GradleSpecifier & other) const
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@ void LaunchProfile::clear()
|
||||
m_mainClass.clear();
|
||||
m_appletClass.clear();
|
||||
m_libraries.clear();
|
||||
m_mavenFiles.clear();
|
||||
m_traits.clear();
|
||||
m_jarMods.clear();
|
||||
m_mainJar.reset();
|
||||
@@ -158,33 +157,25 @@ void LaunchProfile::applyLibrary(LibraryPtr library)
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchProfile::applyMavenFile(LibraryPtr mavenFile)
|
||||
{
|
||||
if(!mavenFile->isActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(mavenFile->isNative())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unlike libraries, we do not keep only one version or try to dedupe them
|
||||
m_mavenFiles.append(Library::limitedCopy(mavenFile));
|
||||
}
|
||||
|
||||
const LibraryPtr LaunchProfile::getMainJar() const
|
||||
{
|
||||
return m_mainJar;
|
||||
}
|
||||
|
||||
void LaunchProfile::applyMainJar(LibraryPtr jar)
|
||||
void LaunchProfile::applyMainJar(LibraryPtr jar, bool removeMainJar)
|
||||
{
|
||||
if(jar)
|
||||
if(removeMainJar)
|
||||
{
|
||||
m_mainJar.reset();
|
||||
}
|
||||
else if(jar)
|
||||
{
|
||||
m_mainJar = jar;
|
||||
}
|
||||
else
|
||||
{
|
||||
// mainJar was not specified, NOOP
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchProfile::applyProblemSeverity(ProblemSeverity severity)
|
||||
@@ -270,11 +261,6 @@ const QList<LibraryPtr> & LaunchProfile::getNativeLibraries() const
|
||||
return m_nativeLibraries;
|
||||
}
|
||||
|
||||
const QList<LibraryPtr> & LaunchProfile::getMavenFiles() const
|
||||
{
|
||||
return m_mavenFiles;
|
||||
}
|
||||
|
||||
void LaunchProfile::getLibraryFiles(
|
||||
const QString& architecture,
|
||||
QStringList& jars,
|
||||
|
||||
@@ -20,8 +20,7 @@ public: /* application of profile variables from patches */
|
||||
void applyJarMods(const QList<LibraryPtr> &jarMods);
|
||||
void applyMods(const QList<LibraryPtr> &jarMods);
|
||||
void applyLibrary(LibraryPtr library);
|
||||
void applyMavenFile(LibraryPtr library);
|
||||
void applyMainJar(LibraryPtr jar);
|
||||
void applyMainJar(LibraryPtr jar, bool removeMainJar);
|
||||
void applyProblemSeverity(ProblemSeverity severity);
|
||||
/// clear the profile
|
||||
void clear();
|
||||
@@ -38,7 +37,6 @@ public: /* getters for profile variables */
|
||||
const QList<LibraryPtr> & getJarMods() const;
|
||||
const QList<LibraryPtr> & getLibraries() const;
|
||||
const QList<LibraryPtr> & getNativeLibraries() const;
|
||||
const QList<LibraryPtr> & getMavenFiles() const;
|
||||
const LibraryPtr getMainJar() const;
|
||||
void getLibraryFiles(
|
||||
const QString & architecture,
|
||||
@@ -81,13 +79,10 @@ private:
|
||||
/// the list of libraries
|
||||
QList<LibraryPtr> m_libraries;
|
||||
|
||||
/// the list of maven files to be placed in the libraries folder, but not acted upon
|
||||
QList<LibraryPtr> m_mavenFiles;
|
||||
|
||||
/// the main jar
|
||||
LibraryPtr m_mainJar;
|
||||
|
||||
/// the list of native libraries
|
||||
/// the list of libraries
|
||||
QList<LibraryPtr> m_nativeLibraries;
|
||||
|
||||
/// traits, collected from all the version files (version files can only add)
|
||||
|
||||
@@ -3,18 +3,24 @@
|
||||
|
||||
#include <net/Download.h>
|
||||
#include <net/ChecksumValidator.h>
|
||||
#include <minecraft/forge/ForgeXzDownload.h>
|
||||
#include <Env.h>
|
||||
#include <FileSystem.h>
|
||||
#include <BuildConfig.h>
|
||||
|
||||
|
||||
void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32,
|
||||
QStringList& native64, const QString &overridePath) const
|
||||
void Library::getApplicableFiles(
|
||||
OpSys system,
|
||||
QStringList& jar,
|
||||
QStringList& native,
|
||||
QStringList& native32,
|
||||
QStringList& native64,
|
||||
const QString &overridePath
|
||||
) const
|
||||
{
|
||||
bool local = isLocal();
|
||||
bool local = isInstanceLocal();
|
||||
auto actualPath = [&](QString relPath)
|
||||
{
|
||||
QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
|
||||
QFileInfo out(FS::PathCombine("libraries", relPath));
|
||||
if(local && !overridePath.isEmpty())
|
||||
{
|
||||
QString fileName = out.fileName();
|
||||
@@ -54,9 +60,9 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
|
||||
{
|
||||
QList<NetActionPtr> out;
|
||||
bool stale = isAlwaysStale();
|
||||
bool local = isLocal();
|
||||
bool instanceLocal = isInstanceLocal();
|
||||
|
||||
auto check_local_file = [&](QString storage)
|
||||
auto check_instance_local_file = [&](QString storage)
|
||||
{
|
||||
QFileInfo fileinfo(storage);
|
||||
QString fileName = fileinfo.fileName();
|
||||
@@ -72,9 +78,9 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
|
||||
|
||||
auto add_download = [&](QString storage, QString url, QString sha1)
|
||||
{
|
||||
if(local)
|
||||
if(instanceLocal)
|
||||
{
|
||||
return check_local_file(storage);
|
||||
return check_instance_local_file(storage);
|
||||
}
|
||||
auto entry = cache->resolveEntry("libraries", storage);
|
||||
if(stale)
|
||||
@@ -82,25 +88,34 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
|
||||
entry->setStale(true);
|
||||
}
|
||||
if (!entry->isStale())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Net::Download::Options options;
|
||||
if(stale)
|
||||
{
|
||||
options |= Net::Download::Option::AcceptLocalFiles;
|
||||
}
|
||||
|
||||
if(sha1.size())
|
||||
if (isForge())
|
||||
{
|
||||
auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
|
||||
auto dl = Net::Download::makeCached(url, entry, options);
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
|
||||
qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(dl);
|
||||
qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(ForgeXzDownload::make(url, storage, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(Net::Download::makeCached(url, entry, options));
|
||||
qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
if(sha1.size())
|
||||
{
|
||||
auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
|
||||
auto dl = Net::Download::makeCached(url, entry, options);
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
|
||||
qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(dl);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(Net::Download::makeCached(url, entry, options));
|
||||
qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -172,7 +187,7 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
|
||||
|
||||
if (m_repositoryURL.isEmpty())
|
||||
{
|
||||
return BuildConfig.LIBRARY_BASE + raw_storage;
|
||||
return URLConstants::LIBRARY_BASE + raw_storage;
|
||||
}
|
||||
|
||||
if(m_repositoryURL.endsWith('/'))
|
||||
@@ -226,7 +241,7 @@ bool Library::isActive() const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Library::isLocal() const
|
||||
bool Library::isInstanceLocal() const
|
||||
{
|
||||
return m_hint == "local";
|
||||
}
|
||||
@@ -236,23 +251,9 @@ bool Library::isAlwaysStale() const
|
||||
return m_hint == "always-stale";
|
||||
}
|
||||
|
||||
void Library::setStoragePrefix(QString prefix)
|
||||
bool Library::isForge() const
|
||||
{
|
||||
m_storagePrefix = prefix;
|
||||
}
|
||||
|
||||
QString Library::defaultStoragePrefix()
|
||||
{
|
||||
return "libraries/";
|
||||
}
|
||||
|
||||
QString Library::storagePrefix() const
|
||||
{
|
||||
if(m_storagePrefix.isEmpty())
|
||||
{
|
||||
return defaultStoragePrefix();
|
||||
}
|
||||
return m_storagePrefix;
|
||||
return m_hint == "forge-pack-xz";
|
||||
}
|
||||
|
||||
QString Library::filename(OpSys system) const
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Rule.h"
|
||||
#include "minecraft/OpSys.h"
|
||||
#include "GradleSpecifier.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include "MojangDownloadInfo.h"
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
@@ -45,7 +46,6 @@ public:
|
||||
newlib->m_extractExcludes = base->m_extractExcludes;
|
||||
newlib->m_nativeClassifiers = base->m_nativeClassifiers;
|
||||
newlib->m_rules = base->m_rules;
|
||||
newlib->m_storagePrefix = base->m_storagePrefix;
|
||||
newlib->m_mojangDownloads = base->m_mojangDownloads;
|
||||
newlib->m_filename = base->m_filename;
|
||||
return newlib;
|
||||
@@ -92,8 +92,6 @@ public: /* methods */
|
||||
return m_nativeClassifiers.size() != 0;
|
||||
}
|
||||
|
||||
void setStoragePrefix(QString prefix = QString());
|
||||
|
||||
/// Set the url base for downloads
|
||||
void setRepositoryURL(const QString &base_url)
|
||||
{
|
||||
@@ -145,7 +143,15 @@ public: /* methods */
|
||||
bool isActive() const;
|
||||
|
||||
/// Returns true if the library is contained in an instance and false if it is shared
|
||||
bool isLocal() const;
|
||||
bool isInstanceLocal() const;
|
||||
|
||||
/// Returns true if the library cannot be downloaded (was built locally somehow)
|
||||
bool isLocalBuilt() const;
|
||||
|
||||
bool isLocal() const
|
||||
{
|
||||
return isInstanceLocal() || isLocalBuilt();
|
||||
}
|
||||
|
||||
/// Returns true if the library is to always be checked for updates
|
||||
bool isAlwaysStale() const;
|
||||
@@ -158,11 +164,6 @@ public: /* methods */
|
||||
QStringList & failedLocalFiles, const QString & overridePath) const;
|
||||
|
||||
private: /* methods */
|
||||
/// the default storage prefix used by MultiMC
|
||||
static QString defaultStoragePrefix();
|
||||
|
||||
/// Get the prefix - root of the storage to be used
|
||||
QString storagePrefix() const;
|
||||
|
||||
/// Get the relative file path where the library should be saved
|
||||
QString storageSuffix(OpSys system) const;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <QTest>
|
||||
#include "TestUtil.h"
|
||||
|
||||
#include "minecraft/MojangVersionFormat.h"
|
||||
#include "minecraft/OneSixVersionFormat.h"
|
||||
#include "minecraft/Library.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
@@ -18,7 +17,7 @@ private:
|
||||
jsonFile.open(QIODevice::ReadOnly);
|
||||
auto data = jsonFile.readAll();
|
||||
jsonFile.close();
|
||||
return MojangVersionFormat::libraryFromJson(QJsonDocument::fromJson(data).object(), file);
|
||||
return OneSixVersionFormat::libraryFromJson(QJsonDocument::fromJson(data).object(), file);
|
||||
}
|
||||
// get absolute path to expected storage, assuming default cache prefix
|
||||
QStringList getStorage(QString relative)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "MinecraftInstance.h"
|
||||
#include <minecraft/launch/CreateGameFolders.h>
|
||||
#include <minecraft/launch/CreateServerResourcePacksFolder.h>
|
||||
#include <minecraft/launch/ExtractNatives.h>
|
||||
#include <minecraft/launch/PrintInstanceInfo.h>
|
||||
#include <settings/Setting.h>
|
||||
@@ -33,12 +33,11 @@
|
||||
#include "icons/IIconList.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include "PackProfile.h"
|
||||
#include "ComponentList.h"
|
||||
#include "AssetsUtils.h"
|
||||
#include "MinecraftUpdate.h"
|
||||
#include "MinecraftLoadAndCheck.h"
|
||||
#include <minecraft/gameoptions/GameOptions.h>
|
||||
#include <minecraft/update/FoldersTask.h>
|
||||
|
||||
#define IBUS "@im=ibus"
|
||||
|
||||
@@ -101,18 +100,13 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
|
||||
auto launchMethodOverride = m_settings->registerSetting("OverrideMCLaunchMethod", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("MCLaunchMethod"), launchMethodOverride);
|
||||
|
||||
// Native library workarounds
|
||||
auto nativeLibraryWorkaroundsOverride = m_settings->registerSetting("OverrideNativeWorkarounds", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("UseNativeOpenAL"), nativeLibraryWorkaroundsOverride);
|
||||
m_settings->registerOverride(globalSettings->getSetting("UseNativeGLFW"), nativeLibraryWorkaroundsOverride);
|
||||
|
||||
// DEPRECATED: Read what versions the user configuration thinks should be used
|
||||
m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
|
||||
m_settings->registerSetting("LWJGLVersion", "");
|
||||
m_settings->registerSetting("ForgeVersion", "");
|
||||
m_settings->registerSetting("LiteloaderVersion", "");
|
||||
|
||||
m_components.reset(new PackProfile(this));
|
||||
m_components.reset(new ComponentList(this));
|
||||
m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
|
||||
auto setting = m_settings->getSetting("LWJGLVersion");
|
||||
m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
|
||||
@@ -130,14 +124,14 @@ QString MinecraftInstance::typeName() const
|
||||
return "Minecraft";
|
||||
}
|
||||
|
||||
std::shared_ptr<PackProfile> MinecraftInstance::getPackProfile() const
|
||||
std::shared_ptr<ComponentList> MinecraftInstance::getComponentList() const
|
||||
{
|
||||
return m_components;
|
||||
}
|
||||
|
||||
QSet<QString> MinecraftInstance::traits() const
|
||||
{
|
||||
auto components = getPackProfile();
|
||||
auto components = getComponentList();
|
||||
if (!components)
|
||||
{
|
||||
return {"version-incomplete"};
|
||||
@@ -271,7 +265,7 @@ QStringList MinecraftInstance::getNativeJars() const
|
||||
QStringList MinecraftInstance::extraArguments() const
|
||||
{
|
||||
auto list = BaseInstance::extraArguments();
|
||||
auto version = getPackProfile();
|
||||
auto version = getComponentList();
|
||||
if (!version)
|
||||
return list;
|
||||
auto jarMods = getJarMods();
|
||||
@@ -811,11 +805,6 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
return process;
|
||||
}
|
||||
|
||||
// create the .minecraft folder and server-resource-packs (workaround for Minecraft bug MCL-3732)
|
||||
{
|
||||
process->appendStep(new CreateGameFolders(pptr));
|
||||
}
|
||||
|
||||
// run pre-launch command if that's needed
|
||||
if(getPreLaunchCommand().size())
|
||||
{
|
||||
@@ -840,7 +829,7 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
process->appendStep(new ModMinecraftJar(pptr));
|
||||
}
|
||||
|
||||
// Scan mods folders for mods
|
||||
// if there are any jar mods
|
||||
{
|
||||
process->appendStep(new ScanModFolders(pptr));
|
||||
}
|
||||
@@ -850,6 +839,11 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
|
||||
process->appendStep(new PrintInstanceInfo(pptr, session));
|
||||
}
|
||||
|
||||
// create the server-resource-packs folder (workaround for Minecraft bug MCL-3732)
|
||||
{
|
||||
process->appendStep(new CreateServerResourcePacksFolder(pptr));
|
||||
}
|
||||
|
||||
// extract native jars if needed
|
||||
{
|
||||
process->appendStep(new ExtractNatives(pptr));
|
||||
|
||||
@@ -10,7 +10,7 @@ class ModFolderModel;
|
||||
class WorldList;
|
||||
class GameOptions;
|
||||
class LaunchStep;
|
||||
class PackProfile;
|
||||
class ComponentList;
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance
|
||||
{
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
|
||||
////// Profile management //////
|
||||
std::shared_ptr<PackProfile> getPackProfile() const;
|
||||
std::shared_ptr<ComponentList> getComponentList() const;
|
||||
|
||||
////// Mod Lists //////
|
||||
std::shared_ptr<ModFolderModel> loaderModList() const;
|
||||
@@ -120,7 +120,7 @@ private:
|
||||
QString prettifyTimeDuration(int64_t duration);
|
||||
|
||||
protected: // data
|
||||
std::shared_ptr<PackProfile> m_components;
|
||||
std::shared_ptr<ComponentList> m_components;
|
||||
mutable std::shared_ptr<ModFolderModel> m_loader_mod_list;
|
||||
mutable std::shared_ptr<ModFolderModel> m_core_mod_list;
|
||||
mutable std::shared_ptr<ModFolderModel> m_resource_pack_list;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "MinecraftLoadAndCheck.h"
|
||||
#include "MinecraftInstance.h"
|
||||
#include "PackProfile.h"
|
||||
#include "ComponentList.h"
|
||||
|
||||
MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *parent) : Task(parent), m_inst(inst)
|
||||
{
|
||||
@@ -9,7 +9,7 @@ MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *p
|
||||
void MinecraftLoadAndCheck::executeTask()
|
||||
{
|
||||
// add offline metadata load task
|
||||
auto components = m_inst->getPackProfile();
|
||||
auto components = m_inst->getComponentList();
|
||||
components->reload(Net::Mode::Offline);
|
||||
m_task = components->getCurrentTask();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "Env.h"
|
||||
#include <minecraft/forge/ForgeXzDownload.h>
|
||||
#include "MinecraftUpdate.h"
|
||||
#include "MinecraftInstance.h"
|
||||
|
||||
@@ -23,8 +24,9 @@
|
||||
#include <QDataStream>
|
||||
|
||||
#include "BaseInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "minecraft/ComponentList.h"
|
||||
#include "minecraft/Library.h"
|
||||
#include "net/URLConstants.h"
|
||||
#include <FileSystem.h>
|
||||
|
||||
#include "update/FoldersTask.h"
|
||||
@@ -49,7 +51,7 @@ void MinecraftUpdate::executeTask()
|
||||
|
||||
// add metadata update task if necessary
|
||||
{
|
||||
auto components = m_inst->getPackProfile();
|
||||
auto components = m_inst->getComponentList();
|
||||
components->reload(Net::Mode::Online);
|
||||
auto task = components->getCurrentTask();
|
||||
if(task)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 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 file except in compliance with the License.
|
||||
|
||||
@@ -36,7 +36,7 @@ struct MojangLibraryDownloadInfo
|
||||
{
|
||||
return artifact.get();
|
||||
}
|
||||
|
||||
|
||||
return classifiers[classifier].get();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,379 +0,0 @@
|
||||
#include "MojangVersionFormat.h"
|
||||
#include "OneSixVersionFormat.h"
|
||||
#include "MojangDownloadInfo.h"
|
||||
|
||||
#include "Json.h"
|
||||
using namespace Json;
|
||||
#include "ParseUtils.h"
|
||||
|
||||
static const int CURRENT_MINIMUM_LAUNCHER_VERSION = 18;
|
||||
|
||||
static MojangAssetIndexInfo::Ptr assetIndexFromJson (const QJsonObject &obj);
|
||||
static MojangDownloadInfo::Ptr downloadInfoFromJson (const QJsonObject &obj);
|
||||
static MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson (const QJsonObject &libObj);
|
||||
static QJsonObject assetIndexToJson (MojangAssetIndexInfo::Ptr assetidxinfo);
|
||||
static QJsonObject libDownloadInfoToJson (MojangLibraryDownloadInfo::Ptr libinfo);
|
||||
static QJsonObject downloadInfoToJson (MojangDownloadInfo::Ptr info);
|
||||
|
||||
namespace Bits
|
||||
{
|
||||
static void readString(const QJsonObject &root, const QString &key, QString &variable)
|
||||
{
|
||||
if (root.contains(key))
|
||||
{
|
||||
variable = requireString(root.value(key));
|
||||
}
|
||||
}
|
||||
|
||||
static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj)
|
||||
{
|
||||
// optional, not used
|
||||
readString(obj, "path", out->path);
|
||||
// required!
|
||||
out->sha1 = requireString(obj, "sha1");
|
||||
out->url = requireString(obj, "url");
|
||||
out->size = requireInteger(obj, "size");
|
||||
}
|
||||
|
||||
static void readAssetIndex(MojangAssetIndexInfo::Ptr out, const QJsonObject &obj)
|
||||
{
|
||||
out->totalSize = requireInteger(obj, "totalSize");
|
||||
out->id = requireString(obj, "id");
|
||||
// out->known = true;
|
||||
}
|
||||
}
|
||||
|
||||
MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject &obj)
|
||||
{
|
||||
auto out = std::make_shared<MojangDownloadInfo>();
|
||||
Bits::readDownloadInfo(out, obj);
|
||||
return out;
|
||||
}
|
||||
|
||||
MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject &obj)
|
||||
{
|
||||
auto out = std::make_shared<MojangAssetIndexInfo>();
|
||||
Bits::readDownloadInfo(out, obj);
|
||||
Bits::readAssetIndex(out, obj);
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(!info->path.isNull())
|
||||
{
|
||||
out.insert("path", info->path);
|
||||
}
|
||||
out.insert("sha1", info->sha1);
|
||||
out.insert("size", info->size);
|
||||
out.insert("url", info->url);
|
||||
return out;
|
||||
}
|
||||
|
||||
MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject &libObj)
|
||||
{
|
||||
auto out = std::make_shared<MojangLibraryDownloadInfo>();
|
||||
auto dlObj = requireObject(libObj.value("downloads"));
|
||||
if(dlObj.contains("artifact"))
|
||||
{
|
||||
out->artifact = downloadInfoFromJson(requireObject(dlObj, "artifact"));
|
||||
}
|
||||
if(dlObj.contains("classifiers"))
|
||||
{
|
||||
auto classifiersObj = requireObject(dlObj, "classifiers");
|
||||
for(auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++)
|
||||
{
|
||||
auto classifier = iter.key();
|
||||
auto classifierObj = requireObject(iter.value());
|
||||
out->classifiers[classifier] = downloadInfoFromJson(classifierObj);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(libinfo->artifact)
|
||||
{
|
||||
out.insert("artifact", downloadInfoToJson(libinfo->artifact));
|
||||
}
|
||||
if(libinfo->classifiers.size())
|
||||
{
|
||||
QJsonObject classifiersOut;
|
||||
for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
|
||||
{
|
||||
classifiersOut.insert(iter.key(), downloadInfoToJson(iter.value()));
|
||||
}
|
||||
out.insert("classifiers", classifiersOut);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(!info->path.isNull())
|
||||
{
|
||||
out.insert("path", info->path);
|
||||
}
|
||||
out.insert("sha1", info->sha1);
|
||||
out.insert("size", info->size);
|
||||
out.insert("url", info->url);
|
||||
out.insert("totalSize", info->totalSize);
|
||||
out.insert("id", info->id);
|
||||
return out;
|
||||
}
|
||||
|
||||
void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFile *out)
|
||||
{
|
||||
Bits::readString(in, "id", out->minecraftVersion);
|
||||
Bits::readString(in, "mainClass", out->mainClass);
|
||||
Bits::readString(in, "minecraftArguments", out->minecraftArguments);
|
||||
if(out->minecraftArguments.isEmpty())
|
||||
{
|
||||
QString processArguments;
|
||||
Bits::readString(in, "processArguments", processArguments);
|
||||
QString toCompare = processArguments.toLower();
|
||||
if (toCompare == "legacy")
|
||||
{
|
||||
out->minecraftArguments = " ${auth_player_name} ${auth_session}";
|
||||
}
|
||||
else if (toCompare == "username_session")
|
||||
{
|
||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
|
||||
}
|
||||
else if (toCompare == "username_session_version")
|
||||
{
|
||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
|
||||
}
|
||||
else if (!toCompare.isEmpty())
|
||||
{
|
||||
out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
|
||||
}
|
||||
}
|
||||
Bits::readString(in, "type", out->type);
|
||||
|
||||
Bits::readString(in, "assets", out->assets);
|
||||
if(in.contains("assetIndex"))
|
||||
{
|
||||
out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex"));
|
||||
}
|
||||
else if (!out->assets.isNull())
|
||||
{
|
||||
out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets);
|
||||
}
|
||||
|
||||
out->releaseTime = timeFromS3Time(in.value("releaseTime").toString(""));
|
||||
out->updateTime = timeFromS3Time(in.value("time").toString(""));
|
||||
|
||||
if (in.contains("minimumLauncherVersion"))
|
||||
{
|
||||
out->minimumLauncherVersion = requireInteger(in.value("minimumLauncherVersion"));
|
||||
if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
|
||||
{
|
||||
out->addProblem(
|
||||
ProblemSeverity::Warning,
|
||||
QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!")
|
||||
.arg(out->minimumLauncherVersion)
|
||||
.arg(CURRENT_MINIMUM_LAUNCHER_VERSION));
|
||||
}
|
||||
}
|
||||
if(in.contains("downloads"))
|
||||
{
|
||||
auto downloadsObj = requireObject(in, "downloads");
|
||||
for(auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++)
|
||||
{
|
||||
auto classifier = iter.key();
|
||||
auto classifierObj = requireObject(iter.value());
|
||||
out->mojangDownloads[classifier] = downloadInfoFromJson(classifierObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename)
|
||||
{
|
||||
VersionFilePtr out(new VersionFile());
|
||||
if (doc.isEmpty() || doc.isNull())
|
||||
{
|
||||
throw JSONValidationError(filename + " is empty or null");
|
||||
}
|
||||
if (!doc.isObject())
|
||||
{
|
||||
throw JSONValidationError(filename + " is not an object");
|
||||
}
|
||||
|
||||
QJsonObject root = doc.object();
|
||||
|
||||
readVersionProperties(root, out.get());
|
||||
|
||||
out->name = "Minecraft";
|
||||
out->uid = "net.minecraft";
|
||||
out->version = out->minecraftVersion;
|
||||
// out->filename = filename;
|
||||
|
||||
|
||||
if (root.contains("libraries"))
|
||||
{
|
||||
for (auto libVal : requireArray(root.value("libraries")))
|
||||
{
|
||||
auto libObj = requireObject(libVal);
|
||||
|
||||
auto lib = MojangVersionFormat::libraryFromJson(libObj, filename);
|
||||
out->libraries.append(lib);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObject& out)
|
||||
{
|
||||
writeString(out, "id", in->minecraftVersion);
|
||||
writeString(out, "mainClass", in->mainClass);
|
||||
writeString(out, "minecraftArguments", in->minecraftArguments);
|
||||
writeString(out, "type", in->type);
|
||||
if(!in->releaseTime.isNull())
|
||||
{
|
||||
writeString(out, "releaseTime", timeToS3Time(in->releaseTime));
|
||||
}
|
||||
if(!in->updateTime.isNull())
|
||||
{
|
||||
writeString(out, "time", timeToS3Time(in->updateTime));
|
||||
}
|
||||
if(in->minimumLauncherVersion != -1)
|
||||
{
|
||||
out.insert("minimumLauncherVersion", in->minimumLauncherVersion);
|
||||
}
|
||||
writeString(out, "assets", in->assets);
|
||||
if(in->mojangAssetIndex && in->mojangAssetIndex->known)
|
||||
{
|
||||
out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
|
||||
}
|
||||
if(in->mojangDownloads.size())
|
||||
{
|
||||
QJsonObject downloadsOut;
|
||||
for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
|
||||
{
|
||||
downloadsOut.insert(iter.key(), downloadInfoToJson(iter.value()));
|
||||
}
|
||||
out.insert("downloads", downloadsOut);
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch)
|
||||
{
|
||||
QJsonObject root;
|
||||
writeVersionProperties(patch.get(), root);
|
||||
if (!patch->libraries.isEmpty())
|
||||
{
|
||||
QJsonArray array;
|
||||
for (auto value: patch->libraries)
|
||||
{
|
||||
array.append(MojangVersionFormat::libraryToJson(value.get()));
|
||||
}
|
||||
root.insert("libraries", array);
|
||||
}
|
||||
|
||||
// write the contents to a json document.
|
||||
{
|
||||
QJsonDocument out;
|
||||
out.setObject(root);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
LibraryPtr MojangVersionFormat::libraryFromJson(const QJsonObject &libObj, const QString &filename)
|
||||
{
|
||||
LibraryPtr out(new Library());
|
||||
if (!libObj.contains("name"))
|
||||
{
|
||||
throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field");
|
||||
}
|
||||
out->m_name = libObj.value("name").toString();
|
||||
|
||||
Bits::readString(libObj, "url", out->m_repositoryURL);
|
||||
if (libObj.contains("extract"))
|
||||
{
|
||||
out->m_hasExcludes = true;
|
||||
auto extractObj = requireObject(libObj.value("extract"));
|
||||
for (auto excludeVal : requireArray(extractObj.value("exclude")))
|
||||
{
|
||||
out->m_extractExcludes.append(requireString(excludeVal));
|
||||
}
|
||||
}
|
||||
if (libObj.contains("natives"))
|
||||
{
|
||||
QJsonObject nativesObj = requireObject(libObj.value("natives"));
|
||||
for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
|
||||
{
|
||||
if (!it.value().isString())
|
||||
{
|
||||
qWarning() << filename << "contains an invalid native (skipping)";
|
||||
}
|
||||
OpSys opSys = OpSys_fromString(it.key());
|
||||
if (opSys != Os_Other)
|
||||
{
|
||||
out->m_nativeClassifiers[opSys] = it.value().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (libObj.contains("rules"))
|
||||
{
|
||||
out->applyRules = true;
|
||||
out->m_rules = rulesFromJsonV4(libObj);
|
||||
}
|
||||
if (libObj.contains("downloads"))
|
||||
{
|
||||
out->m_mojangDownloads = libDownloadInfoFromJson(libObj);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject MojangVersionFormat::libraryToJson(Library *library)
|
||||
{
|
||||
QJsonObject libRoot;
|
||||
libRoot.insert("name", (QString)library->m_name);
|
||||
if (!library->m_repositoryURL.isEmpty())
|
||||
{
|
||||
libRoot.insert("url", library->m_repositoryURL);
|
||||
}
|
||||
if (library->isNative())
|
||||
{
|
||||
QJsonObject nativeList;
|
||||
auto iter = library->m_nativeClassifiers.begin();
|
||||
while (iter != library->m_nativeClassifiers.end())
|
||||
{
|
||||
nativeList.insert(OpSys_toString(iter.key()), iter.value());
|
||||
iter++;
|
||||
}
|
||||
libRoot.insert("natives", nativeList);
|
||||
if (library->m_extractExcludes.size())
|
||||
{
|
||||
QJsonArray excludes;
|
||||
QJsonObject extract;
|
||||
for (auto exclude : library->m_extractExcludes)
|
||||
{
|
||||
excludes.append(exclude);
|
||||
}
|
||||
extract.insert("exclude", excludes);
|
||||
libRoot.insert("extract", extract);
|
||||
}
|
||||
}
|
||||
if (library->m_rules.size())
|
||||
{
|
||||
QJsonArray allRules;
|
||||
for (auto &rule : library->m_rules)
|
||||
{
|
||||
QJsonObject ruleObj = rule->toJson();
|
||||
allRules.append(ruleObj);
|
||||
}
|
||||
libRoot.insert("rules", allRules);
|
||||
}
|
||||
if(library->m_mojangDownloads)
|
||||
{
|
||||
auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads);
|
||||
libRoot.insert("downloads", downloadsObj);
|
||||
}
|
||||
return libRoot;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <minecraft/VersionFile.h>
|
||||
#include <minecraft/Library.h>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT MojangVersionFormat
|
||||
{
|
||||
friend class OneSixVersionFormat;
|
||||
protected:
|
||||
// does not include libraries
|
||||
static void readVersionProperties(const QJsonObject& in, VersionFile* out);
|
||||
// does not include libraries
|
||||
static void writeVersionProperties(const VersionFile* in, QJsonObject& out);
|
||||
public:
|
||||
// version files / profile patches
|
||||
static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename);
|
||||
static QJsonDocument versionFileToJson(const VersionFilePtr &patch);
|
||||
|
||||
// libraries
|
||||
static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
|
||||
static QJsonObject libraryToJson(Library *library);
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
#include <QTest>
|
||||
#include <QDebug>
|
||||
#include "TestUtil.h"
|
||||
|
||||
#include "minecraft/MojangVersionFormat.h"
|
||||
|
||||
class MojangVersionFormatTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
static QJsonDocument readJson(const char *file)
|
||||
{
|
||||
auto path = QFINDTESTDATA(file);
|
||||
QFile jsonFile(path);
|
||||
jsonFile.open(QIODevice::ReadOnly);
|
||||
auto data = jsonFile.readAll();
|
||||
jsonFile.close();
|
||||
return QJsonDocument::fromJson(data);
|
||||
}
|
||||
static void writeJson(const char *file, QJsonDocument doc)
|
||||
{
|
||||
QFile jsonFile(file);
|
||||
jsonFile.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
auto data = doc.toJson(QJsonDocument::Indented);
|
||||
qDebug() << QString::fromUtf8(data);
|
||||
jsonFile.write(data);
|
||||
jsonFile.close();
|
||||
}
|
||||
|
||||
private
|
||||
slots:
|
||||
void test_Through_Simple()
|
||||
{
|
||||
QJsonDocument doc = readJson("data/1.9-simple.json");
|
||||
auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9-simple.json");
|
||||
auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
|
||||
writeJson("1.9-simple-passthorugh.json", doc2);
|
||||
|
||||
QCOMPARE(doc.toJson(), doc2.toJson());
|
||||
}
|
||||
|
||||
void test_Through()
|
||||
{
|
||||
QJsonDocument doc = readJson("data/1.9.json");
|
||||
auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9.json");
|
||||
auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
|
||||
writeJson("1.9-passthorugh.json", doc2);
|
||||
QCOMPARE(doc.toJson(), doc2.toJson());
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(MojangVersionFormatTest)
|
||||
|
||||
#include "MojangVersionFormat_test.moc"
|
||||
|
||||
@@ -1,21 +1,167 @@
|
||||
#include "OneSixVersionFormat.h"
|
||||
#include <Json.h>
|
||||
#include "minecraft/ParseUtils.h"
|
||||
#include <minecraft/MojangVersionFormat.h>
|
||||
|
||||
class MojangVersionFormat
|
||||
{
|
||||
friend class OneSixVersionFormat;
|
||||
protected:
|
||||
// does not include libraries
|
||||
static void readVersionProperties(const QJsonObject& in, VersionFile* out);
|
||||
// does not include libraries
|
||||
static void writeVersionProperties(const VersionFile* in, QJsonObject& out);
|
||||
public:
|
||||
// libraries
|
||||
static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
|
||||
static QJsonObject libraryToJson(Library *library);
|
||||
};
|
||||
|
||||
|
||||
using namespace Json;
|
||||
|
||||
static void readString(const QJsonObject &root, const QString &key, QString &variable)
|
||||
static const int CURRENT_MINIMUM_LAUNCHER_VERSION = 18;
|
||||
|
||||
namespace
|
||||
{
|
||||
void readString(const QJsonObject &root, const QString &key, QString &variable)
|
||||
{
|
||||
if (root.contains(key))
|
||||
{
|
||||
variable = requireString(root.value(key));
|
||||
}
|
||||
}
|
||||
|
||||
void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj)
|
||||
{
|
||||
// optional, not used
|
||||
readString(obj, "path", out->path);
|
||||
// required!
|
||||
out->sha1 = requireString(obj, "sha1");
|
||||
out->url = ensureString(obj, "url", QString());
|
||||
out->size = requireInteger(obj, "size");
|
||||
}
|
||||
|
||||
void readAssetIndex(MojangAssetIndexInfo::Ptr out, const QJsonObject &obj)
|
||||
{
|
||||
out->totalSize = requireInteger(obj, "totalSize");
|
||||
out->id = requireString(obj, "id");
|
||||
// out->known = true;
|
||||
}
|
||||
|
||||
MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject &obj)
|
||||
{
|
||||
auto out = std::make_shared<MojangAssetIndexInfo>();
|
||||
::readDownloadInfo(out, obj);
|
||||
::readAssetIndex(out, obj);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(!info->path.isNull())
|
||||
{
|
||||
out.insert("path", info->path);
|
||||
}
|
||||
out.insert("sha1", info->sha1);
|
||||
out.insert("size", info->size);
|
||||
out.insert("url", info->url);
|
||||
out.insert("totalSize", info->totalSize);
|
||||
out.insert("id", info->id);
|
||||
return out;
|
||||
}
|
||||
|
||||
MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject &obj)
|
||||
{
|
||||
auto out = std::make_shared<MojangDownloadInfo>();
|
||||
::readDownloadInfo(out, obj);
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(!info->path.isNull())
|
||||
{
|
||||
out.insert("path", info->path);
|
||||
}
|
||||
out.insert("sha1", info->sha1);
|
||||
out.insert("size", info->size);
|
||||
out.insert("url", info->url);
|
||||
return out;
|
||||
}
|
||||
|
||||
MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject &libObj)
|
||||
{
|
||||
auto out = std::make_shared<MojangLibraryDownloadInfo>();
|
||||
auto dlObj = requireObject(libObj.value("downloads"));
|
||||
if(dlObj.contains("artifact"))
|
||||
{
|
||||
out->artifact = downloadInfoFromJson(requireObject(dlObj, "artifact"));
|
||||
}
|
||||
if(dlObj.contains("classifiers"))
|
||||
{
|
||||
auto classifiersObj = requireObject(dlObj, "classifiers");
|
||||
for(auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++)
|
||||
{
|
||||
auto classifier = iter.key();
|
||||
auto classifierObj = requireObject(iter.value());
|
||||
out->classifiers[classifier] = downloadInfoFromJson(classifierObj);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const QString &filename)
|
||||
{
|
||||
LibraryPtr out = MojangVersionFormat::libraryFromJson(libObj, filename);
|
||||
LibraryPtr out(new Library());
|
||||
if (!libObj.contains("name"))
|
||||
{
|
||||
throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field");
|
||||
}
|
||||
out->m_name = libObj.value("name").toString();
|
||||
|
||||
::readString(libObj, "url", out->m_repositoryURL);
|
||||
if (libObj.contains("extract"))
|
||||
{
|
||||
out->m_hasExcludes = true;
|
||||
auto extractObj = requireObject(libObj.value("extract"));
|
||||
for (auto excludeVal : requireArray(extractObj.value("exclude")))
|
||||
{
|
||||
out->m_extractExcludes.append(requireString(excludeVal));
|
||||
}
|
||||
}
|
||||
if (libObj.contains("natives"))
|
||||
{
|
||||
QJsonObject nativesObj = requireObject(libObj.value("natives"));
|
||||
for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
|
||||
{
|
||||
if (!it.value().isString())
|
||||
{
|
||||
qWarning() << filename << "contains an invalid native (skipping)";
|
||||
}
|
||||
OpSys opSys = OpSys_fromString(it.key());
|
||||
if (opSys != Os_Other)
|
||||
{
|
||||
out->m_nativeClassifiers[opSys] = it.value().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (libObj.contains("rules"))
|
||||
{
|
||||
out->applyRules = true;
|
||||
out->m_rules = rulesFromJsonV4(libObj);
|
||||
}
|
||||
if (libObj.contains("downloads"))
|
||||
{
|
||||
out->m_mojangDownloads = libDownloadInfoFromJson(libObj);
|
||||
}
|
||||
|
||||
readString(libObj, "MMC-hint", out->m_hint);
|
||||
readString(libObj, "MMC-absulute_url", out->m_absoluteURL);
|
||||
readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL);
|
||||
@@ -24,20 +170,155 @@ LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo)
|
||||
{
|
||||
QJsonObject out;
|
||||
if(libinfo->artifact)
|
||||
{
|
||||
out.insert("artifact", downloadInfoToJson(libinfo->artifact));
|
||||
}
|
||||
if(libinfo->classifiers.size())
|
||||
{
|
||||
QJsonObject classifiersOut;
|
||||
for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
|
||||
{
|
||||
classifiersOut.insert(iter.key(), downloadInfoToJson(iter.value()));
|
||||
}
|
||||
out.insert("classifiers", classifiersOut);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
QJsonObject OneSixVersionFormat::libraryToJson(Library *library)
|
||||
{
|
||||
QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
|
||||
if (library->m_absoluteURL.size())
|
||||
QJsonObject libRoot;
|
||||
libRoot.insert("name", (QString)library->m_name);
|
||||
if (!library->m_repositoryURL.isEmpty())
|
||||
{
|
||||
libRoot.insert("url", library->m_repositoryURL);
|
||||
}
|
||||
if (library->isNative())
|
||||
{
|
||||
QJsonObject nativeList;
|
||||
auto iter = library->m_nativeClassifiers.begin();
|
||||
while (iter != library->m_nativeClassifiers.end())
|
||||
{
|
||||
nativeList.insert(OpSys_toString(iter.key()), iter.value());
|
||||
iter++;
|
||||
}
|
||||
libRoot.insert("natives", nativeList);
|
||||
if (library->m_extractExcludes.size())
|
||||
{
|
||||
QJsonArray excludes;
|
||||
QJsonObject extract;
|
||||
for (auto exclude : library->m_extractExcludes)
|
||||
{
|
||||
excludes.append(exclude);
|
||||
}
|
||||
extract.insert("exclude", excludes);
|
||||
libRoot.insert("extract", extract);
|
||||
}
|
||||
}
|
||||
if (library->m_rules.size())
|
||||
{
|
||||
QJsonArray allRules;
|
||||
for (auto &rule : library->m_rules)
|
||||
{
|
||||
QJsonObject ruleObj = rule->toJson();
|
||||
allRules.append(ruleObj);
|
||||
}
|
||||
libRoot.insert("rules", allRules);
|
||||
}
|
||||
if(library->m_mojangDownloads)
|
||||
{
|
||||
auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads);
|
||||
libRoot.insert("downloads", downloadsObj);
|
||||
}
|
||||
|
||||
// MultiMC extensions
|
||||
if (library->m_absoluteURL.size()) {
|
||||
libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
|
||||
if (library->m_hint.size())
|
||||
}
|
||||
if (library->m_hint.size()) {
|
||||
libRoot.insert("MMC-hint", library->m_hint);
|
||||
if (library->m_filename.size())
|
||||
}
|
||||
if (library->m_filename.size()) {
|
||||
libRoot.insert("MMC-filename", library->m_filename);
|
||||
if (library->m_displayname.size())
|
||||
}
|
||||
if (library->m_displayname.size()) {
|
||||
libRoot.insert("MMC-displayname", library->m_displayname);
|
||||
}
|
||||
|
||||
return libRoot;
|
||||
}
|
||||
|
||||
void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFile *out)
|
||||
{
|
||||
::readString(in, "id", out->minecraftVersion);
|
||||
::readString(in, "mainClass", out->mainClass);
|
||||
::readString(in, "minecraftArguments", out->minecraftArguments);
|
||||
if(out->minecraftArguments.isEmpty())
|
||||
{
|
||||
QString processArguments;
|
||||
::readString(in, "processArguments", processArguments);
|
||||
QString toCompare = processArguments.toLower();
|
||||
if (toCompare == "legacy")
|
||||
{
|
||||
out->minecraftArguments = " ${auth_player_name} ${auth_session}";
|
||||
}
|
||||
else if (toCompare == "username_session")
|
||||
{
|
||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
|
||||
}
|
||||
else if (toCompare == "username_session_version")
|
||||
{
|
||||
out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
|
||||
}
|
||||
else if (!toCompare.isEmpty())
|
||||
{
|
||||
out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
|
||||
}
|
||||
}
|
||||
::readString(in, "type", out->type);
|
||||
|
||||
::readString(in, "assets", out->assets);
|
||||
if(in.contains("assetIndex"))
|
||||
{
|
||||
out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex"));
|
||||
}
|
||||
else if (!out->assets.isNull())
|
||||
{
|
||||
out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets);
|
||||
}
|
||||
|
||||
out->releaseTime = timeFromS3Time(in.value("releaseTime").toString(""));
|
||||
out->updateTime = timeFromS3Time(in.value("time").toString(""));
|
||||
|
||||
if (in.contains("minimumLauncherVersion"))
|
||||
{
|
||||
out->minimumLauncherVersion = requireInteger(in.value("minimumLauncherVersion"));
|
||||
if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
|
||||
{
|
||||
out->addProblem(
|
||||
ProblemSeverity::Warning,
|
||||
QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!")
|
||||
.arg(out->minimumLauncherVersion)
|
||||
.arg(CURRENT_MINIMUM_LAUNCHER_VERSION)
|
||||
);
|
||||
}
|
||||
}
|
||||
if(in.contains("downloads"))
|
||||
{
|
||||
auto downloadsObj = requireObject(in, "downloads");
|
||||
for(auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++)
|
||||
{
|
||||
auto classifier = iter.key();
|
||||
auto classifierObj = requireObject(iter.value());
|
||||
out->mojangDownloads[classifier] = downloadInfoFromJson(classifierObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder)
|
||||
{
|
||||
VersionFilePtr out(new VersionFile());
|
||||
@@ -144,14 +425,14 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
}
|
||||
}
|
||||
|
||||
auto readLibs = [&](const char * which, QList<LibraryPtr> & out)
|
||||
auto readLibs = [&](const char * which)
|
||||
{
|
||||
for (auto libVal : requireArray(root.value(which)))
|
||||
{
|
||||
QJsonObject libObj = requireObject(libVal);
|
||||
// parse the library
|
||||
auto lib = libraryFromJson(libObj, filename);
|
||||
out.append(lib);
|
||||
out->libraries.append(lib);
|
||||
}
|
||||
};
|
||||
bool hasPlusLibs = root.contains("+libraries");
|
||||
@@ -160,27 +441,31 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
{
|
||||
out->addProblem(ProblemSeverity::Warning,
|
||||
QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
|
||||
readLibs("libraries", out->libraries);
|
||||
readLibs("+libraries", out->libraries);
|
||||
readLibs("libraries");
|
||||
readLibs("+libraries");
|
||||
}
|
||||
else if (hasLibs)
|
||||
{
|
||||
readLibs("libraries", out->libraries);
|
||||
readLibs("libraries");
|
||||
}
|
||||
else if(hasPlusLibs)
|
||||
{
|
||||
readLibs("+libraries", out->libraries);
|
||||
}
|
||||
|
||||
if(root.contains("mavenFiles")) {
|
||||
readLibs("mavenFiles", out->mavenFiles);
|
||||
readLibs("+libraries");
|
||||
}
|
||||
|
||||
// if we have mainJar, just use it
|
||||
if(root.contains("mainJar"))
|
||||
{
|
||||
QJsonObject libObj = requireObject(root, "mainJar");
|
||||
out->mainJar = libraryFromJson(libObj, filename);
|
||||
auto val = root.value("mainJar");
|
||||
if(val.isNull())
|
||||
{
|
||||
out->removeMainJar = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonObject libObj = requireObject(root, "mainJar");
|
||||
out->mainJar = libraryFromJson(libObj, filename);
|
||||
}
|
||||
}
|
||||
// else reconstruct it from downloads and id ... if that's available
|
||||
else if(!out->minecraftVersion.isEmpty())
|
||||
@@ -198,10 +483,7 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
// FIXME: this will eventually break...
|
||||
else
|
||||
{
|
||||
out->addProblem(
|
||||
ProblemSeverity::Error,
|
||||
QObject::tr("URL for the main jar could not be determined - Mojang removed the server that we used as fallback.")
|
||||
);
|
||||
lib->setAbsoluteUrl(URLConstants::getLegacyJarUrl(out->minecraftVersion));
|
||||
}
|
||||
out->mainJar = lib;
|
||||
}
|
||||
@@ -254,6 +536,40 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
|
||||
return out;
|
||||
}
|
||||
|
||||
void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObject& out)
|
||||
{
|
||||
writeString(out, "id", in->minecraftVersion);
|
||||
writeString(out, "mainClass", in->mainClass);
|
||||
writeString(out, "minecraftArguments", in->minecraftArguments);
|
||||
writeString(out, "type", in->type);
|
||||
if(!in->releaseTime.isNull())
|
||||
{
|
||||
writeString(out, "releaseTime", timeToS3Time(in->releaseTime));
|
||||
}
|
||||
if(!in->updateTime.isNull())
|
||||
{
|
||||
writeString(out, "time", timeToS3Time(in->updateTime));
|
||||
}
|
||||
if(in->minimumLauncherVersion != -1)
|
||||
{
|
||||
out.insert("minimumLauncherVersion", in->minimumLauncherVersion);
|
||||
}
|
||||
writeString(out, "assets", in->assets);
|
||||
if(in->mojangAssetIndex && in->mojangAssetIndex->known)
|
||||
{
|
||||
out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
|
||||
}
|
||||
if(in->mojangDownloads.size())
|
||||
{
|
||||
QJsonObject downloadsOut;
|
||||
for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
|
||||
{
|
||||
downloadsOut.insert(iter.key(), downloadInfoToJson(iter.value()));
|
||||
}
|
||||
out.insert("downloads", downloadsOut);
|
||||
}
|
||||
}
|
||||
|
||||
QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch)
|
||||
{
|
||||
QJsonObject root;
|
||||
@@ -271,6 +587,10 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
|
||||
{
|
||||
root.insert("mainJar", libraryToJson(patch->mainJar.get()));
|
||||
}
|
||||
else if(patch->removeMainJar)
|
||||
{
|
||||
root.insert("mainJar", QJsonValue());
|
||||
}
|
||||
writeString(root, "appletClass", patch->appletClass);
|
||||
writeStringList(root, "+tweakers", patch->addTweakers);
|
||||
writeStringList(root, "+traits", patch->traits.toList());
|
||||
@@ -283,15 +603,6 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
|
||||
}
|
||||
root.insert("libraries", array);
|
||||
}
|
||||
if (!patch->mavenFiles.isEmpty())
|
||||
{
|
||||
QJsonArray array;
|
||||
for (auto value: patch->mavenFiles)
|
||||
{
|
||||
array.append(OneSixVersionFormat::libraryToJson(value.get()));
|
||||
}
|
||||
root.insert("mavenFiles", array);
|
||||
}
|
||||
if (!patch->jarMods.isEmpty())
|
||||
{
|
||||
QJsonArray array;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user