Кастомные на тивные блок-энтити
Ссылаясь на сказанное в статье Определение блоков и предметов в Java
, если регистрация кастомных блоков и предметов находится на первом месте в списке самых важных возможностей Inner Core, которые, к сожалению, JavaScript-only, второе место в этом списке несомненно занимают тайл-энтити.
Система классов кастомных нативных блок-энтити, представленная в KEX RELEASE 4.0
, закрывает сразу два недостатка тайл-энтити Inner Core, первый из которых — это невозможность работать с ними в Java, а второй - относительно низкая производительность из-за 100%-ной JavaScript-реализации.
Java-блок-энтити регистрируются в нативном коде как новые типы ванильных тайлов (таким же образом, как штуки типа сундука, воронки, варочной стойки, печки и т.д.). Каждый экземпляр Java-блок-энтити привязан к соответствующему нативному объекту тайла. Сам Майнкрафт вызывает большинство ключевых методов, в то время как Java-объект является лишь набором этих методов, определённым разработчиком мода.
Определение класса кастомного блок-энтити
Базовый Java-класс для кастомных нативных блок-энтити - vsdum.kex.modules.tileentity.BlockActor
. Несмотря на отсутствие абстрактных методов, он объявлён как абстракный класс, для того, чтобы вы не устанавливали этот класс-пустышку как прототип блок-энтити для какого-то блока.
Конструктор BlockActor
принимает три ключевых параметра, которые вы обязательно должны передать в вызов super
в конструкторе класса вашего кастомного блок-энтити.
Самый элементарный пример:
package visualstudiodan.kextest;
import vsdum.kex.modules.tileentity.BlockActor;
import vsdum.kex.util.mcmath.BlockPos;
public class MyBlockEntity extends BlockActor {
public MyBlockEntity(long ptr, int type, BlockPos blockPos)
{
super(ptr, type, blockPos);
}
}
Регистрация нового типа блок-энтити
Следующий шаг - регистрация авто-сгенерированного числового ID типа блок-энтити для нашего нового класса блок-энтити. Мы позже используем этот числовой ID для назначения этого блок-энтити определённому блоку, которому мы хотим.
Метод TileEntityModule.registerTileEntityType(typeName, callback)
принимает уникальный строковой идентификатор блок-энтити (традиционно написанный в змеином регистре) и функцию, которая будет вызываться каждый раз, когда кастомный тайл собирается быть создан, и должна возвращать объект экземпляра блок-энтити. Эта функция предоставляет вам те самые три ключевых параметра, упомянутых ранее. Метод возвращает сгенерированный числовой ID ново-зарегистрированного типа блок-энтити. Для того, чтобы его использовать, вы должны где-то сохранить этот ID. На мой взгляд, лучшая практика это публичное статичное константное
поле.
Базовый пример как функция калбека создания тайл-энтити должна выглядеть:
new TileEntityCreationCallback() {
@Override public BlockActor create(long ptr, int type, BlockPos pos)
{
return new MyBlockEntity(ptr, type, pos);
}
}
Используя лямбда-синтаксис Java 8, она станет гораздо менее громоздкой:
(ptr, type, pos) -> new MyBlockEntity(ptr, type, pos)
Более того, в нашем случае мы не должны дополнительно ничего делать, кроме как создать сам объект блок-энтити, так что мы можем просто сослаться на конструктор нашего класса блок-энтити:
MyBlockEntity::new
Наконец, вот как мы зарегистрируем наш новый тип блок-энтити и сохраним его сгенерированный числовой ID в статичном поле:
public static final int TYPE_ID = TileEntityModule.registerTileEntityType("my_tile", MyBlockEntity::new);
Назначение блок-энтити блоку
Есть два способа назначения вашего кастомного типа блок-энтити определённому блоку. Первый способ - используя метод TileEntityModule.registerForBlock(blockID, type)
.
Вы можете вызвать его либо в Java:
public class MyBlock extends Block {
public MyBlock()
{
super("my_block");
// this.addVariation(...), properties, ...
}
static {
MyBlock registered = BlockRegistry.register(new MyBlock());
TileEntityModule.registerForBlock(registered.getId(), MyBlockEntity.TYPE_ID);
}
}
... либо в JavaScript/TypeScript:
IDRegistry.genBlockID("my_block");
Block.createBlock("my_block", [{...}]);
const TYPE_ID = WRAP_JAVA("visualstudiodan.kextest.MyBlockEntity").TYPE_ID;
KEX.TileEntityModule.registerForBlock(BlockID.my_block, TYPE_ID);
Второй способ, являющийся эксклюзивным для блоков, зарегистрированных через Java - имплементирование компонента IHasBlockActor
:
public class MyBlock extends Block implements IHasBlockActor {
public MyBlock()
{
super("my_block");
// this.addVariation(...), properties, ...
}
@Override public int getTileEntityType()
{
return MyBlockEntity.TYPE_ID;
}
static {
BlockRegistry.register(new MyBlock());
}
}
Вы можете увидеть список главных методов класса BlockActor
здесь или зайдя прямо в файл BlockActor.java в публичном GitHub-репозитории KernelExtension
Напоследок, новый метод getCustomBlockEntity
был добавлен в класс ExtendedBlockSource
, для получения Java-объекта экземпляра кастомного нативного блок-энтити на данных координатах, если оно там присутствует.