Добавляем новый блок
Всё ниже написанное пишется в методе init()
:
fun init() {
// Тут всё ниже написанное //
}
Создание регистратора блоков
Для начала нужно создать регистратор, чтоб в последующем создавать новые блоки и добавлять их в игру.
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries
val BLOCKS = DefferedRegister.create(ForgeRegistries.BLOCKS, modId: String)
modId
- это куда будет добавлятся предмет. Можно вписать сюда"hollowengine"
и тогда все предметы будут из модаHollowEngine
.
Создание блока
Финальная реuистрация всех блоков
Теперь для регистрации всех созданных предметов в конце приписываем следующее:
BLOCKS.register(MOD_BUS)
Блок-предмет
Всё это конечно круто. Но как размещать блоки?
Не бойтесь. Прибегать к команде /setblock x y z <modId>:<newBlockId>
не придётся)
// Создаём регистраторы для предметов //
val ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, "best_mod")
val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "best_mod")
// Записываем наш блок в переменную. Сам блок долнех находится в скрипте - выше блока-предмета //
val COOL_BLOCK = BLOCKS.register("cool_block") {...}
// Создаём наш блок-предмет. ID предмета должен быть тот же, что и у блока ?/
ITEMS.register("cool_block") {
// Обычный предмет //
BlockItem(
COOL_BLOCK.get(), // Передаём блок через переменную
Item.Properties()
<Параметры предмета>
)
// Функциональный предмет //
object: BlockItem(
COOL_BLOCK.get(), // Передаём блок через переменную
Item.Properties()
<Параметры предмета>
) {
<Методы предмета>
}
}
// Регистрируем все созданые предметы и блоки //
ITEMS.register(MOD_BUS)
BLOCKS.register(MOD_BUS)
Ресурсы для предмета
Модель
Теперь если вам вдруг не понравился красивый и сочый куб с фиолетово-чёрными четверть кадратиками, то следуйте иструкции ниже:
Когда игра хочет отобразить модель блока, то она пойдёт искать ссылки на модель в файле:
blockstates/<newBlockId>.json
, в этом файле и определяется как будет выглядеть модель при таких-то условиях.
Так что создайтеjson
файл с именемnewBlockId
который вы указали по следующему пути:assets/modId/blockstates/<newBlockId>.json
, где за местоmodId
должна стоять папка с именем, который вы указали при создании регистратора.
Если в регистраторе указан
best_mod
:DeferredRegister.create(ForgeRegistries.BLOCKS, "best_mod")
то за место
modId
- ставлюbest_mod
:assets/best_mod/blockstates
И если создал предмет с
ID
cool_block
:BLOCKS.register("cool_block") {...}
то и имя файла должно быть
cool_block.json
:assets/best_mod/blockstates/cool_block.json
.
Дальше заполните файл по следующему шаблону:
Пример. assets/best_mod/blockstates/cool_block.json{
"variants": {
// Блок без всяких видов. Просто блок //
"": { "model": "best_mod:block/cool_basic_block.json" },
// Если у блока к примеру есть поворот в зависимости с какой стороны он был поставлен //
"facing=north": { "model": "best_mod:block/cool_north_block.json" }, // Северная сторона. FACING: NORTH
"facing=south": { "model": "best_mod:block/cool_south_block.json", "y": 180 }, // Южная сторона. FACING: SOUTH
"facing=west": { "model": "best_mod:block/cool_west_block.json", "y": 270 }, // Западная сторона. FACING: WEST
"facing=east": { "model": "best_mod:block/cool_east_block.json", "y": 90 } // Восточная сторона. FACING: EAST
}
}Простой пример:
- Блок будет иметь одну и ту же модель всегда. Поворот (если вы сделали такое):
facing=north
: Блок будет смотреть лицевой стороной на север (где лицо блока можно узнать поN
вBlockbench
).facing=south
: Блок будет смотреть лицевой стороной на юг, повернув его на 180 градусов (т.е. назад),facing=west
: Блок будет смотреть лицевой стороной на запад, повернув его на на 270 градусов (т.е. влево),facing=east
: Блок будет смотреть лицевой стороной на восток, повернув его на 90 градусов (т.е. вправо)
model
- Как раз этот параметр и определяет, откуда брать модель для блока при таком-то варианте.best_mod:block/cool_basic_block.json
- модель лежит по пути: `assets/best_mod/models/block/cool_basic_block.json
Текстура
Текстуру вы можеет размещать где угодно, всё потому что путь к текстуре указывается в файле
модели блока. Так что если вдруг модель встала, а текстуры нету (вы всё равно выдете
фиолетово-чёрные четверть квадратики на модели) - то проверье, что текстура правильно определила
свои META-данные
:
Если вдруг META-данные
вдруг не соответствуют, то сначала сохраните текстуру там, где вам
нужно, а уже после уже - сохраните модель.
Если и после META-данные
не изменились, то придётся вам изменять вручную.
Имя: Убедитесь что имя текстуры, совпадает с именем файла текстуры,
Папка: Убедитесь что папка указана правильно, где находита текстура (путь указывается относительно папки
modId
),
Пространство имён: это
modId
. Убедитесь что оно указано правильно и совпадает с указаннымmodId
который вы указали в регистратореDefferedRegister
.
Результат (Пример)
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.block.state.BlockBehaviour
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.material.Material
import net.minecraft.world.entity.player.Player
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.level.Level
import net.minecraft.network.chat.Component
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.InteractionResult
import net.minecraft.core.particles.ParticleTypes
import ru.hollowhorizon.hollowengine.common.tabs.HOLLOWENGINE_TAB
fun init() {
val ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, "test") // Для блок-предмета
val BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "test")
val AMOGUS_BLOCK = BLOCKS.register("amogus") {
object: Block(
BlockBehaviour.Properties.of(Material.CLOTH_DECORATION)
.noCollission()
.destroyTime(1f)
.explosionResistance(1f)
) {
@Deprecated("Ok")
override fun use(
pState: BlockState,
pLevel: Level,
pPos: BlockPos,
pPlayer: Player,
pHand: InteractionHand,
pHit: BlockHitResult
): InteractionResult {
if(pLevel.isClientSide && pHand == InteractionHand.MAIN_HAND) {
pLevel.addParticle(
ParticleTypes.NOTE,
pPos.x.toDouble(), pPos.y.toDouble(), pPos.z.toDouble(),
0.0, 0.5, 0.0
)
pPlayer.swing(pHand)
return InteractionResult.SUCCESS
} else
return InteractionResult.PASS
}
}
}
// Блок-предмет //
val AMOGUS_ITEM = ITEMS.register("amogus") {
object: BlockItem(
AMOGUS_BLOCK.get(),
Item.Properties()
.stacksTo(8)
.tab(HOLLOWENGINE_TAB)
) {
override fun use(
pLevel: Level,
pPlayer: Player,
pHand: InteractionHand
): InteractionResultHolder<ItemStack> {
if(pLevel.isClientSide && pHand == InteractionHand.MAIN_HAND) {
val pPos = pPlayer.position()
val pVec = pPlayer.getViewVector(1f)
val handOffset = -0.3
val particlePos = pPos.add(
pVec.x * 0.5 + handOffset,
pVec.y * 0.5,
pVec.z * 0.5
)
pLevel.addParticle(
ParticleTypes.NOTE,
particlePos.x, particlePos.y + 1, particlePos.z,
0.0, 0.5, 0.0
)
pPlayer.swing(pHand)
}
return super.use(pLevel, pPlayer, pHand)
}
}
}
BLOCKS.register(MOD_BUS)
ITEMS.register(MOD_BUS) // Для блок-предмета
}
Перевод предмета
Если вас вдруг не устраивает такое имя предмета, то это легко решается.
Создайте файл
ru_ru.json
- для Русского языка, или(и)en_us.json
- для Англиского языка по следующему пути:assets/<modId>/lang/*
и впишите в эти файлы следующее:lang/ru_ru.json и lang/en_us.json{
"block.<modId>.<newItemId>": "<TranslationText>"
}Где за место
<modID>
- вставтеid
вашего мода (в моём случает - этоtest
) и за место<newItemId>
-id
предмета, который вы добавили (в моём случае - этоamogus
).
У меня получилось так:
В ru_ru.json{
"block.test.amogus": "Амогус"
}В en_us.json{
"block.test.amogus": "Amogus"
}