JoinGG

Server resource packs in Minecraft without breaking joins

The server.properties keys for a server resource pack, why the SHA-1 must change whenever the file does, and how to test before players find the failure.

SweetMask · 5 min read

When an optional server resource pack fails, most players never tell you. The client shows a brief "1 out of 1 pack(s) failed to download" notice, then loads the world with vanilla textures. Your server log records nothing. Avoiding that takes three settings in server.properties: a direct-download link in resource-pack, the file's current SHA-1 in resource-pack-sha1, and require-resource-pack left off until the pack has been tested.

Five keys in server.properties

The server reads these at startup, so any change needs a restart.

resource-pack=https://example.net/packs/survival-v7.zip
resource-pack-sha1=
resource-pack-id=
require-resource-pack=false
resource-pack-prompt=

resource-pack is an HTTP or HTTPS address that returns a ZIP file of at most 250 MiB, the ceiling the Minecraft Wiki gives. resource-pack-sha1 is the SHA-1 of that exact file in 40 lowercase hexadecimal characters: optional on paper, necessary in practice. require-resource-pack (1.17 onwards) disconnects anyone who declines, and resource-pack-prompt adds your own text to the accept screen as a text component; check the wiki for the syntax your version expects. resource-pack-id (1.20.3 onwards) is an optional UUID identifying the pack to clients, derived from the URL if left empty.

When the server rewrites the file, the address may appear as https\://...: Java's properties format escaping the colon, and harmless. The rest of server.properties is covered separately, as are the files Paper adds on top.

The client requests the address and expects ZIP bytes back, so a share page with a download button fails. These work:

  • Dropbox, with dl=0 at the end of the share link changed to dl=1, which Dropbox documents as forcing a download.
  • A GitHub release asset linked by its tag. Avoid /releases/latest/download/, which always serves the newest upload and can change the file before you change the hash.
  • A web server you control, the most predictable option.
  • MCPacks (mc-packs.net), a free host for server packs, capped at 95 MB.

Google Drive and OneDrive share links open a preview page, so the client downloads HTML. Source servers handle the same job with FastDL, a plain web server doing the downloads. Check any link from a machine that has never seen it:

curl -sSL -o check.zip "https://example.net/packs/survival-v7.zip"
sha1sum check.zip

Matching hashes mean the host serves the file you think it does.

Why the hash has to change with the file

The client caches server packs: since 1.20.3, up to 20 of them in the downloads folder of the game directory, with a log.json recording each download. The hash tells it whether a cached copy is current. Without one, the protocol documentation notes, the client cannot verify the file and will likely download it again, wasting bandwidth on every join.

An out-of-date hash is worse. Replace the ZIP at the same address and keep the old SHA-1, and players who have the old pack keep using it, because it still matches, while anyone new downloads the new file, fails the check and gets nothing. So every change to the pack means a new hash and a restart. Re-zipping unchanged files usually changes the hash too, because ZIP entries carry timestamps, and a new file name per build stops caches along the way from serving an old copy.

Generate the hash with sha1sum pack.zip on Linux, shasum -a 1 pack.zip on macOS, or (Get-FileHash pack.zip -Algorithm SHA1).Hash.ToLower() in PowerShell, which otherwise prints uppercase.

Size and pack format

250 MiB is a ceiling, not a target: every new player downloads the whole pack before playing, the same trade-off as the download cost of a modpack.

The pack's pack.mcmeta declares the game versions it was made for. Older packs use a single pack_format number; since 1.21.9 (snapshot 25w31a) packs use min_format and max_format, with pack_format still required when a pack also supports older versions. The numbers change with most releases, so look up your server's exact version in the wiki's pack format table rather than copying them from an old pack.

More than one pack

server.properties holds one pack. Since 1.20.3 a server can push several and remove them individually, and plugins use that: on Paper through Adventure's sendResourcePacks and a ResourcePackRequest, which either replaces a player's existing server packs or stacks new ones on top (Paper's resource pack page shows the calls). Plugins that add custom items usually build and serve their own pack, so find out how yours expects to share the client before also setting resource-pack.

Bedrock players on Geyser

Geyser does not convert Java packs. Bedrock players need a Bedrock pack (.mcpack or .zip) in Geyser's packs folder: plugins/Geyser-<platform>/packs/ on plugin platforms, config/Geyser-<platform>/packs/ on Fabric and NeoForge. force-resource-packs is on by default, so a Bedrock player who declines cannot connect. Packs can also be sent by URL, but Geyser's pack documentation lists the Bedrock client's demands: a direct link, an exact Content-Length and Content-Type: application/zip.

GeyserMC points to two conversion tools. Rainbow is a client-side Fabric mod for packs that add custom items, blocks and similar content, and it also writes Geyser's mappings. Thunder is for packs that only retexture vanilla content and is still marked as a work in progress. Bedrock has its own caching trap: Microsoft's manifest reference says a previously imported pack is only replaced when the version in its manifest.json is higher, so raise it with every change. For the wider differences, see what each edition can join.

Testing before the players do

  1. Download the pack from its public address on another machine and compare its SHA-1 with your local copy.
  2. Restart the server after editing server.properties.
  3. Join with a client that has never had the pack, such as a launcher installation with its own game directory. The download screen should appear.
  4. If it does not, read the client's logs/latest.log and downloads/log.json.
  5. Change one texture, rebuild, update the hash, restart and rejoin with the same client. It should download again.
  6. Only then set require-resource-pack=true.

When players say the pack did not load

Ask what they saw, word for word. A "pack(s) failed to download" notice means the file never arrived intact, so check the link and the hash. "Server resource pack couldn't be applied" means it arrived and the game could not use it, which points at the ZIP. Then ask them to look at the Server Resource Packs option on your server's entry in their multiplayer list: set to Disabled, it declines an optional pack without asking. School and office networks that block file hosts look exactly like a bad link, one more reason to host the pack somewhere dull and permanent. If none of that explains it, their latest.log will; it is the only log that can, because your server never sees the download.

Tags
minecraftresource packsserver configuration
Share

SweetMask

Published · 5 min read

All articles

Keep reading