Перейти к содержанию

Прокси#

Перед началом создания модов надо понять и правильно использовать очень важную вещь.

Дело в том, что Minecraft состоит из нескольких частей:

  • Физический клиент — это программа, которую вы запускаете с помощью лаунчера.
  • Физический сервер, который часто называется выделенным сервером — программа, которая запускается с помощью файлов типа minecraft_server.jar.
  • Логический клиент отвечает за отображение моделей и текстур, за прием данных от мышки и клавиатуры, за отображение GUI.
  • Логический сервер отвечает за всю игровую логику: спавн мобов, погоду, обновление инвентарей, AI и все другие механики игры.

Зачем надо это знать? А затем, что при попытке выполнить отрисовку текстуры блока на стороне сервера он незамедлительно крашнется! И наоборот, попытка реализовывать игровую механику (открытие GUI, создание взрывов) на стороне клиента может привести к непредсказуемым багам, появлению пустых твердых блоков, рассинхронизации и так далее...

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

CommonProxy#

Для начала нам надо создать класс для выполнения действий, которые должны выполняться на стороне и клиента, и сервера.

Для этого создайте пакет proxy внутри пакета нашего мода и класс CommonProxy внутри него. Объявите внутри класса три уже знакомых вам метода:

  • preInit
  • init
  • postInit
public class CommonProxy
{
    public void preInit(FMLPreInitializationEvent event)
    {

    }

    public void init(FMLInitializationEvent event)
    {

    }

    public void postInit(FMLPostInitializationEvent event) {

    }

}

ClientProxy#

Теперь создадим класс для действий, которые должны выполняться только на стороне клиента, а именно:

  • Регистрация моделей блоков/мобов/предметов
  • Регистрация рендеров этих самых моделей
  • ...

Для этого создадим класс ClientProxy, наследующий класс CommonProxy в пакете proxy:

public class ClientProxy extends CommonProxy
{
    @Override
    public void preInit(FMLPreInitializationEvent event)
    {
        super.preInit(event);
    }

    @Override
    public void init(FMLInitializationEvent event)
    {
        super.init(event);
    }

    @Override
    public void postInit(FMLPostInitializationEvent event)
    {
        super.postInit(event);
    }
}

Заметьте, что мы вызываем все три метода из CommonProxy с помощью super, чтобы они обязательно выполнились на стороне клиента.

Регистрация в главном файле#

Теперь мы полностью можем управлять, какие части нашего мода должны выполняться на сервере, клиенте, или вообще на обеих сторонах.

Теперь вернемся в главный файл нашего мода и скажем Forge об этом. Для того, чтобы это сделать, создадим переменную proxy типа CommonProxy и добавим к ней аннотацию @SidedProxy:

@SidedProxy(clientSide = "ru.ivasik.tutorial.proxy.ClientProxy", serverSide = "ru.ivasik.tutorial.proxy.CommonProxy")
public static CommonProxy proxy;

Эта аннотация содержит два поля, которые обозначают пути до классов ClientProxy и CommonProxy. При запуске, Forge будет автоматически определять нужную сторону (клиент/сервер) и создавать объект класса ClientProxy или CommonProxy.

Последнее, что нам нужно сделать: выполнить три метода (preInit, init, postInit) в нашем главном файле мода:

@EventHandler
public void preInit(FMLPreInitializationEvent event)
{
    proxy.preInit(event);
}

@EventHandler
public void init(FMLInitializationEvent event)
{
    proxy.init(event);
}

@EventHandler
public void postInit(FMLPostInitializationEvent event)
{
    proxy.postInit(event);
}

Полный код главного файла мода:

package ru.ivasik.tutorial;

import ru.mcmodding.testmod.proxy.CommonProxy;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

@Mod(modid = Tutorial.MODID /* имя мода */, version = Tutorial.VERSION /* его версия */)
public class Tutorial
{
    public static final String MODID = "tut";
    public static final String VERSION = "1.0";

    @SidedProxy(clientSide = "ru.ivasik.tutorial.proxy.ClientProxy", serverSide = "ru.ivasik.tutorial.proxy.CommonProxy")
    public static CommonProxy proxy;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
        proxy.preInit(event);
    }

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        proxy.init(event);
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event) 
    {
        proxy.postInit(event);
    }
}