Всем привет! Клиентские моды во многом отличаются от глобальных. Но чем?
Основное различие заключается в том, что клиентские моды работают только на стороне игрока и не требуют установки на сервер. Они изменяют визуальную часть, добавляют удобства в управлении или предоставляют вспомогательные функции (например, мини-карты, моды на интерфейс или оптимизацию).
В этом гайде мы разберём, как создать Forge-мод, который будет работать исключительно на клиенте.
(на примере буду работать на MCreator)
Откройте главный класс мода (у меня это "LemonadeMod"), после найдите инициализирующий класс, после напишите следующие -
// в public (название класса без class)
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); // может быть другое название за место modEventBus
modEventBus.addListener(this::setupClient);
// создаем класс setupClient
private void setupClient(final FMLClientSetupEvent event) {
event.enqueueWork(() -> {
if (FMLEnvironment.dist == Dist.CLIENT) {
new LemonadeModClient(); // наш класс
}
});
}FMLJavaModLoadingContext.get()- получает контекст загрузки мода..getModEventBus()- возвращает шину событий (EventBus), специфичную для вашего мода.modEventBus- это просто название переменной, вы можете назвать её как угодно (например,eventBus).
addListener- регистрирует метод (в данном случаеsetupClient), который будет вызываться при наступлении определённого события.this::setupClient- ссылка на методsetupClientв текущем классе.
FMLClientSetupEvent- событие, которое вызывается, когда Forge готов к настройке клиентской части мода.Этот метод вызывается только на клиенте (не на сервере).
enqueueWork- добавляет задачу в очередь выполнения на основном потоке Minecraft.Используется, потому что некоторые операции (например, регистрация рендеров) должны выполняться в основном потоке игры.
FMLEnvironment.dist- проверяет, в каком окружении работает код (CLIENTилиDEDICATED_SERVER).Dist.CLIENT- гарантирует, что код внутри блока выполнится только на клиенте (избыточная проверка, так какFMLClientSetupEventи так вызывается только на клиенте).
LemonadeModClient()- инициализирует клиентскую часть мода (например, регистрирует рендеры для сущностей, блоков и т. д.).
Создаем класс LemonadeModClient -
package net.genamistik.lemonade;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.api.distmarker.Dist;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class LemonadeModClient {
public LemonadeModClient() {
}
@SubscribeEvent
public static void init(FMLCommonSetupEvent event) {
new LemonadeModClient();
}
@Mod.EventBusSubscriber
private static class ForgeBusEvents {
@SubscribeEvent
public static void serverLoad(ServerStartingEvent event) {
}
@OnlyIn(Dist.CLIENT)
@SubscribeEvent
public static void clientLoad(FMLClientSetupEvent event) {
}
}
}@Mod.EventBusSubscriber– указывает, что этот класс подписывается на события Forge.bus = Mod.EventBusSubscriber.Bus.MOD– означает, что он слушает события Mod-шины (а не Forge-шины).
public LemonadeModClient()– пустой конструктор. Обычно здесь инициализируются клиентские вещи (рендеры, текстуры и т. д.), но в данном случае он пуст.
@SubscribeEvent– метод будет вызван при наступлении событияFMLCommonSetupEvent.FMLCommonSetupEvent– событие, которое вызывается на обеих сторонах (клиент и сервер) во время загрузки мода.new LemonadeModClient()– создаёт экземпляр клиентского класса.
@Mod.EventBusSubscriber
private static class ForgeBusEvents {
@SubscribeEvent
public static void serverLoad(ServerStartingEvent event) {
}
@OnlyIn(Dist.CLIENT)
@SubscribeEvent
public static void clientLoad(FMLClientSetupEvent event) {
}
}Данный кусок кода ForgeBusEvents это подписка на Forge-шину (а не Mod-шину), поэтому он может слушать другие события.
@SubscribeEvent
public static void serverLoad(ServerStartingEvent event) {
}ServerStartingEvent– вызывается при старте сервера.
(Можно использовать для регистрации команд, инициализации данных и т. д.)
@OnlyIn(Dist.CLIENT)
@SubscribeEvent
public static void clientLoad(FMLClientSetupEvent event) {
}@OnlyIn(Dist.CLIENT)– гарантирует, что метод не вызовется на сервере (иначе будет краш).FMLClientSetupEvent– вызывается только на клиенте, когда можно безопасно регистрировать рендеры, текстуры и т. д.
И все! Он стал клиентским модом!
Для проверки зайдем с MCreator на сервер 217.106.107.100:27481.
И вы увидите -

Давайте проверим добавив кнопку (на главное меню/стоп экран) и при нажатии майнкрафт будет закрыт (класс TestKnopkaOverlay) -
package net.genamistik.lemonade.client.screens;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.gui.screens.PauseScreen;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class TestKnopkaOverlay {
@SubscribeEvent
public static void onScreenInit(ScreenEvent.Init event) {
if (event.getScreen() instanceof TitleScreen || event.getScreen() instanceof PauseScreen) {
int w = Minecraft.getInstance().getWindow().getGuiScaledWidth();
int h = Minecraft.getInstance().getWindow().getGuiScaledHeight();
// Координаты кнопки: w / 2 + -90, h / 2 + -4
int buttonX = w / 2 - 130; // X = центр экрана - 90
int buttonY = h / 2 - 8; // Y = центр экрана - 4
// Создаем кнопку с желтой "L" (или другим текстом)
Button button = Button.builder(
Component.literal("§eL"), // Желтая "L"
btn -> Minecraft.getInstance().stop()
)
.bounds(
buttonX, // Позиция X
buttonY, // Позиция Y
20, 20 // Размер кнопки (можно настроить)
)
.build();
event.addListener(button);
}
}
}(его не надо регистрировать)
И на главном меню со стоп меню вы увидите кнопку "L" (желтый)\
Удачной разработки!