Игры админов — часть 4.1, Minecraft

Posted: 2015-03-05 in IT
Метки:

Всем привет. В прошлых выпусках серии «Игры админов» я рассказал, как настроить и запустить собственные игровые сервера для относительно простых в настройке игр жанра «3D-Action» на примере таких классических игр, как Doom2, Quake2, Quake3 и UT-2004. Возможно, как-нибудь напишу про настройку Counter-Strike-ов, но там в принципе не сильно сложнее, хотя и есть свои подводные камни.
В этих играх игровой мир статичен, игрок может только собирать периодически появляющиеся предметы и стрелять в других игроков, а из ценных данных у нас были только конфиги сервера да статистика матчей, и что самое главное — каждый матч никак не завязан на результаты предыдущих.
Честно, просто, кибер-спортивно.

Получив навыки настройки линуксовых ВПС-ок для игр жанра «экшен», пора попробовать свои силы в новом жанре.
Поехали.

Сразу скажу — если вы просто хотите запустить сервер «по-быстрому» — имеет смысл взять готовую сборку. Но в этом случае многие тонкости настройки (коих там просто немеряно по сравнению с любой стрелялкой) и понимание игровой механики останутся за кадром, да и авторы сборок часто могут оставлять бэкдоры, с помощью которых ваш поднять сервер могут серьезно испортить.

Рассказ будет длинным, ключевых моментов очень много, наберитесь терпения.
Своей целью я поставлю поднятие максимально безопасного и максимально честного сервера, насколько это вообще возможно для игры такого типа.

1. Техническая часть.

Как и клиент, сервер игры написан на Java. Это хорошо в плане переносимости и лёгкости создания плагинов — ява есть везде, но совершенно нехорошо в плане производительности и потребуления ресурсов. То есть из требований к хостингу у нас только наличие Java. Версия джавы 1.8 прекрасно подходит, так что ставим её и не забываем обновить систему до упора. В будущем нам понадобятся веб-сервер (апач или нжинкс) и MySQL любых версий. Не забудем также поставить пакеты mc и screen, они нам пригодятся.

Сам сервер обычно состоит из ядра, главного конфига и большой кучи плагинов, каждый из которых часто имеет свои конфиги и даже свои базы данных. Запускать мы его будем, естественно, от отдельного Linux-пользователя. Для труЪ-параноиков сразу скажу, что в SELinux-контексте user_u сервер прекрасно себя чувствует, и если у вас есть возможность задействовать SELinux — это стоит сделать. Однако внутри OpenVZ-контейнера SELinux не работает, поэтому ограничимся тем, что есть — то есть обычным пользователем.

Есть две версии ядер — Bukkit и Spigot. Я рекомендую последний, версии 1.7 и выше. Спигот заметно менее прожорлив по памяти, чем баккит.
При настройке нам также придется изучать много мануалов и ставить плагины, поэтому дам ссылки сразу:
http://www.rubukkit.org/
http://minecraft-ru.gamepedia.com/
http://www.curse.com/bukkit-plugins/minecraft

Будем считать, что наш сервер стоит в каталоге /home/minecraft/mc1.
Начнём мы с создания стартового скрипта. Почему ? Просто по причине совершенно зверского количества парамтеров и переменных, с которыми, возможно, придется повозиться 🙂

start_script.sh
#!/bin/sh

SrvPath='/home/minecraft/mc1'; # ServerPath
SrvFile='spigot.jar'; # Server JAR-file
SrvUser='minecraft'; # Unix-user for running server
SrvRoom='MC1'; # Screen-room for server

mem_opts='-Xmx6G -Xms512M -Xincgc';
d_opts='-Djava.net.preferIPv4Stack=true -Dfile.encoding=utf-8';
xx_opts='-server -XX:MaxPermSize=512M -XX:+AggressiveOpts -XX:UseSSE=3 -XX:+UseFastAccessorMethods -XX:+UseLargePages -XX:+UseConcMarkSweepGC -XX:+UseLargePages -XX:+OptimizeStringConcat -XX:+OptimizeFill';
debug_opts='-Dcom.sun.management.jmxremote.port=3334 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true';
# -Djline.terminal=jline.UnsupportedTerminal

screen -wipe

start() {
echo "Start Minecraft Server..."
EXIST_PROCESS=`ps axfu | grep $SrvFile | grep java`;
if [ "$EXIST_PROCESS" ]
then echo " server already running..."; exit;
fi
cd $SrvPath;
screen -dmS $SrvRoom java $mem_opts $d_opts $xx_opts -jar $SrvFile nogui;
}

start();

Как видите, опций масса, и значительная их часть касается работы с памятью и возможностями отладки. И это мы ещё даже не начали смотреть конфиги =)

2. Базовые конфиги

Главный конфиг сервера — файл server.properties — хранит глобальные настройки:
#Minecraft server properties
spawn-protection=16
query.port=25565
server-name=My First Minecraft Server
force-gamemode=true
allow-nether=true
gamemode=0
enable-query=true
spawn-monsters=true
op-permission-level=1
announce-player-achievements=true
pvp=true
level-type=LARGEBIOMES
enable-command-block=false
max-players=50
max-world-size=29999984
rcon.port=25575
server-port=25565
debug=false
spawn-npcs=true
allow-flight=false
level-name=world
view-distance=10
spawn-animals=true
white-list=false
generate-structures=true
online-mode=false
max-build-height=256
enable-rcon=false
motd=Welcome to my First Minecraft Server. Have fun!

Важнейший параметр тут — online-mode. Если стоит false, то сервер НЕ БУДЕТ аннонсирован на мастер-серверах, но и заходить туда смогут игроки с любыми клиентами. Если же стоит true — то для захода в игру сервер будет проверять наличие клиентского логина на мастер-сервере, и игрокам потребуется купленный и валидный лицензионный ключ. В первом режиме заметно сложнее бороться с нечестными игроками, но зато и возни с лицензией никакой нет. Это сделано удобно, в отличие от того же стима, где создание более свободного для доступа сервера может потребовать незаурядных извращений. Какой тип будет у вас — решать вам лично.
Также тут указан режим игры по-умолчанию, сетевые порты, имя и приветствие сервера, а также наиболее важные лимиты — запрет работы командного блока (опаснейшая штука!), лимит высоты мира, параметры генерации ландшафта и спавна монстров, параметры удаленного доступа и опроса и лимит числа игроков.

Есть также вспомогательные конфиги, но тоже относящиеся к главным — например, файлы spigot.yml / bukkit.yml
В них описаны дополнительные параметры — например, параметры интенсивности спавна монстров, скорость роста деревьев/травы/грибов, тексты некоторых системных сообщений (например, о рестарте) и самое главное (для спигота) — так называемый оребфускатор. Это такая зашитая в ядро функция, скрывающая от игрока координаты ценных блоков до тех пор, пока он не приблизится к ним на заданное расстояние. Он ощутимо кушает ресурсы, но является необходимым, если вы хотите обеспечить честные условия добычи игровых ресурсов, противодействуя читам класса XRay.
Вот пример настроек оребфускатора:
...
world-settings:
default:
verbose: true
anti-xray:
enabled: true
engine-mode: 1
hide-blocks:
- 14
- 15
- 16
- 21
- 48
- 49
- 54
- 56
- 73
- 74
- 82
- 129
- 130
replace-blocks:
- 1
- 5
...

Если у вас есть отдельные карты (миры), где игроки не могут ничего строить или ломать (например, арены или квест-зоны), то имеет смысл именно в этих мирах оребфускатор выключить — он мало поможет читеру на такой карте, но будет есть лишние ресурсы.
Обратите внимание на формат. Если server.properties — это по сути обычный INI-файл, то все остальные конфиги — иерархичны, и пишутся в формате YAML, что означает необходимость повышенного внимания к табуляциям, пробелам и символам переноса строки.

Теперь можно сделать пробный запуск. На этом этапе сервер ещё непригоден для полноценной игры, но уже можно зайти туда (пока что под любым ником и без пароля), побегать, посмотреть, как генерируется мир. На этом этапе уже будет создан файл-профиль игрока в /home/minecraft/mc1/world/playerdata/.dat , где в бинарном виде хранится текущий инвентарь игрока и содержимое эндер-сундука (аналог банковской ячейки, доступ куда имеет только сам игрок и админы).

Все остальные вещи — авторизация игроков, система прокачки навыков, защита своих построек, защита от читерства, логирование, ведение статистики, информирование игроков, магазины и экономика, трейд и бартер, стартовые наборы вещей, управление доступами, реализация арен и так называемых встроенных «мини-игр», а также изрядное число средств защиты и администрирования — делаются сторонними плагинами, и в ядро сервера не входят!

Плагинов этих просто охуитительное количество, есть уйма вариантов и аналогов, отличающихся форматами конфигов, функциональностью, скоростью работы, и конечно же — количеством глюков и совместимостью с другими глюками другими плагинами. Да, именно так — настройка плагинов — одна из основным, и при этом самых сложных частей настройки.

Вообщем, схема получается такая: поставив ядро и создав первый мир, можно построить в нём первую постройку и поставить базовые плагины защиты, после чего плавно развивать проект, добавляя новые постройки и прикручивая новые плагины. Процесс это небыстрый, требующий много времени и сил.

3. Бэкапы

Важный момент. В отличие от экшена, в ммо-играх история предыдущих действий игрока напрямую влияет на его текущее состояние. Тут как в настройку сервера, так и в сам процесс игры вложено намного больше сил и времени. Поэтому перед тем, как мы начнём что-то стороить и обвешивать сервер плагинами, самое время прикрутить бэкапы!
Делать мы их будем локально, и забирать по сети другим сервером, как написано вот в этой статье. Не путайте настоящий бэкап (делаемый скриптом, и в который НЕЛЬЗЯ вмешаться со стороны пользователя minecraft, с сохранением состояния мира по команде /save-all, которая просто пишет на диск закэшированные в памяти данные!!)
У нас в бэкапе участвуют три системных пользователя:
root — делает бэкап как системных конфигов ВПС-ки, так и каталога с игрой, включая базы данных (а они у нас будут, куда же без них)
minecraft — от него запускается игровой сервер
backuper — отдает бэкапы по сети.
Пример скрипта для бэкапа:
#!/bin/bash

date=`date "+%Y_%m_%d"`; # current date [YYYY_mm_dd]
days_store='5'; # Number of backups (N last days)
dir_open=/Backups/ # directory for store backups
tgz_bin='tar --acls -p --xattrs --label="Minecraft.Server" --gzip -cf '; # Tar/GZip binary + options
mysqldump_bin='/usr/bin/mysqldump --defaults-extra-file=/root/backup/mysql.cnf --extended-insert --quick ';

echo "mkdir $date ..."
mkdir -p $dir_open/$date
chown -R root:backuper $dir_open/$date
chmod 770 $dir_open/$date

echo 'change dir';
cd $dir_open/$date

echo 'Pack...'
$tgz_bin home_root.tgz /root /home/backuper
$tgz_bin home_minecraft.tgz /home/minecraft
$tgz_bin http://www.tgz /var/www/html

$tgz_bin etc.tgz /var/spool/cron \
/etc/sysconfig/network-scripts/ifcfg-* /etc/sysconfig/ip*tables* /etc/httpd /etc/my.cnf /etc/php.ini \
/etc/sudoers /etc/rc.d/rc.local /etc/resolv.conf /etc/rsyslog.conf /etc/passwd /etc/shadow /etc/group /etc/fstab \
/etc/sysctl.conf /boot/grub2/grub.cfg /etc/ssh /etc/fstab \
/etc/selinux/config /etc/selinux/targeted/seusers* /etc/selinux/targeted/modules/active/*.local /etc/selinux/targeted/contexts/files/*.local

$mysqldump_bin mysql user db tables_priv columns_priv proxies_priv | gzip -9 -c > mysql_sys.gz
$mysqldump_bin --databases minecraft | gzip -9 -c > mysql_minecraft.gz

sha256sum * > _minecraft.server.sha256

echo ' ... Delete old backups ...';
find $dir_open -mtime +$days_store -delete # store backups for N last days

echo " ... Complete !\n\n";
Самое время проверить скрипт и убедиться, что бэкапы делаются правильно. Такой подход поможет вам быстро восстановить сервер, даже если его специально уронят или взломают злоумышленники.

Имея на руках текущий бэкап, можно приступать к настройке плагинов. Но поскольку плагины меняют и усложняют игровой процесс, который тут и так заметно сложнее, чем «беги-хватай_пушки-мочи_козлов», то сперва имеест смысл этот самый игровой процесс немного изучить чтением следующих манов, чтобы не накосячить в настройке плагинов:

http://minecraft-ru.gamepedia.com/Игровой_процесс
http://minecraft-ru.gamepedia.com/Блоки
http://minecraft-ru.gamepedia.com/Предметы
http://vminecraft.ru/272-komandy-admina-na-servere-minecraft.html

4. Основные плагины

Теперь настроим базовые плагины. Каждый плагин представляет собой jar-файл, который кладётся в /home/minecraft/mc1/plugins, а рядом с ним создаётся подкаталог с настройками. Некоторые плагины делают по отдельному конфигу на игрока и если они не умеют в базы данных — то вы слегка попали =)
Что касается баз данных — их надо использовать в обязательном порядке, если нет явных противопоказаний! Хорошая практика — делать для каждого плагина свой логин в mysql, давая ему доступ только к своим таблицам. Это менее удобно при обновлениях и установке, но более безопасно при использовании.

4.1 AuthMe

Авторизует игроков, ведёт дату последнего логина, проверяет требования к допустимым символам в логине, проверяет качество паролей.
Часть конфига:
$ cat /home/minecraft/mc1/plugins/AuthMe/
DataSource:
mySQLColumnName: username
mySQLTablename: authme
mySQLUsername: mcft_authme
backend: mysql
mySQLColumnLastLogin: lastlogin
mySQLDatabase: minecraft
mySQLPort: '3306'
mySQLColumnIp: ip
mySQLHost: 127.0.0.1
mySQLColumnPassword: password
mySQLPassword:
caching: true
...
settings:
restrictions:
allowChat: false
allowCommands:
- /login
- /register
- /l
- /reg
- /passpartu
- /email
- /captcha
maxRegPerIp: 1
maxNicknameLength: 20
ForceSingleSession: true
teleportUnAuthedToSpawn: true
minNicknameLength: 3
allowMovement: false
timeout: 90
allowedNicknameCharacters: '[a-zA-Z0-9_-а-яА-Я]*'
allowedMovementRadius: 100
enablePasswordVerifier: true
ProtectInventoryBeforeLogIn: true
displayOtherAccounts: true
spawnPriority: authme,essentials,multiverse,default
maxLoginPerIp: 0
maxJoinPerIp: 0
GameMode:
ForceSurvivalMode: true
ResetInventoryIfCreative: false
security:
minPasswordLength: 4
unLoggedinGroup: unLoggedinGroup
passwordHash: SHA256
doubleMD5SaltLength: 8
unsafePasswords:
- '123456'
- password
registration:
enabled: true
messageInterval: 5
force: true
enableEmailRegistrationSystem: false
doubleEmailCheck: false
forceKickAfterRegister: false
forceLoginAfterRegister: false
messagesLanguage: ru
forceCommands: []
forceCommandsAsConsole: []
useWelcomeMessage: true
broadcastWelcomeMessage: false
delayJoinMessage: false
Security:
SQLProblem:
stopServer: true
console:
noConsoleSpam: false
removePassword: true
logConsole: false
Protection:
enableAntiBot: true
antiBotSensibility: 5
antiBotDuration: 10

Как создать БД из sql-дампа и выдать на неё права доступа — гуглим сами.

4.2 Essentials

Данный плагин умеет кучу всего: стартовые наборы вещей («киты»), запоминание данных о последней сессии (время входа и выхода, IP, координаты в игровом мире, координаты домашней точки из /sethome), системные точки телепортации («варпы» для /warp ), тексты для книжек в китах, сообщение при логине на сервер, команда списка правил /rules, различные точки спавна для разных групп игроков, паузы при использовании телепортации, управление AFK (режим, когда игрок отошел на пару минут) и многое другое.
Конфиг там негуманный совершенно, 40 Кб текста.
Из важного — там можно поменять стартовый набор вещей (/kit start), добавить свои наборы вещей для разных целей, и обязательно проверить, чтобы не были разрешены те таблички, который вы не используете!

4.3 LWC

Обеспечивает защиту блоков. Двери, сундуки, раздатчики, печки, ворота и тому подобные блоки могут быть защищены этим плагином, чтобы только владелец сундука мог открывать его и делатье его доступным друзьям. Важная вещь — можно настроить автоматическую защиту — например, когда только что установленный сундук будет сразу же закреплен за установившим его игроком.
Важный момент — интеграция с WorldGuard (не забываем про совместимость глюков!) и использование базы данных.

4.4 WorldGuard

Обеспечивает защиту регионов. Если LWC защищает доступ в конкретный сундук или конкретную дверь (блок), то WG защищает ОБЛАСТЬ — так называемый приватный регион. Важный момент — данный плагин ОЧЕНЬ плохо работает с MySQL. Причём не исключена ситуация, когда плагин выпадет, но не остановит сервер. Как итог — весьма изрядные разрушения от нашествия вандалов.
Именно тут хранятся приватные регионы игроков (чтобы в них не могли строить и ломать другие игроки), тут же задаются лимиты на количество приватных областей для игроков, а также можно натсроить глобальные флаги защиты для миров — например, запретить разрушения блоков взрывами.
Немного конфигов:
$ cat config.yml
#
# WorldGuard's main configuration file
#
# This is the global configuration file. Anything placed into here will
# be applied to all worlds. However, each world has its own configuration
# file to allow you to replace most settings in here for that world only.

regions:
enable: true
wand: 288
max-claim-volume: 300000
max-region-count-per-player:
default: 3
security:
deop-everyone-on-join: true
block-in-game-op-command: true
op-permissions: false
ignition:
block-tnt: false
block-tnt-block-damage: false
block-lighter: false
mobs:
block-creeper-explosions: false
block-creeper-block-damage: false
player-damage:
disable-fall-damage: false
disable-lava-damage: false
disable-fire-damage: false

Самый важный момент тут — отключить OP-пермишены. Вообще о команде /op следует забыть и никогда о ней не вспоминать, и никогда её не применять. Для выдачи разрешений существует специальный плагин, гораздо более гибкий и более параноидальный в плане настроек.

4.5 PermissionsEx

Этот плагин управляет доступами, причём на весьма низком уровне. Детализация потрясает — можно очень тонко задать, какие группы игроков и каким образом смогут использовать те или иные блоки, какие функции будут доступны в каждом из плагинов, и так далее. Из удобного — есть отладочный режим, позволяющий отслеживать, какие именно права доступа проверяются плагином при тех или иных событиях. Это, на мой взгляд, один из самых трудных в настройке плагинов, если вы, конечно, хотите сделать по-уму.
В главном конфиге плагина отключаем OP-пермишены (allowOps: false).
Например, если вы хотите сделать группу Creative-пользователей, которые смогут строить, но которые не смогут устраивать массовые раздачи топового шмота и накручивать себе балансы, можно сделать такую настройку для этой группы:

creative:
permissions:
- -trade.*
- -securityvillagers.trade
- essentials.kits.creative
- anticheat.check.(fastbreak|fastplace)
- -essentials.signs.use.(heal|weather|repair|enchant)
- -essentials.suicide
- essentials.(clearinventory|back|fly|gamemode)
- -modifyworld.blocks.place.(*diamond*|*emerald*|*gold*|lapis*|beacon|*chest*|*hopper*|*furnace*|dispenser*|dropper*|enchantmenttable|*quartz*|*iron*|anvil|jukebox|noteblock|step:7|redstoneblock|redstoneore|poweredrail|brewingstand|mobspawner|skull*|*lava*|water|tnt)
- -modifyworld.items.use.*.on.block.(*diamond*|*emerald*|*gold*|lapis*|beacon|*chest*|*hopper*|*furnace*|dispenser*|dropper*|enchantmenttable|*quartz*|*iron*|anvil|jukebox|noteblock|step:7|redstoneblock|redstoneore|poweredrail|brewingstand|mobspawner|skull*|*lava*|water|tnt)
- -modifyworld.items.use.*.on.entity.(minecartchest|minecarthopper|furnace|dispenser*|dropper*|itemframe)
- -modifyworld.items.use.*.on.block.(chest*|enderchest*|trappedchest*|hopper|dispenser*|dropper*|furnace*)
- -modifyworld.items.use.(*minecart*).on.block.(*rails*)
- -modifyworld.items.(drop|pickup|throw|enchant|craft).*
- -modifyworld.items.(use|hold).(*eye*)
- -modifyworld.damage.take.*
- -modifyworld.damage.deal.player.*
- -modifyworld.bucket.empty.(lava|water)
- worldedit.navigation.up
- creativegates.(create|destroy)
- -Chestshop.*
inheritance:
- default
worlds:
world_nether:
permissions:
- modifyworld.damage.deal.player.*
pvp:
permissions:
- modifyworld.damage.take.*
- modifyworld.damage.deal.player.*
- modifyworld.items.throw.potion*
hungergames:
permissions:
- modifyworld.damage.take.*
- modifyworld.damage.deal.player.*
- modifyworld.items.use.*.on.block.(chest*)
options:
prefix: '&6[&aСтроитель&6] &f'
default: false

Это надёжный способ обеспечить достаточно честную игру при изначально нечестной разнице в условиях. Кроме того, взлом любой учетной записи подобного аккаунта приведет к заметно меньшим последствиям для сервера в целом.

В принципе, с этим набором плагинов уже можно вполне себе играть. Тонкостей конечно ещё масса, и есть ещё много других полезных плагинов, но это уже тема для следующей статьи, а тут уже и так 2263 слов.

Обсуждение закрыто.