Сервер Minecraft хранит список игроков в пяти JSON-файлах в корне сервера: ops.json (операторы и их уровень), whitelist.json (кому можно заходить), banned-players.json и banned-ips.json (кому нельзя) и usercache.json (таблица соответствия имён и UUID). Каждая запись привязана к UUID, а не к имени. Сервер читает файлы в память при старте и записывает весь список обратно на диск при каждом изменении командой, поэтому файл, который вы отредактировали вручную при работающем сервере, незаметно откатывается. Безопасное правило короткое: пока сервер работает, используйте /op, /whitelist и /ban, а файлы правьте только на остановленном сервере.
Рабочий 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 }]Дальше в статье мы разберём каждый файл по полям, что записывают команды, что можно сделать ручной правкой и нельзя командой, как offline mode ломает сразу все эти списки и - раз по этому же запросу сюда часто попадают - что означают значения level-type в server.properties. Вопросы политики - кто вообще должен быть оператором и как строить ранги через LuckPerms - разобраны в статье Minecraft whitelist и права, а эта статья именно о самих файлах.
Пять файлов в одной таблице#
| Файл | Кто меняет | Что хранит |
|---|---|---|
ops.json | /op, /deop | Операторы, их уровень, обход лимита слотов |
whitelist.json | /whitelist add/remove | Игроки, которым можно заходить при включённом whitelist |
banned-players.json | /ban, /pardon | Забаненные аккаунты, причина, срок |
banned-ips.json | /ban-ip, /pardon-ip | Забаненные адреса, причина, срок |
usercache.json | Сам сервер при каждом входе | Недавно виденные имена и UUID |
Все пять - это JSON-массивы объектов. Все пять лежат рядом с server.properties, а не внутри папки мира, поэтому они общие для всех измерений и переживают смену level-name. Начните новый мир на новый сезон, и ваши операторы, whitelist и баны останутся нетронутыми. Удалите папку мира - они всё равно на месте; удалите корень сервера - они пропадут, и об этом стоит помнить, когда вы решаете, что должны охватывать ваши бэкапы.
Эти файлы заменили текстовые в версии 1.7.6, когда Minecraft перешёл с имён на UUID. Если на старом сервере вы найдёте ops.txt, white-list.txt, banned-players.txt или banned-ips.txt, это остатки. Современный сервер один раз их конвертирует и после этого игнорирует, так что правка таких файлов ничего не даёт.
Те же файлы есть на серверах vanilla, Paper, Spigot, Purpur, Fabric и NeoForge, потому что они принадлежат коду ванильного сервера, на котором построены все остальные. Плагины могут добавлять поверх свои списки - EssentialsX хранит данные по каждому игроку, у LuckPerms своё хранилище, - но эти пять файлов ведут себя одинаково на любом из них.
ops.json по полям#
Каждый оператор - это один объект с четырьмя полями.
| Поле | Тип | Значение |
|---|---|---|
uuid | строка | Аккаунт. Именно по нему сервер сопоставляет игрока |
name | строка | Последнее известное имя. Только для удобства |
level | от 1 до 4 | Уровень прав оператора |
bypassesPlayerLimit | true/false | Можно зайти, когда достигнут max-players |
uuid - единственное поле, по которому сервер узнаёт игрока. name записывается для вашего удобства и обновляется, когда игрок заходит под новым именем; устаревшее имя вреда не приносит. Обратное неверно: запись с пропущенным или неверно оформленным uuid при загрузке файла пропускается без ошибки, которую вы скорее всего заметите, так что запись, написанная вручную только с именем, для сервера просто не существует.
level - то поле, ради которого стоит править файл вручную. /op <player> всегда записывает значение op-permission-level из server.properties, по умолчанию 4. У /op нет аргумента, который задаёт уровень, поэтому, если вам нужен один игрок на уровне 4, а другой на уровне 2, вам придётся либо менять op-permission-level перед каждым /op с перезапуском между ними, либо вписать число в файл. Коротко о четырёх уровнях:
1- обходит защиту спауна и больше ничего.2- команды в стиле читов, такие как/gamemode,/give,/tpи командные блоки.3- управление игроками:/kick,/ban,/op,/whitelist.4- всё, включая/stop.
Полная таблица и причина, по которой на сервере с плагинами уровни значат гораздо меньше, чем кажется (плагины обычно выдают свои права всем операторам независимо от уровня), разобраны в статье о правах. На Paper считайте, что level управляет только ванильными командами.
bypassesPlayerLimit позволяет этому игроку зайти, когда на сервере уже набралось max-players человек. /op записывает false для нового оператора и сохраняет прежнее значение, когда вы повторно делаете оператором того же игрока, а true не выставляет ни одна команда, так что включить это можно только в файле. Именно эта настройка позволяет администратору попасть на полный сервер и разобраться, что его заполнило.
Ещё два нюанса. Операторы полностью обходят whitelist, поэтому старая запись оператора - это вход, который whitelist remove не закроет. А /deop полностью удаляет запись, а не понижает уровень: уровня 0, до которого можно было бы понизить, не существует.
whitelist.json#
[ { "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Notch" }, { "uuid": "853c80ef-3c37-49fd-aa49-938b674adae6", "name": "jeb_" }]Два поля, те же правила: сопоставляется uuid, а name - украшение. Файл учитывается только при white-list=true в server.properties и сохраняется, когда whitelist выключен, так что, включив его позже, вы получите ровно тот же набор людей.
Whitelist - единственный список с командой перезагрузки. /whitelist reload заново читает whitelist.json с диска, поэтому это единственный из пяти файлов, который можно безопасно править вручную при работающем сервере, - при условии, что вы выполните reload раньше, чем что-либо другое перезапишет файл. При enforce-whitelist=true reload также отключает всех игроков онлайн, которых больше нет в списке.
Когда вы выполняете /whitelist add <name>, серверу нужен UUID для этого имени. Сначала он смотрит в usercache.json, а если имени там нет, обращается к сервису профилей Mojang. Поэтому команда работает для игрока, который ни разу не заходил, и поэтому она отвечает "That player does not exist", когда имя написано с ошибкой, было изменено или принадлежит gamertag Bedrock, а не аккаунту Java.
banned-players.json и banned-ips.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" }][ { "ip": "203.0.113.45", "created": "2026-10-15 14:05:10 +0000", "source": "Server", "expires": "forever", "reason": "Ban evasion" }]| Поле | Пример | Значение |
|---|---|---|
created | 2026-10-15 14:03:22 +0000 | Когда выдан бан |
source | Server, Rcon, имя игрока | Кто его выдал |
expires | forever или дата | Когда бан истекает |
reason | Произвольный текст | Показывается игроку на экране отключения |
source - это имя того, что выполнило команду: Server для консоли, Rcon для удалённой консоли или имя оператора. Если причина не указана, vanilla записывает Banned by an operator.
Самое интересное - expires. У ванильного /ban нет аргумента длительности, и он всегда пишет forever, но сервер учитывает дату в этом поле. Впишите метку времени в том же формате, что и created, - "2026-10-22 14:00:00 +0000" - и после этого момента бан перестанет действовать. Именно так хранятся временные баны от плагинов вроде EssentialsX: в этом же файле, с настоящей датой окончания. Если формат неверный, дата может не распознаться, так что копируйте вид created в точности, включая пробел перед смещением часового пояса.
Команды, все на уровне оператора 3:
| Команда | Действие |
|---|---|
ban <player> [reason] | Добавляет в banned-players.json, кикает, если игрок онлайн |
ban-ip <player or address> [reason] | Добавляет адрес в banned-ips.json |
pardon <player> | Снимает бан с игрока |
pardon-ip <address> | Снимает бан с адреса |
banlist [players or ips] | Выводит текущие списки |
ban-ip с именем игрока банит его текущий адрес, и это удобная форма, когда он онлайн. Баны по адресу - грубый инструмент. Многие домашние подключения меняют адрес при переподключении, в мобильных сетях тысячи людей сидят за одним адресом, а VPN обходит такой бан за секунды. Сначала используйте бан аккаунта, а бан по адресу - как дополнение против упорного создания альтернативных аккаунтов, и будьте готовы время от времени снимать бан с невиновного игрока.
У списков банов в vanilla нет команды перезагрузки, поэтому ручные правки в них требуют остановленного сервера.
usercache.json#
[ { "name": "Notch", "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "expiresOn": "2026-11-15 14:03:22 +0000" }]Это не файл прав. Это кэш имён и UUID, которые сервер уже определил, и он обновляется при каждом входе игрока. Команды используют его, чтобы превратить имя в UUID, не спрашивая Mojang, так же делают головы игроков, /whitelist add и команды бана для игроков, которых нет онлайн. expiresOn выставляется примерно на месяц вперёд; просроченная запись определяется заново при следующей необходимости. Размер файла ограничен примерно тысячей последних использованных записей, поэтому на загруженном сервере он остаётся небольшим.
Поскольку это только кэш, usercache.json можно безопасно удалить на остановленном сервере - он пересоберётся по мере захода игроков. Иногда это и есть решение, когда старое имя переименованного игрока продолжает указывать на чужой аккаунт или когда после переключения между online и offline режимом файл забит UUID, которые больше ни с чем не совпадают. Не правьте его вручную, чтобы "исправить" личность игрока: сервер всё равно перезапишет вашу правку при следующем входе, а значение имеет та личность, что записана в остальных четырёх файлах.
Почему ручные правки перезаписываются, пока сервер работает#
У поведения, на которое попадаются все, простая причина. При старте сервер читает каждый список в память. С этого момента настоящей считается копия в памяти. Когда любая команда меняет список - /op, /deop, /whitelist add, /ban, /pardon или плагин, вызывающий тот же код, - сервер сериализует список из памяти и записывает весь файл заново. Всё, что он не загрузил, при этой записи не сохраняется.
Так что правка ops.json в файловом менеджере при работающем сервере только кажется удавшейся - файл на диске показывает ваше изменение, - а потом исчезает, как только кого-то сделают оператором, забанят или внесут в whitelist. Ваша правка никогда не была в памяти, и следующая запись заменяет файл тем, что там было. Верно и обратное: правка, сделанная при работающем сервере, не действует, пока её не загрузят, а для операторов и банов это означает перезапуск.
Есть и более неприятный вариант. Если вы сохраните один из этих файлов с синтаксической ошибкой JSON - обычно это запятая после последней записи, реже пропущенная кавычка, - сервер запишет в лог предупреждение о том, что не смог загрузить список, и продолжит работу с пустым списком в памяти. Ваши операторы перестают быть операторами, whitelist никого не пускает, кроме операторов, а баны сняты. Следующая же команда, затрагивающая этот список, записывает пустой список обратно на диск, заменяя ваш сломанный файл со всеми записями в нём.
Порядок действий, который работает всегда:
- Остановите сервер и дождитесь полного завершения работы.
- Сделайте копию файла, который собираетесь править, или бэкап сервера.
- Внесите правку. Сохраните корректный JSON-массив: запятые между объектами, ни одной после последнего, все ключи и строки в двойных кавычках.
- Если не уверены, вставьте файл в любой JSON-валидатор.
- Запустите сервер и прочитайте начало лога на предмет предупреждений о загрузке.
- Выполните из консоли
/op,/whitelist listили/banlist, чтобы убедиться, что список содержит то, что вы ожидаете.
Для одного только whitelist есть короткий путь: отредактируйте, сохраните и сразу выполните /whitelist reload.
На RE:NODE файловый менеджер редактирует эти файлы прямо в браузере с подсветкой синтаксиса, из-за которой лишняя запятая видна ещё до сохранения, а SFTP работает с учётными данными, создаваемыми для каждого сервера, если вы предпочитаете свой редактор - подробности в статье SFTP и файловый менеджер. В консоли хранится история команд, так что шаг проверки занимает пару нажатий клавиш. А слот бэкапа позволяет сделать снимок перед правкой; восстановление - это одна кнопка, о ней рассказано в статье Бэкап и восстановление мира Minecraft.
Offline mode и ловушка с UUID#
Все списки здесь привязаны к UUID, а то, откуда берутся UUID, определяет online-mode. Поэтому именно эта настройка чаще всего ломает сразу все пять файлов.
При online-mode=true UUID игрока выдаёт Mojang. Он принадлежит аккаунту, переживает смену имени и именно его записывают все команды. Это UUID версии 4: третья группа символов начинается с 4, как в 069a79f4-44e9-4726-....
При online-mode=false сервер ничего не спрашивает у Mojang. Он вычисляет UUID из самого имени, хэшируя текст OfflinePlayer: и следующее за ним точное имя пользователя. Это UUID версии 3, и его третья группа начинается с 3. Один и тот же аккаунт даёт две совершенно разные личности:
| Режим | UUID Notch |
|---|---|
| Online | 069a79f4-44e9-4726-a5be-fca90e38aaf5 |
| Offline | b50ad385-829d-3141-a216-7e7d7539ba7f |
Последствия вытекают прямо отсюда:
- Переключение режима делает осиротевшими все записи. Оператор, назначенный в online режиме, перестаёт быть оператором после переключения в offline, а whitelist не пускает никого из своего списка. Инвентари, достижения и данные плагинов тоже привязаны к UUID, поэтому они тоже как будто исчезают: старые файлы игроков по-прежнему лежат в папке мира под старыми UUID.
- В offline регистр имени важен. Хэшируется точная строка, поэтому
Notchиnotch- это два разных offline-игрока. - Смена ника в offline - это новый игрок. За именем нет аккаунта, поэтому новое имя означает новый UUID и пустой инвентарь.
- Whitelist в offline может записать не тот UUID. На многих версиях
/whitelist addи/opвсё равно сначала пробуют поиск в Mojang, если имя принадлежит настоящему аккаунту Java, и переходят к offline UUID, только если он не удался. Тогда в записи окажется online UUID, который никогда не совпадёт с offline-игроком, пришедшим на сервер. Надёжные решения: дать игроку один раз зайти при выключенном whitelist, чтобы в кэше появился его offline UUID, или вписать offline UUID в файл самостоятельно.
Вычислить offline UUID можно несколькими строками на Python. Java строит его через UUID.nameUUIDFromBytes, и этот код воспроизводит результат точно:
import hashlib, uuid, sysname = sys.argv[1]h = bytearray(hashlib.md5(("OfflinePlayer:" + name).encode("utf-8")).digest())h[6] = (h[6] & 0x0F) | 0x30 # version 3h[8] = (h[8] & 0x3F) | 0x80 # IETF variantprint(uuid.UUID(bytes=bytes(h)))$ python3 offline_uuid.py Notchb50ad385-829d-3141-a216-7e7d7539ba7fЕдинственное законное место для online-mode=false - бэкенд-сервер за прокси Velocity или BungeeCord. Прокси проводит аутентификацию в Mojang и при настроенном forwarding передаёт настоящий online UUID на бэкенд, так что в списках бэкенда лежат UUID версии 4, хотя у него самого online-mode выключен. Если в usercache.json проксируемого бэкенда появляются UUID версии 3, значит, forwarding не работает и каждый игрок приходит с личностью, выведенной из имени. Исправьте forwarding раньше всего остального; как это сделать, описано в руководстве по сети на Velocity. Игроки Bedrock через Geyser и Floodgate - это уже третий случай со своими сгенерированными UUID, см. Geyser и кроссплатформенная игра с Bedrock.
Правильный перенос сервера из offline в online режим означает переписать каждый список с новыми UUID и переименовать файлы данных каждого игрока в world/playerdata/, а также всё, что хранят по UUID плагины. Это миграция, а не смена настройки, и перед ней нужен бэкап.
level-type в server.properties#
Вторая половина вопроса, который приводит людей сюда, - строка level-type=minecraft\:normal. Она выбирает пресет мира, используемый при генерации. В версиях 1.19 и новее значения имеют пространство имён:
| Значение | Что получится |
|---|---|
minecraft:normal | Стандартный рельеф. По умолчанию |
minecraft:flat | Суперплоский мир, форма задаётся generator-settings |
minecraft:large_biomes | Обычный рельеф с биомами в несколько раз крупнее |
minecraft:amplified | Экстремальный вертикальный рельеф |
minecraft:single_biome_surface | Один биом везде |
Обратная косая черта перед двоеточием - это формат файла свойств Java: собственный писатель сервера экранирует каждое двоеточие, поэтому в сгенерированном им файле написано minecraft\:normal. Когда сервер читает файл обратно, minecraft\:normal и minecraft:normal в значении означают одно и то же, так что можно вводить любую форму. Недопустимо другое - нераспознанное значение, например опечатка minecraft:largebiomes: на текущих версиях это даёт обычный мир, а не внятную ошибку, и вы узнаёте об этом, только когда игроки уже гуляют по нему.
Старые версии использовали простые слова: default, flat, largeBiomes, amplified, а в некоторых версиях buffet или customized. Современные серверы переводят распространённые старые названия в значения с пространством имён, так что старый файл продолжает работать, но в новых конфигурациях пишите форму с пространством имён.
Три практических замечания:
- Работает только при создании мира. Когда
level.datуже существует, генератор хранится в мире, и сменаlevel-typeничего не меняет. Чтобы попробовать другой пресет, укажите вlevel-nameновую папку, и сервер сгенерирует свежий мир рядом со старым. - `amplified` заметно нагружает CPU. Генерация amplified-чанков ощутимо медленнее обычной, и на общем ядре это проявляется как скачки лагов, пока игроки исследуют карту. Сгенерируйте игровую область заранее, до открытия сервера, - как это сделать, объясняет статья граница мира и предварительная генерация.
- `large_biomes` - для большого числа игроков. Разнесённые биомы дают место каждому ценой долгих прогулок до нужного.
Сиды, JSON generator-settings для плоских миров и датапаки генерации вроде Terralith разобраны в статье кастомная генерация мира, а остальной файл - в статье все ключи server.properties.
Устранение неполадок со списками#
Я отредактировал ops.json, и никто не оператор. Либо сервер работал и перезаписал вашу правку, либо JSON не разобрался, и сервер загрузил пустой список. Остановите сервер, откройте файл и проверьте его.
Игрок есть в whitelist.json, но не может зайти. Сравните UUID в файле с тем, что окажется в usercache.json после его попытки подключиться. UUID версии 3 с одной стороны и версии 4 с другой означает несовпадение online/offline. Проверьте и то, что white-list имеет то значение, которое вы думаете: /whitelist on записывает настройку на диск, так что устаревший вручную отредактированный server.properties может расходиться с тем, что делает сервер.
`/whitelist add` говорит, что игрока не существует. Опечатка, недавняя смена ника, gamertag Bedrock или сервер не может достучаться до сервиса профилей Mojang. Дайте игроку один раз зайти при выключенном whitelist или добавьте UUID вручную на остановленном сервере.
Игрок, с которого сняли бан, всё равно забанен. Проверьте banned-ips.json. Игрок, забаненный через ban-ip, остаётся за дверью и после pardon, потому что бан по адресу - отдельный список, и для него нужен pardon-ip.
Баны вернулись после перезапуска. Кого-то разбанили в файле, пока сервер работал. Список в памяти всё ещё содержал бан и записал его обратно. Используйте /pardon.
Сервер полон, и администратор не может зайти. Выставьте "bypassesPlayerLimit": true в записи администратора на остановленном сервере или увеличьте max-players - значение, которое ограничивает только слоты, а не производительность само по себе.
FAQ#
Можно ли добавить оператора, не запуская сервер?
Да. Впишите запись в ops.json с UUID игрока, уровнем от 1 до 4 и bypassesPlayerLimit, сохраните файл валидным JSON и запустите сервер. UUID должен быть верным; найдите его по предыдущему входу в usercache.json или через любой сервис поиска UUID Mojang для серверов в online режиме.
Используется ли поле name в этих файлах для чего-нибудь?
Почти нет. Сопоставление идёт по UUID, а имя сервер обновляет при следующем входе игрока. Неверное или устаревшее имя в записи не создаёт проблем, пока UUID правильный; верное имя с неверным UUID не делает ничего.
Как сделать временный бан без плагина?
Забаньте игрока как обычно, остановите сервер, замените в его записи expires с forever на метку времени в том же формате, что и created, и снова запустите сервер. После этого времени бан перестанет действовать.
Безопасно ли удалять usercache.json?
На остановленном сервере - да. Это только кэш, и он пересобирается по мере захода игроков. После удаления первой команде с именем игрока, которого нет онлайн, придётся снова обратиться к Mojang.
Почему /op не даёт тот уровень, который я задал в ops.json?
Он каждый раз записывает op-permission-level из server.properties, перезаписывая любой уровень, который был у игрока. Задавайте уровни в файле на остановленном сервере и не делайте этого игрока оператором повторно.
Меняет ли level-type что-нибудь в уже существующем мире?
Нет. Генератор фиксируется при создании мира и хранится в level.dat. Изменение строки влияет только на мир, сгенерированный после него, обычно потому, что level-name указывает на новую папку.


