-
-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for downloading and installing informal modrinth packs #272
Conversation
- Add additional test cases to ModrinthApiPackFetcher - ProjectRef knows how to extract project ID/version from URL
I'm sorry, these changes are way too disruptive. You'll need to be extremely minimal in your refactoring. Specifically,
|
I felt the need for restructure to get my head around the code for tests, but now with the tests i can comfortably undo many of code-wise refactors.
I will re-merge these changes into the original package and see how i can minimize restructuring. I will propose a class structure to minimize structural changes:
Noted. What are the modern practices for this? Would I just name the interface without the I can tell I'm not quite getting the Reactive Streams just yet; I'm in the middle of giving the docs a read-through, and i would appreciate feedback on the way the I expect I will be leaving the I appreciate and welcome any additional feedback, i do not aim to be disruptive. 😄 |
- Remove ModrinthModpack class and config - Use InstallModrinthModpackCommand as source of config
Sorry for my less-than-constructive initial feedback. It didn't help that I only had a few minutes at the time to reply via the mobile app. I also apologize for the total lack of existing unit tests for the Modrinth commands. I was going to suggest I write those before you proceed, but you beat me to it 😀. Please refer to I prefer the sound of your revised strategy. In fact, I am expecting a majority or all of the changes to reside in As for avoiding "I" prefix. Yes, just name interfaces sensibly and intuitively. It shouldn't take a prefix to identify it's an interface...and in most cases the object oriented design should make interface/class non-important to the user/caller. For the reactive calls, I recommend glancing through https://projectreactor.io/docs/core/release/reference/ and/or https://projectreactor.io/learn. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wanted to pass along a few initial code comments.
src/main/java/me/itzg/helpers/modrinth/ModrinthApiPackFetcher.java
Outdated
Show resolved
Hide resolved
src/main/java/me/itzg/helpers/modrinth/ModrinthApiPackFetcher.java
Outdated
Show resolved
Hide resolved
src/main/java/me/itzg/helpers/modrinth/ModrinthApiPackFetcher.java
Outdated
Show resolved
Hide resolved
src/main/java/me/itzg/helpers/modrinth/ModrinthPackInstaller.java
Outdated
Show resolved
Hide resolved
- No longer passing InstallModrinthModpackCommand as config - Expect ModrinthApiClient to be passed in, vs constructed
- no longer consume InstallModrinthModpackCommand as config - add initial unit test demonstrating minimum assembly and extraction of modrinth pack
private final boolean forceModloaderReinstall; | ||
private final SharedFetchArgs sharedFetchArgs; | ||
|
||
public ModrinthPackInstaller(ModrinthApiClient apiClient, SharedFetchArgs sharedFetchArgs, Path zipFile, Path outputDirectory, Path resultsFile, boolean forceModloaderReinstall) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just thinking, rather pass in SharedFetchArgs
it would be cleaner to pass in SharedFetch.Options
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part confuses me: the only consumer of this in the whole class is the Quilt loader installer; why does the Quilt loader need it while Forge and Fabric don't? (I acknowledge this question is for my curiosity and desire for architectural consistency; having spent so much time in this code now, i want to come back to this class and clean it up but that falls beyond the scope of what i am trying to achieve here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair question 🙂. I have been evolving the design over time, so Quilt is the newer of the three implementations with cleaner shared fetch usage. If you're interested in a little extra cleanup, the SharedFetch.Options
should really be passed in rather than the default used here from the Options.builder().build()
call.
mc-image-helper/src/main/java/me/itzg/helpers/fabric/FabricLauncherInstaller.java
Line 48 in 580e62b
try (SharedFetch sharedFetch = sharedFetch("fabric", Options.builder().build())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and Forge installer is "pre shared fetch", so it's calling me.itzg.helpers.http.Fetch#fetch
to create one-off instances.
The latest changes are looking really good. Thanks for jumping into this feature BTW. |
- private functions in ModrinthModpackIndex use apiClient field
- ModrinthPackInstaller returns both Index and list of installed files (Required for generating manifest) - ModrinthTestHelpers.createModrinthPack returns byte array (Enables gluing whole test arch without writing tempfiles)
71260a9
to
51ea538
Compare
- Broken state, needs investigation
- cleanup test broken
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just taking a quick look at a recent change
void testProjectRefHasProjectSlug() { | ||
projectRefUT = new ProjectRef(this.expectedSlug, null); | ||
|
||
assertEquals(expectedSlug, projectRefUT.getIdOrSlug()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please switch to https://assertj.github.io/doc/ rather than using the junit assertions. It'll be consistent with the rest of the project and they are much more expressive.
Just got it tested out and i was able to use it to download my self-hosted modpack. Due to the nature of my pack i would prefer not to share its URL for validation testing; if necessary I can assemble another one and share its URL with you. What are the next steps for getting this merged? |
It seems like unit tests will be sufficient, so don't worry about providing an additional mrpack URL for further manual testing. From here the only remaining step is code review and iterating on changes from that. |
Sorry, I needed to put a fix in for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great overall! Very nice refactorings. Please switch to AssertJ -- I provided a specific comment where it would have helped even more so.
src/main/java/me/itzg/helpers/modrinth/ModrinthPackInstaller.java
Outdated
Show resolved
Hide resolved
src/test/java/me/itzg/helpers/modrinth/InstallModrinthModpackCommandTest.java
Outdated
Show resolved
Hide resolved
I just took the body of the mainline |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All looks great. I'll get this merged and cut a release. Don't worry if you find any follow up issues during final integration with the docker image repo -- can iterate on a follow up PR as needed.
) | ||
.doOnNext(version -> log.debug("Resolved version={} from projectRef={}", version.getVersionNumber(), projectRef)) | ||
.publishOn(Schedulers.boundedElastic()) // since next item does I/O | ||
.filter(version -> needsInstall(prevManifest, project, version)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kMaiSmith I just realized you seem to have removed this "force synchronize" feature. Can you create a follow up PR to put it back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created #290 to track this
@kMaiSmith I needed to revert this PR in #292. It has caused a couple of regressions one of which is critical since it prevents users from restart their container with a previously installed modpack. |
...I will revisit this over the weekend to see if I can fix the versionId being null in the resulting manifest. |
Hi there! I'm curious about the status of this PR. I'm looking to share an informal modrinth pack with friends by storing the As an aside, the existing feature to auto-fetch modpacks from modrinth is awesome. I'm coming back to minecraft after a few years and I'm amazed at how slick self-hosting a modded minecraft server is nowadays! |
This MR is merged and ready to use in the image. The only thing left to implement is handling local mrpack files, but your use case is covered with hosting in GitHub repo. |
...looks like I need to fix the docs at https://docker-minecraft-server.readthedocs.io/en/latest/types-and-platforms/mod-platforms/modrinth-modpacks/#modpack-project |
...and I misspoke, the final integration using mrpack URLs may not have been completed. |
Thanks for taking a look! I was wondering if it had slipped through the cracks since it was merged and then reverted, and GitHub doesn't really make that state visible. |
FYI changes in this PR were restored in #293 |
Backs #271
Purpose
Decouple the Modrinth
.mrpack
fetching mechanism from the pack installation mechanism to enable installing packs beyond the Modrinth APIStrategy
InstallModrinthModpackCommand
class into its own package, leaving theInstallModrinthModpackCommand
a thin wrapper for the new package interfaceModrinthAPIPackFetcher
class backed by theIModrinthPackFetcher
interfaceModrinthHttpPackFetcher
to fetch non-Modrinth-API packs also implementing theIModrinthPackFetcher
class to capture
.mrpack` extraction logicModrinthModpack
base class which is responsible for coordinating the fetch and install actionsChecklist
.mrpack
from Modrinth APIInstallModrinthModpackCommand
to use new logicmodrinth
package