В этом гайде вы узнаете как добавить на
Minestom сервер базовые механики Minecraft. Начать стоит с того, что если вы не знакомы с Minestom, вам следует прочесть
мою новость об этой библиотеке, поскольку без понимания самых основ вы вряд ли поймёте о чём будет идти речь в этом гайде. Мы разберём как вернуть логи, освещение, online-mode, выпадение блоков, подбирание блоков и выбрасывание блоков, ведь по стандарту на вашем сервере не будет ничего из этого, т.к. вам нужно имплементировать всё вручную.
Разбираем структуру проекта и добавляем логи
Думаю, что начать следует именно с этого, т.к. для добавления логов нужно добавить новую зависимость в
Gradle, а именно
SLF4J Simple Provider. На момент написания этого гайда последней версией библиотеки
Simple Provider была
2.0.16. Узнать текущую последнюю версию можно на
официальном сайте Maven Repository. Для добавления новой зависимости открываем
build.gradle и вписываем новую строку в секцию
dependencies:
implementation group: 'org.slf4j', name: 'slf4j-simple', version: '2.0.16'
После этого перезагружаем
Gradle, он загрузит библиотеку и мы сможем создать логгер:
public static final Logger logger = LoggerFactory.getLogger(Main.class);
Готово! Инициализировав логгер в главном классе мы сможем использовать его и в других классах, поскольку его модификатор доступа -
public.
Для этого гайда я так же создам отдельные классы -
InstanceUtil и
EventUtil, в которых мы и будем работать с мирами и ивентами сервера.
Отдельные классы InstanceUtil и EventUtil
Для начала создадим InstanceUtil, в котором мы будем управлять инстанциями (мирами) нашего сервера. Так же создадим метод initWorld(), который будет создавать мир:
public class InstanceUtil {
private static final InstanceManager instanceManager = MinecraftServer.getInstanceManager();
public static InstanceContainer instanceContainer = instanceManager.createInstanceContainer();
public static void initWorld() {
instanceContainer.setGenerator(unit -> {
unit.modifier().fillHeight(0, 40, Block.GRASS_BLOCK);
});
Main.logger.info("World is initialized!");
}
}
Добавляем соответствующую строку в главный класс:
InstanceUtil.initWorld();
Далее создадим EventUtil, в котором мы будем управлять ивентами на сервере:
public class EventUtil {
private static final GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
public static void registerEvents() {
globalEventHandler.addListener(AsyncPlayerConfigurationEvent.class, event -> {
final Player player = event.getPlayer();
String username = player.getUsername();
event.setSpawningInstance(InstanceUtil.instanceContainer);
player.setRespawnPoint(new Pos(0, 42, 0));
Main.logger.info(String.format("Player %s joined the server!", username));
});
Main.logger.info("Events are registered!");
}
}
После этого пропишем соответствующую строчку в главном классе:
EventUtil.registerEvents();
После этих действий скомпилируем наш сервер и увидим в консоли следующее:
Все сообщения отобразились в консоли, сервер работает и я смог зайти на сервер, а это значит что мы всё сделали правильно, удостоверились в работоспособности нашего кода и структуризовали наш проект. С этого момента работать с ним станет явно проще и удобнее.
Добавляем освещение и online-mode
Начнём с освещения. В
Minestom у любого
InstanceContainer (мира) по стандарту задан тип чанков
DynamicChunk, который умеет только хранить информацию об существующих в нём блоках, но не имеет других функций (освещение например). Для добавления в мир освещения мы поменяем провайдер чанков в методе
initWorld() в классе
InstanceUtil:
instanceContainer.setChunkSupplier(LightingChunk::new);
Данную строчку я вписал между генерацией мира и оповещением в консоль об успешной инициализации мира.
Для добавления
online-mode на сервер нам необходимо инициализировать утилиту
MojangAuth в главном классе:
MojangAuth.init();
После добавления этих двух строчек компилируем наш сервер и заходим на сервер:
Как мы видим, теперь в мире есть освещение и у игрока появился скин, а в табе появились иконки возле никнеймов. Данный этап можно считать успешно завершённым.
Возвращаем выпадение, выбрасывание и подбирание блоков
В связи с тем, что Minestom является библиотекой для создания серверов со своей кастомной логикой, по стандарту в нём не имплементированы эти три простые элемента игры, но в этой части гайда я объясню вам как их вернуть.
Начнём с выпадения блоков. Для этого нам нужно добавить
Listener на ивент
PlayerBlockBreakEvent, в котором мы сначала получим блок и, в случае если блок не является
null, создаём сначала виртуальный предмет, потом на его основе создаём физический энтити (блок), которому прописываем логику появления, а именно спавн по центру блока и задержку на подбирание в полсекунды:
globalEventHandler.addListener(PlayerBlockBreakEvent.class, event -> {
var material = event.getBlock().registry().material();
if (material != null) {
var itemStack = ItemStack.of(material);
ItemEntity itemEntity = new ItemEntity(itemStack);
itemEntity.setInstance(event.getInstance(), event.getBlockPosition().add(0.5, 0.5, 0.5));
itemEntity.setPickupDelay(Duration.ofMillis(500));
}
});
Далее добавим выбрасывание блоков. Для этого нам нужно улавливать ивент
ItemDropEvent и прописать ему в логику получение выброшенного предмета и его спавн в определённой позиции с определённым
ускорением (да, вы можете сделать так чтобы блок выбрасывался на 1000 блоков от игрока) Как по мне, то данную фишку можно использовать при создании какой-нибудь миниигры (волейбол, как вариант):
globalEventHandler.addListener(ItemDropEvent.class, event -> {
ItemEntity itemEntity = new ItemEntity(event.getItemStack());
itemEntity.setInstance(event.getInstance(), event.getPlayer().getPosition());
itemEntity.setVelocity(event.getPlayer().getPosition().add(0, 1, 0).direction().mul(2));
itemEntity.setPickupDelay(Duration.ofMillis(500));
});
Ну и последнее, подбор блоков. Здесь мы будем ловить ивент
PickupItemEvent, в логику которого добавим получение предмета и его добавление в инвентарь, в случае если предмет подобран
игроком:
globalEventHandler.addListener(PickupItemEvent.class, event -> {
var itemStack = event.getItemStack();
if (event.getLivingEntity() instanceof Player player) {
player.getInventory().addItemStack(itemStack);
}
});
Готово! Компилируем наш сервер и проверяем работоспособность. Если вы всё сделали правильно, то на сервере при ломании блоков должны выпадать блоки, при нажатии на клавишу выбрасывания блоков они должны выбрасываться и при поднятии блоков с земли они должны добавляться в ваш инвентарь.
Для большего удобства можно добавить соответствующие сообщения в консоль:
Как мы можем видеть,
Minestom даёт действительно невероятные возможности в кастомизации вашего сервера. По факту, при разработке сервера на базе этой библиотеки вы ничем не ограничены, ведь под вашим контролем находятся абсолютно все элементы игры. Вы можете использовать сторонние библиотеки, полностью кастомизировать генерацию мира, ресурспаки, датапаки, ивенты, количество миров, разрешения игроков, команды сервера и не только. Абсолютно всё можно реализовать по своему, за что
Minestom лично от меня получает 5 мем. Благодарю вас за прочтение данного гайда и желаю вам удачи в создании своего сервера мечты!