Compare commits

..

1 Commits

Author SHA1 Message Date
Petr Mrázek
7f26fff8d0 NOISSUE Update libnbtplusplus 2019-07-13 23:41:09 +02:00
464 changed files with 15111 additions and 12868 deletions

5
.arcconfig Normal file
View File

@@ -0,0 +1,5 @@
{
"project_id": "MultiMC5",
"conduit_uri": "http://ph.multimc.org"
}

25
.clang-format Normal file
View 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
View 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:
---------------------------

View File

@@ -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

View File

@@ -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.

View File

@@ -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
View File

@@ -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
View 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"

View File

@@ -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))!**

View File

@@ -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 6)
# 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)

View File

@@ -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.

View File

@@ -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 [![Build Status](https://travis-ci.org/MultiMC/MultiMC5.svg?branch=develop)](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). 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 &copy; 2013-2021 MultiMC Contributors
Copyright &copy; 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>

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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
)
@@ -211,10 +213,8 @@ set(MINECRAFT_SOURCES
minecraft/auth/flows/RefreshTask.cpp
minecraft/auth/flows/ValidateTask.h
minecraft/auth/flows/ValidateTask.cpp
minecraft/gameoptions/GameOptions.h
minecraft/gameoptions/GameOptions.cpp
minecraft/update/AssetUpdateTask.h
minecraft/update/AssetUpdateTask.cpp
minecraft/update/FMLLibrariesTask.cpp
@@ -223,11 +223,10 @@ set(MINECRAFT_SOURCES
minecraft/update/FoldersTask.h
minecraft/update/LibrariesTask.cpp
minecraft/update/LibrariesTask.h
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
@@ -240,16 +239,12 @@ set(MINECRAFT_SOURCES
minecraft/launch/PrintInstanceInfo.h
minecraft/launch/ReconstructAssets.cpp
minecraft/launch/ReconstructAssets.h
minecraft/launch/ScanModFolders.cpp
minecraft/launch/ScanModFolders.h
minecraft/legacy/LegacyModList.h
minecraft/legacy/LegacyModList.cpp
minecraft/legacy/LegacyInstance.h
minecraft/legacy/LegacyInstance.cpp
minecraft/legacy/LegacyUpgradeTask.h
minecraft/legacy/LegacyUpgradeTask.cpp
minecraft/GradleSpecifier.h
minecraft/MinecraftInstance.cpp
minecraft/MinecraftInstance.h
@@ -257,8 +252,8 @@ 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
@@ -284,33 +279,26 @@ set(MINECRAFT_SOURCES
minecraft/VersionFile.h
minecraft/VersionFilterData.h
minecraft/VersionFilterData.cpp
minecraft/Mod.h
minecraft/Mod.cpp
minecraft/SimpleModList.h
minecraft/SimpleModList.cpp
minecraft/World.h
minecraft/World.cpp
minecraft/WorldList.h
minecraft/WorldList.cpp
minecraft/mod/Mod.h
minecraft/mod/Mod.cpp
minecraft/mod/ModDetails.h
minecraft/mod/ModFolderModel.h
minecraft/mod/ModFolderModel.cpp
minecraft/mod/ModFolderLoadTask.h
minecraft/mod/ModFolderLoadTask.cpp
minecraft/mod/LocalModParseTask.h
minecraft/mod/LocalModParseTask.cpp
# Assets
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,22 +306,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
@@ -346,8 +318,8 @@ add_unit_test(Library
)
# FIXME: shares data with FileSystem test
add_unit_test(ModFolderModel
SOURCES minecraft/mod/ModFolderModel_test.cpp
add_unit_test(SimpleModList
SOURCES minecraft/SimpleModList_test.cpp
DATA testdata
LIBS MultiMC_logic
)
@@ -454,14 +426,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 +443,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,18 +477,17 @@ set(LOGIC_SOURCES
${ICONS_SOURCES}
${FTB_SOURCES}
${FLAME_SOURCES}
${MODPACKSCH_SOURCES}
${TECHNIC_SOURCES}
${ATLAUNCHER_SOURCES}
)
message(STATUS "FOO! ${LOGIC_SOURCES}")
add_library(MultiMC_logic SHARED ${LOGIC_SOURCES})
set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
generate_export_header(MultiMC_logic)
# Link
target_link_libraries(MultiMC_logic 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

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors
/* Copyright 2013-2019 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*

View File

@@ -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

View File

@@ -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;
}

View File

@@ -174,11 +174,6 @@ bool copy::operator()(const QString &offset)
bool deletePath(QString path)
{
bool OK = true;
QFileInfo finfo(path);
if(finfo.isFile()) {
return QFile::remove(path);
}
QDir dir(path);
if (!dir.exists())
@@ -299,7 +294,7 @@ QString NormalizePath(QString path)
}
}
QString badFilenameChars = "\"\\/?<>:;*|!+\r\n";
QString badFilenameChars = "\"\\/?<>:*|!+\r\n";
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
{

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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!!!

View File

@@ -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;
};

View File

@@ -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.
@@ -100,10 +100,6 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
{
return pdata->name();
}
case Qt::AccessibleTextRole:
{
return tr("%1 Instance").arg(pdata->name());
}
case Qt::ToolTipRole:
{
return pdata->instanceRoot();
@@ -160,8 +156,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 +174,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 +186,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 +200,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 +213,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 +229,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 +238,7 @@ void InstanceList::deleteInstance(const InstanceId& id)
return;
}
if(m_instanceGroupIndex.remove(id))
if(m_groupMap.remove(id))
{
saveGroupList();
}
@@ -520,7 +511,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 +544,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 +568,7 @@ void InstanceList::saveGroupList()
void InstanceList::loadGroupList()
{
qDebug() << "Will load group list now.";
QSet<QString> groupSet;
QString groupFileName = m_instDir + "/instgroups.json";
@@ -627,8 +619,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 +630,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 +685,6 @@ void InstanceList::on_InstFolderChanged(const Setting &setting, QVariant value)
}
}
void InstanceList::on_GroupStateChanged(const QString& group, bool collapsed)
{
qDebug() << "Group" << group << (collapsed ? "collapsed" : "expanded");
if(collapsed) {
m_collapsedGroups.insert(group);
} else {
m_collapsedGroups.remove(group);
}
saveGroupList();
}
class InstanceStaging : public Task
{
Q_OBJECT
@@ -833,9 +815,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);
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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,13 +18,12 @@
#include <QString>
#include <QFileInfo>
#include <QSet>
#include "minecraft/mod/Mod.h"
#include "minecraft/Mod.h"
#include <functional>
#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);
}

View File

@@ -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));
}

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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);
}
}
}

View File

@@ -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:

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors
/* Copyright 2013-2019 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2021 MultiMC Contributors
/* Copyright 2013-2019 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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()

View File

@@ -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.

View File

@@ -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;

View File

@@ -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

View File

@@ -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,21 @@
#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_saveTimer, &QTimer::timeout, this, &ComponentList::save_internal);
}
PackProfile::~PackProfile()
ComponentList::~ComponentList()
{
saveNow();
}
@@ -97,7 +95,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 +118,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 +151,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 +208,7 @@ static bool loadPackProfile(PackProfile * parent, const QString & filename, cons
// BEGIN: save/load logic
void PackProfile::saveNow()
void ComponentList::saveNow()
{
if(saveIsScheduled())
{
@@ -219,18 +217,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 +243,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 +284,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 +296,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 +307,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 +317,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 +337,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 +429,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 +596,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 +623,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 +650,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 +677,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 +691,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 +709,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 +727,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 +737,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 +746,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();
@@ -767,9 +765,8 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const
{
switch (column)
{
case NameColumn: {
return patch->isEnabled() ? Qt::Checked : Qt::Unchecked;
}
case NameColumn:
return d->components.at(row)->isEnabled() ? Qt::Checked : Qt::Unchecked;
default:
return QVariant();
}
@@ -779,7 +776,7 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const
switch (column)
{
case NameColumn:
return patch->getName();
return d->components.at(row)->getName();
case VersionColumn:
{
if(patch->isCustom())
@@ -822,7 +819,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 +837,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)
{
@@ -859,42 +856,38 @@ QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int r
}
return QVariant();
}
// FIXME: zero precision mess
Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const
Qt::ItemFlags ComponentList::flags(const QModelIndex &index) const
{
if (!index.isValid()) {
if (!index.isValid())
return Qt::NoItemFlags;
}
Qt::ItemFlags outFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
int row = index.row();
if (row < 0 || row >= d->components.size()) {
if (row < 0 || row >= d->components.size())
return Qt::NoItemFlags;
}
auto patch = d->components.at(row);
// TODO: this will need fine-tuning later...
if(patch->canBeDisabled() && !d->interactionDisabled)
if(patch->canBeDisabled())
{
outFlags |= Qt::ItemIsUserCheckable;
}
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 +923,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 +966,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
@@ -1023,7 +1016,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 +1078,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 +1139,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 +1161,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 +1170,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 +1196,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())
@@ -1212,14 +1205,3 @@ QString PackProfile::getComponentVersion(const QString& uid) const
}
return QString();
}
void PackProfile::disableInteraction(bool disable)
{
if(d->interactionDisabled != disable) {
d->interactionDisabled = disable;
auto size = d->components.size();
if(size) {
emit dataChanged(index(0), index(size - 1));
}
}
}

View File

@@ -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);
@@ -136,7 +134,6 @@ private slots:
void updateSucceeded();
void updateFailed(const QString & error);
void componentDataChanged();
void disableInteraction(bool disable);
private:
bool load();
@@ -148,5 +145,5 @@ private:
private: /* data */
std::unique_ptr<PackProfileData> d;
std::unique_ptr<ComponentListData> d;
};

View File

@@ -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;
@@ -37,6 +38,5 @@ struct PackProfileData
QTimer m_saveTimer;
shared_qobject_ptr<Task> m_updateTask;
bool loaded = false;
bool interactionDisabled = true;
};

View File

@@ -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();
}

View File

@@ -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:

View File

@@ -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;

View File

@@ -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,22 +157,6 @@ 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;
@@ -270,11 +253,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,

View File

@@ -20,7 +20,6 @@ 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 applyProblemSeverity(ProblemSeverity severity);
/// clear the profile
@@ -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)

View File

@@ -3,9 +3,9 @@
#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,
@@ -88,19 +88,26 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
{
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 +179,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('/'))
@@ -236,6 +243,11 @@ bool Library::isAlwaysStale() const
return m_hint == "always-stale";
}
bool Library::isForge() const
{
return m_hint == "forge-pack-xz";
}
void Library::setStoragePrefix(QString prefix)
{
m_storagePrefix = prefix;

View File

@@ -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"

View File

@@ -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>
@@ -21,24 +21,22 @@
#include "minecraft/launch/ModMinecraftJar.h"
#include "minecraft/launch/ClaimAccount.h"
#include "minecraft/launch/ReconstructAssets.h"
#include "minecraft/launch/ScanModFolders.h"
#include "java/launch/CheckJava.h"
#include "java/JavaUtils.h"
#include "meta/Index.h"
#include "meta/VersionList.h"
#include "mod/ModFolderModel.h"
#include "SimpleModList.h"
#include "WorldList.h"
#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 +99,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 +123,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 +264,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();
@@ -557,38 +550,37 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session)
out << "";
}
auto printModList = [&](const QString & label, ModFolderModel & model) {
if(model.size())
if(loaderModList()->size())
{
out << "Mods:";
for(auto & mod: loaderModList()->allMods())
{
out << QString("%1:").arg(label);
auto modList = model.allMods();
std::sort(modList.begin(), modList.end(), [](Mod &a, Mod &b) {
auto aName = a.filename().completeBaseName();
auto bName = b.filename().completeBaseName();
return aName.localeAwareCompare(bName) < 0;
});
for(auto & mod: modList)
{
if(mod.type() == Mod::MOD_FOLDER)
{
out << u8" [📁] " + mod.filename().completeBaseName() + " (folder)";
continue;
}
if(!mod.enabled())
continue;
if(mod.type() == Mod::MOD_FOLDER)
continue;
// TODO: proper implementation would need to descend into folders.
if(mod.enabled()) {
out << u8" [✔️] " + mod.filename().completeBaseName();
}
else {
out << u8" [❌] " + mod.filename().completeBaseName() + " (disabled)";
}
}
out << "";
out << " " + mod.filename().completeBaseName();
}
};
out << "";
}
printModList("Mods", *(loaderModList().get()));
printModList("Core Mods", *(coreModList().get()));
if(coreModList()->size())
{
out << "Core Mods:";
for(auto & coremod: coreModList()->allMods())
{
if(!coremod.enabled())
continue;
if(coremod.type() == Mod::MOD_FOLDER)
continue;
// TODO: proper implementation would need to descend into folders.
out << " " + coremod.filename().completeBaseName();
}
out << "";
}
auto & jarMods = profile->getJarMods();
if(jarMods.size())
@@ -811,11 +803,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,16 +827,16 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
process->appendStep(new ModMinecraftJar(pptr));
}
// Scan mods folders for mods
{
process->appendStep(new ScanModFolders(pptr));
}
// print some instance info here...
{
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));
@@ -905,47 +892,43 @@ JavaVersion MinecraftInstance::getJavaVersion() const
return JavaVersion(settings()->get("JavaVersion").toString());
}
std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList() const
std::shared_ptr<SimpleModList> MinecraftInstance::loaderModList() const
{
if (!m_loader_mod_list)
{
m_loader_mod_list.reset(new ModFolderModel(loaderModsDir()));
m_loader_mod_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction);
m_loader_mod_list.reset(new SimpleModList(loaderModsDir()));
}
m_loader_mod_list->update();
return m_loader_mod_list;
}
std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
std::shared_ptr<SimpleModList> MinecraftInstance::coreModList() const
{
if (!m_core_mod_list)
{
m_core_mod_list.reset(new ModFolderModel(coreModsDir()));
m_core_mod_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction);
m_core_mod_list.reset(new SimpleModList(coreModsDir()));
}
m_core_mod_list->update();
return m_core_mod_list;
}
std::shared_ptr<ModFolderModel> MinecraftInstance::resourcePackList() const
std::shared_ptr<SimpleModList> MinecraftInstance::resourcePackList() const
{
if (!m_resource_pack_list)
{
m_resource_pack_list.reset(new ModFolderModel(resourcePacksDir()));
m_resource_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ModFolderModel::disableInteraction);
m_resource_pack_list.reset(new SimpleModList(resourcePacksDir()));
}
m_resource_pack_list->update();
return m_resource_pack_list;
}
std::shared_ptr<ModFolderModel> MinecraftInstance::texturePackList() const
std::shared_ptr<SimpleModList> MinecraftInstance::texturePackList() const
{
if (!m_texture_pack_list)
{
m_texture_pack_list.reset(new ModFolderModel(texturePacksDir()));
m_texture_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_texture_pack_list.get(), &ModFolderModel::disableInteraction);
m_texture_pack_list.reset(new SimpleModList(texturePacksDir()));
}
m_texture_pack_list->update();
return m_texture_pack_list;
}

View File

@@ -1,16 +1,17 @@
#pragma once
#include "BaseInstance.h"
#include <java/JavaVersion.h>
#include "minecraft/mod/Mod.h"
#include "minecraft/Mod.h"
#include <QProcess>
#include <QDir>
#include "multimc_logic_export.h"
class ModFolderModel;
class ModsModel;
class SimpleModList;
class WorldList;
class GameOptions;
class LaunchStep;
class PackProfile;
class ComponentList;
class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance
{
@@ -64,13 +65,14 @@ public:
////// Profile management //////
std::shared_ptr<PackProfile> getPackProfile() const;
std::shared_ptr<ComponentList> getComponentList() const;
////// Mod Lists //////
std::shared_ptr<ModFolderModel> loaderModList() const;
std::shared_ptr<ModFolderModel> coreModList() const;
std::shared_ptr<ModFolderModel> resourcePackList() const;
std::shared_ptr<ModFolderModel> texturePackList() const;
std::shared_ptr<ModsModel> modsModel() const;
std::shared_ptr<SimpleModList> loaderModList() const;
std::shared_ptr<SimpleModList> coreModList() const;
std::shared_ptr<SimpleModList> resourcePackList() const;
std::shared_ptr<SimpleModList> texturePackList() const;
std::shared_ptr<WorldList> worldList() const;
std::shared_ptr<GameOptions> gameOptionsModel() const;
@@ -120,11 +122,12 @@ private:
QString prettifyTimeDuration(int64_t duration);
protected: // data
std::shared_ptr<PackProfile> 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;
mutable std::shared_ptr<ModFolderModel> m_texture_pack_list;
std::shared_ptr<ComponentList> m_components;
mutable std::shared_ptr<ModsModel> m_mods_model;
mutable std::shared_ptr<SimpleModList> m_loader_mod_list;
mutable std::shared_ptr<SimpleModList> m_core_mod_list;
mutable std::shared_ptr<SimpleModList> m_resource_pack_list;
mutable std::shared_ptr<SimpleModList> m_texture_pack_list;
mutable std::shared_ptr<WorldList> m_world_list;
mutable std::shared_ptr<GameOptions> m_game_options;
};

View File

@@ -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();

View File

@@ -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.

View File

@@ -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)

View File

@@ -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.

433
api/logic/minecraft/Mod.cpp Normal file
View File

@@ -0,0 +1,433 @@
/* Copyright 2013-2019 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <QDir>
#include <QString>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <quazip.h>
#include <quazipfile.h>
#include "Mod.h"
#include "settings/INIFile.h"
#include <FileSystem.h>
#include <QDebug>
Mod::Mod(const QFileInfo &file)
{
repath(file);
m_changedDateTime = file.lastModified();
}
void Mod::repath(const QFileInfo &file)
{
m_file = file;
QString name_base = file.fileName();
m_type = Mod::MOD_UNKNOWN;
if (m_file.isDir())
{
m_type = MOD_FOLDER;
m_name = name_base;
m_mmc_id = name_base;
}
else if (m_file.isFile())
{
if (name_base.endsWith(".disabled"))
{
m_enabled = false;
name_base.chop(9);
}
else
{
m_enabled = true;
}
m_mmc_id = name_base;
if (name_base.endsWith(".zip") || name_base.endsWith(".jar"))
{
m_type = MOD_ZIPFILE;
name_base.chop(4);
}
else if (name_base.endsWith(".litemod"))
{
m_type = MOD_LITEMOD;
name_base.chop(8);
}
else
{
m_type = MOD_SINGLEFILE;
}
m_name = name_base;
}
if (m_type == MOD_ZIPFILE)
{
QuaZip zip(m_file.filePath());
if (!zip.open(QuaZip::mdUnzip))
return;
QuaZipFile file(&zip);
if (zip.setCurrentFile("mcmod.info"))
{
if (!file.open(QIODevice::ReadOnly))
{
zip.close();
return;
}
ReadMCModInfo(file.readAll());
file.close();
zip.close();
return;
}
else if (zip.setCurrentFile("fabric.mod.json"))
{
if (!file.open(QIODevice::ReadOnly))
{
zip.close();
return;
}
ReadFabricModInfo(file.readAll());
file.close();
zip.close();
return;
}
else if (zip.setCurrentFile("forgeversion.properties"))
{
if (!file.open(QIODevice::ReadOnly))
{
zip.close();
return;
}
ReadForgeInfo(file.readAll());
file.close();
zip.close();
return;
}
zip.close();
}
else if (m_type == MOD_FOLDER)
{
QFileInfo mcmod_info(FS::PathCombine(m_file.filePath(), "mcmod.info"));
if (mcmod_info.isFile())
{
QFile mcmod(mcmod_info.filePath());
if (!mcmod.open(QIODevice::ReadOnly))
return;
auto data = mcmod.readAll();
if (data.isEmpty() || data.isNull())
return;
ReadMCModInfo(data);
}
}
else if (m_type == MOD_LITEMOD)
{
QuaZip zip(m_file.filePath());
if (!zip.open(QuaZip::mdUnzip))
return;
QuaZipFile file(&zip);
if (zip.setCurrentFile("litemod.json"))
{
if (!file.open(QIODevice::ReadOnly))
{
zip.close();
return;
}
ReadLiteModInfo(file.readAll());
file.close();
}
zip.close();
}
}
// NEW format
// https://github.com/MinecraftForge/FML/wiki/FML-mod-information-file/6f62b37cea040daf350dc253eae6326dd9c822c3
// OLD format:
// https://github.com/MinecraftForge/FML/wiki/FML-mod-information-file/5bf6a2d05145ec79387acc0d45c958642fb049fc
void Mod::ReadMCModInfo(QByteArray contents)
{
auto getInfoFromArray = [&](QJsonArray arr)->void
{
if (!arr.at(0).isObject())
return;
auto firstObj = arr.at(0).toObject();
m_mod_id = firstObj.value("modid").toString();
m_name = firstObj.value("name").toString();
m_version = firstObj.value("version").toString();
m_homeurl = firstObj.value("url").toString();
m_updateurl = firstObj.value("updateUrl").toString();
m_homeurl = m_homeurl.trimmed();
if(!m_homeurl.isEmpty())
{
// fix up url.
if (!m_homeurl.startsWith("http://") && !m_homeurl.startsWith("https://") &&
!m_homeurl.startsWith("ftp://"))
{
m_homeurl.prepend("http://");
}
}
m_description = firstObj.value("description").toString();
QJsonArray authors = firstObj.value("authorList").toArray();
if (authors.size() == 0)
authors = firstObj.value("authors").toArray();
if (authors.size() == 0)
m_authors = "";
else if (authors.size() >= 1)
{
m_authors = authors.at(0).toString();
for (int i = 1; i < authors.size(); i++)
{
m_authors += ", " + authors.at(i).toString();
}
}
m_credits = firstObj.value("credits").toString();
return;
}
;
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
// this is the very old format that had just the array
if (jsonDoc.isArray())
{
getInfoFromArray(jsonDoc.array());
}
else if (jsonDoc.isObject())
{
auto val = jsonDoc.object().value("modinfoversion");
if(val.isUndefined())
val = jsonDoc.object().value("modListVersion");
int version = val.toDouble();
if (version != 2)
{
qCritical() << "BAD stuff happened to mod json:";
qCritical() << contents;
return;
}
auto arrVal = jsonDoc.object().value("modlist");
if(arrVal.isUndefined())
arrVal = jsonDoc.object().value("modList");
if (arrVal.isArray())
{
getInfoFromArray(arrVal.toArray());
}
}
}
// https://fabricmc.net/wiki/documentation:fabric_mod_json
void Mod::ReadFabricModInfo(QByteArray contents)
{
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
auto object = jsonDoc.object();
auto schemaVersion = object.contains("schemaVersion") ? object.value("schemaVersion").toInt(0) : 0;
m_mod_id = object.value("id").toString();
m_version = object.value("version").toString();
m_name = object.contains("name") ? object.value("name").toString() : m_mod_id;
m_description = object.value("description").toString();
if (schemaVersion >= 1)
{
QJsonArray authors = object.value("authors").toArray();
m_authors = "";
for (int i = 0; i < authors.size(); i++)
{
QString author_name = authors.at(i).isObject()
? authors.at(i).toObject().value("name").toString()
: authors.at(i).toString();
if (i > 0)
m_authors += ", " + author_name;
else {
m_authors += author_name;
}
}
if (object.contains("contact"))
{
QJsonObject contact = object.value("contact").toObject();
if (contact.contains("homepage"))
m_homeurl = contact.value("homepage").toString();
}
}
}
void Mod::ReadForgeInfo(QByteArray contents)
{
// Read the data
m_name = "Minecraft Forge";
m_mod_id = "Forge";
m_homeurl = "http://www.minecraftforge.net/forum/";
INIFile ini;
if (!ini.loadFile(contents))
return;
QString major = ini.get("forge.major.number", "0").toString();
QString minor = ini.get("forge.minor.number", "0").toString();
QString revision = ini.get("forge.revision.number", "0").toString();
QString build = ini.get("forge.build.number", "0").toString();
m_version = major + "." + minor + "." + revision + "." + build;
}
void Mod::ReadLiteModInfo(QByteArray contents)
{
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
auto object = jsonDoc.object();
if (object.contains("name"))
{
m_mod_id = m_name = object.value("name").toString();
}
if (object.contains("version"))
{
m_version = object.value("version").toString("");
}
else
{
m_version = object.value("revision").toString("");
}
m_mcversion = object.value("mcversion").toString();
m_authors = object.value("author").toString();
m_description = object.value("description").toString();
m_homeurl = object.value("url").toString();
}
bool Mod::replace(Mod &with)
{
if (!destroy())
return false;
bool success = false;
auto t = with.type();
if (t == MOD_ZIPFILE || t == MOD_SINGLEFILE || t == MOD_LITEMOD)
{
qDebug() << "Copy: " << with.m_file.filePath() << " to " << m_file.filePath();
success = QFile::copy(with.m_file.filePath(), m_file.filePath());
}
if (t == MOD_FOLDER)
{
success = FS::copy(with.m_file.filePath(), m_file.path())();
}
if (success)
{
m_name = with.m_name;
m_mmc_id = with.m_mmc_id;
m_mod_id = with.m_mod_id;
m_version = with.m_version;
m_mcversion = with.m_mcversion;
m_description = with.m_description;
m_authors = with.m_authors;
m_credits = with.m_credits;
m_homeurl = with.m_homeurl;
m_type = with.m_type;
m_file.refresh();
}
return success;
}
bool Mod::destroy()
{
if (m_type == MOD_FOLDER)
{
QDir d(m_file.filePath());
if (d.removeRecursively())
{
m_type = MOD_UNKNOWN;
return true;
}
return false;
}
else if (m_type == MOD_SINGLEFILE || m_type == MOD_ZIPFILE || m_type == MOD_LITEMOD)
{
QFile f(m_file.filePath());
if (f.remove())
{
m_type = MOD_UNKNOWN;
return true;
}
return false;
}
return true;
}
QString Mod::version() const
{
switch (type())
{
case MOD_ZIPFILE:
case MOD_LITEMOD:
return m_version;
case MOD_FOLDER:
return "Folder";
case MOD_SINGLEFILE:
return "File";
default:
return "VOID";
}
}
bool Mod::enable(bool value)
{
if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER)
return false;
if (m_enabled == value)
return false;
QString path = m_file.absoluteFilePath();
if (value)
{
QFile foo(path);
if (!path.endsWith(".disabled"))
return false;
path.chop(9);
if (!foo.rename(path))
return false;
}
else
{
QFile foo(path);
path += ".disabled";
if (!foo.rename(path))
return false;
}
m_file = QFileInfo(path);
m_enabled = value;
return true;
}
bool Mod::operator==(const Mod &other) const
{
return mmc_id() == other.mmc_id();
}
bool Mod::strongCompare(const Mod &other) const
{
return mmc_id() == other.mmc_id() && version() == other.version() && type() == other.type();
}

View File

@@ -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.
@@ -16,16 +16,8 @@
#pragma once
#include <QFileInfo>
#include <QDateTime>
#include <QList>
#include <memory>
#include "multimc_logic_export.h"
#include "ModDetails.h"
class MULTIMC_LOGIC_EXPORT Mod
class Mod
{
public:
enum ModType
@@ -37,7 +29,6 @@ public:
MOD_LITEMOD, //!< The mod is a litemod
};
Mod() = default;
Mod(const QFileInfo &file);
QFileInfo filename() const
@@ -48,14 +39,54 @@ public:
{
return m_mmc_id;
}
QString mod_id() const
{
return m_mod_id;
}
ModType type() const
{
return m_type;
}
QString mcversion() const
{
return m_mcversion;
}
;
bool valid()
{
return m_type != MOD_UNKNOWN;
}
QString name() const
{
QString name = m_name.trimmed();
if(name.isEmpty() || name == "Example Mod")
{
return m_mmc_id;
}
return m_name;
}
QString version() const;
QString homeurl() const
{
return m_homeurl;
}
QString description() const
{
return m_description;
}
QString authors() const
{
return m_authors;
}
QString credits() const
{
return m_credits;
}
QDateTime dateTimeChanged() const
{
@@ -67,51 +98,46 @@ public:
return m_enabled;
}
const ModDetails &details() const;
QString name() const;
QString version() const;
QString homeurl() const;
QString description() const;
QStringList authors() const;
bool enable(bool value);
// delete all the files of this mod
bool destroy();
// replace this mod with a copy of the other
bool replace(Mod &with);
// change the mod's filesystem path (used by mod lists for *MAGIC* purposes)
void repath(const QFileInfo &file);
bool shouldResolve() {
return !m_resolving && !m_resolved;
}
bool isResolving() {
return m_resolving;
}
int resolutionTicket()
{
return m_resolutionTicket;
}
void setResolving(bool resolving, int resolutionTicket) {
m_resolving = resolving;
m_resolutionTicket = resolutionTicket;
}
void finishResolvingWithDetails(std::shared_ptr<ModDetails> details){
m_resolving = false;
m_resolved = true;
m_localDetails = details;
}
// WEAK compare operator - used for replacing mods
bool operator==(const Mod &other) const;
bool strongCompare(const Mod &other) const;
private:
void ReadMCModInfo(QByteArray contents);
void ReadFabricModInfo(QByteArray contents);
void ReadForgeInfo(QByteArray contents);
void ReadLiteModInfo(QByteArray contents);
protected:
// FIXME: what do do with those? HMM...
/*
void ReadModInfoData(QString info);
void ReadForgeInfoData(QString infoFileData);
*/
QFileInfo m_file;
QDateTime m_changedDateTime;
QString m_mmc_id;
QString m_name;
QString m_mod_id;
bool m_enabled = true;
bool m_resolving = false;
bool m_resolved = false;
int m_resolutionTicket = 0;
ModType m_type = MOD_UNKNOWN;
std::shared_ptr<ModDetails> m_localDetails;
QString m_name;
QString m_version;
QString m_mcversion;
QString m_homeurl;
QString m_updateurl;
QString m_description;
QString m_authors;
QString m_credits;
ModType m_type;
};

View File

@@ -144,14 +144,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,20 +160,16 @@ 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
@@ -198,10 +194,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;
}
@@ -283,15 +276,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;

View File

@@ -1,7 +1,7 @@
#pragma once
#include <minecraft/VersionFile.h>
#include <minecraft/PackProfile.h>
#include <minecraft/ComponentList.h>
#include <minecraft/Library.h>
#include <QJsonDocument>

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

Some files were not shown because too many files have changed in this diff Show More