PowerfulJS
Переписанный с версии 1.20.1, PowerfulJS теперь действительно мощный!
PowerfulJS 1.21 теперь имеет улучшенную обработку capabilities, полную поддержку ProbeJS и значительно лучшую производительность!
Для старой документации PowerfulJS ознакомьтесь с репозиторием GitHub
Введение в систему Capability
Capability от Neoforge унифицировали реализацию предметов, блоков, сущностей... для обработки общего поведения. Таким образом, любой блок, который реализует capability item handler
, сможет получать или предоставлять предметы воронке, любые предметы, которые реализуют capability fluid handler
, смогут быть заполнены жидкостным резервуаром Mekanism.
PowerfulJS позволяет создателям модпаков добавлять capabilities к этим объектам. Таким образом, с присоединёнными capabilities вы можете сделать так, чтобы печь имела хранилище FE или жидкости, или корпус батареи, который можно заполнить, чтобы сделать батарею... Возможности бесконечны.
Быстрое использование
Этот раздел знакомит с тем, как использовать PowerfulJS для реализации некоторых простых вещей. Код может работать с установленным PowerfulJS, но всегда рекомендуется устанавливать ProbeJS, чтобы получить поддержку IDE в VSCode.
1. Добавление capabilities
Capabilities могут быть присоединены к 3 типам объектов: item
, block
и entity
, есть также четвёртый тип — block entity
, но он включён в capabilities block
.
Регистрация capability происходит при запуске, простой пример добавления capabilities будет таким:
PowerfulEvents.registerCapabilities(event => {
// Добавляет capability, который имеет постоянный запас FE
//
// Теперь блок редстоуна может производить 100 FE/тик постоянно,
// однако, вам нужен экстрактор (например, кабель MEK в режиме
// извлечения), чтобы получить энергию, так как сам блок
// не будет распределять энергию по окружению
event.registerBlock('powerfuljs:constant_energy', {
maxExtract: 100,
maxReceive: 0,
}, "redstone_block")
// Добавляет резервуар с фиксированной ёмкостью и определённым
// максимальным вводом/выводом
event.registerBlockEntity('powerfuljs:fixed_storage_fluid', {
capacity: 2000,
maxExtract: 250,
maxReceive: 250,
}, 'minecraft:furnace')
// и то же самое для хранилища FE энергии
event.registerBlockEntity('powerfuljs:fixed_storage_fe', {
maxExtract: 1000,
maxReceive: 1000,
capacity: 10000,
}, 'minecraft:furnace')
// Добавляет capability жидкости, который имеет постоянный запас жидкости
//
// Просто подключите трубу и извлекайте бесконечную лаву!
// СЛИШКОМ МОЩНО!!!!!
event.registerBlock('powerfuljs:constant_fluid', {
content: Fluid.of('lava', 1000),
maxReceive: 0
}, 'minecraft:lava')
// ...так что вы можете ограничить это, сделав его доступным
// только при определённых условиях, как здесь мы проверяем,
// является ли он исходным блоком и находится ли в биоме "низера",
// который является nether_waste.
//
// Однако вам не следует полагаться на этот валидатор, если
// блок может изменить своё состояние во время работы, как печь.
// Capability будет переиспользован для многих машин по
// соображениям производительности, и `validate` не будет
// вызываться, так как capability уже предоставлен.
.validate((blockContext, info) => {
return blockContext.state().fluidState.source &&
blockContext.level().getBiome(blockContext.pos())
.registeredName
.includes("nether")
})
// Также сделайте так, чтобы `нетерак` и `душ песок` можно было заполнить
// лавой
//
// При заполнении они превращаются в `магма блок`
//
// Есть некоторые различия в разных строителях capabilities,
// вы можете использовать ProbeJS, чтобы узнать, какие вещи
// поддерживаются каждым строителем
event.registerItem('powerfuljs:fixed_storage_fluid', {
capacity: 1000,
maxReceive: 20,
maxExtract: 20,
validator: "minecraft:lava",
changeItemWhen: {
full: [
{ fluid: "minecraft:lava", item: "minecraft:magma_block" }
]
}
}, 'netherrack', 'soul_sand')
})
2. Перехват тикания
Чтобы сделать capabilities, присоединённые к блоку, более полезными, PowerfulJS также реализовал способ перехватывать исходную логику тикания блока, а также принудительно заставлять блок, который не тикает, тикать.
Система под названием RuleSet
используется для определения фактической логики, чтобы сбалансировать производительность с гибкостью. Теоретически, реализация любой логики с помощью этой системы имеет производительность, сравнимую с нативной Java, хотя это всё ещё сильно зависит от вашего способа реализации.
Перехват тикания регистрируется при загрузке серверного скрипта, так что вы также можете перезагрузить серверный скрипт, чтобы обновить поведение. Однако для любого блока, в который уже внедрена логика, вам нужно сломать и заменить их, чтобы обновить тикер.
Пример показан ниже:
PowerfulEvents.interceptTicking(event => {
let burningFurnaceOfAnyDirection = [
"minecraft:furnace[lit=true, facing=west]",
"minecraft:furnace[lit=true, facing=east]",
"minecraft:furnace[lit=true, facing=north]",
"minecraft:furnace[lit=true, facing=south]"
]
event.intercept('minecraft:furnace', () => [
// Мы проверяем работающую печь
Rules.matchBlock(burningFurnaceOfAnyDirection)
// Мы включаем печь, если она не работает,
// чтобы она могла нормально обнаруживать рецепты
.negate()
// Если она работает
.or(
// Если у неё есть 1000 мБ лавы, то продолжаем работу
Rules.hasFluid(Fluid.lava(1000), null)
// И мы также расходуем 1 мБ лавы и производим 5 FE
.effect(Effects.drainFluid(Fluid.lava(1), null))
.effect(Effects.fillEnergy(5, null))
)
// Итак, если печь не работает, или печь работает
// с жидкостью, мы включаем логику печи
// (предыдущее правило оценивается как true), в противном
// случае мы отключаем её (оценивается как false)
.effect(Effects.toggleEnable())
])
// Логика, описанная выше, заставит печь требовать как минимум
// 1000 мБ лавы для работы и производить 5 FE/тик ценой 1 мБ/тик лавы
// Сундук не тикает сам по себе, мы принудительно заставляем сундук
// начать тикать с пустой логикой, чтобы затем добавить нашу логику
// путём перехвата
event.forceTicker('chest', true)
event.intercept('chest', () => [
// Каждые 20 тиков
Rules.every(20).effect(
// Получите печенье!
Effects.insertItem('cookie', null)
)
])
})