Hostowanie resource packa dla serwera Minecraft: kompletny przewodnik (2026)

Hostowanie resource packa dla serwera Minecraft: kompletny przewodnik (2026)

Jesli twoj serwer ma customowe modele przez ItemsAdder albo Oraxen, wlasny font, tlumaczenia na cztery jezyki albo po prostu vanilla pack z lore-teksturami, predzej czy pozniej trafisz na to samo pytanie: gdzie ten zip ma lezec, zeby klient sciagal go szybko, bez zerwan i bez Failed to download resource pack. W tym przewodniku przechodzimy po tym, jak poprawnie hostowac packa, jak wygenerowac sha1, jakie klucze w server.properties dziala na 1.21+ i czemu Discord CDN wypadl z gry pod koniec 2024 roku.

Czemu hostowac packa samemu, a nie przez plugin

Minecraft 1.20.3+ potrafi wyslac klientowi nawet piecdziesiat resource packow przez API serwera, ale samo bundle z teksturami nigdy nie idzie przez polaczenie Minecrafta. Vanillowy klient otwiera zwykly HTTPS GET na URL z resource-pack= (albo URL od plugina) i ciagnie zip bezposrednio. Serwer Minecrafta nie bierze udzialu w tej wymianie: nie obchodzi go, czy pack lezy obok jara czy na innym kontynencie, wazne zeby URL odpowiedzial i hash sie zgadzal.

Z tego wynika prosta zasada: predkosc i stabilnosc downloadu packa nie maja nic wspolnego z twoim hostingiem Minecrafta, tylko z tym gdzie lezy zip. Jezeli pack jest serwowany z taniej amerykanskiej VPS na 100 Mbps, gracz z Polski na zwyklej domowej linii czeka 30 sekund tylko na ciagnieciu liny, a kazdy malenki problem TCP konczy sie timeoutem. Polozenie packa za normalnym CDN (Cloudflare, Bunny, R2) sprawia, ze ten sam download konczy sie w 2-3 sekundy niezaleznie od regionu.

Drugi punkt: force-resource-pack=true plus poprawny resource-pack-sha1 to klucz do tego, zeby klient albo automatycznie zaakceptowal packa, albo czysto wywalil sie na Failed to apply resource pack. Bez sha1 klient sciaga packa za kazdym razem na join, czyli marnujemy ruch lub sekundy po stronie gracza. Z dobrym sha1 klient cachuje archiwum po pierwszym pobraniu i przy nastepnym wejsciu po prostu wyciaga je z dysku.

Przygotowanie packa: pack.mcmeta, format, zip

Zanim cokolwiek hostuje, sprawdz strukture packa. Bazowy uklad dla Minecraft 1.21+:

my-pack/
  pack.mcmeta
  pack.png
  assets/
    minecraft/
      textures/
      models/
      lang/
      sounds/

pack.mcmeta dla 1.21.4 (Java Edition) niesie pack_format. Kazda wersja klienta ma swoj numer, aktualna tabela jest na minecraft.wiki w artykule Pack format. Stan na srodek 2025: 1.21.4 to pack_format 46, a 1.21 to 34. Zly numer nie wywala bledu, klient po prostu po cichu nie laduje czesci tekstur.

{
  "pack": {
    "pack_format": 46,
    "supported_formats": [34, 46],
    "description": "MyServer textures 1.21+"
  },
  "language": {
    "pl_pl": {"name": "Polski", "region": "Poland", "bidirectional": false}
  }
}

supported_formats pozwala klientom roznych wersji akceptowac to samo archiwum, a language jest istotne tylko jak wrzucasz wlasne lang/pl_pl.json na vanilla. Nie zapomnij pack.png (64x64 albo 128x128, zwykly PNG); klient pokazuje go w liscie.

Budowa archiwum. Trick: zipuje sie zawartosc, nie folder:

cd my-pack
zip -r -9 ../my-pack.zip . -x "*.DS_Store" -x ".*"

Walidacja: unzip -l my-pack.zip | head powinno pokazac pack.mcmeta i assets/ na samej gorze, bez wrappera my-pack/. Jesli wewnatrz jest dodatkowy folder, klient krzyczy Couldn't load resource pack: invalid pack format.

Generowanie sha1: sha1sum i narzedzia online

Minecraft sprawdza dokladnie SHA-1 z bajtow zip, bez soli, bez sztuczek. Linux/macOS:

sha1sum my-pack.zip
8f3a9c1d4e2b6f7a8d9e0f1a2b3c4d5e6f708192  my-pack.zip

Windows w PowerShell:

Get-FileHash -Algorithm SHA1 .\my-pack.zip

Hash w server.properties musi byc lowercase, inaczej vanillowy klient wywala pack hash mismatch. Jesli edytujesz plik recznie, kopiuj wynik sha1sum jeden do jednego. Jezeli automatyzujesz update packa, dodaj krok do CI:

HASH=$(sha1sum my-pack.zip | awk '{print $1}')
echo "resource-pack-sha1=${HASH}" > .env.pack

.env.pack jest potem podlozone w twojem szablonie server.properties przy deployu.

Opcja 1: GitHub raw

Najtanszy i najprostszy sposob, zwlaszcza jak pack juz jest w gicie. Tworzysz publiczne repo, wrzucasz my-pack.zip, bierzesz raw URL:

https://raw.githubusercontent.com/<user>/<repo>/main/my-pack.zip

Plusy: za darmo, wersjonowanie przez tagi i commity, prosty rollback. Minusy i pulapki:

  • GitHub oficjalnie nie poleca raw jako CDN dla binariow. Jak twoj pack pobiera sie tysiace razy na godzine, mozesz dostac rate limit, a w skrajnych przypadkach konto trafi do flagi.
  • Jeden plik w zwyklym repo to limit okolo 100 MB; wieksze packi potrzebuja Git LFS, a LFS ma swoj URL i swoje limity transferu.
  • Latencja srednia. raw.githubusercontent.com idzie przez GitHuba i Fastly, dla wiekszosci regionow ok, ale rzadko najszybciej.

Kiedy pasuje: maly serwer, pack do 20 MB, mniej niz 100-200 graczy online.

Opcja 2: Mc-Packs.net

Serwis dedykowany pod resource packi do serwerow. Wrzucasz zip przez formularz na mc-packs.net, dostajesz bezposredni URL plus policzony sha1. Maja API zeby rotowac ten sam URL przy update.

Plusy: za darmo, brak wlasnej infry, sha1 gotowy do skopiowania. Minusy: zalezysz od cudzego serwisu; jak ich box rzezni, pack przestaje sie ladowac, a ty dowiadujesz sie z czatu. Free tier bez SLA, bez gwarancji ze link bedzie zyl za rok.

Kiedy pasuje: serwer testowy, mala produkcja albo backup mirror dla glownego hosta.

Opcja 3: Cloudflare R2

R2 to S3-kompatybilny obiektowy storage od Cloudflare bez oplat za egress (kluczowa roznica wzgledem AWS S3). Storage kosztuje grosze, downloady graczy nic. Dokumentacja na developers.cloudflare.com/r2.

Bazowy flow:

  1. Tworzysz bucket w R2.
  2. Wrzucasz zip przez rclone albo aws s3 cp z endpointem R2.
  3. Bindujesz publiczna domene (packs.example.net) do bucketu w R2 settings.
  4. Ustawiasz Cache-Control: public, max-age=31536000, immutable na zipie, zeby klienci i edge Cloudflare nie szli ponownie po origin.

Wrzucanie przez rclone:

rclone copy ./my-pack.zip r2:my-bucket/ --header-upload "Cache-Control: public,max-age=31536000,immutable"

URL do server.properties:

https://packs.example.net/my-pack-v12.zip

Zwroc uwage na -v12 w nazwie. To celowe: zamiast walczyc z inwalidacja cache, kazda nowa wersja packa dostaje nowa nazwe pliku, sha1 sie zmienia, gracze ciagna nowy plik, cache dziala czysto. Na R2 za darmo, na innych CDN tez best practice.

Plusy R2: anycast Cloudflare, brak egress billingu, natywna integracja z cache CF, prosta publiczna domena. Minusy: jednorazowa konfiguracja z API Cloudflare i rclone, ale robisz to raz.

Opcja 4: Self-hosted nginx albo Caddy

Jezeli juz prowadzisz VPS albo dedyk pod strone serwera, hostuj statyki tam. Minimalny nginx:

server {
    listen 443 ssl http2;
    server_name packs.example.net;

    ssl_certificate /etc/letsencrypt/live/packs.example.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/packs.example.net/privkey.pem;

    root /var/www/packs;

    location ~* \.zip$ {
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header Access-Control-Allow-Origin "*";
        sendfile on;
        tcp_nopush on;
    }
}

Caddy jeszcze krocej:

packs.example.net {
    root * /var/www/packs
    file_server
    header /*.zip Cache-Control "public, max-age=31536000, immutable"
}

Plusy: pelna kontrola, prawie zerowa latencja jak host packa i host serwera siedza w tym samym DC. Minusy: ty odpowiadasz za uptime, backupy i lacze. Z 100 Mbps i 200 graczami od razu po restarcie lacze sie nasyca na 30 sekund i ktos zlapie timeout.

Sensowny default: postaw Cloudflare w trybie proxy (pomaranczowa chmura) przed wlasnym nginxem. Dostajesz darmowe edge caching, a spike rozprasza sie na edge.

Discord CDN: czemu NIE

Przez lata adminzy wrzucali zip w prywatny kanal Discorda i kopiowali URL do server.properties. Dzialalo wieki, i do konca 2023 te URLe byly stale.

Pod koniec 2023 Discord wyrolowal podpisane tymczasowe URLe (?ex=...&is=...&hm=...), a wiosna 2024 stalo sie to standardem dla wszystkich attachmentow. Podpis wygasa po okolo 24 godzinach. Czyli jak dzisiaj wrzucisz taki URL, jutro twoi gracze widza Failed to download resource pack. Sztuczki z botem rotujacym podpis tez nie ratuja; ToS Discorda wprost zakazuje uzywania ich CDN jako hostingu pod inne projekty.

Wniosek: Discord CDN umarl dla resource packow. Jesli twoja server.properties dzisiaj wskazuje na cdn.discordapp.com/..., przeskocz na ktorakolwiek opcje powyzej zanim chat zacznie krzyczec.

Konfig server.properties

Na Paper/Spigot/Folia 1.21+ kluczowe sa te opcje:

resource-pack=https://packs.example.net/my-pack-v12.zip
resource-pack-sha1=8f3a9c1d4e2b6f7a8d9e0f1a2b3c4d5e6f708192
require-resource-pack=true
resource-pack-prompt=Required textures for the server

Co warto wiedziec:

  • resource-pack-sha1 to wlasciwa nazwa klucza, nie resource-pack-hash, nie sha-1. Udokumentowane na minecraft.wiki w sekcji Server.properties.
  • require-resource-pack=true to nowoczesny odpowiednik starego force-resource-pack. Jak gracz odmowi, serwer kickuje go z wiadomoscia z resource-pack-prompt (albo defaultowa, jak prompt pusty).
  • 1.20.3 i starsze mialy limit 224 znakow na URL. 1.20.3+ limit usunal, ale trzymaj sie pod 1024 znakami; niektore launchery i mody jeszcze obcinaja.
  • resource-pack-prompt przyjmuje prosty JSON text component, mozesz kolorowac i tlumaczyc.

Po edycji server.properties musisz zrestartowac serwer; hot-reload tych kluczy nie dziala.

Per-player packi: ItemsAdder, Oraxen, force-resource-pack pluginy

Przez server.properties mozesz wyslac jeden pack. W 1.20.3+ serwerowe API moze pchnac do piecdziesieciu packow na sesje, i kazdy duzy plugin do customowych itemow z tego korzysta.

ItemsAdder i Oraxen same hostuja packa: instalujesz plugin, on generuje zip, podnosi wbudowany HTTP serwer (albo oddaje twojemu nginxowi) i wysyla graczowi przez ProtocolLib lub Paper API. Twoja jedyna robota to upewnic sie, ze port nasluchu jest dostepny z internetu, a nie tylko z LAN.

Jak chcesz wlasnego packa na gorze, sa pluginy typu ResourcePackHost lub ForceResourcePack ktore na PlayerJoinEvent wysylaja pack przez Player#setResourcePack(url, sha1). Maja zwykle takze opcje per-permission lub per-world: lobby pack na hubie, survival pack na serwerze rozgrywki.

Specjalny przypadek: BungeeCord/Velocity. Na proxy nie ma server.properties, pack idzie albo przez Velocity API, albo przez plugin na backendzie. Wiekszosc setupow idzie druga droga, bo to daje punkt kontroli per serwer.

Wielojezykowe packi

Jesli masz serwer z tlumaczeniami ru/en/de, masz dwie drogi: jeden duzy pack z folderami lang/ na wszystkie jezyki (klient sam wybiera odpowiedni na podstawie ustawien), albo kilka packow i dystrybucja per gracz przez plugin i locale.

Vanilla droga jest czystsza: assets/minecraft/lang/ru_ru.json, en_us.json, de_de.json w jednym zipie, w pack.mcmeta w sekcji language. Archiwum prawie nie rosnie (lang to JSONy 50-200 KB), a wszystko dziala bez plugina.

Jesli packi mocno rozjezdzaja sie (Halloween-tekstury tylko dla ru klientow), to routing per locale przez plugin z Player#getLocale().

Tabela opcji hostingu

SposobKosztPredkoscLimityKiedy brac
GitHub rawza darmosredni100 MB plik, soft rate-limitmaly serwer, pack do 20 MB
Mc-Packs.netza darmosrednibrak SLA, cudza infratest, mirror, mala prod
Cloudflare R2grosze/mcwysoki (anycast)egress free, dowolny rozmiar bucketusrednia/duza prod
Nginx/Caddykoszt VPSzalezy od laczatwoj uptime, twoje backupyjuz masz VPS
Klasyczny S3$$$ za egresswysokiegress zabija budgetjuz na AWS
Discord CDNza darmokrotkoURL umiera w 24hnigdy

Debugging: pack sie nie laduje

Symptomy i gdzie kopac:

  1. Failed to download resource pack. Sprawdzic URL recznie przez curl -I. Jak 200 OK i sensowne Content-Type (application/zip albo application/octet-stream), idziesz dalej. 403 znaczy ze CDN cie blokuje, sprawdz reguly. Timeout znaczy URL nie rozwiazuje sie z obcego boxa; fixuj DNS lub firewall.

  2. Pack hash mismatch. W 99% to mismatch sha1 miedzy server.properties a samym plikiem. Przeliczyc przez sha1sum, wkleic dokladnie, restart serwera.

  3. Gracze mowia, ze pack sciaga sie, ale tekstury sie nie aplikuja. Sprawdz pack_format w pack.mcmeta, prawdopodobnie nie pasuje do wersji klienta. Dodaj supported_formats jako tablice.

  4. Couldn't load resource pack: invalid pack format. W zipie jest dodatkowy folder-wrapper. Przepakuj przez cd my-pack && zip -r ../my-pack.zip ., nie zip -r my-pack.zip my-pack/.

  5. Custom CA. Jak pack siedzi za samopodpisanym TLS, vanillowy klient odmawia. Lecisz na Let's Encrypt, ZeroSSL albo inne publiczne CA.

Wersjonowanie bez bolu

Najczestszy bug przy update packa: podmieniles zip na tym samym URL, odswiezeles sha1 w configu, zrestartowales serwer, ale czesc graczy wciaz laduje stary pack z cache. Cache jest po URL, nie po zawartosci.

Fix: kazda nowa wersja packa dostaje nowa nazwe pliku. Zamiast pack.zip, lec pack-v1.zip, pack-v2.zip. Zadnej inwalidacji cache, zadnego Cache-Control: no-cache, swiezy gracz ciagnie aktualnego builda. Stare pliki mozna wywalic za tydzien-dwa, jak wszyscy nadgonia.

Ten sam trick rozwiazuje dlugi cache CDN: edge Cloudflare lub Bunny moze trzymac plik dniami, a ty wgrales nowego builda piec minut temu. Wersjonowane nazwy omijaja konflikt zupelnie.

FAQ

Czy moge serwowac packa po HTTP bez TLS? Technicznie tak, vanilla klient akceptuje http://. W praktyce nie: niektore sieci firmowe i dostawcy filtruja nieznane HTTP hosty, a Let's Encrypt jest darmowy i instaluje sie dwoma komendami.

Co z packiem 200 MB? Klient zaakceptuje, ale rozwaz podzial na base + addon i wysylke drugiego kawalka przez API ItemsAdder/Oraxen. Duzy zip to dlugi download na mobile i wieksza szansa na zerwanie polaczenia.

Czemu immutable w Cache-Control? Mowi przegladarce/klientowi, ze ten URL nigdy sie nie zmieni. Z wersjonowana nazwa (pack-v12.zip) to prawda, i klient przestaje wysylac requesty rewalidacyjne.

SHA-1 jest zlamany, czy moge SHA-256? Mozesz, od Minecraft 1.20.3+ przez API serwera w Player#setResourcePack z parametrem hash, ale pole w server.properties nadal nazywa sie resource-pack-sha1. Sila kryptograficzna nie jest tu istotna, hash to tylko check integralnosci i klucz cache.

Co z packami Bedrock? Bedrock dziala inaczej: pack idzie przez sam protokol Minecrafta, bez HTTP. Przy crossplay przez Geyser/Floodgate customowe packi Bedrock leza osobno w folderach behavior_packs i resource_packs swiata.

Czy moge serwowac packa wprost z serwera Minecraft? Technicznie tak, plugin Paper moze podniesc maly web serwer. W praktyce nie: ruch packa walczy z ruchem graczy o to samo lacze, a tickrate cierpi pod obciazeniem. Trzymaj pack na osobnym hoscie albo CDN.

Kiedy pack jest serwowany z CDN z poprawnym sha1, wersjonowanymi nazwami i sensownym Cache-Control, historia downloadu przestaje byc problemem. Gracze dostaja tekstury w pare sekund, cache dziala transparentnie, a przy update po prostu wgrywasz nowy plik z nowa nazwa i podstawiasz swiezy hash w configu.


Chroń swój serwer przed atakami DDoS

Darmowa ochrona z konfiguracją w 5 minut. 1 TB ruchu w zestawie.

Wypróbuj za darmo


Powiązane artykuły