itzg / mc-image-helper

This tool does the complicated bits for the itzg/minecraft-server image
MIT License
59 stars 26 forks source link

Modrinth: Support unpublished Modrinth packs #271

Open kMaiSmith opened 1 year ago

kMaiSmith commented 1 year ago

Context

I use the Modrinth .mrpack format to hand role modpacks for distributing privately, this has proven a very helpful for keeping me and my friends synchronized with the modpack for our server. However, since i am not able to publish this modpack to modrinth due to licensing issues i would like to be able to point the Minecraft Docker image to my .mrpack url and have the modpack be installed to spec.

This backs itzg/minecraft-docker-server#2144

Proposed solution

I need this feature for my local service instance, so I intend to attempt to separate the Modrinth pack downloading code from the pack installation code and leverage the existing HTTP classes to facilitate HTTP downloads of .mrpack.

I am not sure this calls for changing the interface to the Modrinth part of the CLI, so to leverage this functionality when implemented you would specify the Modrinth Project to be a URL to your .mrpack. The Modrinth installer logic would infer from URLs ending in .mrpack to do a direct fetch rather than an API lookup.

Notes

@itzg Please advise if you think a better approach could be taken

I expect this to take me some time to implement

itzg commented 1 year ago

That overall approach sounds good. What were your thoughts about identifying when the installation of the mrpack is up to date? Would you be hosting the file on a web server that supports https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since ?

If you quickly find the changes will be overwhelming, then just let me know. This is a feature I was personally interested in implementing fairly soon anyway.

kMaiSmith commented 1 year ago

I had not yet fully considered the how to avoid redundant .mrpack downloads. I did notice the Modrinth API based fetch flow avoiding redundant downloads based on pack version metadata; given the lack of metadata available before fetching the pack the If-Modified-Since header would work well and be straightforward.

It could also be configured to respect a simple documented pattern, say <slug>.<version>.mrpack; if the modpack file matches this pattern the version and modpack name could be extracted and tracked a la Modrinth API modpacks.

One question i have so far to support implementation, does http.SharedFetch support fetching from multiple hosts from a single instance of SharedFetch?

edit: Question 2: is there a tangible difference between a Modrinth project ID and a project Slug? They seem to be used interchangeably, i am wondering if it is safe to continue doing so

itzg commented 1 year ago

I had not yet fully considered the how to avoid redundant .mrpack downloads. I did notice the Modrinth API based fetch flow avoiding redundant downloads based on pack version metadata; given the lack of metadata available before fetching the pack the If-Modified-Since header would work well and be straightforward.

I'm still leaning towards this since it requires no extra steps on the user and is a deterministic identifier. Again, the only downside is that some file servers don't support that mechanism, but that's not a big deal since it'll just download every time in those cases.

It could also be configured to respect a simple documented pattern, say <slug>.<version>.mrpack; if the modpack file matches this pattern the version and modpack name could be extracted and tracked a la Modrinth API modpacks.

That's an interesting idea, but might be too much too expect upon the the end user.

One question i have so far to support implementation, does http.SharedFetch support fetching from multiple hosts from a single instance of SharedFetch?

Yes. The only thing that might be making it look like single host support is the uriBuilder instance in ModrinthClient.

edit: Question 2: is there a tangible difference between a Modrinth project ID and a project Slug? They seem to be used interchangeably, i am wondering if it is safe to continue doing so

They are different things but their API tends to accept either

https://docs.modrinth.com/api-spec/