====== Состояния блока ======
Каждый тип блока в Minecraft представлен единственным экземпляром ''Block''.
Это делает невозможным изменение состояния определенного блока простым изменением состояния экземпляра ''Block'',
так как это повлияет на любой другой блок этого типа!
Но что, если вы // действительно // хотите задать единственное состояние блока, чтобы оно могло изменяться в зависимости от некоторого условия?
Вот для чего нужны ''BlockState''.
Допустим, нам нужен блок, который может вызывать молнию, но только при зарядке.
Сначала мы определяем логическое свойство блока - независимо от того, заряжено оно или нет (будьте осторожны, чтобы не импортировать неправильное BooleanProperty!):
public class ChargeableBlock extends Block {
public static final BooleanProperty CHARGED = BooleanProperty.of("charged");
// Экземпляр блока. Вы можете разместить его где угодно.
public static final ChargeableBlock CHARGEABLE_BLOCK = Registry.register(
Registry.BLOCK,
new Identifier("tutorial", "chargeable_block"),
new ChargeableBlock( /* напишите здесь что-нибудь подходящее */ ));
}
Затем нам нужно зарегистрировать свойства блока, переопределив ''appendProperties'', а затем добавить свойство ''CHARGED'':
public class ChargeableBlock extends Block {
[...]
@Override
protected void appendProperties(StateManager.Builder builder) {
builder.add(CHARGED);
}
}
Затем нам нужно установить состояние нашего свойства по умолчанию в конструкторе блока (чтобы задать несколько свойств, выполните вызовы цепочки ''with()''):
public class ChargeableBlock extends Block {
[...]
public ChargeableBlock(Settings settings) {
super(settings);
setDefaultState(getStateManager().getDefaultState().with(CHARGED, false));
}
}
NТеперь нам нужно иметь возможность заряжать блок с помощью метода ''onUse'', вызывая внутри него метод ''world.setBlockState()'' (''playSound'' совершенно необязателен, но он помогает нам узнать, что блок заряжен).
public class ChargeableBlock extends Block {
[...]
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
player.playSound(SoundEvents.BLOCK_RESPAWN_ANCHOR_CHARGE, 1, 1);
world.setBlockState(pos, state.with(CHARGED, true));
return ActionResult.SUCCESS;
}
}
И, наконец, чтобы использовать свойство ''CHARGED'', мы вызываем ''onSteppedOn'' с ''world.getBlockState(pos).get(CHARGED)'' внутри него:
public class ChargeableBlock extends Block {
[...]
@Override
public void onSteppedOn(World world, BlockPos pos, BlockState state, Entity entity) {
if (world.getBlockState(pos).get(CHARGED)){
// Вызов молнии в блоке
LightningEntity lightningEntity = (LightningEntity) EntityType.LIGHTNING_BOLT.create(world);
lightningEntity.refreshPositionAfterTeleport(Vec3d.ofBottomCenter(pos));
world.spawnEntity(lightningEntity);
}
world.setBlockState(pos, state.with(CHARGED, false));
super.onSteppedOn(world, pos, state, entity);
}
}
==== Добавление моделей для состояний блока ====
Вы также можете изменить текстуру и модель вашего блока в зависимости от состояния. Это делается с помощью файла JSON, называемого "JSON состояний блока(blockstate JSON)". Всем блокам нужен этот JSON, независимо от того, имеют они несколько состояний или нет, но содержимое JSON может быть таким простым или сложным, как вам нравится. Если вы хотите изменить текстуры вашего блока в зависимости от состояния, вам //понадобится// несколько моделей.
Допустим, вы регистрируете экземпляр ''Chargeable'' с идентификатором ''tutorial:chargeable_block''. Minecraft будет искать файл по пути ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json'' для загрузки состояния. Если вы не хотите, чтобы ваш блок менял модели между состояниями, JSON файл может быть очень простым. Это выглядело бы примерно так:
{
"variants": {
"": { "model": "tutorial:block/chargeable_block" }
}
}
Давайте разберем этот простой пример. В этом JSON есть пара важных частей:
* ''%%"variants"%%'' определяет, какую модель следует использовать для каждого возможного состояния блока. Мы немного подробнее рассмотрим варианты.
* Вариант с именем ''%%""%%'' (пустая строка) будет применяться к //каждой// перестановке состояния блока. Если у вас есть вариант ''%%""%%'', у вас не должно быть никаких других вариантов в JSON, иначе будет плохо.
* Объект, назначенный варианту ''%%""%%'' , может иметь различные добавленные к нему свойства, такие как вращение или манипулирование текстурой. Ознакомьтесь со связанной страницей модели ниже для получения дополнительной документации о том, какие свойства можно добавить. Все варианты //должны// содержать свойство ''%%"model"%%''.
* Свойству ''%%"model"%%'' всегда передается идентификатор модели. В этом случае игра будет смотреть в местоположении ''src/main/resources/assets/tutorial/models/block/chargeable_block.json''. Идентификатор здесь может быть любым. Он //не должен// совпадать с идентификатором вашего блока, но если у вас есть только один вариант, вероятно, так и должно быть. Модели блоков имеют свои собственные настройки, которые очень хорошо задокументированы на вики-странице Minecraft, ссылка на которую приведена ниже. Вы можете либо написать JSON вручную, либо использовать такую программу, как [[https://blockbench.net|Blockbench]] чтобы сгенерировать его было проще.
Если вы хотите иметь разные модели для каждого состояния блока, вам следует добавить несколько вариантов. Для того же расположения ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json'', которое мы использовали выше, ваш файл модели, вероятно, будет выглядеть следующим образом:
{
"variants": {
"charged=false": { "model": "tutorial:block/chargeable_block" },
"charged=true": { "model": "tutorial:block/chargeable_block_charged" }
}
}
В этом JSON есть два варианта, по одному для каждой возможности свойства ''CHARGED'', которое мы определили выше. Поскольку мы присвоили свойству строковое имя ''charged'' в Java, это то, что мы используем здесь. Логические значения имеют только два состояния, но если вы используете свойства, основанные на целых числах или перечислениях, у вас будет больше вариантов.
Варианты основаны на возможных перестановках свойств, добавленных в ваш блок. Свойство может быть полностью проигнорировано в JSON файле состояний, если вы хотите, как в первом JSON файле состояний, где мы проигнорировали свойство ''charged'', но если вы хотите включить свойство в один вариант, оно должно быть включено во //все// комбинации. Если бы у ''tutorial:chargeable_block'' также было логическое свойство с именем ''glowing'', и вы хотели изменить модель в зависимости от того, светилась ли она и была ли она заряжена, вам понадобились бы четыре варианта: не заряженный и не светящийся, заряженный и не светящийся, не заряженный и светящийся, и заряженный и светящийся. Одна и та же модель может быть назначена нескольким вариантам, если вам это нужно.
Это всего лишь простое введение в JSON файл состояний блока. Все трюки, которые вы можете выполнять с помощью этих JSON, задокументированы на [[https://minecraft.gamepedia.com/Model|Майнкрафт википедии (англ.)]], , а также примеры того, как функции используются в ваниле. Желаю удачи!
==== Примечание о производительности ====
Каждое возможное состояние блока регистрируется в начале игры. Это означает, что если у вас есть 14 логических свойств, блок имеет 2 ^ 14 = 16384 различных состояния и зарегистрировано 2 ^ 14 состояний. По этой причине блоки не должны содержать слишком много свойств состояний блока. Скорее, состояния блоков должны быть в основном зарезервированы для визуальных элементов, а [[ru:tutorial:blockentity|Сущность блока]] следует использовать для более продвинутого состояния.