Compare commits

..

230 Commits

Author SHA1 Message Date
Petr Mrázek
464b05f6bf NOISSUE fix typo in changelog 2021-03-21 20:45:06 +01:00
Petr Mrázek
4b02b3f84a NOISSUE add warning to the ATLauncher pack page 2021-03-21 20:34:28 +01:00
Petr Mrázek
b1047d839e NOISSUE update changelog 2021-03-21 20:21:50 +01:00
AppleTheGolden
613afce705 NOISSUE add github issue forms 2021-03-19 00:24:52 +01:00
Petr Mrázek
af5b1beb64 Merge pull request #3646 from sambhavsaggi/openssl_doc_update
Fix #3638: OpenSSL download links in BUILD.md are dead
2021-03-10 04:19:43 +01:00
Petr Mrázek
84c673c5ba GH-3467 fix stall-out in ScanModFolders when the folders don't exist 2021-03-10 03:58:24 +01:00
Petr Mrázek
0c98589a7f GH-3602 Create .minecraft before running pre-launch commands 2021-03-10 03:58:24 +01:00
Sambhav Saggi
10e7f48347 Fix #3638 2021-03-08 09:24:37 -05:00
Petr Mrázek
0a869fc9ed Merge pull request #3623 from jamierocks/ftb/jarmods
Support jarmods and Fabric for modpacks.ch
2021-02-27 04:10:06 +01:00
Jamie Mansfield
9c69b0cdde NOISSUE Install jarmods for modpacks.ch
This patch will now install any jarmods from modpacks.ch packs,
searching the 'jarmods' directory to find them.
2021-02-25 14:43:04 +00:00
Jamie Mansfield
9d91cd496f NOISSUE Download all mods before writing the instance for modpacks.ch
This is prepatory work for implementing jarmods support for
modpacks.ch, where we will need to look through files in a directory -
which would require that those files are present at such time.

This might even fix some weird bugs, maybe - I've not encountered any
bugs from how this previously worked, but I feel that what's going on
is slightly clearer now.
2021-02-25 14:34:51 +00:00
Jamie Mansfield
384680ca13 NOISSUE Support Fabric mod loader for modpacks.ch
There aren't any (currently) packs on modpacks.ch that use Fabric, but
they do have support in their modpacklauncher. This patch just means
we preemptively have support should any packs that require it be
introduced.
2021-02-25 13:55:26 +00:00
Petr Mrázek
1edcd9b86e NOISSUE implement deleting skins 2021-02-11 02:23:00 +01:00
Petr Mrázek
280903e52b Merge pull request #3597 from jamierocks/atl/search
NOISSUE Add search to ATLauncher
2021-02-11 01:59:24 +01:00
Jamie Mansfield
152d476f20 NOISSUE Add search to ATLauncher 2021-02-11 00:57:07 +00:00
Petr Mrázek
40bdb0ffd6 Merge pull request #3593 from jamierocks/atl/description-view
NOISSUE Show ATLauncher pack descriptions in text browser
2021-02-10 18:38:04 +01:00
Petr Mrázek
1e59dafd75 Merge pull request #3594 from jamierocks/ftb/description-view
NOISSUE Show FTB pack descriptions in text browser
2021-02-10 18:37:34 +01:00
Jamie Mansfield
6eabd336ee NOISSUE Show FTB pack descriptions in text browser 2021-02-10 16:57:46 +00:00
Jamie Mansfield
003e019048 NOISSUE Show ATLauncher pack descriptions in text browser 2021-02-10 16:11:59 +00:00
Petr Mrázek
6b3b7ded2d GH-3130 fix uploading skins by using the new skins endpoint 2021-02-10 03:32:17 +01:00
Petr Mrázek
485f123362 Merge pull request #3311 from AbigailBuccaneer/develop
Fix endianness handling errors
2021-02-09 23:12:32 +01:00
Petr Mrázek
7265abf763 NOISSUE sprinkle suspendSave all over pack import tasks 2021-02-09 22:46:51 +01:00
Petr Mrázek
7ca5cf0e70 Merge pull request #3592 from Scotsguy/develop
NOISSUE Swap discord invite with vanity url
2021-02-09 22:02:12 +01:00
AppleTheGolden
f3205ebf25 NOISSUE Swap discord invite with vanity url 2021-02-09 22:00:20 +01:00
Petr Mrázek
e8b9176736 NOISSUE update macOS build instructions 2021-02-09 21:08:45 +01:00
Petr Mrázek
13a7f8d3b7 NOISSUE fix multiple issues in ATLauncher integration 2021-02-09 05:04:23 +01:00
Petr Mrázek
434369ca7c NOISSUE tweak ATLauncher pack cache names to avoid filesystem issues 2021-02-08 02:23:35 +01:00
Petr Mrázek
c54d922f26 NOISSUE and fix one more build fail 2021-02-07 23:54:29 +01:00
Petr Mrázek
85d5e9ff23 NOISSUE fix some build fails on linux and windows 2021-02-07 23:51:10 +01:00
Jamie Mansfield
ab19b86341 GH-405 ATLauncher Support 2021-02-07 23:30:24 +01:00
Petr Mrázek
5e980ceef2 Merge pull request #3556 from Zipdox/develop
Fix packaging issue caused by qt5-default
2021-02-07 02:24:42 +01:00
Petr Mrázek
1cf60a01d5 Merge pull request #3538 from Scotsguy/develop
NOISSUE Update Copyright Year
2021-02-07 02:23:31 +01:00
Petr Mrázek
ba4a1a68bd Merge pull request #3537 from rbutoi/argv0
Use argv[0] to print program name on a CLI error.
2021-02-07 02:21:25 +01:00
Petr Mrázek
11f7a432c4 Merge pull request #3583 from chrhasse/develop
Fix catching polymorphic type by value error
2021-02-07 02:16:59 +01:00
Christopher Hasse
047546c59e Fix catching polymorphic type by value error
fixes #3579
2021-02-06 18:55:44 -06:00
Petr Mrázek
75c14990e5 Merge pull request #3580 from kb-1000/remove-proxy-auth-from-log
NOISSUE Remove proxy user and password from the MultiMC log
2021-02-06 20:47:56 +01:00
kb1000
71bb50f64c NOISSUE Remove proxy user and password from the MultiMC log 2021-02-06 20:16:04 +01:00
Petr Mrázek
1868e0ccf1 GH-3229 fix copy seed button not working for newer worlds
Added the `optional-bare` library and refactored NBT reading
code to support this change.
2021-02-06 15:58:03 +01:00
Petr Mrázek
f8ca96a335 NOISSUE update changelog for 0.6.12 2021-02-06 13:13:53 +01:00
Petr Mrázek
5a7c1f9edf NOISSUE force kill button to reevaluate its style on state change 2021-02-05 03:18:21 +01:00
Petr Mrázek
359905a8ef NOISSUE set instance dialog launch/kill button object name 2021-02-05 02:46:59 +01:00
Petr Mrázek
8eee4e3e6c Merge pull request #3562 from kb-1000/technic-fix-1710-forge
Fix up 1.7.10 forge versions for Technic platform import by removing -1.7.10 suffix
2021-01-29 13:02:04 +01:00
kb1000
df2b9adc1e Fix up 1.7.10 forge versions for Technic platform import by removing -1.7.10 suffix 2021-01-29 10:18:33 +01:00
Zipdox
61004a25ec Fix packaging issue caused by qt5-default 2021-01-26 21:47:26 +01:00
AppleTheGolden
0de064eb35 NOISSUE Update Copyright Year 2021-01-18 08:28:54 +01:00
Radu Butoi
1cb9382282 Use argv[0] to print program name on a CLI error. 2021-01-17 16:58:32 -05:00
Petr Mrázek
02887536f7 Merge pull request #3524 from TreyRuffy/SessionServerFix
Switch Session Server
2021-01-17 18:53:03 +00:00
TreyRuffy
9100373af2 Switch Session Server
sessionserver.mojang.com has been down for a while and it looks like it is no longer in use.
https://bugs.mojang.com/browse/WEB-3166?focusedCommentId=820167&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-820167

I have switched the url to session.minecraft.net
2021-01-11 19:26:40 -07:00
Petr Mrázek
dc45d46e9c NOISSUE fix the metainfo file 2021-01-07 11:54:08 +01:00
Petr Mrázek
e9abf8a2d4 Merge pull request #3436 from Moresteck/develop
NOISSUE Corrected the fix for Classic saving, fixes Indev compatibility
2021-01-07 10:27:25 +00:00
Petr Mrázek
a1a3f0d492 Merge pull request #3476 from joshua-stone/metainfo-support
NOISSUE Add metainfo support
2021-01-07 10:05:59 +00:00
Joshua Stone
331f6df9e5 Improve metadata for screenshots 2020-12-10 11:43:37 -05:00
Joshua Stone
e9b779aa77 Update documentation WRT .rpm contents 2020-12-08 13:25:34 -05:00
Joshua Stone
42d124ed2b Move metainfo to ubuntu oflder so it can be used in both .rpm and .deb builds 2020-12-08 13:23:52 -05:00
Joshua Stone
a9a78c74db Fix contact email 2020-12-08 01:13:11 -05:00
Joshua Stone
d55030367e Use metainfodir macro directly 2020-12-08 00:55:50 -05:00
Joshua Stone
65990a1bf1 Remove disclaimer 2020-12-08 00:42:16 -05:00
Joshua Stone
399109728f Update RPM .spec to include metainfo file 2020-12-08 00:38:43 -05:00
Joshua Stone
c1161e2377 Add metainfo.xml for improving package metadata 2020-12-08 00:30:29 -05:00
Petr Mrázek
66b0ed2669 Merge pull request #3400 from MatejKafka/patch-1
Update BUILD.md with details for Windows build process
2020-12-02 01:57:30 +01:00
kb1000
f4d58e17ee NOISSUE Add pack author and description to technic modpack import page 2020-11-30 00:31:27 +01:00
Petr Mrázek
6aa126be30 Merge pull request #3460 from kb-1000/rpm-package
NOISSUE Add an RPM package
2020-11-30 00:19:25 +01:00
Petr Mrázek
58d168bda2 Merge pull request #3442 from jamierocks/ftb-sorts
NOISSUE Add sorting options to FTB pack install page
2020-11-30 00:13:41 +01:00
Jamie Mansfield
5eace10d51 NOISSUE Continue requesting packs after ignoring one
This was a mishap on my part, fortunately quickly exposed as the
combination of GH-3463 and GH-3464 made no packs visible.
2020-11-29 13:58:20 +00:00
Jamie Mansfield
b8c6a42f49 NOISSUE Add sorting options to FTB pack install page 2020-11-29 13:46:14 +00:00
Petr Mrázek
ed11d33054 Merge pull request #3464 from jamierocks/ftb/ignore-dud-packs
NOISSUE Ignore 'dud' FTB packs
2020-11-29 00:16:00 +01:00
Petr Mrázek
11a21b57e4 Merge pull request #3463 from jamierocks/ftb/new-api
NOISSUE Use new modpacks.ch route for listing packs
2020-11-29 00:15:24 +01:00
Jamie Mansfield
7321a4fd3d NOISSUE Ignore 'dud' FTB packs
There is no guarantee from modpacks.ch that modpacks contain any
versions, which is currently an issue with pack 63 (Direwolf20 1.5).
2020-11-28 22:13:53 +00:00
Jamie Mansfield
6249a54ba2 NOISSUE Use new modpacks.ch route for listing packs 2020-11-28 22:06:35 +00:00
kb1000
58c2228247 NOISSUE Add an RPM package for MultiMC
The RPM package reuses the files from the Ubuntu package.
2020-11-27 19:28:46 +01:00
Petr Mrázek
88d6b6ea3f GH-3427 add low effort datapack button to worlds 2020-11-24 22:31:49 +01:00
Petr Mrázek
66c0999901 Merge pull request #3438 from jamierocks/technic-zip-fix
GH-3437 Extract Technic single zip packs to correct place
2020-11-14 16:14:50 +01:00
Jamie Mansfield
edfea9894e NOISSUE Cleanup Technic support 2020-11-13 16:38:18 +00:00
Jamie Mansfield
fd1a8f039a GH-3437 Extract Technic single zip packs to correct place 2020-11-13 16:33:52 +00:00
Moresteck
49126fa8e2 NOISSUE Corrected the fix for Classic saving, fixes Indev compatibility 2020-11-12 14:58:12 +00:00
Matej Kafka
7da2fd5b8b Update BUILD.md
Extended description of Windows build process based on about 6 hours wasted on trial and error.
2020-10-25 03:54:59 +01:00
Petr Mrázek
eb3e6e4c6a NOISSUE give technic icon a darker outline 2020-10-13 22:35:43 +02:00
Petr Mrázek
4197ae0128 NOISSUE remove obsolete TODO comment from SolderPackInstallTask 2020-10-13 22:20:28 +02:00
Petr Mrázek
a7216ecca1 NOISSUE use Json parsing helpers to process technic search results 2020-10-13 22:18:42 +02:00
Petr Mrázek
4689571c24 NOISSUE fix build: QTemporaryDir::filePath was added in Qt 5.9 2020-10-13 22:01:01 +02:00
Petr Mrázek
4c62776044 Merge pull request #3195 from kb-1000/technic-import
Technic pack import
2020-10-13 21:44:20 +02:00
kb1000
8021fb25d0 GH-469 Implement support for importing and searching for Technic Platform and Solder modpacks
This does not support any custom modpack.jar for 1.6 or newer, it simply uses standard Forge then.
Supports Forge and Fabric, and JAR mods for 1.5 and older.
2020-10-13 21:34:16 +02:00
Petr Mrázek
762ddaea65 Merge pull request #3372 from jamierocks/ftb-data-temp-fix
GH-3304 Temporarily ignore download failures for FTB packs
2020-10-12 01:36:56 +02:00
Jamie Mansfield
05ffcf706b GH-3304 Temporarily ignore download failures for FTB packs
This is a temporary measure, to match FTB's own installer, to allow
packs to download while FTB work on fixing the data from their API.
2020-10-12 00:28:05 +01:00
Petr Mrázek
dded11004f NOISSUE adapt to work on Windows, fix reading symlink targets on POSIX 2020-10-12 01:01:51 +02:00
Petr Mrázek
f1284ab96b NOISSUE just eliminate QCOMPARE. it doesn't work at all. 2020-10-11 23:50:36 +02:00
Petr Mrázek
3aca4cbe20 NOISSUE tweak QCOMPARE vs QVERIFY
... the Qt test framework is annoyingly complicated and brittle.
... it may have to be replaced with something more reliable.
2020-10-11 23:45:41 +02:00
Petr Mrázek
015c34bb38 NOISSUE dis-ambiguate call to ensureBoolean in PackageManifest 2020-10-11 23:32:57 +02:00
Petr Mrázek
a49472349d NOISSUE fix constructing Path from iterators
Old Qt doesn't have the iterator-based constructors...
2020-10-11 23:28:38 +02:00
Petr Mrázek
0946c7c138 NOISSUE basic code for downloading JREs from Mojang
Not integrated yet, but the logic has tests and shouldn't
be too shaky. Integration comes next.
2020-10-11 23:20:35 +02:00
Petr Mrázek
5180536cc3 NOISSUE add a way to use native system versions of OpenAL and GLFW
If your OS comes with patched/fixed/newer versions of those,
you can now check the checkboxes and stop using the old ones
shipped by Mojang.
2020-09-10 23:10:17 +02:00
Petr Mrázek
27e43d037e NOISSUE remove translations from CheckJava launch step 2020-09-07 22:33:57 +02:00
Petr Mrázek
feae420450 NOISSUE add 'java.vendor' to the checker and display/log the value 2020-09-07 22:28:41 +02:00
AbigailBuccaneer
6995a2e1ba Avoid undefined behaviour when byteswapping
`a << b` is undefined when `a` is negative, and `a >> b` is
implementation-defined. The correct thing to do here is to cast to
unsigned, swap the bytes there and then swap back.

This also improves performance on some compilers: Clang is smart enough
to recognise that we're byteswapping here and reduce it to a single
`bswap` instruction on x86_64, but only for the unsigned versions.
2020-08-24 18:52:08 +01:00
AbigailBuccaneer
0f2757f000 Remove extra semicolons from big-endian handling
Fixes #3296.
2020-08-24 17:43:58 +01:00
Petr Mrázek
8a0027c73a NOISSUE Add world icons and world icon reset button 2020-08-22 01:34:55 +02:00
Petr Mrázek
c6c9feb3a2 NOISSUE attempt to fix build on macOS 2020-08-21 02:40:19 +02:00
Jamie Mansfield
b0f5f4cb13 GH-3095 New FTB platform support
Models are based on the models from my go-modpacksch library.

License:
========
The MIT License (MIT)

Copyright (c) Jamie Mansfield <https://www.jamiemansfield.me/>
Copyright (c) contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
2020-08-21 02:24:29 +02:00
Petr Mrázek
e7f373496e GH-3234 Add support for custom meta URLs at build time
This is not particularly interesting for non-developers.
Also includes some internal restructuring of URL constants in general.
2020-07-18 16:22:05 +02:00
Petr Mrázek
3158082b16 Merge pull request #3239 from haykam821/intermediary-errors
Fix Fabric loader error messages being reused for intermediary mappings
2020-07-18 12:31:45 +02:00
Petr Mrázek
814407ccec Merge pull request #3241 from Bowser65/feature/render-overlay
Minor: Render the skin overlay in SkinUtils
2020-07-18 12:31:14 +02:00
Bowser65
155f4f7471 NOISSUE render the skin overlay in SkinUtils 2020-07-12 19:36:40 +02:00
haykam821
90d45d2abf Fix Fabric loader error messages being reused for intermediary mappings 2020-07-09 12:17:59 -04:00
Petr Mrázek
cd57e354fe NOISSUE fix a bunch of valgrind errors 2020-06-28 13:25:53 +02:00
Petr Mrázek
a0ef20a264 NOISSUE rename ComponentList to PackProfile
It's not just components, so the naming needed cleaning up.
2020-06-27 12:02:31 +02:00
Petr Mrázek
4ca62916f5 GH-3189 update the nbt library 2020-06-07 21:32:42 +02:00
Petr Mrázek
41590f2e50 NOISSUE Switch twitch modpack page to use a QListView
This makes the lazy loading of the paginated search results
actually work.
2020-06-07 11:15:17 +02:00
Petr Mrázek
03dc8ddf81 Merge pull request #3169 from kb-1000/fix-accessibility-2
Allow compiling MultiMC using Qt builds without accessibility again
2020-05-30 15:34:18 +02:00
kb1000
79208a7383 Allow compiling MultiMC using Qt builds without accessibility again 2020-05-30 15:32:38 +02:00
Petr Mrázek
3680f1e599 Merge pull request #2864 from Hubcapp/patch-1
Update BUILD.md
2020-05-29 01:56:53 +02:00
Petr Mrázek
c4779e5a35 Merge pull request #3127 from OverMighty/develop
fix: add support for args with spaces to MultiMC::messageReceived()
2020-05-29 01:55:27 +02:00
Petr Mrázek
aad34f3679 Merge pull request #3165 from kvverti/wsl-messages
Clarify WSL error messages
2020-05-29 00:59:28 +02:00
Thalia Nero
0047ca454f Clarify WSL error messages 2020-05-28 17:59:54 -04:00
Petr Mrázek
07a1052c69 Fix. 2020-05-28 23:31:50 +02:00
Petr Mrázek
ba6a97557a NOISSUE prevent evil from winning 2020-05-28 23:17:50 +02:00
Petr Mrázek
e7f79c9076 Remove some old forge hacks
Forge apparently removed all `.pack.xz` files without warning.
It broke a bunch of stuff, as always. But it also means we don't need some ugly code anymore.

This is removed:

- Support for 'forge-pack-xz' and the forge-specific file download compression.
- The pack200 library we no longer need.

This stays:

- The LZMA decompression library - we may still want to use it.
2020-05-19 15:13:16 +02:00
Petr Mrázek
9eaa636908 GH-2802 remove extra remapping of indexes in VersionPage model 2020-05-17 19:56:59 +02:00
Petr Mrázek
997c25620a GH-3131 fix not working with proxy ports > 32767 2020-05-17 13:59:30 +02:00
OverMighty
bbcacec6ec fix: add support for args with spaces to MultiMC::messageReceived()
Previously, when the main instance of MultiMC would receive an `import`
or `launch` message from another instance, it would split the message on
each space, and only read the first word of the argument (zip path/URL
or instance ID). This commit fixes that problem by sectioning the
message string instead.
2020-05-04 11:37:02 +02:00
OverMighty
313a6574c1 chore: pull changes from upstream 2020-05-04 11:36:41 +02:00
Petr Mrázek
5ca5661c23 NOISSUE expose twitch pack url, description and author list 2020-04-29 21:17:51 +02:00
Petr Mrázek
cb0887ffa8 Merge branch 'develop' of https://github.com/Moresteck/MultiMC5 into develop 2020-04-29 20:32:47 +02:00
Moresteck
1f9378af9f NOISSUE Fixed online saving in early Classic versions 2020-04-19 20:31:04 +01:00
John C. Allwein
5c921589f1 NOISSUE fix compiling of api/logic/Version.cpp
-Wrange-loop-construct triggers this error in clang
2020-04-19 14:36:42 -04:00
Petr Mrázek
130e1263b6 Merge pull request #3046 from Ghalid/mac-build-instructions
Fix macOS build instructions so that git submodule commands succeed
2020-04-11 02:33:02 +02:00
Petr Mrázek
296ff6de96 NOISSUE Add pagination support to twitch pack search
Try searching for 'craft'. Now it gives ALL the results, not just
the first page of 25.
2020-04-01 02:08:11 +02:00
Petr Mrázek
5e951299b2 NOISSUE fix build 2020-04-01 00:59:18 +02:00
Petr Mrázek
3ff93a4216 NOISSUE Bare-bones twitch pack browser 2020-04-01 00:44:24 +02:00
Petr Mrázek
21ac860e27 Bump dev version to 0.6.12 2020-03-29 04:03:04 +02:00
Petr Mrázek
3ad9ea507e NOISSUE update version number, changelog and credits in about dialog 2020-03-29 03:12:57 +02:00
Petr Mrázek
c9e851f12f GH-2544 enable Forge install button for >= 1.13 2020-03-28 15:55:12 +01:00
Petr Mrázek
0281845fc8 GH-2544 allow adding files to libraries without affecting classpath
This is done by adding library-like objects into the `mavenFiles`
list in version JSONs.
2020-03-27 02:23:15 +01:00
Petr Mrázek
e6cc65cf69 NOISSUE no means no, #2 2020-03-26 10:38:13 +01:00
Petr Mrázek
ebb17cb5f8 NOISSUE no means no. 2020-03-26 03:51:14 +01:00
Ghalid
164bb6c78c NOISSUE change directory before running git submodule commands in mac instructions 2020-03-22 12:17:56 -04:00
Petr Mrázek
69490535d0 Merge pull request #2979 from Brottweiler/desktop-entry-tweak
Tweak GenericName for Linux desktop entry
2020-02-25 18:02:09 +01:00
Brottweiler
95a09ba099 GH-2979 Tweak GenericName 2020-02-24 19:39:22 +01:00
Petr Mrázek
6cb956b45b NOISSUE Nice. 2020-02-24 18:59:36 +01:00
OverMighty
47fa7b3f8c GH-2988 add --import command-line option
When specified, opens the "Import from zip" dialog as soon as the main
window is shown, with the URL field prefilled with the argument given to
the option.

Closes #2998
2020-02-24 18:52:26 +01:00
OverMighty
381c12547f feat: allow telling the main process to import a zip
This commit enhances the IPC message system and adds a new IPC command
in order to allow secondary MultiMC processes that were started by
executing MultiMC with the `--import` command-line option to tell the
main MutliMC process to open the "Import from zip" dialog window and
prefill the URL field with the specified URL.
2020-02-09 16:17:41 +01:00
OverMighty
060d6955e1 style: follow upstream code style 2020-02-09 15:45:31 +01:00
Petr Mrázek
d58481e0de NOISSUE fix some changelog wording 2020-02-09 00:03:20 +01:00
Petr Mrázek
08f85f1a93 Update changelog and set version to 0.6.8 2020-02-08 15:00:20 +01:00
OverMighty
bc04d89c32 feat: add --import command-line option
When specified, opens the "Import from zip" dialog as soon as the main
window is shown, with the URL field prefilled with the argument given to
the option.

Closes #2998
2020-02-05 12:37:09 +01:00
Petr Mrázek
bc98181ec2 GH-2769 add an option to not copy play time when copying instances 2020-01-09 15:31:32 +01:00
Petr Mrázek
6a095deea6 GH-2832 add .minecraft and libraries buttons to version page 2020-01-09 13:45:46 +01:00
Petr Mrázek
355e5e24da GH-2819 mod list filter now also looks at descriptions and authors 2020-01-08 21:12:45 +01:00
Petr Mrázek
8bdff97ac0 GH-2839 remove username wording from login and account dialogs 2020-01-08 13:37:05 +01:00
Petr Mrázek
6288805f37 GH-2853 fix collapsing state being sticky in group view
Now it resets properly and collapsing a group doesn't make
all subsequent clicks collapse groups.
2020-01-08 09:00:54 +01:00
Petr Mrázek
0d157d86b5 NOISSUE add wget as a dependency for deb package 2020-01-08 06:28:42 +01:00
Petr Mrázek
f413e61cd8 NOISSUE Do not crash when dependencies are customized and conflict 2020-01-08 04:41:47 +01:00
Petr Mrázek
3581f5384f GH-2880 make services status widget open a valid page
https://help.mojang.com/ no longer has API status
2020-01-07 08:56:00 +01:00
Petr Mrázek
480b298635 NOISSUE Attempt to add build status and test teamcity build reporting 2019-11-27 00:35:42 +01:00
Petr Mrázek
b54b25231e Remove travis-ci and github actions leftovers 2019-11-26 21:09:37 +01:00
Petr Mrázek
43628556ed NOISSUE fix comment in Commandline.h 2019-11-26 19:06:45 +01:00
Petr Mrázek
b5adff14ab NOISSUE remove dead reference to TwitchPage.ui 2019-11-18 02:38:08 +01:00
Petr Mrázek
af5120c828 GH-2859 remove twitch page and modpack import from URL
The functionality was broken, beyond repair and an ongoing maintenance
nightmare.
2019-11-18 00:38:36 +01:00
Petr Mrázek
47ed2f48d4 NOISSUE put legacy FTB support in a namespace, fix its base URL 2019-11-03 23:48:12 +01:00
Petr Mrázek
0c9340a3d2 NOISSUE fix translation string for Twitch drop area 2019-10-14 23:51:36 +02:00
Petr Mrázek
9cc5ebcdd1 GH-2859 improve UI for twitch pack import with drag&drop 2019-10-14 02:31:53 +02:00
Petr Mrázek
c60647523e NOISSUE remove remains of what could have been technic integration 2019-10-14 01:05:38 +02:00
Petr Mrázek
9165232ba4 NOISSUE remove unused 'PackagesPage' 2019-10-13 22:31:14 +02:00
Petr Mrázek
31d0507e07 NOISSUE make the main window title only 'MultiMC' for screen readers 2019-10-05 22:51:55 +02:00
Petr Mrázek
cca766cfd9 Merge pull request #2871 from kb-1000/fix-accessibility-fix
Remove include of qtguiglobal.h
2019-10-01 16:15:45 +02:00
kb1000
0d41bc5e13 Remove include of qtguiglobal.h 2019-10-01 15:55:40 +02:00
Petr Mrázek
e27309d08a Merge pull request #2870 from kb-1000/fix-accessibility
Add checks for QT_NO_ACCESSIBILITY to prevent build issues with Qt without accessibility
2019-10-01 15:40:39 +02:00
kb1000
dec6759e61 Add checks for QT_NO_ACCESSIBILITY to prevent build issues with Qt without accessibility 2019-10-01 14:28:06 +02:00
Petr Mrázek
ce7917048a NOISSUE remove more html rom About dialog 2019-09-30 23:50:32 +02:00
Hubcapp
e6b5d9656a Update BUILD.md
the `git clone` command provided doesn't work and gives this error on Debian
```
$ git clone --recursive git@github.com:MultiMC/MultiMC5.git src
Cloning into 'src'...
The authenticity of host 'github.com (192.30.253.113)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.253.113' (RSA) to the list of known hosts.
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
I am suggesting an alternative command to provide to users in BUILD.md instead.
2019-09-27 09:01:25 -05:00
Petr Mrázek
e6936212d6 NOISSUE remove some ugly html strings to make translating slightly nicer 2019-09-27 00:23:30 +02:00
Petr Mrázek
1210d3abf1 NOISSUE fix display of european portuguese in language lists 2019-09-27 00:23:03 +02:00
Petr Mrázek
ffe84d6ec7 NOISSUE remove some dead things 2019-09-26 20:08:47 +02:00
Petr Mrázek
19015de258 NOISSUE correct some parts of the README, one more translation string change 2019-09-26 09:03:25 +02:00
Petr Mrázek
5c0c26cd25 TRANSLATIONS-82 fix typos: resove -> resolve 2019-09-25 22:31:09 +02:00
Petr Mrázek
4cc7427eb4 TRANSLATIONS-73 remove some strings that don't show up in the UI 2019-09-25 22:29:50 +02:00
Petr Mrázek
6531aaa7bc Try using github actions
Let's see how badly this goes
2019-09-19 10:56:11 +02:00
Petr Mrázek
a35a2e877e NOISSUE remove nonsensical logic related to 'MultiMC.app/' prefixes in update manifests 2019-09-19 01:13:02 +02:00
Petr Mrázek
4e93c4d012 NOISSUE escape tcversion more 2019-09-17 01:26:37 +02:00
Petr Mrázek
7bb23b4142 NOISSUE add some escaping to make the tc version print actually do something 2019-09-17 01:22:00 +02:00
Petr Mrázek
b420f4bafb Merge pull request #2849 from AshleighTheCutie/develop
Message cleanup
2019-09-17 01:12:45 +02:00
Petr Mrázek
0e0a017175 NOISSUE add a way to extract the version into a TC variable 2019-09-17 00:53:30 +02:00
Ashleigh
137fe7e3c0 Cleaned up messages, made some more descriptive, made some nicer. 2019-09-14 22:31:13 -05:00
Ashleigh
9689e5cea7 Added text notifying that password change may cause logout 2019-09-14 22:12:23 -05:00
Petr Mrázek
1ede75aa79 Merge pull request #2848 from AshleighTheCutie/develop
Window Size to 800x600
2019-09-15 04:34:03 +02:00
Ashleigh
9ee3a84817 Window Size to 800x600 2019-09-14 21:15:51 -05:00
Petr Mrázek
8750ca8b36 NOISSUE add bee icon 2019-08-26 02:25:42 +02:00
Petr Mrázek
1747f413b9 GH-851 save, load and use group expansion status 2019-08-20 02:58:27 +02:00
Petr Mrázek
6d975748c0 Merge pull request #2796 from QuImUfu/bug_fix
GH-2787 fix "Download All" button
2019-08-14 22:12:58 +02:00
Petr Mrázek
b050c7c075 Merge pull request #2803 from kb-1000/escape-semicolon
Escape ; too in instance folder names
2019-08-14 22:12:39 +02:00
Kaeptm Blaubaer
84e0cb1daa Escape ; too in instance folder names 2019-08-13 07:39:00 +02:00
Petr Mrázek
5074a97cb3 NOISSUE tweak toolbar and custom widget titles for better translations 2019-08-10 20:12:42 +02:00
Petr Mrázek
441e8980b8 NOISSUE fix small memory leaks 2019-08-10 19:58:58 +02:00
Johannes Michael Andreas Merl
84c53273ce GH-2787 fix "Download All" button 2019-08-09 00:11:42 +02:00
Petr Mrázek
c291946d2a NOISSUE do not lose selection on mod enable/disable toggle 2019-08-05 00:46:59 +02:00
Petr Mrázek
dfb30d9139 NOISSUE warn users about MS Edge being bad 2019-08-04 21:14:59 +02:00
Petr Mrázek
4ed67413ac GH-988 add ability to toggle mods with keyboard 2019-08-04 21:13:50 +02:00
Petr Mrázek
d31184f9a4 GH-2738 check for being in the temp folder better 2019-08-04 18:11:55 +02:00
Petr Mrázek
b75ba53d4b GH-2785 fix crash caused by starting multiple mod folder update tasks 2019-08-04 11:12:19 +02:00
Petr Mrázek
9037873928 NOISSUE update changelog 2019-08-04 06:26:09 +02:00
Petr Mrázek
ce4a55bc3b NOISSUE fix listing of mods in log, improve display with unicode 2019-08-04 05:08:40 +02:00
Petr Mrázek
6b82e942d0 NOISSUE fix build on linux 2019-08-04 03:39:25 +02:00
Petr Mrázek
a3ffa3d665 NOISSUE asynchronous, parallel mod folder listing and mod resolving 2019-08-04 03:27:53 +02:00
Petr Mrázek
7d13e31198 NOISSUE refactor Mod a bunch, get rid of dead code 2019-08-03 05:30:46 +02:00
Petr Mrázek
40c9af1a8b NOISSUE remove dependency of legacy mod list on the Mod class 2019-08-03 03:12:48 +02:00
Petr Mrázek
f5f3149dcf NOISSUE update changelog and version 2019-08-03 00:48:34 +02:00
Petr Mrázek
7b00d47fe0 NOISSUE tweak UI geometry and remove old language selection 2019-08-02 23:52:19 +02:00
Petr Mrázek
930d39b5f2 GH-2550 soring of mods by enabled status, cascade sorting to name and version 2019-07-31 01:28:55 +02:00
Petr Mrázek
bafcf93eb1 NOISSUE fix bug with drag & drop not working with empty mod list 2019-07-31 01:27:35 +02:00
Petr Mrázek
bd93c3b4e0 NOISSUE fix build 2019-07-30 01:25:37 +02:00
Petr Mrázek
09f7a426ab GH-2722 GH-2762 Improve mod list sorting
Sorting by version understands version numbers
Sorting by name removes 'The' prefixes before sorting
2019-07-30 01:16:56 +02:00
Petr Mrázek
e4fd50e210 NOISSUE make the language translation prompt translateable 2019-07-30 01:16:02 +02:00
Petr Mrázek
3ee5a63c5c NOISSUE make notes page focusable with tab key 2019-07-25 01:13:47 +02:00
Petr Mrázek
7dfe73df0c NOISSUE add context menus to pages with toolbars 2019-07-25 01:02:30 +02:00
Petr Mrázek
c3e61536a3 NOISSUE automatically open the log page when starting the instance 2019-07-24 00:24:02 +02:00
Petr Mrázek
a0e45c5d1d NOISSUE fix build 2019-07-23 01:05:23 +02:00
Petr Mrázek
bf38021937 NOISSUE improve toolbars 2019-07-23 00:48:14 +02:00
Petr Mrázek
1e5b595923 NOISSUE fix build failures 2019-07-22 01:44:19 +02:00
Petr Mrázek
d6c6653872 NOISSUE Add basic accessibility support to GroupView 2019-07-22 01:40:52 +02:00
Petr Mrázek
3b32730526 Merge pull request #2758 from telans/patch-1
Fix translation repository link
2019-07-21 01:33:31 +02:00
telans
1703dbeb57 Fix translation repository link 2019-07-21 10:50:30 +12:00
Petr Mrázek
81fdde6fdd NOISSUE convert accounts page to use a toolbar for the side menu 2019-07-19 08:29:31 +02:00
Petr Mrázek
3d5869e1cf NOISSUE fix overly large margins in the instance settings page 2019-07-17 02:17:09 +02:00
Petr Mrázek
edc5378333 NOISSUE add spacer to the screenshot page toolbar 2019-07-17 02:09:54 +02:00
Petr Mrázek
95febe5436 NOISSUE convert rest of the instance pages to use toolbars for side menus 2019-07-17 02:01:29 +02:00
Petr Mrázek
5b153a5165 GH-2748 disable the version page toolbar labels 2019-07-16 08:58:00 +02:00
Petr Mrázek
decd4ae7ab NOISSUE Make mod folder pages use toolbars instead of button layouts 2019-07-16 01:30:53 +02:00
Petr Mrázek
2eec1df1a0 NOISSUE hide main toolbar toggle action instead of working around it 2019-07-16 01:30:09 +02:00
Petr Mrázek
6fde775b90 NOISSUE Show Version page while the instancer is running.
All controls are disabled.
2019-07-15 23:16:34 +02:00
Petr Mrázek
80b3efff11 NOISSUE Do not hide mods list pages when the instance is running.
Instead, disable (most of) the controls.
2019-07-15 01:07:21 +02:00
Petr Mrázek
e4273d6a17 GH-358 Make version page use a toolbar for all the actions
This should make it possible to make it fit on small screens again.
2019-07-14 05:37:10 +02:00
464 changed files with 12863 additions and 15276 deletions

View File

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

View File

@@ -1,25 +0,0 @@
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

View File

@@ -1,51 +0,0 @@
<!--
Before submitting this issue, please make sure you have:
1. Filled out this form completely, the only optional field is "additional info".
- Use as many details as possible and state the problem clearly.
2. Proof-read your ENTIRE issue report.
- Grammar and spelling mistakes make issue reports harder to understand.
3. Made sure your problem is not caused by an issue in your own modpack.
- We provide support for MultiMC, not your modpack. Problems with your modpack will be ignored.
4. Given the issue a descriptive title.
- A good title includes a brief summary of the issue and avoids things such as "Help" and "What?!".
Use of UPPERCASE is discouraged, as it reads like someone is screaming.
5. Place all information below the ---- of lines.
- It makes the issue look pretty
If you believe your issue to be a bug, please make sure you check the wiki page: https://github.com/MultiMC/MultiMC5/wiki/Report-a-Bug
-->
System Information
-----------------------------
MultiMC version:
Operating System:
Summary of the issue or suggestion:
----------------------------------------------
What should happen:
------------------------------
Steps to reproduce the issue (Add more if needed):
-------------------------------------------------------------
1.
2.
3.
Suspected cause:
---------------------------
Logs/Screenshots:
----------------------------
[//]: # (Please refer to https://github.com/MultiMC/MultiMC5/wiki/Log-Upload for instructions on how to attach your logs.)
Additional Info:
---------------------------

52
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Bug Report
description: File a bug report
labels: [bug, needs-triage]
issue_body: false
body:
- type: markdown
attributes:
value: |
If you need help with running Minecraft, please visit us [on our Discord](https://discord.gg/multimc) before making a bug report.
Before submitting a bug report, please make sure you have read this *entire* form, and that:
* You have read the [FAQ](https://github.com/MultiMC/MultiMC5/wiki/FAQ) and it has not answered your question
* Your bug is not caused by Minecraft or any mods you have installed.
* Your issue has not been reported before, [make sure to use the search function!](https://github.com/MultiMC/MultiMC5/issues)
**Do not forget to give your issue a descriptive title.** "Bug in the instance screen" makes it hard to distinguish issues at a glance.
- type: dropdown
attributes:
label: Operating System
description: If you know this bug occurs on multiple operating systems, select all you have tested.
multiple: true
options:
- Windows
- macOS
- Linux
- Other
- type: textarea
attributes:
label: Description of bug
description: What did you expect to happen, what happened, and why is it incorrect?
placeholder: The cat button should show a cat, but it showed a dog instead!
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: A bulleted list, or an exported instance if relevant.
placeholder: "* Press the cat button"
validations:
required: true
- type: textarea
attributes:
label: Suspected cause
description: If you know what could be causing this bug, describe it here.
validations:
required: false
- type: checkboxes
attributes:
label: This issue is unique
options:
- label: I have searched the issue tracker and did not find an issue describing my bug.
required: true

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: MultiMC Discord
url: https://discord.gg/multimc
about: Please ask for support here before opening an issue.

41
.github/ISSUE_TEMPLATE/suggestion.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
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,8 +9,7 @@ resources/MultiMCLauncher.jar
html/
# Project Files
MultiMC5.kdev4
MultiMC.pro.user
*.pro.user
CMakeLists.txt.user
CMakeLists.txt.user.*
/.project

View File

@@ -1,38 +0,0 @@
# 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)
* [OS X](#os-x)
* [macOS](#macos)
# Note
@@ -50,7 +50,7 @@ mkdir ~/MultiMC && cd ~/MultiMC
mkdir build
mkdir install
# clone the complete source
git clone --recursive git@github.com:MultiMC/MultiMC5.git src
git clone --recursive https://github.com/MultiMC/MultiMC5.git src
# configure the project
cd build
cmake -DCMAKE_INSTALL_PREFIX=../install ../src
@@ -92,14 +92,19 @@ 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
* [OpenSSL](http://slproweb.com/products/Win32OpenSSL.html) -- Newest Win32 OpenSSL Light
- http://download.qt.io/new_archive/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe
- Download the MinGW version (MSVC version does not work).
* [OpenSSL](https://github.com/IndySockets/OpenSSL-Binaries/tree/master/Archive/) -- Win32 OpenSSL, version 1.0.2g (from 2016)
- https://github.com/IndySockets/OpenSSL-Binaries/raw/master/Archive/openssl-1.0.2g-i386-win32.zip
- the usual OpenSSL for Windows (http://slproweb.com/products/Win32OpenSSL.html) only provides the newest version of OpenSSL, and we need the 1.0.2g version
- **Download the 32-bit version, not 64-bit.**
- Microsoft Visual C++ 2008 Redist is required for this, there's a link on the OpenSSL download page above next to the main download.
- We use a custom build of OpenSSL that doesn't have this dependency. For normal development, the custom build is not necessary though.
* [zlib 1.2+](http://gnuwin32.sourceforge.net/packages/zlib.htm) - the Setup is fine
* [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)
Put it somewhere on the `PATH`, so that it is accessible from the console.
Ensure that OpenSSL, zlib, Java and CMake are on `PATH`.
## Getting set up
@@ -115,9 +120,8 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt
- Installation can take a very long time, go grab a cup of tea or something and let it work.
### Installing OpenSSL
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).
1. Download .zip file from the link above.
2. Unzip and add the directory to PATH, so CMake can find it.
### Installing CMake
1. Run the CMake installer,
@@ -140,6 +144,24 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt
- 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.
@@ -150,36 +172,32 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt
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.
# OS X
# macOS
### Install prerequisites:
* install homebrew
* then:
```
brew install qt5
brew tap homebrew/versions
brew install gcc48
brew install cmake
```
- 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/)
### 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 https://github.com/MultiMC/MultiMC5.git
git submodule init
git submodule update
git clone --recursive https://github.com/MultiMC/MultiMC5.git
cd MultiMC5
mkdir build
cd build
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
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 \
..
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,7 +2,15 @@ cmake_minimum_required(VERSION 3.1)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
if(IS_IN_SOURCE_BUILD)
message(AUTHOR_WARNING "You are building MultiMC in-source. This is NOT recommended!")
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()
endif()
if(WIN32)
@@ -13,6 +21,7 @@ endif()
project(MultiMC)
enable_testing()
##################################### Set CMake options #####################################
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -46,7 +55,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 6)
set(MultiMC_VERSION_HOTFIX 12)
# Build number
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@@ -60,6 +69,9 @@ 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")
@@ -77,6 +89,7 @@ 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 ################################
@@ -141,7 +154,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-2019 MultiMC Contributors")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2015-2021 MultiMC Contributors")
# directories to look for dependencies
set(DIRS ${QT_LIBS_DIR} ${QT_LIBEXECS_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@@ -247,14 +260,15 @@ 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-2019 MultiMC Contributors
Copyright 2012-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
@@ -128,35 +128,6 @@
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
@@ -252,3 +223,31 @@
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,21 +13,22 @@ 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/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.
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.
### Building
If you want to build MultiMC yourself, check [BUILD.md](BUILD.md) for build instructions.
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.
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.
Just follow the existing formatting.
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.
## Translations
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).
Translations can be done [on crowdin](https://translate.multimc.org).
## 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.
@@ -38,8 +39,41 @@ Apache covers reasonable use for the name - a mention of the project's origins i
## License
Copyright &copy; 2013-2019 MultiMC Contributors
Copyright &copy; 2013-2021 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-2019 MultiMC Contributors
/* 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.
@@ -18,6 +18,7 @@
#include "Env.h"
#include <QFile>
#include <QPainter>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
@@ -35,10 +36,14 @@ QPixmap getFaceFromCache(QString username, int height, int width)
if (fskin.exists())
{
QPixmap skin(fskin.fileName());
if(!skin.isNull())
QPixmap skinTexture(fskin.fileName());
if(!skinTexture.isNull())
{
return skin.copy(8, 8, 8, 8).scaled(height, width, Qt::KeepAspectRatio);
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);
}
}

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -119,8 +119,6 @@ set(NET_SOURCES
net/PasteUpload.cpp
net/PasteUpload.h
net/Sink.h
net/URLConstants.cpp
net/URLConstants.h
net/Validator.h
)
@@ -213,8 +211,10 @@ 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,10 +223,11 @@ 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/CreateServerResourcePacksFolder.cpp
minecraft/launch/CreateServerResourcePacksFolder.h
minecraft/launch/CreateGameFolders.cpp
minecraft/launch/CreateGameFolders.h
minecraft/launch/ModMinecraftJar.cpp
minecraft/launch/ModMinecraftJar.h
minecraft/launch/DirectJavaLaunch.cpp
@@ -239,12 +240,16 @@ 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
@@ -252,8 +257,8 @@ set(MINECRAFT_SOURCES
minecraft/LaunchProfile.h
minecraft/Component.cpp
minecraft/Component.h
minecraft/ComponentList.cpp
minecraft/ComponentList.h
minecraft/PackProfile.cpp
minecraft/PackProfile.h
minecraft/ComponentUpdateTask.cpp
minecraft/ComponentUpdateTask.h
minecraft/MinecraftLoadAndCheck.h
@@ -279,26 +284,33 @@ 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
# Forge and all things forge related
minecraft/forge/ForgeXzDownload.h
minecraft/forge/ForgeXzDownload.cpp
# Minecraft services
minecraft/services/SkinUpload.cpp
minecraft/services/SkinUpload.h
minecraft/services/SkinDelete.cpp
minecraft/services/SkinDelete.h
# Skin upload utilities
minecraft/SkinUpload.cpp
minecraft/SkinUpload.h
mojang/PackageManifest.h
mojang/PackageManifest.cpp
)
add_unit_test(GradleSpecifier
@@ -306,6 +318,22 @@ 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
@@ -318,8 +346,8 @@ add_unit_test(Library
)
# FIXME: shares data with FileSystem test
add_unit_test(SimpleModList
SOURCES minecraft/SimpleModList_test.cpp
add_unit_test(ModFolderModel
SOURCES minecraft/mod/ModFolderModel_test.cpp
DATA testdata
LIBS MultiMC_logic
)
@@ -426,15 +454,14 @@ set(META_SOURCES
)
set(FTB_SOURCES
modplatform/ftb/FtbPackFetchTask.h
modplatform/ftb/FtbPackFetchTask.cpp
modplatform/ftb/FtbPackInstallTask.h
modplatform/ftb/FtbPackInstallTask.cpp
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/FtbPrivatePackManager.h
modplatform/ftb/FtbPrivatePackManager.cpp
modplatform/ftb/PackHelpers.h
modplatform/legacy_ftb/PackHelpers.h
)
set(FLAME_SOURCES
@@ -443,8 +470,31 @@ set(FLAME_SOURCES
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
modplatform/flame/UrlResolvingTask.h
modplatform/flame/UrlResolvingTask.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
)
add_unit_test(Index
@@ -477,17 +527,18 @@ 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 xz-embedded MultiMC_unpack200 systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES} optional-bare BuildConfig)
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-2019 MultiMC Contributors
/* Copyright 2013-2021 MultiMC Contributors
*
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
*

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* Copyright 2013-2021 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,7 +96,11 @@ 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());
@@ -159,11 +163,9 @@ void Env::updateProxySettings(QString proxyTypeStr, QString addr, int port, QStr
proxyDesc = "DERP proxy: ";
break;
}
proxyDesc += QString("%3@%1:%2 pass %4")
proxyDesc += QString("%1:%2")
.arg(proxy.hostName())
.arg(proxy.port())
.arg(proxy.user())
.arg(proxy.password());
.arg(proxy.port());
qDebug() << proxyDesc;
}

View File

@@ -174,6 +174,11 @@ 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())
@@ -294,7 +299,7 @@ QString NormalizePath(QString path)
}
}
QString badFilenameChars = "\"\\/?<>:*|!+\r\n";
QString badFilenameChars = "\"\\/?<>:;*|!+\r\n";
QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
{

View File

@@ -5,9 +5,10 @@
#include "pathmatcher/RegexpMatcher.h"
#include <QtConcurrentRun>
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves)
InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
{
m_origInstance = origInstance;
m_keepPlaytime = keepPlaytime;
if(!copySaves)
{
@@ -46,6 +47,9 @@ 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);
explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
protected:
//! Entry point for tasks.
@@ -28,4 +28,5 @@ 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/ComponentList.h"
#include "minecraft/PackProfile.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.getComponentList();
auto components = inst.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
inst.setName(m_instName);

View File

@@ -1,3 +1,18 @@
/* 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"
@@ -11,10 +26,12 @@
// FIXME: this does not belong here, it's Minecraft/Flame specific
#include "minecraft/MinecraftInstance.h"
#include "minecraft/ComponentList.h"
#include "minecraft/PackProfile.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)
{
@@ -23,8 +40,6 @@ InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
void InstanceImportTask::executeTask()
{
InstancePtr newInstance;
if (m_sourceUrl.isLocalFile())
{
m_archivePath = m_sourceUrl.toLocalFile();
@@ -82,6 +97,7 @@ 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())
@@ -91,6 +107,14 @@ 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
@@ -98,7 +122,6 @@ void InstanceImportTask::processZipPack()
root = flameFound;
m_modpackType = ModpackType::Flame;
}
if(m_modpackType == ModpackType::Unknown)
{
emitFailed(tr("Archive does not contain a recognized modpack type."));
@@ -115,7 +138,7 @@ void InstanceImportTask::processZipPack()
void InstanceImportTask::extractFinished()
{
m_packZip.reset();
if (m_extractFuture.result().isEmpty())
if (!m_extractFuture.result())
{
emitFailed(tr("Failed to extract modpack"));
return;
@@ -161,6 +184,9 @@ 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;
@@ -236,7 +262,7 @@ void InstanceImportTask::processFlame()
mcVersion.remove(QRegExp("[.]+$"));
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
}
auto components = instance.getComponentList();
auto components = instance.getPackProfile();
components->buildingFromScratch();
components->setComponentVersion("net.minecraft", mcVersion, true);
if(!forgeVersion.isEmpty())
@@ -288,7 +314,7 @@ void InstanceImportTask::processFlame()
qDebug() << info.fileName();
jarMods.push_back(info.absoluteFilePath());
}
auto profile = instance.getComponentList();
auto profile = instance.getPackProfile();
profile->installJarMods(jarMods);
// nuke the original files
FS::deletePath(jarmodsPath);
@@ -371,6 +397,14 @@ 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,3 +1,18 @@
/* 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"
@@ -9,6 +24,8 @@
#include "settings/SettingsObject.h"
#include "QObjectPtr.h"
#include <nonstd/optional>
class QuaZip;
namespace Flame
{
@@ -29,6 +46,7 @@ private:
void processZipPack();
void processMultiMC();
void processFlame();
void processTechnic();
private slots:
void downloadSucceeded();
@@ -44,11 +62,12 @@ private: /* data */
QString m_archivePath;
bool m_downloadRequired = false;
std::unique_ptr<QuaZip> m_packZip;
QFuture<QStringList> m_extractFuture;
QFutureWatcher<QStringList> m_extractFutureWatcher;
QFuture<nonstd::optional<QStringList>> m_extractFuture;
QFutureWatcher<nonstd::optional<QStringList>> m_extractFutureWatcher;
enum class ModpackType{
Unknown,
MultiMC,
Flame
Flame,
Technic
} m_modpackType = ModpackType::Unknown;
};

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -100,6 +100,10 @@ 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();
@@ -156,8 +160,8 @@ GroupId InstanceList::getInstanceGroup(const InstanceId& id) const
{
return GroupId();
}
auto iter = m_groupMap.find(inst->id());
if(iter != m_groupMap.end())
auto iter = m_instanceGroupIndex.find(inst->id());
if(iter != m_instanceGroupIndex.end())
{
return *iter;
}
@@ -174,8 +178,8 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
}
bool changed = false;
auto iter = m_groupMap.find(inst->id());
if(iter != m_groupMap.end())
auto iter = m_instanceGroupIndex.find(inst->id());
if(iter != m_instanceGroupIndex.end())
{
if(*iter != name)
{
@@ -186,12 +190,12 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
else
{
changed = true;
m_groupMap[id] = name;
m_instanceGroupIndex[id] = name;
}
if(changed)
{
m_groups.insert(name);
m_groupNameCache.insert(name);
auto idx = getInstIndex(inst.get());
emit dataChanged(index(idx), index(idx), {GroupRole});
saveGroupList();
@@ -200,7 +204,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
QStringList InstanceList::getGroups()
{
return m_groups.toList();
return m_groupNameCache.toList();
}
void InstanceList::deleteGroup(const QString& name)
@@ -213,7 +217,7 @@ void InstanceList::deleteGroup(const QString& name)
auto instGroupName = getInstanceGroup(instID);
if(instGroupName == name)
{
m_groupMap.remove(instID);
m_instanceGroupIndex.remove(instID);
qDebug() << "Remove" << instID << "from group" << name;
removed = true;
auto idx = getInstIndex(instance.get());
@@ -229,6 +233,11 @@ 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);
@@ -238,7 +247,7 @@ void InstanceList::deleteInstance(const InstanceId& id)
return;
}
if(m_groupMap.remove(id))
if(m_instanceGroupIndex.remove(id))
{
saveGroupList();
}
@@ -511,7 +520,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_groupMap.begin(); iter != m_groupMap.end(); iter++)
for (auto iter = m_instanceGroupIndex.begin(); iter != m_instanceGroupIndex.end(); iter++)
{
QString id = iter.key();
QString group = iter.value();
@@ -544,7 +553,7 @@ void InstanceList::saveGroupList()
auto name = iter.key();
QJsonObject groupObj;
QJsonArray instanceArr;
groupObj.insert("hidden", QJsonValue(QString("false")));
groupObj.insert("hidden", QJsonValue(m_collapsedGroups.contains(name)));
for (auto item : list)
{
instanceArr.append(QJsonValue(item));
@@ -568,7 +577,6 @@ void InstanceList::saveGroupList()
void InstanceList::loadGroupList()
{
qDebug() << "Will load group list now.";
QSet<QString> groupSet;
QString groupFileName = m_instDir + "/instgroups.json";
@@ -619,7 +627,8 @@ void InstanceList::loadGroupList()
return;
}
m_groupMap.clear();
QSet<QString> groupSet;
m_instanceGroupIndex.clear();
// Iterate through all the groups.
QJsonObject groupMapping = rootObj.value("groups").toObject();
@@ -630,37 +639,35 @@ 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_groupMap[(*iter2).toString()] = groupName;
m_instanceGroupIndex[(*iter2).toString()] = groupName;
}
}
m_groupsLoaded = true;
m_groups.unite(groupSet);
m_groupNameCache.unite(groupSet);
qDebug() << "Group list loaded.";
}
@@ -685,6 +692,17 @@ 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
@@ -815,9 +833,9 @@ bool InstanceList::commitStagedInstance(const QString& path, const QString& inst
qWarning() << "Failed to move" << path << "to" << destination;
return false;
}
m_groupMap[instID] = groupName;
m_instanceGroupIndex[instID] = groupName;
instanceSet.insert(instID);
m_groups.insert(groupName);
m_groupNameCache.insert(groupName);
emit instancesChanged();
emit instanceSelectRequest(instID);
}

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -99,6 +99,8 @@ 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);
@@ -134,6 +136,7 @@ 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);
@@ -154,12 +157,14 @@ private:
int m_watchLevel = 0;
bool m_dirty = false;
QList<InstancePtr> m_instances;
QSet<QString> m_groups;
QSet<QString> m_groupNameCache;
SettingsObjectPtr m_globalSettings;
QString m_instDir;
QFileSystemWatcher * m_watcher;
QMap<InstanceId, GroupId> m_groupMap;
// FIXME: this is so inefficient that looking at it is almost painful.
QSet<QString> m_collapsedGroups;
QMap<InstanceId, GroupId> m_instanceGroupIndex;
QSet<InstanceId> instanceSet;
bool m_groupsLoaded = false;
bool m_instancesProbed = false;

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -208,16 +208,27 @@ bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & re
// ours
QStringList MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
nonstd::optional<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;
if (!zip->goToFirstFile())
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())
{
qWarning() << "Failed to seek to first file in zip";
return QStringList();
return nonstd::nullopt;
}
do
{
QString name = zip->getCurrentFileName();
@@ -235,7 +246,7 @@ QStringList MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QSt
{
qWarning() << "Failed to extract file" << name << "to" << absFilePath;
JlCompress::removeFile(extracted);
return QStringList();
return nonstd::nullopt;
}
extracted.append(absFilePath);
qDebug() << "Extracted file" << name;
@@ -244,12 +255,58 @@ QStringList MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QSt
}
// ours
QStringList MMCZip::extractDir(QString fileCompressed, QString dir)
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)
{
QuaZip zip(fileCompressed);
if (!zip.open(QuaZip::mdUnzip))
{
return {};
// 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, "", 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-2019 MultiMC Contributors
/* 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.
@@ -18,12 +18,13 @@
#include <QString>
#include <QFileInfo>
#include <QSet>
#include "minecraft/Mod.h"
#include "minecraft/mod/Mod.h"
#include <functional>
#include "multimc_logic_export.h"
#include <JlCompress.h>
#include <nonstd/optional>
namespace MMCZip
{
@@ -57,7 +58,9 @@ namespace MMCZip
/**
* Extract a subdirectory from an archive
*/
QStringList MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
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);
/**
* Extract a whole archive.
@@ -66,6 +69,26 @@ 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.
*/
QStringList MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
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);
}

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-2019 MultiMC Contributors
/* 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.

View File

@@ -115,7 +115,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
}
}
if(!results.contains("os.arch") || !results.contains("java.version") || !success)
if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success)
{
result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
emit checkFinished(result);
@@ -124,6 +124,7 @@ 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";
@@ -132,6 +133,7 @@ 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,6 +17,7 @@ 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-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -33,17 +33,17 @@ void CheckJava::executeTask()
if (perInstance)
{
emit logLine(
tr("The java binary \"%1\" couldn't be found. Please fix the java path "
QString("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(tr("The java binary \"%1\" couldn't be found. Please set up java in "
emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in "
"the settings.").arg(m_javaPath),
MessageLevel::Warning);
}
emitFailed(tr("Java path is not valid."));
emitFailed(QString("Java path is not valid."));
return;
}
else
@@ -56,12 +56,13 @@ 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)
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedVendor.size() == 0)
{
m_JavaChecker = new JavaChecker();
emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
emit logLine(QString("Checking Java version..."), MessageLevel::MultiMC);
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
m_JavaChecker->m_path = realJavaPath;
m_JavaChecker->performCheck();
@@ -71,7 +72,8 @@ void CheckJava::executeTask()
{
auto verString = instance->settings()->get("JavaVersion").toString();
auto archString = instance->settings()->get("JavaArchitecture").toString();
printJavaInfo(verString, archString);
auto vendorString = instance->settings()->get("JavaVendor").toString();
printJavaInfo(verString, archString, vendorString);
}
emitSucceeded();
}
@@ -83,16 +85,16 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
case JavaCheckResult::Validity::Errored:
{
// Error message displayed if java can't start
emit logLine(tr("Could not start java:"), MessageLevel::Error);
emit logLine(QString("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(tr("Could not start java!"));
emitFailed(QString("Could not start java!"));
return;
}
case JavaCheckResult::Validity::ReturnedInvalidData:
{
emit logLine(tr("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
emit logLine(QString("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);
@@ -102,9 +104,10 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
case JavaCheckResult::Validity::Valid:
{
auto instance = m_parent->instance();
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform);
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.javaVendor);
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;
@@ -112,9 +115,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
}
}
void CheckJava::printJavaInfo(const QString& version, const QString& architecture)
void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor)
{
emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
emit logLine(QString("Java is version %1, using %2-bit architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::MultiMC);
printSystemInfo(true, architecture == "64");
}
@@ -124,13 +127,13 @@ void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
auto system64 = Sys::isSystem64bit();
if(cpu64 != system64)
{
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);
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);
}
if(javaIsKnown)
{
if(javaIs64bit != system64)
{
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);
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);
}
}
}

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -35,7 +35,7 @@ private slots:
void checkJavaFinished(JavaCheckResult result);
private:
void printJavaInfo(const QString & version, const QString & architecture);
void printJavaInfo(const QString & version, const QString & architecture, const QString & vendor);
void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
private:

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.
@@ -24,6 +24,8 @@
#include "Env.h"
#include "Json.h"
#include "BuildConfig.h"
class ParsingValidator : public Net::Validator
{
public: /* con/des */
@@ -53,7 +55,9 @@ public: /* methods */
auto fname = m_entity->localFilename();
try
{
m_entity->parse(Json::requireObject(Json::requireDocument(data, fname), fname));
auto doc = Json::requireDocument(data, fname);
auto obj = Json::requireObject(doc, fname);
m_entity->parse(obj);
return true;
}
catch (const Exception &e)
@@ -74,7 +78,7 @@ Meta::BaseEntity::~BaseEntity()
QUrl Meta::BaseEntity::url() const
{
return QUrl("https://meta.multimc.org/v1/").resolved(localFilename());
return QUrl(BuildConfig.META_URL).resolved(localFilename());
}
bool Meta::BaseEntity::loadLocalFile()
@@ -87,7 +91,9 @@ bool Meta::BaseEntity::loadLocalFile()
// TODO: check if the file has the expected checksum
try
{
parse(Json::requireObject(Json::requireDocument(fname, fname), fname));
auto doc = Json::requireDocument(fname, fname);
auto obj = Json::requireObject(doc, fname);
parse(obj);
return true;
}
catch (const Exception &e)

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.
@@ -18,7 +18,7 @@
#include <QDateTime>
#include "JsonFormat.h"
#include "minecraft/ComponentList.h"
#include "minecraft/PackProfile.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-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2015-2019 MultiMC Contributors
/* Copyright 2015-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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -27,7 +27,7 @@
#include "FileSystem.h"
#include "net/Download.h"
#include "net/ChecksumValidator.h"
#include "net/URLConstants.h"
#include "BuildConfig.h"
namespace {
QSet<QString> collectPathsFromDir(QString dirPath)
@@ -308,7 +308,7 @@ QString AssetObject::getLocalPath()
QUrl AssetObject::getUrl()
{
return URLConstants::RESOURCE_BASE + getRelPath();
return BuildConfig.RESOURCE_BASE + getRelPath();
}
QString AssetObject::getRelPath()

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -5,13 +5,13 @@
#include "meta/Version.h"
#include "VersionFile.h"
#include "minecraft/ComponentList.h"
#include "minecraft/PackProfile.h"
#include <FileSystem.h>
#include <QSaveFile>
#include "OneSixVersionFormat.h"
#include <assert.h>
Component::Component(ComponentList * parent, const QString& uid)
Component::Component(PackProfile * parent, const QString& uid)
{
assert(parent);
m_parent = parent;
@@ -19,7 +19,7 @@ Component::Component(ComponentList * parent, const QString& uid)
m_uid = uid;
}
Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> version)
Component::Component(PackProfile * parent, std::shared_ptr<Meta::Version> version)
{
assert(parent);
m_parent = parent;
@@ -31,7 +31,7 @@ Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> vers
m_loaded = version->isLoaded();
}
Component::Component(ComponentList * parent, const QString& uid, std::shared_ptr<VersionFile> file)
Component::Component(PackProfile * 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 ComponentList;
class PackProfile;
class LaunchProfile;
namespace Meta
{
@@ -22,11 +22,11 @@ class MULTIMC_LOGIC_EXPORT Component : public QObject, public ProblemProvider
{
Q_OBJECT
public:
Component(ComponentList * parent, const QString &uid);
Component(PackProfile * parent, const QString &uid);
// DEPRECATED: remove these constructors?
Component(ComponentList * parent, std::shared_ptr<Meta::Version> version);
Component(ComponentList * parent, const QString & uid, std::shared_ptr<VersionFile> file);
Component(PackProfile * parent, std::shared_ptr<Meta::Version> version);
Component(PackProfile * parent, const QString & uid, std::shared_ptr<VersionFile> file);
virtual ~Component(){};
void applyTo(LaunchProfile *profile);
@@ -73,7 +73,7 @@ signals:
void dataChanged();
public: /* data */
ComponentList * m_parent;
PackProfile * m_parent;
// BEGIN: persistent component list properties
/// ID of the component

View File

@@ -1,7 +1,7 @@
#include "ComponentUpdateTask.h"
#include "ComponentList_p.h"
#include "ComponentList.h"
#include "PackProfile_p.h"
#include "PackProfile.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 ComponentList.
* The reactor should be the only entry into manipulating the PackProfile.
* See: https://en.wikipedia.org/wiki/Reactor_pattern
*/
/*
* 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?
* 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?
* If the component list changes, start over.
*/
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList* list, QObject* parent)
ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile* 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 loadComponentList(ComponentPtr component, shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
static LoadResult loadPackProfile(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 = loadComponentList(component, loadTask, d->netmode);
singleResult = loadPackProfile(component, loadTask, d->netmode);
loadType = RemoteLoadStatus::Type::List;
break;
}
@@ -244,7 +244,7 @@ void ComponentUpdateTask::loadComponents()
});
RemoteLoadStatus status;
status.type = loadType;
status.componentListIndex = componentIndex;
status.PackProfileIndex = componentIndex;
d->remoteLoadStatusList.append(status);
taskIndex++;
}
@@ -451,13 +451,17 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
auto & comp = (*compIter);
if(comp->getVersion() != req.equalsVersion)
{
if(comp->m_dependencyOnly)
{
decision = Decision::VersionNotSame;
}
else
{
if(comp->isCustom()) {
decision = Decision::LockedVersionNotSame;
} else {
if(comp->m_dependencyOnly)
{
decision = Decision::VersionNotSame;
}
else
{
decision = Decision::LockedVersionNotSame;
}
}
break;
}
@@ -491,7 +495,7 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
}
// FIXME, TODO: decouple dependency resolution from loading
// FIXME: This works directly with the ComponentList internals. It shouldn't! It needs richer data types than ComponentList uses.
// FIXME: This works directly with the PackProfile internals. It shouldn't! It needs richer data types than PackProfile uses.
// FIXME: throw all this away and use a graph
void ComponentUpdateTask::resolveDependencies(bool checkOnly)
{
@@ -644,7 +648,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.componentListIndex);
auto component = d->m_list->getComponent(taskSlot.PackProfileIndex);
component->m_loaded = true;
component->updateCachedData();
}

View File

@@ -4,7 +4,7 @@
#include "net/Mode.h"
#include <memory>
class ComponentList;
class PackProfile;
struct ComponentUpdateTaskData;
class ComponentUpdateTask : public Task
@@ -18,7 +18,7 @@ public:
};
public:
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList * list, QObject *parent = 0);
explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, PackProfile * list, QObject *parent = 0);
virtual ~ComponentUpdateTask();
protected:

View File

@@ -5,7 +5,7 @@
#include <QList>
#include "net/Mode.h"
class ComponentList;
class PackProfile;
struct RemoteLoadStatus
{
@@ -15,7 +15,7 @@ struct RemoteLoadStatus
List,
Version
} type = Type::Version;
size_t componentListIndex = 0;
size_t PackProfileIndex = 0;
bool finished = false;
bool succeeded = false;
QString error;
@@ -23,7 +23,7 @@ struct RemoteLoadStatus
struct ComponentUpdateTaskData
{
ComponentList * m_list = nullptr;
PackProfile * m_list = nullptr;
QList<RemoteLoadStatus> remoteLoadStatusList;
bool remoteLoadSuccessful = true;
size_t remoteTasksInProgress = 0;

View File

@@ -11,6 +11,7 @@ void LaunchProfile::clear()
m_mainClass.clear();
m_appletClass.clear();
m_libraries.clear();
m_mavenFiles.clear();
m_traits.clear();
m_jarMods.clear();
m_mainJar.reset();
@@ -157,6 +158,22 @@ 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;
@@ -253,6 +270,11 @@ 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,6 +20,7 @@ public: /* application of profile variables from patches */
void applyJarMods(const QList<LibraryPtr> &jarMods);
void applyMods(const QList<LibraryPtr> &jarMods);
void applyLibrary(LibraryPtr library);
void applyMavenFile(LibraryPtr library);
void applyMainJar(LibraryPtr jar);
void applyProblemSeverity(ProblemSeverity severity);
/// clear the profile
@@ -37,6 +38,7 @@ 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,
@@ -79,10 +81,13 @@ 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 libraries
/// the list of native 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,26 +88,19 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
{
options |= Net::Download::Option::AcceptLocalFiles;
}
if (isForge())
if(sha1.size())
{
qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
out.append(ForgeXzDownload::make(url, storage, entry));
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
{
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;
}
out.append(Net::Download::makeCached(url, entry, options));
qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
}
return true;
};
@@ -179,7 +172,7 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
if (m_repositoryURL.isEmpty())
{
return URLConstants::LIBRARY_BASE + raw_storage;
return BuildConfig.LIBRARY_BASE + raw_storage;
}
if(m_repositoryURL.endsWith('/'))
@@ -243,11 +236,6 @@ 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,7 +12,6 @@
#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/CreateServerResourcePacksFolder.h>
#include <minecraft/launch/CreateGameFolders.h>
#include <minecraft/launch/ExtractNatives.h>
#include <minecraft/launch/PrintInstanceInfo.h>
#include <settings/Setting.h>
@@ -21,22 +21,24 @@
#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 "SimpleModList.h"
#include "mod/ModFolderModel.h"
#include "WorldList.h"
#include "icons/IIconList.h"
#include <QCoreApplication>
#include "ComponentList.h"
#include "PackProfile.h"
#include "AssetsUtils.h"
#include "MinecraftUpdate.h"
#include "MinecraftLoadAndCheck.h"
#include <minecraft/gameoptions/GameOptions.h>
#include <minecraft/update/FoldersTask.h>
#define IBUS "@im=ibus"
@@ -99,13 +101,18 @@ 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 ComponentList(this));
m_components.reset(new PackProfile(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());
@@ -123,14 +130,14 @@ QString MinecraftInstance::typeName() const
return "Minecraft";
}
std::shared_ptr<ComponentList> MinecraftInstance::getComponentList() const
std::shared_ptr<PackProfile> MinecraftInstance::getPackProfile() const
{
return m_components;
}
QSet<QString> MinecraftInstance::traits() const
{
auto components = getComponentList();
auto components = getPackProfile();
if (!components)
{
return {"version-incomplete"};
@@ -264,7 +271,7 @@ QStringList MinecraftInstance::getNativeJars() const
QStringList MinecraftInstance::extraArguments() const
{
auto list = BaseInstance::extraArguments();
auto version = getComponentList();
auto version = getPackProfile();
if (!version)
return list;
auto jarMods = getJarMods();
@@ -550,37 +557,38 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session)
out << "";
}
if(loaderModList()->size())
{
out << "Mods:";
for(auto & mod: loaderModList()->allMods())
auto printModList = [&](const QString & label, ModFolderModel & model) {
if(model.size())
{
if(!mod.enabled())
continue;
if(mod.type() == Mod::MOD_FOLDER)
continue;
// TODO: proper implementation would need to descend into folders.
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;
}
out << " " + mod.filename().completeBaseName();
if(mod.enabled()) {
out << u8" [✔️] " + mod.filename().completeBaseName();
}
else {
out << u8" [❌] " + mod.filename().completeBaseName() + " (disabled)";
}
}
out << "";
}
out << "";
}
};
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 << "";
}
printModList("Mods", *(loaderModList().get()));
printModList("Core Mods", *(coreModList().get()));
auto & jarMods = profile->getJarMods();
if(jarMods.size())
@@ -803,6 +811,11 @@ 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())
{
@@ -827,16 +840,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));
@@ -892,43 +905,47 @@ JavaVersion MinecraftInstance::getJavaVersion() const
return JavaVersion(settings()->get("JavaVersion").toString());
}
std::shared_ptr<SimpleModList> MinecraftInstance::loaderModList() const
std::shared_ptr<ModFolderModel> MinecraftInstance::loaderModList() const
{
if (!m_loader_mod_list)
{
m_loader_mod_list.reset(new SimpleModList(loaderModsDir()));
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->update();
return m_loader_mod_list;
}
std::shared_ptr<SimpleModList> MinecraftInstance::coreModList() const
std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
{
if (!m_core_mod_list)
{
m_core_mod_list.reset(new SimpleModList(coreModsDir()));
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->update();
return m_core_mod_list;
}
std::shared_ptr<SimpleModList> MinecraftInstance::resourcePackList() const
std::shared_ptr<ModFolderModel> MinecraftInstance::resourcePackList() const
{
if (!m_resource_pack_list)
{
m_resource_pack_list.reset(new SimpleModList(resourcePacksDir()));
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->update();
return m_resource_pack_list;
}
std::shared_ptr<SimpleModList> MinecraftInstance::texturePackList() const
std::shared_ptr<ModFolderModel> MinecraftInstance::texturePackList() const
{
if (!m_texture_pack_list)
{
m_texture_pack_list.reset(new SimpleModList(texturePacksDir()));
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->update();
return m_texture_pack_list;
}

View File

@@ -1,17 +1,16 @@
#pragma once
#include "BaseInstance.h"
#include <java/JavaVersion.h>
#include "minecraft/Mod.h"
#include "minecraft/mod/Mod.h"
#include <QProcess>
#include <QDir>
#include "multimc_logic_export.h"
class ModsModel;
class SimpleModList;
class ModFolderModel;
class WorldList;
class GameOptions;
class LaunchStep;
class ComponentList;
class PackProfile;
class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance
{
@@ -65,14 +64,13 @@ public:
////// Profile management //////
std::shared_ptr<ComponentList> getComponentList() const;
std::shared_ptr<PackProfile> getPackProfile() const;
////// Mod Lists //////
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<ModFolderModel> loaderModList() const;
std::shared_ptr<ModFolderModel> coreModList() const;
std::shared_ptr<ModFolderModel> resourcePackList() const;
std::shared_ptr<ModFolderModel> texturePackList() const;
std::shared_ptr<WorldList> worldList() const;
std::shared_ptr<GameOptions> gameOptionsModel() const;
@@ -122,12 +120,11 @@ private:
QString prettifyTimeDuration(int64_t duration);
protected: // data
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;
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;
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 "ComponentList.h"
#include "PackProfile.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->getComponentList();
auto components = m_inst->getPackProfile();
components->reload(Net::Mode::Offline);
m_task = components->getCurrentTask();

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -14,7 +14,6 @@
*/
#include "Env.h"
#include <minecraft/forge/ForgeXzDownload.h>
#include "MinecraftUpdate.h"
#include "MinecraftInstance.h"
@@ -24,9 +23,8 @@
#include <QDataStream>
#include "BaseInstance.h"
#include "minecraft/ComponentList.h"
#include "minecraft/PackProfile.h"
#include "minecraft/Library.h"
#include "net/URLConstants.h"
#include <FileSystem.h>
#include "update/FoldersTask.h"
@@ -51,7 +49,7 @@ void MinecraftUpdate::executeTask()
// add metadata update task if necessary
{
auto components = m_inst->getComponentList();
auto components = m_inst->getPackProfile();
components->reload(Net::Mode::Online);
auto task = components->getCurrentTask();
if(task)

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,433 +0,0 @@
/* 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

@@ -144,14 +144,14 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
}
}
auto readLibs = [&](const char * which)
auto readLibs = [&](const char * which, QList<LibraryPtr> & out)
{
for (auto libVal : requireArray(root.value(which)))
{
QJsonObject libObj = requireObject(libVal);
// parse the library
auto lib = libraryFromJson(libObj, filename);
out->libraries.append(lib);
out.append(lib);
}
};
bool hasPlusLibs = root.contains("+libraries");
@@ -160,16 +160,20 @@ 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");
readLibs("+libraries");
readLibs("libraries", out->libraries);
readLibs("+libraries", out->libraries);
}
else if (hasLibs)
{
readLibs("libraries");
readLibs("libraries", out->libraries);
}
else if(hasPlusLibs)
{
readLibs("+libraries");
readLibs("+libraries", out->libraries);
}
if(root.contains("mavenFiles")) {
readLibs("mavenFiles", out->mavenFiles);
}
// if we have mainJar, just use it
@@ -194,7 +198,10 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
// FIXME: this will eventually break...
else
{
lib->setAbsoluteUrl(URLConstants::getLegacyJarUrl(out->minecraftVersion));
out->addProblem(
ProblemSeverity::Error,
QObject::tr("URL for the main jar could not be determined - Mojang removed the server that we used as fallback.")
);
}
out->mainJar = lib;
}
@@ -276,6 +283,15 @@ 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/ComponentList.h>
#include <minecraft/PackProfile.h>
#include <minecraft/Library.h>
#include <QJsonDocument>

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.
@@ -32,21 +32,23 @@
#include <QTimer>
#include <Json.h>
#include "ComponentList.h"
#include "ComponentList_p.h"
#include "PackProfile.h"
#include "PackProfile_p.h"
#include "ComponentUpdateTask.h"
ComponentList::ComponentList(MinecraftInstance * instance)
PackProfile::PackProfile(MinecraftInstance * instance)
: QAbstractListModel()
{
d.reset(new ComponentListData);
d.reset(new PackProfileData);
d->m_instance = instance;
d->m_saveTimer.setSingleShot(true);
d->m_saveTimer.setInterval(5000);
connect(&d->m_saveTimer, &QTimer::timeout, this, &ComponentList::save_internal);
d->interactionDisabled = instance->isRunning();
connect(d->m_instance, &BaseInstance::runningStatusChanged, this, &PackProfile::disableInteraction);
connect(&d->m_saveTimer, &QTimer::timeout, this, &PackProfile::save_internal);
}
ComponentList::~ComponentList()
PackProfile::~PackProfile()
{
saveNow();
}
@@ -95,7 +97,7 @@ static QJsonObject componentToJsonV1(ComponentPtr component)
return obj;
}
static ComponentPtr componentFromJsonV1(ComponentList * parent, const QString & componentJsonPattern, const QJsonObject &obj)
static ComponentPtr componentFromJsonV1(PackProfile * parent, const QString & componentJsonPattern, const QJsonObject &obj)
{
// critical
auto uid = Json::requireString(obj.value("uid"));
@@ -118,7 +120,7 @@ static ComponentPtr componentFromJsonV1(ComponentList * parent, const QString &
}
// Save the given component container data to a file
static bool saveComponentList(const QString & filename, const ComponentContainer & container)
static bool savePackProfile(const QString & filename, const ComponentContainer & container)
{
QJsonObject obj;
obj.insert("formatVersion", currentComponentsFileVersion);
@@ -151,7 +153,7 @@ static bool saveComponentList(const QString & filename, const ComponentContainer
}
// Read the given file into component containers
static bool loadComponentList(ComponentList * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container)
static bool loadPackProfile(PackProfile * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container)
{
QFile componentsFile(filename);
if (!componentsFile.exists())
@@ -208,7 +210,7 @@ static bool loadComponentList(ComponentList * parent, const QString & filename,
// BEGIN: save/load logic
void ComponentList::saveNow()
void PackProfile::saveNow()
{
if(saveIsScheduled())
{
@@ -217,18 +219,18 @@ void ComponentList::saveNow()
}
}
bool ComponentList::saveIsScheduled() const
bool PackProfile::saveIsScheduled() const
{
return d->dirty;
}
void ComponentList::buildingFromScratch()
void PackProfile::buildingFromScratch()
{
d->loaded = true;
d->dirty = true;
}
void ComponentList::scheduleSave()
void PackProfile::scheduleSave()
{
if(!d->loaded)
{
@@ -243,30 +245,30 @@ void ComponentList::scheduleSave()
d->m_saveTimer.start();
}
QString ComponentList::componentsFilePath() const
QString PackProfile::componentsFilePath() const
{
return FS::PathCombine(d->m_instance->instanceRoot(), "mmc-pack.json");
}
QString ComponentList::patchesPattern() const
QString PackProfile::patchesPattern() const
{
return FS::PathCombine(d->m_instance->instanceRoot(), "patches", "%1.json");
}
QString ComponentList::patchFilePathForUid(const QString& uid) const
QString PackProfile::patchFilePathForUid(const QString& uid) const
{
return patchesPattern().arg(uid);
}
void ComponentList::save_internal()
void PackProfile::save_internal()
{
qDebug() << "Component list save performed now for" << d->m_instance->name();
auto filename = componentsFilePath();
saveComponentList(filename, d->components);
savePackProfile(filename, d->components);
d->dirty = false;
}
bool ComponentList::load()
bool PackProfile::load()
{
auto filename = componentsFilePath();
QFile componentsFile(filename);
@@ -284,7 +286,7 @@ bool ComponentList::load()
// load the new component list and swap it with the current one...
ComponentContainer newComponents;
if(!loadComponentList(this, filename, patchesPattern(), newComponents))
if(!loadPackProfile(this, filename, patchesPattern(), newComponents))
{
qCritical() << "Failed to load the component config for instance" << d->m_instance->name();
return false;
@@ -296,7 +298,7 @@ bool ComponentList::load()
// disconnect all the old components
for(auto component: d->components)
{
disconnect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
disconnect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
}
d->components.clear();
d->componentIndex.clear();
@@ -307,7 +309,7 @@ bool ComponentList::load()
qWarning() << "Ignoring duplicate component entry" << component->m_uid;
continue;
}
connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
d->components.append(component);
d->componentIndex[component->m_uid] = component;
}
@@ -317,7 +319,7 @@ bool ComponentList::load()
}
}
void ComponentList::reload(Net::Mode netmode)
void PackProfile::reload(Net::Mode netmode)
{
// Do not reload when the update/resolve task is running. It is in control.
if(d->m_updateTask)
@@ -337,29 +339,29 @@ void ComponentList::reload(Net::Mode netmode)
}
}
shared_qobject_ptr<Task> ComponentList::getCurrentTask()
shared_qobject_ptr<Task> PackProfile::getCurrentTask()
{
return d->m_updateTask;
}
void ComponentList::resolve(Net::Mode netmode)
void PackProfile::resolve(Net::Mode netmode)
{
auto updateTask = new ComponentUpdateTask(ComponentUpdateTask::Mode::Resolution, netmode, this);
d->m_updateTask.reset(updateTask);
connect(updateTask, &ComponentUpdateTask::succeeded, this, &ComponentList::updateSucceeded);
connect(updateTask, &ComponentUpdateTask::failed, this, &ComponentList::updateFailed);
connect(updateTask, &ComponentUpdateTask::succeeded, this, &PackProfile::updateSucceeded);
connect(updateTask, &ComponentUpdateTask::failed, this, &PackProfile::updateFailed);
d->m_updateTask->start();
}
void ComponentList::updateSucceeded()
void PackProfile::updateSucceeded()
{
qDebug() << "Component list update/resolve task succeeded for" << d->m_instance->name();
d->m_updateTask.reset();
invalidateLaunchProfile();
}
void ComponentList::updateFailed(const QString& error)
void PackProfile::updateFailed(const QString& error)
{
qDebug() << "Component list update/resolve task failed for" << d->m_instance->name() << "Reason:" << error;
d->m_updateTask.reset();
@@ -429,7 +431,7 @@ static void upgradeDeprecatedFiles(QString root, QString instanceName)
* - Part is taken from the old order.json file.
* - Part is loaded from loose json files in the instance's `patches` directory.
*/
bool ComponentList::migratePreComponentConfig()
bool PackProfile::migratePreComponentConfig()
{
// upgrade the very old files from the beginnings of MultiMC 5
upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
@@ -596,17 +598,17 @@ bool ComponentList::migratePreComponentConfig()
}
}
// new we have a complete list of components...
return saveComponentList(componentsFilePath(), components);
return savePackProfile(componentsFilePath(), components);
}
// END: save/load
void ComponentList::appendComponent(ComponentPtr component)
void PackProfile::appendComponent(ComponentPtr component)
{
insertComponent(d->components.size(), component);
}
void ComponentList::insertComponent(size_t index, ComponentPtr component)
void PackProfile::insertComponent(size_t index, ComponentPtr component)
{
auto id = component->getID();
if(id.isEmpty())
@@ -623,16 +625,16 @@ void ComponentList::insertComponent(size_t index, ComponentPtr component)
d->components.insert(index, component);
d->componentIndex[id] = component;
endInsertRows();
connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
connect(component.get(), &Component::dataChanged, this, &PackProfile::componentDataChanged);
scheduleSave();
}
void ComponentList::componentDataChanged()
void PackProfile::componentDataChanged()
{
auto objPtr = qobject_cast<Component *>(sender());
if(!objPtr)
{
qWarning() << "ComponentList got dataChenged signal from a non-Component!";
qWarning() << "PackProfile got dataChenged signal from a non-Component!";
return;
}
if(objPtr->getID() == "net.minecraft") {
@@ -650,10 +652,10 @@ void ComponentList::componentDataChanged()
}
index++;
}
qWarning() << "ComponentList got dataChenged signal from a Component which does not belong to it!";
qWarning() << "PackProfile got dataChenged signal from a Component which does not belong to it!";
}
bool ComponentList::remove(const int index)
bool PackProfile::remove(const int index)
{
auto patch = getComponent(index);
if (!patch->isRemovable())
@@ -677,7 +679,7 @@ bool ComponentList::remove(const int index)
return true;
}
bool ComponentList::remove(const QString id)
bool PackProfile::remove(const QString id)
{
int i = 0;
for (auto patch : d->components)
@@ -691,7 +693,7 @@ bool ComponentList::remove(const QString id)
return false;
}
bool ComponentList::customize(int index)
bool PackProfile::customize(int index)
{
auto patch = getComponent(index);
if (!patch->isCustomizable())
@@ -709,7 +711,7 @@ bool ComponentList::customize(int index)
return true;
}
bool ComponentList::revertToBase(int index)
bool PackProfile::revertToBase(int index)
{
auto patch = getComponent(index);
if (!patch->isRevertible())
@@ -727,7 +729,7 @@ bool ComponentList::revertToBase(int index)
return true;
}
Component * ComponentList::getComponent(const QString &id)
Component * PackProfile::getComponent(const QString &id)
{
auto iter = d->componentIndex.find(id);
if (iter == d->componentIndex.end())
@@ -737,7 +739,7 @@ Component * ComponentList::getComponent(const QString &id)
return (*iter).get();
}
Component * ComponentList::getComponent(int index)
Component * PackProfile::getComponent(int index)
{
if(index < 0 || index >= d->components.size())
{
@@ -746,7 +748,7 @@ Component * ComponentList::getComponent(int index)
return d->components[index].get();
}
QVariant ComponentList::data(const QModelIndex &index, int role) const
QVariant PackProfile::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
@@ -765,8 +767,9 @@ QVariant ComponentList::data(const QModelIndex &index, int role) const
{
switch (column)
{
case NameColumn:
return d->components.at(row)->isEnabled() ? Qt::Checked : Qt::Unchecked;
case NameColumn: {
return patch->isEnabled() ? Qt::Checked : Qt::Unchecked;
}
default:
return QVariant();
}
@@ -776,7 +779,7 @@ QVariant ComponentList::data(const QModelIndex &index, int role) const
switch (column)
{
case NameColumn:
return d->components.at(row)->getName();
return patch->getName();
case VersionColumn:
{
if(patch->isCustom())
@@ -819,7 +822,7 @@ QVariant ComponentList::data(const QModelIndex &index, int role) const
return QVariant();
}
bool ComponentList::setData(const QModelIndex& index, const QVariant& value, int role)
bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
{
@@ -837,7 +840,7 @@ bool ComponentList::setData(const QModelIndex& index, const QVariant& value, int
return false;
}
QVariant ComponentList::headerData(int section, Qt::Orientation orientation, int role) const
QVariant PackProfile::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal)
{
@@ -856,38 +859,42 @@ QVariant ComponentList::headerData(int section, Qt::Orientation orientation, int
}
return QVariant();
}
Qt::ItemFlags ComponentList::flags(const QModelIndex &index) const
// FIXME: zero precision mess
Qt::ItemFlags PackProfile::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())
if(patch->canBeDisabled() && !d->interactionDisabled)
{
outFlags |= Qt::ItemIsUserCheckable;
}
return outFlags;
}
int ComponentList::rowCount(const QModelIndex &parent) const
int PackProfile::rowCount(const QModelIndex &parent) const
{
return d->components.size();
}
int ComponentList::columnCount(const QModelIndex &parent) const
int PackProfile::columnCount(const QModelIndex &parent) const
{
return NUM_COLUMNS;
}
void ComponentList::move(const int index, const MoveDirection direction)
void PackProfile::move(const int index, const MoveDirection direction)
{
int theirIndex;
if (direction == MoveUp)
@@ -923,22 +930,22 @@ void ComponentList::move(const int index, const MoveDirection direction)
scheduleSave();
}
void ComponentList::invalidateLaunchProfile()
void PackProfile::invalidateLaunchProfile()
{
d->m_profile.reset();
}
void ComponentList::installJarMods(QStringList selectedFiles)
void PackProfile::installJarMods(QStringList selectedFiles)
{
installJarMods_internal(selectedFiles);
}
void ComponentList::installCustomJar(QString selectedFile)
void PackProfile::installCustomJar(QString selectedFile)
{
installCustomJar_internal(selectedFile);
}
bool ComponentList::installEmpty(const QString& uid, const QString& name)
bool PackProfile::installEmpty(const QString& uid, const QString& name)
{
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
if(!FS::ensureFolderPathExists(patchDir))
@@ -966,7 +973,7 @@ bool ComponentList::installEmpty(const QString& uid, const QString& name)
return true;
}
bool ComponentList::removeComponent_internal(ComponentPtr patch)
bool PackProfile::removeComponent_internal(ComponentPtr patch)
{
bool ok = true;
// first, remove the patch file. this ensures it's not used anymore
@@ -1016,7 +1023,7 @@ bool ComponentList::removeComponent_internal(ComponentPtr patch)
return ok;
}
bool ComponentList::installJarMods_internal(QStringList filepaths)
bool PackProfile::installJarMods_internal(QStringList filepaths)
{
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
if(!FS::ensureFolderPathExists(patchDir))
@@ -1078,7 +1085,7 @@ bool ComponentList::installJarMods_internal(QStringList filepaths)
return true;
}
bool ComponentList::installCustomJar_internal(QString filepath)
bool PackProfile::installCustomJar_internal(QString filepath)
{
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
if(!FS::ensureFolderPathExists(patchDir))
@@ -1139,7 +1146,7 @@ bool ComponentList::installCustomJar_internal(QString filepath)
return true;
}
std::shared_ptr<LaunchProfile> ComponentList::getProfile() const
std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
{
if(!d->m_profile)
{
@@ -1161,7 +1168,7 @@ std::shared_ptr<LaunchProfile> ComponentList::getProfile() const
return d->m_profile;
}
void ComponentList::setOldConfigVersion(const QString& uid, const QString& version)
void PackProfile::setOldConfigVersion(const QString& uid, const QString& version)
{
if(version.isEmpty())
{
@@ -1170,7 +1177,7 @@ void ComponentList::setOldConfigVersion(const QString& uid, const QString& versi
d->m_oldConfigVersions[uid] = version;
}
bool ComponentList::setComponentVersion(const QString& uid, const QString& version, bool important)
bool PackProfile::setComponentVersion(const QString& uid, const QString& version, bool important)
{
auto iter = d->componentIndex.find(uid);
if(iter != d->componentIndex.end())
@@ -1196,7 +1203,7 @@ bool ComponentList::setComponentVersion(const QString& uid, const QString& versi
}
}
QString ComponentList::getComponentVersion(const QString& uid) const
QString PackProfile::getComponentVersion(const QString& uid) const
{
const auto iter = d->componentIndex.find(uid);
if (iter != d->componentIndex.end())
@@ -1205,3 +1212,14 @@ QString ComponentList::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-2019 MultiMC Contributors
/* 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.
@@ -31,10 +31,10 @@
#include "net/Mode.h"
class MinecraftInstance;
struct ComponentListData;
struct PackProfileData;
class ComponentUpdateTask;
class MULTIMC_LOGIC_EXPORT ComponentList : public QAbstractListModel
class MULTIMC_LOGIC_EXPORT PackProfile : public QAbstractListModel
{
Q_OBJECT
friend ComponentUpdateTask;
@@ -46,8 +46,8 @@ public:
NUM_COLUMNS
};
explicit ComponentList(MinecraftInstance * instance);
virtual ~ComponentList();
explicit PackProfile(MinecraftInstance * instance);
virtual ~PackProfile();
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,6 +114,10 @@ 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;
@@ -121,8 +125,6 @@ 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);
@@ -134,6 +136,7 @@ private slots:
void updateSucceeded();
void updateFailed(const QString & error);
void componentDataChanged();
void disableInteraction(bool disable);
private:
bool load();
@@ -145,5 +148,5 @@ private:
private: /* data */
std::unique_ptr<ComponentListData> d;
std::unique_ptr<PackProfileData> d;
};

View File

@@ -9,9 +9,8 @@
class MinecraftInstance;
using ComponentContainer = QList<ComponentPtr>;
using ComponentIndex = QMap<QString, ComponentPtr>;
using ConnectionList = QList<QMetaObject::Connection>;
struct ComponentListData
struct PackProfileData
{
// the instance this belongs to
MinecraftInstance *m_instance;
@@ -38,5 +37,6 @@ struct ComponentListData
QTimer m_saveTimer;
shared_qobject_ptr<Task> m_updateTask;
bool loaded = false;
bool interactionDisabled = true;
};

View File

@@ -33,7 +33,7 @@ slots:
auto time_parsed = timeFromS3Time(timestamp);
auto time_serialized = timeToS3Time(time_parsed);
QCOMPARE(time_serialized, timestamp);
}

View File

@@ -1,4 +1,4 @@
/* Copyright 2013-2019 MultiMC Contributors
/* 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.

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