Importing Optional Client Mods

Did you know that the MCUpdater team hosts a small pack of client-only mods suitable for inclusion in most serverpacks? No? Well, neither do most of our other users, apparently.

We’ve been doing this for years now, but I realized this week that we’ve never documented the process outside of one-on-one conversations on Discord. Oops 😛 Sorry, I’ll fix that now.

What is “the optional(s) pack”?

So yeah. The optional pack is a whole mess of mods for the recent popular modded MC versions:

  • 1.7.10
  • 1.10.2
  • 1.12.2

When the next major MC version becomes feasible, we will update to support it as well.

All of these mods are safe to include on the client without any server-side support (though there may be server-side support for some mods as well). The pack is maintained and hosted by us as a community resource to save people time and effort – largely by preventing your players from whining about not having access to a popular mod that you don’t use and therefore forgot to include in your already massive pack.

And adding the pack is as simple as adding one line to your XML:

<Import url="https://files.mcupdater.com/optional/ServerPack.xml">optional</Import> 

I typically put this include as the second entry in my <Server/> block, right after the Forge import. This makes it easy to override.

How/why/when do I override optional mods?

In many cases, you can happily import the optionals and then forget about it. But that’s not always the case. Let’s discuss a few scenarios where simply dropping the import into your pack is not enough.

I don’t want people installing mod X

Suppose your server is using TOP. Lots of people use and enjoy it, preferring it over Hwyla. I won’t judge. Even though TehNut jokes about only supporting MCUpdater on the mod’s page :P.

You really don’t want both overlays fighting on your screen – it’s a case of one or the other. And because TOP has a server-side component, if you install it on your server, all of your clients will need to install it… and that means you’ll be serving them a link to TOP and they probably shouldn’t install Hwyla/Waila by accident. If you’re using our optionals pack, we provide links to Hwyla as well as a few of its more popular addons.

Disabling a mod is as simple as adding a line (anywhere after the import) that looks something like:

<Module id='waila'><ModType>Removal</ModType></Module>

Where the ‘id’ is whatever ID is used in the import. (And yes, we call Hwyla “waila” because legacy reasons.)

And that’s it. The mod won’t show up for installation in MCUpdater and your users won’t accidentally get double overlays. Because we annotate any addons with the appropriate dependency attributes, they won’t show up in the list either – after all, if Waila isn’t in your pack and Waila Harvesting depends on it, they can’t install Waila Harvesting, so there’s no point in muddying things further.

The same goes for if you want to prevent people from using Journeymap or anything else really.

I want to provide a custom/different version of mod Y

Maybe you want to target a newer/older version of the mod. Maybe you compiled it yourself or otherwise need to host the mod from a different URL. Maybe we’re just being really slow about updating the public pack.

If there’s a mod we provide that you want to overwrite, you can do it. Just put in an entry in your pack like you would otherwise. As long as the mod ID you provide for your version matches the one in our import, MCUpdater will use whichever <Module/> entry comes last in the pack. If you only want to change one or two elements of the mod entry, you can define it as an Override and just provide the changes – but if you want to replace the whole block, you can do so as if the mod was never imported in the first place.

For an example of import chain overrides, see SMB’s post on incremental updates.

Wait, why are you including Library Z as an optional mod?!

Yeah, I know. Libraries are typically not optional… except when you’re only adding them in order to support an optional mod. So yes, we have a few major libraries in the pack. This isn’t ideal, but it’s also not a problem because if you’re using that library for something else in your pack, you’ll have a normal entry for the mod that installs the version you need. As long as you use the same mod ID, it will override, etc… and everything will play nice together.

In an effort to prevent people from accidentally installing unnecessary libraries (which shouldn’t hurt anything, it’s just a wasted install), the mod names for libraries is prefixed with an obvious “[library]” marker.

Wait again, I see mods in here that depend on Forestry and Thaumcraft and…

Yeah, I know. These are purely client-side addons that don’t need any special attention on the server to work. By specifying them as depending on a content mod, we are able to provide them conditionally. Just like disabling waila will prevent us from showing waila addons to users, serving a pack without forestry will prevent us from showing bee breeding jei addons to them.

If you are using a mod that has optional JEI/IGI-XML/etc… sort of addons that we’re including, make sure you match its ID and users will be able to see the optional addons for it.

When does the pack get updated?

When people complain about it, mostly. Often those people are the MCU team, but anyone in the community can pipe up and let us know that a mod is out of date, etc… There are two ways you can go about encouraging us to update the pack:

  1. Log into our Discord server and tell us.
  2. Send us a PR via https://github.com/mcupdater/pack-optional.

In either case, if it is a legitimate update, we should take care of it in a day or three. If you can’t wait that long, you should update your own pack while you’re waiting for us to update the public copy of the pack.

Argh! You updated the pack and now EVERYTHING IS RUINED!

Sorry. Let us know what update broke your client, and we’ll see what we can do. Either we’ll roll back the change or we’ll provide an alternative mod entry as appropriate.

I really love Mod A, will you add it to the pack so everyone else can enjoy it too?

Maybe. We’ve had to tighten down our criteria for including mods in the public pack. Right now, the requirements are:

  1. The mod must not require any server-side component to function. This means that mods like TOP and Ambidextrous are out because they have to be installed on the server as well as the client.
    • The one minor exception to this are informational sort of plugins like JEI or In-Game-Info XML addons that depend on some 3rd party client+server mod.
  2. The mod must not be perceived by the community as a “cheat”. This means that x-ray stuff or client movement hacks are out. Basically anything that an average server operator might not want their users installing. If you want those on your own pack, more power to you – but they’re not going in the public pack for everyone.
  3. The mod must have an obvious client-side functionality. We’re not installing mods that are merely harmless to install on the client, they need to be there for a reason. So things like Morpheus are out because their functionality is purely server-side.
  4. The mod should be largely self-contained, no weird dependencies. I don’t like putting libraries in the optionals pack. If a mod is otherwise a good fit, but it depends on Modder Joe’s Self-Named Corelib Of Separate Modfulness… we’re probably going to pass. The only libraries I’m including are major ones that people have a reasonable chance of overriding and installing anyway. This isn’t a hard rule, but so if a mod is amazing, we’ll take it – joescorelib and all… but yeah. I really don’t like putting libraries in the optionals pack.

But all of these guidelines aside, we reserve the right to refuse to publicly provide a mod to folks for any reason, no explanation necessary. Maybe the mod has a track record of causing problems for clients. Maybe its author is a jerk. Maybe the mod is brand new, by an untrusted developer, and we want to give it some time. Whatever the case, we’ll try to explain the reasoning for our decision to add/exclude a mod… but don’t make any promises. And those decisions are likely final – continued whining after a decision has been made is unlikely to sway us. We have experience dealing with small children.

But yeah, that’s about it. Take a look at the pack, use it if you like. Join the community on Discord and let us know what you think – we’re doing this to make things better for everyone involved, but we can’t do it without feedback 😉

Zipping Configs for Great Laziness

Okay, I’ll be perfectly frank – using the <ConfigFile/> directive in MCU is usually more trouble than it’s worth. Hear me out, I’m not crazy, honest.

The case for laziness

Providing config files is important – but 99.872% of config files either don’t matter to the client or are full of defaults anyway.

This is especially true if you are running Minecraft 1.7 or later. In the beforetime (ie, back when we wrote the current ServerPack XML schema), servers had to ship tons of config files to make sure everyone’s block and item ID’s matched. Standing up a new modded server was more ID conflict resolution than anything else.

But MC1.7 did away with most of the troublesome ID’s, so that’s not a big deal any more.

So now, most configs control things like difficulty settings and drop tables and stuff like that – stuff that only matters to the server.

And of course, then there are the mods that sync their configs with the client from the server directly… 😉

Therefore, I believe that server maintainers are better off:

  1. Only providing config files that matter to the client
  2. Serving those config files in one big zip file

My usual method

On my servers (with say 80 or so mods), I might have 2 <ConfigFile/> directives in the entire pack – and these would be exclusively <NoOverwrite/> configs so I can provide players with sane defaults for settings that they will likely be changing on their clients (like fixed keybindings or the like).

Every other config file that I need to ship goes in one big zip file that I distribute as an Extract mod. When I edit any config files, I rezip the config directory, recalculate its MD5, and I’m done.

The real benefits

There are a lot of functional reasons why doing things this way.

The biggest reason to me personally is that it makes the XML file easier to look at and edit by hand. Obviously this doesn’t matter as much for people who’re relying on tools like FastPack to do all of their pack updates for them.

The biggest reason everyone else should use this method is that it’s a better experience for end users. When you ship 80 mods and 100 config files, that is 180 files that MCU has to scan with each update check. It’s 180 files that have to be downloaded individually from a server on a fresh install – and if you change 20 config files, that’s 20 files that need to be downloaded for that update.

Even though plain text (like config files) compresses very well (75-90%), zipping them doesn’t save a ton of bandwidth since the files are already so small to begin with. Using a real world example, I have a config directory here with 118 files in it. Uncompressed, that is 1.1mb. Zipped, it shrinks down to 196kb, or a bit over 80% savings… but the real savings isn’t the ~800kb shaved off of the top of a full install.

What it does save is round trips to the web server. Downloading one file is always faster than downloading one hundred – even if they all add up to the same total size of the single file – just because the server is having to start and stop a new download each and every time.

Even if the total huge zip file is bigger than the sum of a dozen updated configs when you’re making a change, the one MD5 check and one download will be nicer for any machine capable of running heavily modded Minecraft in the first place.

There are downsides?

Of course there are. The biggest downside is that you can’t tell what configs are being provided by a pack without actually looking inside the zip.

Additionally, you can’t just change a config file without rebuilding the whole zip (but you’d have to tweak the XML in either case anyway).

Also, if you are using SMB’s incremental pack method, this method really isn’t as appropriate – and you’re probably better off doing things the way he manages them.

How I really do it

Remember how I said I wasn’t crazy? Well, I’m still not. I don’t do this by hand, I wrote a short shell script that does all of this for me.

The absolute last entry in the pack XML will look something like this:

<!-- zip file containing all configs -->
<Module id="configs" name="config files">
    <URL>http://files.mcupdater.com/packname/config.zip</URL>
    <Required>true</Required>
    <ModType inRoot="true">Extract</ModType>
    <MD5>a8196a5d89d752608089ca293c2f90a9</MD5> <!-- auto:config.zip -->
</Module>

That auto:config.zip bit there is important, it’s how my script knows what MD5 to update:

#!/bin/sh
rm config.zip
zip -r config.zip config/
MD5=`md5sum config.zip | cut -f 1 -d ' '`

sed -i.bak 's#<MD5>.*</MD5> <!-- auto:config.zip#<MD5>'${MD5}'</MD5> <!-- auto:config.zip#' ServerPack.xml

diff ServerPack.xml.bak ServerPack.xml

And that’s really all there is to it. I update the contents of the config directory to match my changes and I run the script.

I usually do this directly on the file server, where the config.zip, config/* files, and pack xml are all live versions. When I make this change and push the button, the pack is updated immediately and the next user to update will grab the new zip.

The end result is that I am able to update config files this way faster than by using any other method (fastpack, by-hand, etc…) – so I don’t feel a need to push off config tweaks to a major update cycle. If we need to change a setting on the server, we’ll change the setting, I’ll upload the file, pull the trigger, and the players will have the change before the server is done rebooting.

Bundled Native Executables

We’ve toyed with this in the past, but had bad luck at the time – so players have been always been forced to deal with an executable Jarfile to launch MCU. This is fine for the most part, but it is suboptimal.

Because the bootstrap is so stable these days, we are now revisiting the project to provide native executables to handle the bootstrap for you. This means that instead of downloading and running a jarfile, you will now be able to download an EXE for Windows and an App for Mac users.

NB: The Windows executable isn’t actually available yet – we’ll take care of that out soon.

These files are simply wrappers that launch the standard build jar file for you, but they make it a bit easier to integrate with other systems that don’t want to treat jars like programs.

To download a standard generic MCU bundled native executable, you can find links at our download site, or in the sidebar of this page.

Note, the exe/app are unsigned, so it is entirely possible that it will warn players about it (or possibly even prevent them from running the binary, depending on their local security settings). There isn’t really anything we can do about this, and those players unable to work around such a restriction are best off sticking with the traditional jar distribution.

Custom Bundles

We also acknowledge those community members who have been building custom bootstrap jars for their players and would like to continue supporting them. So the scripts we are using to package the bundles and any instructions on their use are available on github at https://github.com/MCUpdater/MCU-Bundler.