RE:NODE

Minecraft ops.json: příklad, whitelist, bany a usercache

Text: Tým RE:NODE
17 min čtení


Minecraft server drží své lidi v pěti souborech JSON v kořenové složce serveru: ops.json (operátoři a jejich úroveň), whitelist.json (kdo se smí připojit), banned-players.json a banned-ips.json (kdo ne) a usercache.json (vyhledávací tabulka jmen a UUID). Každý záznam je veden podle UUID, ne podle jména. Server je při startu načte do paměti a pokaždé, když je změní nějaký příkaz, zapíše celý seznam zpět na disk. Právě proto se soubor, který jsi ručně upravil za běhu serveru, tiše vrátí do původního stavu. Bezpečné pravidlo je krátké: za běhu serveru používej /op, /whitelist a /ban a soubory upravuj jen při zastaveném serveru.

Funkční ops.json vypadá takto:

ops.json
[  {    "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5",    "name": "Notch",    "level": 4,    "bypassesPlayerLimit": true  },  {    "uuid": "853c80ef-3c37-49fd-aa49-938b674adae6",    "name": "jeb_",    "level": 2,    "bypassesPlayerLimit": false  }]

Zbytek článku projde každý soubor pole po poli, ukáže, co zapisují příkazy, co zvládne ruční úprava a příkaz ne, jak offline režim rozbije všechny tyto seznamy najednou a - protože to samé hledání často skončí tady - co znamenají hodnoty level-type v server.properties. Stránka věci - kdo by vůbec měl být operátor a jak postavit hodnosti pomocí LuckPerms - je v článku Minecraft whitelist a oprávnění; tento článek je o samotných souborech.

Pět souborů přehledně#

SouborMění hoObsahuje
ops.json/op, /deopOperátory, jejich úroveň, obejití limitu slotů
whitelist.json/whitelist add/removeHráče, kteří smějí dovnitř, když je whitelist zapnutý
banned-players.json/ban, /pardonZabanované účty, důvod, vypršení
banned-ips.json/ban-ip, /pardon-ipZabanované adresy, důvod, vypršení
usercache.jsonServer, při každém přihlášeníNedávno viděná jména a UUID

Všech pět je pole objektů ve formátu JSON. Všech pět leží vedle server.properties, ne ve složce světa, takže je sdílí všechny dimenze a přežijí změnu level-name. Založ nový svět pro novou sezónu a operátoři, whitelist i bany zůstanou beze změny. Smaž složku světa a pořád tam jsou; smaž kořen serveru a jsou pryč, což stojí za zapamatování, když rozhoduješ, co všechno budou zálohy pokrývat.

Nahradily prosté textové soubory ve verzi 1.7.6, kdy Minecraft přešel od jmen k UUID. Pokud na starém serveru najdeš ops.txt, white-list.txt, banned-players.txt nebo banned-ips.txt, jsou to pozůstatky. Moderní server je jednou převede a pak je ignoruje, takže jejich úprava nic nedělá.

Stejné soubory existují na serverech vanilla, Paper, Spigot, Purpur, Fabric i NeoForge, protože patří ke kódu vanilla serveru, na kterém jsou všechny postavené. Pluginy mohou přidat vlastní seznamy navíc - EssentialsX si drží data po hráčích, LuckPerms má vlastní úložiště - ale těchto pět souborů se chová na všech stejně.

ops.json, pole po poli#

Každý operátor je jeden objekt se čtyřmi poli.

PoleTypVýznam
uuidstringÚčet. Podle tohoto pole server hledá shodu
namestringPoslední známé jméno. Jen pro oko
level1 až 4Úroveň oprávnění operátora
bypassesPlayerLimittrue/falseSmí se připojit, i když je dosažen max-players

uuid je jediné pole, podle kterého server hráče pozná. name se zapisuje pro tvoje pohodlí a aktualizuje se, když se hráč přihlásí pod novým jménem; zastaralé jméno nic neškodí. Opak neplatí: záznam s chybějícím nebo chybně napsaným uuid se při načítání souboru přeskočí, bez chyby, které by sis pravděpodobně všiml, takže ručně napsaný záznam jen se jménem pro server jednoduše neexistuje.

U level se ruční úprava vyplatí. /op <player> vždy zapíše hodnotu op-permission-level ze server.properties, která je ve výchozím stavu 4. Žádný argument příkazu /op úroveň nenastavuje, takže pokud chceš mít jednoho hráče na úrovni 4 a druhého na úrovni 2, buď před každým /op změníš op-permission-level a mezitím restartuješ, nebo číslo napíšeš přímo do souboru. Čtyři úrovně ve zkratce:

  • 1 - obchází ochranu spawnu a nic víc.
  • 2 - příkazy ve stylu cheatů, například /gamemode, /give, /tp a command bloky.
  • 3 - správa hráčů: /kick, /ban, /op, /whitelist.
  • 4 - všechno, včetně /stop.

Celá tabulka a důvod, proč úrovně na serveru s pluginy znamenají mnohem méně, než se zdá - pluginy obvykle přidělují svá oprávnění všem operátorům bez ohledu na úroveň - jsou v článku o oprávněních. Na Paperu ber level jako řízení pouze vanilla příkazů.

bypassesPlayerLimit dovolí danému hráči připojit se, i když server už drží max-players lidí. /op zapíše false novému operátorovi a u znovu opnutého hráče zachová stávající hodnotu, a žádný příkaz ji nenastaví na true, takže soubor je jediné místo, kde ji lze zapnout. Je to nastavení, které adminovi umožní dostat se na plný server a vyřešit, co ho zaplnilo.

Ještě dvě souvislosti, které je dobré znát. Operátoři obcházejí whitelist úplně, takže starý záznam operátora je cesta dovnitř, kterou whitelist remove nezavře. A /deop záznam odstraní celý, místo aby snížil úroveň - neexistuje úroveň 0, na kterou by šlo někoho degradovat.

whitelist.json#

whitelist.json
[  { "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Notch" },  { "uuid": "853c80ef-3c37-49fd-aa49-938b674adae6", "name": "jeb_" }]

Dvě pole, stejná pravidla: uuid se porovnává, name je dekorace. Soubor se používá, jen když je v server.properties nastaveno white-list=true, a při vypnutí whitelistu zůstává zachován, takže po jeho pozdějším zapnutí se obnoví přesně tatáž skupina lidí.

Whitelist je jediný seznam s příkazem pro opětovné načtení. /whitelist reload znovu přečte whitelist.json z disku, takže je to jediný z pěti souborů, který můžeš bezpečně upravit ručně za běhu serveru - pokud reload spustíš dřív, než soubor přepíše cokoli jiného. Při enforce-whitelist=true reload navíc odpojí všechny připojené hráče, kteří už nejsou na seznamu.

Když spustíš /whitelist add <name>, server k tomu jménu potřebuje UUID. Nejdřív se podívá do usercache.json a pokud tam jméno není, zeptá se profilové služby Mojangu. Proto příkaz funguje i pro hráče, který se nikdy nepřipojil, a proto selže s hláškou „That player does not exist“, když je jméno špatně napsané, bylo změněno nebo patří gamertagu z Bedrocku místo účtu Java.

banned-players.json a banned-ips.json#

Seznamy banů nesou víc polí, protože ban zaznamenává, kdo ho udělil, kdy a proč.

banned-players.json
[  {    "uuid": "36532b5e-c442-3dbb-a24c-c7e55d0f979a",    "name": "Griefer123",    "created": "2026-10-15 14:03:22 +0000",    "source": "Server",    "expires": "forever",    "reason": "Lava-cast over the spawn town"  }]
banned-ips.json
[  {    "ip": "203.0.113.45",    "created": "2026-10-15 14:05:10 +0000",    "source": "Server",    "expires": "forever",    "reason": "Ban evasion"  }]
PolePříkladVýznam
created2026-10-15 14:03:22 +0000Kdy byl ban udělen
sourceServer, Rcon, jméno hráčeKdo ho udělil
expiresforever nebo datumKdy přestane platit
reasonVolný textZobrazí se hráči na obrazovce odpojení

source je název toho, co příkaz spustilo: Server pro konzoli, Rcon pro vzdálenou konzoli, nebo jméno operátora. Když není zadán žádný důvod, vanilla zapíše Banned by an operator.

expires je to zajímavé pole. Vanilla /ban nemá argument pro délku trvání a vždy zapíše forever, ale server datum v tomto poli respektuje. Zapiš časové razítko ve stejném formátu jako created - "2026-10-22 14:00:00 +0000" - a ban po tomto okamžiku přestane platit. Tak se ukládají dočasné bany z pluginů, například EssentialsX: do tohoto samého souboru, se skutečným datem vypršení. Pokud formát nesedí, datum se možná nepodaří přečíst, takže tvar created opiš přesně, včetně mezery před posunem časového pásma.

Příkazy, všechny na úrovni operátora 3:

PříkazÚčinek
ban <player> [reason]Přidá do banned-players.json, připojeného hráče vyhodí
ban-ip <player or address> [reason]Přidá adresu do banned-ips.json
pardon <player>Odstraní ban hráče
pardon-ip <address>Odstraní ban adresy
banlist [players or ips]Vypíše aktuální seznamy

ban-ip zadaný se jménem hráče zabanuje jeho aktuální adresu, což je pohodlná podoba, když je online. Banování adres je hrubý nástroj. Mnoho domácích připojení mění adresu při opětovném připojení, mobilní sítě schovávají tisíce lidí za jednu adresu a VPN to překoná za pár vteřin. Nejdřív použij ban účtu a ban adresy jako doplněk při vytrvalém problému s alternativními účty, a počítej s tím, že občas budeš muset omilostnit nevinného hráče.

Žádný ze seznamů banů nemá ve vanille příkaz pro opětovné načtení, takže ruční úpravy vyžadují zastavený server.

usercache.json#

usercache.json
[  {    "name": "Notch",    "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5",    "expiresOn": "2026-11-15 14:03:22 +0000"  }]

Tohle není soubor s oprávněními. Je to cache jmen a UUID, která server zjistil, obnovovaná při každém přihlášení hráče. Příkazy ji používají k převodu jména na UUID bez dotazu na Mojang, stejně jako hlavy hráčů, /whitelist add a příkazy pro ban offline hráčů. expiresOn se nastavuje zhruba o měsíc dopředu; prošlý záznam se při další potřebě zjistí znovu. Soubor je omezen na zhruba tisíc naposledy použitých záznamů, takže na vytíženém serveru zůstává malý.

Protože je to jen cache, usercache.json je bezpečné smazat při zastaveném serveru - znovu se vytvoří, jak se budou hráči připojovat. Občas je to řešení, když staré jméno přejmenovaného hráče pořád míří na špatný účet, nebo když přechod mezi online a offline režimem nechal soubor plný UUID, která už nic neodpovídají. Neupravuj ho ručně, abys „opravil“ identitu hráče; server tvoji změnu stejně přepíše při dalším přihlášení a identita, na které záleží, je v ostatních čtyřech souborech.

Proč se ruční úpravy za běhu serveru přepíšou#

Chování, které chytí každého, má jednoduchou příčinu. Při startu server načte každý seznam do paměti. Od té chvíle je skutečná kopie ta v paměti. Když kterýkoli příkaz seznam změní - /op, /deop, /whitelist add, /ban, /pardon nebo plugin volající stejný kód - server svůj seznam z paměti serializuje a zapíše celý soubor znovu. Nic, co nenačetl, tento zápis nepřežije.

startupchangewhole file rewrittenoverwritten at next write/op, /ban, /whitelistnebo pluginTvoje ruční úpravaprovedena za běhuops.json na diskunačten jednou při startuSeznam v pamětikopie, která platí
Kde se ruční úprava ztratí

Úprava ops.json ve správci souborů za běhu serveru tedy vypadá, že funguje - soubor na disku tvou změnu ukazuje - a pak zmizí při příštím opnutí, banu nebo přidání na whitelist kohokoli. Tvoje úprava nikdy nebyla v paměti a další zápis soubor nahradí tím, co v paměti bylo. Platí to i obráceně: úprava provedená za běhu serveru nemá žádný účinek, dokud se nenačte, což u operátorů a banů znamená restart.

Existuje i horší varianta. Pokud takový soubor uložíš se syntaktickou chybou v JSON - obvykle čárkou za posledním záznamem, jindy chybějící uvozovkou - server zaloguje varování, že se seznam nepodařilo načíst, a pokračuje s prázdným seznamem v paměti. Tvoji operátoři už nejsou operátoři, tvůj whitelist nepustí nikoho kromě operátorů a tvoje bany jsou zrušeny. Další příkaz, který se seznamu dotkne, pak zapíše prázdný seznam zpět na disk a nahradí tvůj rozbitý soubor i se všemi záznamy v něm.

Postup, který funguje vždy:

  1. Zastav server a počkej, až se úplně vypne.
  2. Udělej kopii souboru, který budeš upravovat, nebo zálohu serveru.
  3. Proveď úpravu. Drž ji jako platné pole JSON: čárky mezi objekty, žádná za posledním, každý klíč a řetězec v dvojitých uvozovkách.
  4. Pokud si nejsi jistý, vlož soubor do libovolného validátoru JSON.
  5. Spusť server a v úvodu logu hledej varování o načítání.
  6. Z konzole spusť /op nebo /whitelist list nebo /banlist a ověř, že seznam obsahuje to, co očekáváš.

Jen u whitelistu existuje zkratka: uprav, ulož a hned spusť /whitelist reload.

Na RE:NODE správce souborů upravuje tyto soubory v prohlížeči se zvýrazněním syntaxe, takže zbloudilá čárka je vidět ještě před uložením, a SFTP funguje s přihlašovacími údaji generovanými pro každý server, pokud dáváš přednost vlastnímu editoru - podrobnosti jsou v článku SFTP a správce souborů. Konzole si pamatuje historii příkazů, takže ověření je pár stisknutých kláves. A slot pro zálohu je k dispozici pro snímek před úpravou; obnovení je jedno tlačítko, popsané v článku Zálohování a obnovení světa v Minecraftu.

Offline režim a past s UUID#

Každý seznam tady je veden podle UUID a online-mode rozhoduje, odkud se UUID berou. Proto je to nastavení, které nejpravděpodobněji rozbije všech pět souborů najednou.

Při online-mode=true UUID hráče vydává Mojang. Patří k účtu, přežije změnu jména a je to, co zapisují všechny příkazy. Jsou to UUID verze 4: třetí skupina znaků začíná 4, jako v 069a79f4-44e9-4726-....

Při online-mode=false se server Mojangu na nic neptá. UUID odvodí ze samotného jména, hashem textu OfflinePlayer: následovaného přesným uživatelským jménem. Jsou to UUID verze 3 a třetí skupina začíná 3. Stejný účet tak vytvoří dvě úplně odlišné identity:

RežimUUID hráče Notch
Online069a79f4-44e9-4726-a5be-fca90e38aaf5
Offlineb50ad385-829d-3141-a216-7e7d7539ba7f

Důsledky z toho přímo plynou:

  • Přepnutí režimu osiří každý záznam. Operátor opnutý v online režimu není po přepnutí do offline režimu operátor a whitelist nepustí nikoho ze svých členů. Jejich inventáře, advancementy a data pluginů jsou vedeny také podle UUID, takže také zdánlivě zmizí - staré soubory hráčů jsou pořád ve složce světa, pod starými UUID.
  • Na velikosti písmen u jména v offline režimu záleží. Hash se počítá z přesného řetězce, takže Notch a notch jsou dva různí offline hráči.
  • Přejmenování je v offline režimu nový hráč. Za jménem není žádný účet, takže nové jméno znamená nové UUID a prázdný inventář.
  • Whitelist v offline režimu může zapsat špatné UUID. V mnoha verzích se /whitelist add a /op stále nejdřív pokusí o dotaz na Mojang, když jméno patří skutečnému účtu Java, a k offline UUID se vrátí, až když to selže. Záznam pak drží online UUID a nikdy se nepotká s offline hráčem, který se připojí. Spolehlivé řešení je nechat hráče jednou se připojit při vypnutém whitelistu, aby cache držela jeho offline UUID, nebo offline UUID zapsat do souboru sám.

Offline UUID spočítáš pár řádky v Pythonu. Java ho sestavuje pomocí UUID.nameUUIDFromBytes a tohle ho reprodukuje přesně:

offline_uuid.py
import hashlib, uuid, sysname = sys.argv[1]h = bytearray(hashlib.md5(("OfflinePlayer:" + name).encode("utf-8")).digest())h[6] = (h[6] & 0x0F) | 0x30  # verze 3h[8] = (h[8] & 0x3F) | 0x80  # varianta IETFprint(uuid.UUID(bytes=bytes(h)))
bash
$ python3 offline_uuid.py Notchb50ad385-829d-3141-a216-7e7d7539ba7f

Jediné legitimní místo pro online-mode=false je backendový server za proxy Velocity nebo BungeeCord. Proxy ověřuje u Mojangu a při nastaveném forwardingu předá backendu skutečné online UUID - takže seznamy backendu drží UUID verze 4, i když má jeho vlastní online-mode vypnutý. Pokud se v usercache.json na backendu za proxy objeví UUID verze 3, forwarding nefunguje a každý hráč přichází s identitou odvozenou ze jména. Oprav forwarding dřív, než uděláš cokoli jiného; popisuje ho průvodce sítí s Velocity. Hráči z Bedrocku přes Geyser a Floodgate jsou třetí případ, s vlastními generovanými UUID - viz Geyser a crossplay s Bedrockem.

Správný přechod serveru z offline do online režimu znamená přepsat každý seznam novými UUID a přejmenovat datové soubory každého hráče v world/playerdata/, plus cokoli, co si pluginy ukládají podle UUID. Je to migrace, ne změna nastavení, a nejdřív je potřeba udělat zálohu.

level-type v server.properties#

Druhá půlka otázky, která sem lidi přivádí, je řádek level-type=minecraft\:normal. Vybírá předvolbu světa použitou při jeho generování. Od verze 1.19 mají hodnoty jmenný prostor:

HodnotaCo dostaneš
minecraft:normalStandardní terén. Výchozí
minecraft:flatSuperflat, tvarovaný pomocí generator-settings
minecraft:large_biomesNormální terén s biomy několikrát většími
minecraft:amplifiedExtrémní svislý terén
minecraft:single_biome_surfaceVšude jeden biom

Zpětné lomítko před dvojtečkou je formát souboru properties v Javě: vlastní zapisovač serveru escapuje každou dvojtečku, takže soubor, který vygeneruje, obsahuje minecraft\:normal. Když server soubor čte zpět, minecraft\:normal a minecraft:normal v hodnotě znamenají přesně totéž, takže můžeš napsat kteroukoli podobu. Nevadí to, co vadí, je nerozpoznaná hodnota - překlep jako minecraft:largebiomes - která ti na současných verzích dá normální svět místo jasné chyby a zjistíš to, až když se po něm hráči procházejí.

Starší verze používaly holá slova: default, flat, largeBiomes, amplified a v některých verzích buffet nebo customized. Moderní servery běžné starší názvy převádějí na ty se jmenným prostorem, takže starý soubor pořád funguje, ale v nových konfiguracích piš podobu se jmenným prostorem.

Tři praktické body:

  • Platí jen při vytvoření světa. Jakmile existuje level.dat, generátor je uložený ve světě a změna level-type nic nedělá. Chceš-li vyzkoušet jinou předvolbu, změň level-name na novou složku, aby server vedle starého světa vygeneroval nový.
  • `amplified` stojí skutečný výkon CPU. Generování amplified chunků je znatelně pomalejší než normálních a na sdíleném jádře se to projeví jako špičky lagů, když hráči prozkoumávají svět. Před otevřením serveru předgeneruj hratelnou oblast - jak na to, vysvětluje hranice světa a předgenerování.
  • `large_biomes` je pro vyšší počty hráčů. Rozprostření biomů dává všem prostor, za cenu dlouhých cest, když hledáš konkrétní biom.

Seedy, JSON generator-settings pro ploché světy a datapacky pro generování světa, například Terralith, jsou popsané v článku vlastní generování světa a zbytek souboru v článku každý klíč v server.properties.

Řešení potíží se seznamy#

Upravil jsem ops.json a nikdo není operátor. Buď server běžel a tvou úpravu přepsal, nebo se JSON nepodařilo přečíst a server načetl prázdný seznam. Zastav server, otevři soubor a zkontroluj ho.

Hráč je ve whitelist.json, ale nemůže se připojit. Porovnej UUID v souboru s tím v usercache.json poté, co se zkusí připojit. UUID verze 3 na jedné straně a verze 4 na druhé znamená nesoulad online/offline. Zkontroluj také, že white-list je nastaveno tak, jak si myslíš: /whitelist on zapisuje nastavení na disk, takže zastaralý ručně upravený server.properties se může lišit od toho, co server dělá.

`/whitelist add` hlásí, že hráč neexistuje. Pravopis, nedávné přejmenování, gamertag z Bedrocku, nebo se server nedokáže dostat k profilové službě Mojangu. Nech hráče jednou se připojit při vypnutém whitelistu, nebo přidej UUID ručně při zastaveném serveru.

Omilostněný hráč je pořád zabanovaný. Zkontroluj banned-ips.json. Hráč zabanovaný pomocí ban-ip zůstává venku i po pardon, protože ban adresy je samostatný seznam a potřebuje pardon-ip.

Bany se po restartu vrátily. Někdo omilostnil v souboru za běhu serveru. Seznam v paměti ban pořád držel a zapsal ho zpět. Použij /pardon.

Server je plný a admin se nemůže dostat dovnitř. Nastav "bypassesPlayerLimit": true u adminova záznamu při zastaveném serveru, nebo zvyš max-players - hodnotu, která omezuje jen sloty, ne výkon sama o sobě.

FAQ#

Mohu přidat operátora, když server neběží?

Ano. Zapiš záznam do ops.json s UUID hráče, úrovní od 1 do 4 a bypassesPlayerLimit, drž soubor jako platný JSON a spusť server. UUID musí být správné; u serverů v online režimu ho najdeš z dřívějšího přihlášení v usercache.json nebo v libovolném vyhledávači UUID od Mojangu.

Používá se pole name v těchto souborech k něčemu?

Sotva. Shoda se hledá podle UUID a server jméno obnoví, když se hráč příště přihlásí. Špatné nebo zastaralé jméno v záznamu nezpůsobí problém, pokud je UUID správné; správné jméno se špatným UUID nedělá vůbec nic.

Jak udělat dočasný ban bez pluginu?

Zabanuj hráče normálně, zastav server, změň u toho záznamu expires z forever na časové razítko ve stejném formátu jako created a spusť server znovu. Ban po tomto čase přestane platit.

Je bezpečné smazat usercache.json?

Při zastaveném serveru ano. Je to jen cache a znovu se vytváří, jak se hráči připojují. Smazání znamená, že první příkaz uvádějící offline hráče se musí znovu zeptat Mojangu.

Proč /op nedá úroveň, kterou jsem nastavil v ops.json?

Pokaždé zapíše op-permission-level ze server.properties a přepíše, jakou úroveň měl hráč předtím. Úrovně nastavuj v souboru při zastaveném serveru a pak už toho hráče znovu neopuj.

Mění level-type něco na existujícím světě?

Ne. Generátor se určí při vytvoření světa a uloží se do level.dat. Změna řádku ovlivní jen svět vygenerovaný po ní, obvykle proto, že level-name míří na novou složku.