⚙ SHOCKY — Сегодня, в 19:53

не могу
мультиблок
влепить текстуры что есть
ибо мультиблок ещё на машине Дбота
This commit is contained in:
DBotThePony 2025-02-07 19:54:17 +07:00
parent c3c43d7af6
commit da13d77af3
Signed by: DBot
GPG Key ID: DCC23B5715498507
37 changed files with 1024 additions and 144 deletions

View File

@ -19,7 +19,7 @@ forge_version=21.1.21
mixingradle_version=0.7.33
mixin_version=0.8.5
kommons_version=3.1.2
kommons_version=3.1.3
jei_version=19.16.4.171
jupiter_version=5.9.2

View File

@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage
import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.data.FlywheelMaterialDataProvider
import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements
import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements
import ru.dbotthepony.mc.otm.datagen.blocks.addBlockModels
@ -85,6 +86,8 @@ object DataGen {
private set
var matterData: MatterDataProvider by WriteOnce()
private set
var flywheelData: FlywheelMaterialDataProvider by WriteOnce()
private set
fun decorativeCubeAll(vararg blocks: Block) {
blockModelProvider.decorativeCubeAll(*blocks)
@ -510,6 +513,7 @@ object DataGen {
this.languageProvider = languageProvider
this.researchProvider = researchProvider
this.matterData = matterData
this.flywheelData = FlywheelMaterialDataProvider(event)
val tagsProvider = TagsProvider(event)
val advancementProvider = object : AdvancementProvider(event.generator.packOutput, event.lookupProvider, event.existingFileHelper, listOf(
@ -542,6 +546,7 @@ object DataGen {
event.generator.addProvider(event.includeServer(), researchProvider)
event.generator.addProvider(event.includeServer(), advancementProvider)
event.generator.addProvider(event.includeServer(), matterData)
event.generator.addProvider(event.includeServer(), flywheelData)
val registrySetBuilder = RegistrySetBuilder()
.add(Registries.DAMAGE_TYPE, ::registerDamageTypes)
@ -603,6 +608,7 @@ object DataGen {
languageProvider.registerProviders()
addMatterData(matterData)
addFlywheelMaterials(flywheelData)
tagsProvider.register()
}

View File

@ -0,0 +1,14 @@
package ru.dbotthepony.mc.otm.datagen
import net.neoforged.neoforge.common.Tags
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.data.FlywheelMaterialDataProvider
import ru.dbotthepony.mc.otm.registry.MBlockTags
fun addFlywheelMaterials(provider: FlywheelMaterialDataProvider) {
provider.add(Tags.Blocks.STORAGE_BLOCKS_DIAMOND, Decimal(1_000_000))
provider.add(Tags.Blocks.STORAGE_BLOCKS_COPPER, Decimal(3_500_000))
provider.add(Tags.Blocks.STORAGE_BLOCKS_IRON, Decimal(3_000_000))
provider.add(Tags.Blocks.STORAGE_BLOCKS_GOLD, Decimal(18_000_000))
provider.add(MBlockTags.TRITANIUM_BLOCKS, Decimal(9_000_000))
}

View File

@ -543,6 +543,30 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.BLACK_HOLE, "Local Anomalous Spacetime Dilation Singular Point")
add(MBlocks.BLACK_HOLE_GENERATOR, "Matter Acceleration Power Generator")
add(MBlocks.FLYWHEEL_SHAFT, "Flywheel Shaft")
add(MBlocks.FLYWHEEL_SHAFT, "desc", "Placed between bearings, safe for decoration")
add(MBlocks.FLYWHEEL_BEARING, "Flywheel Bearing")
add(MBlocks.FLYWHEEL_BEARING, "desc", "Replaces center block of housing at bottom and top, safe for decoration")
add(MBlocks.FLYWHEEL_BATTERY, "Flywheel Controller")
add(MBlocks.FLYWHEEL_BATTERY, "desc", "Multiblock controller, requires housing, bearing, shaft, generator and core material of choice")
add(MBlocks.FLYWHEEL_BATTERY, "desc2", "Can have arbitrary height, with bottom limit of 4 blocks tall")
add(MBlocks.FLYWHEEL_BATTERY, "desc3", "Built as rectangular shape, with base surface of 5 by 5 blocks")
add(MBlocks.FLYWHEEL_BATTERY, "desc4", "Uses Energy *Interface*s as I/O ports, which must be put at same level as generator blocks inside structure,")
add(MBlocks.FLYWHEEL_BATTERY, "desc5", "replacing housing blocks")
add(MBlocks.FLYWHEEL_BATTERY, "desc6", "Important: must replace housing block in wall in middle at same level where flywheel material start,")
add(MBlocks.FLYWHEEL_BATTERY, "desc7", "in other words, controller is put one block above absolute bottom of structure")
add(MBlocks.FLYWHEEL_HOUSING, "Flywheel Housing")
add(MBlocks.FLYWHEEL_HOUSING, "desc", "5xNx5 multiblock casing, safe for decoration")
add(MBlocks.GENERATOR_BLOCK, "Generator Block")
add(MBlocks.GENERATOR_BLOCK, "desc", "Part of multiblock, safe for decoration")
add(MBlocks.ENERGY_INPUT_INTERFACE, "Energy Input Interface")
add(MBlocks.ENERGY_OUTPUT_INTERFACE, "Energy Output Interface")
add(MBlocks.ENERGY_INPUT_HATCH, "Energy Input Hatch")
add(MBlocks.ITEM_INPUT_HATCH, "Item Input Hatch")
add(MBlocks.MATTER_INPUT_HATCH, "Matter Input Hatch")

View File

@ -542,6 +542,30 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.BLACK_HOLE, "Локализированная сингулярная точка аномального искажения пространства-времени")
add(MBlocks.BLACK_HOLE_GENERATOR, "Генератор энергии ускорением материи")
add(MBlocks.FLYWHEEL_SHAFT, "Маховый вал")
add(MBlocks.FLYWHEEL_SHAFT, "desc", "Устанавливается между подшипников")
add(MBlocks.FLYWHEEL_BEARING, "Маховый подшипник")
add(MBlocks.FLYWHEEL_BEARING, "desc", "Заменяет центральный блок корпуса снизу и сверху")
add(MBlocks.FLYWHEEL_BATTERY, "Блок управления маховым хранилищем энергии")
add(MBlocks.FLYWHEEL_BATTERY, "desc", "Мультиблок, который требует подшипники, корпус, вал, блоки генераторов и ядро из материала на ваше усмотрение")
add(MBlocks.FLYWHEEL_BATTERY, "desc2", "Имеет неограниченную высоту, с нижним порогом в 4 блока")
add(MBlocks.FLYWHEEL_BATTERY, "desc3", "Строится как параллелепипед с основной в 5 на 5 блоков")
add(MBlocks.FLYWHEEL_BATTERY, "desc4", "Использует энергетические *интерфейсы* как порты ввода вывода, и они должны быть установлены на том же")
add(MBlocks.FLYWHEEL_BATTERY, "desc5", "уровне, что и блоки генераторов")
add(MBlocks.FLYWHEEL_BATTERY, "desc6", "Важно: должен быть установлен в стене по середине на том же уровне, где находится ядро,")
add(MBlocks.FLYWHEEL_BATTERY, "desc7", "иначе говоря, он заменяет блок корпуса на высоте одного блока относительно 'пола' структуры")
add(MBlocks.FLYWHEEL_HOUSING, "Корпус махового хранилища энергии")
add(MBlocks.FLYWHEEL_HOUSING, "desc", "Мультиблок структура с размерностью 5xNx5")
add(MBlocks.GENERATOR_BLOCK, "Generator Block")
add(MBlocks.GENERATOR_BLOCK, "desc", "Part of multiblock, safe for decoration")
add(MBlocks.ENERGY_INPUT_INTERFACE, "Входной энергетический интерфейс")
add(MBlocks.ENERGY_OUTPUT_INTERFACE, "Выходной энергетический интерфейс")
add(MBlocks.ENERGY_INPUT_HATCH, "Входной энергетический клапан")
add(MBlocks.ITEM_INPUT_HATCH, "Входной предметный клапан")
add(MBlocks.MATTER_INPUT_HATCH, "Входной клапан материи")

View File

@ -45,6 +45,11 @@ fun addDecorativeLoot(lootTables: LootTables) {
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_BARS) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.GENERATOR_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.FLYWHEEL_SHAFT) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.FLYWHEEL_HOUSING) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.FLYWHEEL_BEARING) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.ENGINE) { condition(ExplosionCondition.survivesExplosion()) }
for (block in MBlocks.TRITANIUM_ANVIL)

View File

@ -59,6 +59,14 @@ fun addMachineLoot(lootTables: LootTables) {
lootTables.tile(MBlocks.MATTER_BOTTLER.values)
lootTables.tile(MBlocks.BLACK_HOLE_GENERATOR)
lootTables.tile(MBlocks.FLYWHEEL_BATTERY)
lootTables.tile(MBlocks.ITEM_INPUT_HATCH)
lootTables.tile(MBlocks.ITEM_OUTPUT_HATCH)
lootTables.tile(MBlocks.ENERGY_INPUT_HATCH)
lootTables.tile(MBlocks.ENERGY_OUTPUT_HATCH)
lootTables.tile(MBlocks.MATTER_INPUT_HATCH)
lootTables.tile(MBlocks.MATTER_OUTPUT_HATCH)
lootTables.tile(MBlocks.ENERGY_INPUT_INTERFACE)
lootTables.tile(MBlocks.ENERGY_OUTPUT_INTERFACE)
}

View File

@ -67,6 +67,12 @@ fun addMineableTags(tagsProvider: TagsProvider) {
MBlocks.BLACK_HOLE_GENERATOR,
MBlocks.ITEM_INPUT_HATCH,
MBlocks.ITEM_OUTPUT_HATCH,
MBlocks.ENERGY_INPUT_HATCH,
MBlocks.ENERGY_OUTPUT_HATCH,
MBlocks.MATTER_INPUT_HATCH,
MBlocks.MATTER_OUTPUT_HATCH,
MBlocks.ENERGY_INPUT_INTERFACE,
MBlocks.ENERGY_OUTPUT_INTERFACE,
), Tiers.IRON)
tagsProvider.requiresPickaxe(listOf(

View File

@ -35,9 +35,6 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.items.Appender(MItemTags.MINECART_CARGO_CRATES).add(MItems.CARGO_CRATE_MINECARTS.values)
tagsProvider.items.Appender(MItemTags.MACHINES).add(MItems.MACHINES)
tagsProvider.blocks.Appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it!!.block })
tagsProvider.blocks.Appender(BlockTags.ANVIL).add(MBlocks.TRITANIUM_ANVIL)
tagsProvider.items.Appender(ItemTags.ANVIL).add(MItems.TRITANIUM_ANVIL)

View File

@ -51,6 +51,7 @@ import ru.dbotthepony.mc.otm.config.ItemsConfig
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.config.ToolsConfig
import ru.dbotthepony.mc.otm.data.FlywheelMaterials
import ru.dbotthepony.mc.otm.data.world.DecimalProvider
import ru.dbotthepony.mc.otm.item.ChestUpgraderItem
import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem
@ -204,6 +205,8 @@ object OverdriveThatMatters {
FORGE_BUS.addListener(EventPriority.NORMAL, AndroidResearchManager::reloadEvent)
FORGE_BUS.addListener(EventPriority.NORMAL, AndroidResearchManager::syncEvent)
FORGE_BUS.addListener(EventPriority.NORMAL, FlywheelMaterials::reloadEvent)
FORGE_BUS.addListener(EventPriority.NORMAL, MatterManager::reloadEvent)
FORGE_BUS.addListener(EventPriority.NORMAL, MatterManager::onServerStarted)
FORGE_BUS.addListener(EventPriority.NORMAL, MatterManager::onDataPackSync)

View File

@ -55,6 +55,7 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
field.accept(value)
} else if (value != field.value) {
multiblockSyncher?.close()
multiblock?.close()
multiblock = CONFIGURATIONS[value - 5].value.create(blockPos)
multiblockSyncher = syncher.add0(multiblock!!)
field.accept(value)
@ -67,13 +68,13 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
val energy = CombinedProfiledEnergyStorage(
FlowDirection.NONE,
{ multiblock?.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)?.iterator()?.map { it.energy } ?: ObjectIterators.emptyIterator() },
{ level?.random?.let { RandomSource2Generator(it) } }
{ level?.random }
)
val matter = CombinedProfiledMatterStorage(
FlowDirection.NONE,
{ multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter } ?: ObjectIterators.emptyIterator() },
{ level?.random?.let { RandomSource2Generator(it) } }
{ level?.random }
)
enum class Mode(val label: Component, val tooltip: Component) {
@ -133,6 +134,13 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
return -1
}
override fun setRemoved() {
super.setRemoved()
multiblock?.close()
multiblock = null
}
override fun tick() {
super.tick()

View File

@ -8,6 +8,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.neoforge.capabilities.Capabilities
import net.neoforged.neoforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
@ -17,6 +18,7 @@ import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
@ -37,14 +39,21 @@ class EnergyHatchBlockEntity(
}.also(::addDroppableContainer)
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
private val neighbours = ArrayList<CapabilityCache<IEnergyStorage>>()
init {
savetables.stateful(::energy, ENERGY_KEY)
savetables.stateful(::container, BATTERY_KEY)
// it would cause a lot of frustration if hatches accept stuff only though one face
exposeGlobally(Capabilities.EnergyStorage.BLOCK, energy)
exposeEnergyGlobally(energy)
exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler)
if (!isInput) {
for (side in RelativeSide.entries) {
neighbours.add(CapabilityCache(side, Capabilities.EnergyStorage.BLOCK))
}
}
}
override fun tick() {
@ -60,6 +69,16 @@ class EnergyHatchBlockEntity(
}
}
}
if (!isInput) {
neighbours.forEach {
val get = it.get()
if (get != null) {
moveEnergy(energy, get, simulate = false)
}
}
}
}
}

View File

@ -0,0 +1,123 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.neoforge.capabilities.Capabilities
import net.neoforged.neoforge.energy.IEnergyStorage
import ru.dbotthepony.kommons.collect.flatMap
import ru.dbotthepony.kommons.collect.map
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.CombinedProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.moveEnergy
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockAccess
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
class EnergyInterfaceBlockEntity(
val isInput: Boolean,
type: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState
) : MatteryDeviceBlockEntity(type, blockPos, blockState), IMultiblockListener {
interface Target {
val energyInterfaceTarget: ProfiledEnergyStorage<*>
}
private val multiblocks = LinkedHashSet<IMultiblockAccess>()
val energy = CombinedProfiledEnergyStorage(
FlowDirection.input(isInput),
{ multiblocks.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget } },
{ level?.random }
)
override fun onAddedToMultiblock(multiblock: IMultiblockAccess) {
check(multiblocks.add(multiblock)) { "$this already tracks $multiblock" }
}
override fun onRemovedFromMultiblock(multiblock: IMultiblockAccess) {
check(multiblocks.remove(multiblock)) { "$this does not track $multiblock" }
}
val container = object : MatteryContainer(::markDirtyFast, CAPACITY) {
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
return 1
}
}.also(::addDroppableContainer)
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
private val neighbours = ArrayList<CapabilityCache<IEnergyStorage>>()
init {
savetables.stateful(::container, BATTERY_KEY)
// it would cause a lot of frustration if hatches accept stuff only though one face
exposeEnergyGlobally(energy)
exposeGlobally(Capabilities.ItemHandler.BLOCK, itemHandler)
if (!isInput) {
for (side in RelativeSide.entries) {
neighbours.add(CapabilityCache(side, Capabilities.EnergyStorage.BLOCK))
}
}
}
override fun tick() {
super.tick()
energy.tick()
if (!redstoneControl.isBlockedByRedstone) {
container.forEach {
it.getCapability(Capabilities.EnergyStorage.ITEM)?.let {
if (isInput) {
moveEnergy(it, energy, simulate = false)
} else {
moveEnergy(energy, it, simulate = false)
}
}
}
if (!isInput) {
neighbours.forEach {
val get = it.get()
if (get != null) {
moveEnergy(energy, get, simulate = false)
}
}
}
}
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
return null
}
companion object {
const val CAPACITY = 1
val TARGET = BlockEntityTag(Target::class)
val INPUT_TAG = BlockEntityTag(EnergyInterfaceBlockEntity::class) { it.isInput }
val OUTPUT_TAG = BlockEntityTag(EnergyInterfaceBlockEntity::class) { !it.isInput }
fun input(blockPos: BlockPos, blockState: BlockState): EnergyInterfaceBlockEntity {
return EnergyInterfaceBlockEntity(true, MBlockEntities.ENERGY_INPUT_INTERFACE, blockPos, blockState)
}
fun output(blockPos: BlockPos, blockState: BlockState): EnergyInterfaceBlockEntity {
return EnergyInterfaceBlockEntity(false, MBlockEntities.ENERGY_OUTPUT_INTERFACE, blockPos, blockState)
}
}
}

View File

@ -0,0 +1,229 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import net.minecraft.core.BlockPos
import net.minecraft.core.Vec3i
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.core.getBlockStateNow
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblock
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblockFactory
import ru.dbotthepony.mc.otm.core.multiblock.Strategy
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
import ru.dbotthepony.mc.otm.data.FlywheelMaterials
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
import ru.dbotthepony.mc.otm.registry.game.MBlocks
class FlywheelBatteryBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.FLYWHEEL_BATTERY, blockPos, blockState), EnergyInterfaceBlockEntity.Target {
private var multiblock: ShapedMultiblock? = null
private var lastHeight = -1
var batteryLevel = Decimal.ZERO
private var cachedChargeEfficiency = Decimal.ONE
private inner class Storage : IMatteryEnergyStorage {
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
if (batteryLevel <= Decimal.ZERO) {
return Decimal.ZERO
}
val new = maxOf(batteryLevel - howMuch, Decimal.ZERO)
val diff = batteryLevel - new
if (!simulate)
batteryLevel = new
return diff
}
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
if (batteryLevel >= maxBatteryLevel) {
return Decimal.ZERO
}
val new = minOf(batteryLevel + howMuch * cachedChargeEfficiency, maxBatteryLevel)
val diff = new - batteryLevel
if (!simulate)
batteryLevel = new
return diff
}
override var batteryLevel: Decimal by this@FlywheelBatteryBlockEntity::batteryLevel
override var maxBatteryLevel: Decimal = Decimal.ZERO
override val energyFlow: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL
override val canSetBatteryLevel: Boolean
get() = true
}
private val energy = ProfiledEnergyStorage(Storage())
override val energyInterfaceTarget: ProfiledEnergyStorage<*>
get() = energy
init {
savetables.stateful(::energy, "energy")
savetablesLevel.decimal(::batteryLevel, "battery")
exposeEnergySideless(energy)
}
override fun setRemoved() {
super.setRemoved()
lastHeight = -1
multiblock?.close()
multiblock = null
}
override fun tick() {
super.tick()
val level = level!!
if (multiblock == null || !multiblock!!.update(level, blockRotation.front)) {
var height = 0
val base = blockPos + blockRotation.back.normal * 2
while (level.getBlockStateNow(base.atY(blockPos.y + height)).block == MBlocks.FLYWHEEL_SHAFT) {
height++
}
if (height <= 1) {
lastHeight = 0
multiblock?.close()
multiblock = null
} else if (multiblock == null || lastHeight != height) {
lastHeight = height
multiblock?.close()
multiblock = getConfiguration(height).create(blockPos)
}
}
if (multiblock?.isValid == true) {
// energy.parent.batteryLevel *= Decimal("0.99994")
// this way energy loss is recorded in graph
val entry = multiblock!!.blocks(FLYWHEEL_MATERIAL).reference2IntEntrySet().first()
val material = FlywheelMaterials[entry.key]!!
energy.parent.maxBatteryLevel = material.storage * entry.intValue
cachedChargeEfficiency = material.receiveEfficiency
energy.extractEnergy(energy.parent.batteryLevel * Decimal("0.000004") * material.momentumLossSpeed, false)
} else {
energy.parent.maxBatteryLevel = Decimal.ZERO
energy.extractEnergy(energy.parent.batteryLevel * Decimal("0.0004"), false)
}
}
companion object {
private val FLYWHEEL_MATERIAL = Any()
private val outerRing = listOf(
// front
BlockPos(-1, 0, 0),
BlockPos(-2, 0, 0),
BlockPos( 0, 0, 0),
BlockPos( 1, 0, 0),
BlockPos( 2, 0, 0),
// back
BlockPos(-1, 0, 4),
BlockPos(-2, 0, 4),
BlockPos( 0, 0, 4),
BlockPos( 1, 0, 4),
BlockPos( 2, 0, 4),
// right side
BlockPos(-2, 0, 1),
BlockPos(-2, 0, 2),
BlockPos(-2, 0, 3),
// left side
BlockPos( 2, 0, 1),
BlockPos( 2, 0, 2),
BlockPos( 2, 0, 3),
)
private val configCache = Int2ObjectOpenHashMap<ShapedMultiblockFactory>()
private fun getConfiguration(height: Int): ShapedMultiblockFactory {
return configCache.computeIfAbsent(height, Int2ObjectFunction { createConfiguration(it) })
}
private fun createConfiguration(height: Int): ShapedMultiblockFactory {
return shapedMultiblock {
strategy = Strategy.AND
block(MBlocks.FLYWHEEL_BATTERY)
tag(EnergyInterfaceBlockEntity.TARGET)
builder.customCheck {
it.blocks(FLYWHEEL_MATERIAL).size == 1
}
for (x in -2 .. 2) {
for (z in 0 .. 4) {
relative(Vec3i(x, -1, z)) {
if (x == 0 && z == 2) {
block(MBlocks.FLYWHEEL_BEARING)
} else {
block(MBlocks.FLYWHEEL_HOUSING)
}
}
relative(Vec3i(x, height, z)) {
if (x == 0 && z == 2) {
block(MBlocks.FLYWHEEL_BEARING)
} else {
block(MBlocks.FLYWHEEL_HOUSING)
}
}
}
}
for (y in 0 until height) {
for (x in -1 .. 1) {
for (z in 1 .. 3) {
relative(Vec3i(x, y, z)) {
if (z == 2 && x == 0) {
block(MBlocks.FLYWHEEL_SHAFT)
} else {
if (y == height - 1) {
block(MBlocks.GENERATOR_BLOCK)
} else {
predicate { pos, access, blockState, blockEntity ->
blockState in FlywheelMaterials
}
tagBlock(FLYWHEEL_MATERIAL)
}
}
}
}
}
for (rPos in outerRing) {
if (y == 0 && rPos.x == 0) continue
relative(rPos.atY(y)) {
block(MBlocks.FLYWHEEL_HOUSING)
if (y == height - 1) {
block(MBlocks.ENERGY_INPUT_INTERFACE)
block(MBlocks.ENERGY_OUTPUT_INTERFACE)
tag(EnergyInterfaceBlockEntity.INPUT_TAG)
tag(EnergyInterfaceBlockEntity.OUTPUT_TAG)
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,36 @@
package ru.dbotthepony.mc.otm.block.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.addSimpleDescription
import ru.dbotthepony.mc.otm.block.entity.tech.FlywheelBatteryBlockEntity
class FlywheelBatteryBlock : RotatableMatteryBlock(), EntityBlock {
init {
addSimpleDescription()
for (i in 2 .. 7)
addSimpleDescription(i.toString())
}
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
return FlywheelBatteryBlockEntity(pos, state)
}
override fun <T : BlockEntity?> getTicker(
level: Level,
p_153213_: BlockState,
p_153214_: BlockEntityType<T>
): BlockEntityTicker<T>? {
if (level.isClientSide)
return null
return BlockEntityTicker { _, _, _, t -> if (t is FlywheelBatteryBlockEntity) t.tick() }
}
}

View File

@ -4,6 +4,7 @@ import com.google.common.collect.Streams
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.util.RandomSource
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
@ -45,7 +46,7 @@ private val LOGGER = LogManager.getLogger()
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer
fun <T> Supplier<out Iterator<T>>.iterateProviders(random: RandomGenerator?, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal {
fun <T> Supplier<out Iterator<T>>.iterateProviders(random: RandomSource?, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal {
val providers = get()
val iteratorProvider: () -> Iterator<T>

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability.energy
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.iterateProviders
import ru.dbotthepony.mc.otm.core.collect.map
@ -11,7 +12,7 @@ import java.util.random.RandomGenerator
open class CombinedEnergyStorage(
final override val energyFlow: FlowDirection,
val provider: Supplier<out Iterator<IMatteryEnergyStorage>>,
val random: Supplier<RandomGenerator?> = Supplier { null }
val random: Supplier<RandomSource?> = Supplier { null }
) : IMatteryEnergyStorage {
final override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::extractEnergy)

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability.energy
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.IProfiledStorage
@ -14,7 +15,7 @@ import java.util.random.RandomGenerator
class CombinedProfiledEnergyStorage(
energyFlow: FlowDirection,
provider: Supplier<out Iterator<ProfiledEnergyStorage<*>>>,
random: Supplier<RandomGenerator?> = Supplier { null }
random: Supplier<RandomSource?> = Supplier { null }
) : CombinedEnergyStorage(energyFlow, provider, random), IProfiledMatteryEnergyStorage, IProfiledStorage.Combined, ITickable {
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledEnergyStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledEnergyStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.iterateProviders
import ru.dbotthepony.mc.otm.core.collect.map
@ -11,7 +12,7 @@ import java.util.random.RandomGenerator
open class CombinedMatterStorage(
final override val matterFlow: FlowDirection,
val provider: Supplier<out Iterator<IMatterStorage>>,
val random: Supplier<RandomGenerator?> = Supplier { null }
val random: Supplier<RandomSource?> = Supplier { null }
) : IMatterStorage {
final override var storedMatter: Decimal
get() = provider.get().map { it.storedMatter }.reduce(Decimal.ZERO, Decimal::plus)

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.IProfiledStorage
@ -14,7 +15,7 @@ import java.util.random.RandomGenerator
class CombinedProfiledMatterStorage(
matterFlow: FlowDirection,
provider: Supplier<out Iterator<ProfiledMatterStorage<*>>>,
random: Supplier<RandomGenerator?> = Supplier { null }
random: Supplier<RandomSource?> = Supplier { null }
) : CombinedMatterStorage(matterFlow, provider, random), IProfiledMatterStorage, IProfiledStorage.Combined, ITickable {
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledMatterStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledMatterStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)

View File

@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
import net.minecraft.world.level.block.entity.BlockEntity
import java.util.Collections
class BlockEntitySet<T : BlockEntity>(private val listener: GlobalBlockEntityRemovalListener, val tag: BlockEntityTag<T>) {
class BlockEntitySet<T : Any>(private val listener: GlobalBlockEntityRemovalListener, val tag: BlockEntityTag<T>) {
private val items = Reference2IntOpenHashMap<T>()
val set: Set<T> = Collections.unmodifiableSet(items.keys)
@ -38,7 +38,7 @@ class BlockEntitySet<T : BlockEntity>(private val listener: GlobalBlockEntityRem
fun clear() {
items.keys.forEach {
GlobalBlockEntityRemovalListener.stopListening(it, listener)
GlobalBlockEntityRemovalListener.stopListening(it as BlockEntity, listener)
}
items.clear()

View File

@ -13,9 +13,8 @@ inline fun <reified T : BlockEntity> multiblockEntity(): BlockEntityTag<T> {
*
* Optionally, can have [predicate] specified, which narrows which block entities can be accepted by this tag
*/
class BlockEntityTag<T : BlockEntity>(val clazz: KClass<T>, val predicate: Predicate<in T> = Predicate { true }) :
Predicate<BlockEntity> {
override fun test(t: BlockEntity): Boolean {
class BlockEntityTag<T : Any>(val clazz: KClass<T>, val predicate: Predicate<in T> = Predicate { true }) : Predicate<Any?> {
override fun test(t: Any?): Boolean {
return clazz.isInstance(t) && predicate.test(t as T)
}
}

View File

@ -45,7 +45,7 @@ interface IMultiblockAccess {
return blockStates(GLOBAL_BLOCK_TAG)
}
fun <T : BlockEntity> blockEntities(tag: BlockEntityTag<T>): Set<T>
fun <T : Any> blockEntities(tag: BlockEntityTag<T>): Set<T>
companion object {
val GLOBAL_BLOCK_TAG = Any()

View File

@ -0,0 +1,6 @@
package ru.dbotthepony.mc.otm.core.multiblock
interface IMultiblockListener {
fun onAddedToMultiblock(multiblock: IMultiblockAccess)
fun onRemovedFromMultiblock(multiblock: IMultiblockAccess)
}

View File

@ -0,0 +1,29 @@
package ru.dbotthepony.mc.otm.core.multiblock
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
class MultiblockListenerSet(val parent: IMultiblockAccess) {
private val referencedListeners = Object2IntOpenHashMap<IMultiblockListener>()
fun reference(value: IMultiblockListener) {
val i = referencedListeners.computeInt(value, { _, int -> (int ?: 0) + 1 })
if (i == 1) {
value.onAddedToMultiblock(parent)
}
}
fun dereference(value: IMultiblockListener) {
val i = referencedListeners.computeInt(value, { _, int -> (int ?: 0) - 1 })
if (i <= 0) {
referencedListeners.removeInt(value)
value.onRemovedFromMultiblock(parent)
}
}
fun clear() {
referencedListeners.keys.forEach { it.onRemovedFromMultiblock(parent) }
referencedListeners.clear()
}
}

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.core.multiblock
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
import it.unimi.dsi.fastutil.objects.Reference2IntMap
import it.unimi.dsi.fastutil.objects.Reference2IntMaps
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
@ -35,7 +36,7 @@ import kotlin.collections.ArrayList
import kotlin.collections.HashMap
/**
* [close] is not required to be explicitly called, but it will help in freeing allocated memory faster
* [close] MUST be called when multiblock goes out of scope
*/
class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMultiblockAccess, ISynchable, Closeable, GlobalBlockEntityRemovalListener {
override var isValid: Boolean = false
@ -147,10 +148,16 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
if (be1 != be2) {
if (be1 != null) {
if (be1 is IMultiblockListener)
referencedListeners.dereference(be1)
assignedBlockEntityLists.forEach { it.remove(be1) }
}
if (be2 != null) {
if (be2 is IMultiblockListener)
referencedListeners.reference(be2)
assignedBlockEntityLists.forEach { it.add(be2) }
}
@ -212,6 +219,9 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
val blockEntity = blockEntity
if (blockEntity != null) {
if (blockEntity is IMultiblockListener)
referencedListeners.dereference(blockEntity)
assignedBlockEntityLists.forEach { it.remove(blockEntity) }
}
@ -241,7 +251,13 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
}
fun clear() {
blockEntity = null
val blockEntity = blockEntity
if (blockEntity != null) {
assignedBlockEntityLists.forEach { it.remove(blockEntity) }
}
this.blockEntity = null
blockState = null
lastSuccessfulPathPredicate = -1
@ -251,6 +267,8 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
}
}
private val referencedListeners = MultiblockListenerSet(this)
val index = when (currentDirection) {
Direction.NORTH -> 0
Direction.SOUTH -> 1
@ -284,7 +302,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
private val globalBlocksView = tag2BlockViews[IMultiblockAccess.GLOBAL_BLOCK_TAG]!!
private val globalBlockStatesView = tag2BlockStateViews[IMultiblockAccess.GLOBAL_BLOCK_TAG]!!
private fun <T : BlockEntity> getBlockEntityList(tag: BlockEntityTag<T>): BlockEntitySet<T> {
private fun <T : Any> getBlockEntityList(tag: BlockEntityTag<T>): BlockEntitySet<T> {
val existing = tag2BlockEntity[tag]
if (existing != null)
@ -331,6 +349,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
}
fun clear() {
referencedListeners.clear()
tag2BlockEntity.values.forEach { it.clear() }
tag2BlockState.values.forEach { it.clear() }
tag2Block.values.forEach { it.clear() }
@ -397,23 +416,28 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
return isValid
}
override fun <T : BlockEntity> blockEntities(tag: BlockEntityTag<T>): Set<T> {
override fun <T : Any> blockEntities(tag: BlockEntityTag<T>): Set<T> {
checkAccess()
return (tag2BlockEntity[tag]?.set ?: setOf()) as Set<T>
}
override fun blocks(tag: Any): Reference2IntMap<Block> {
checkAccess()
return tag2BlockViews[tag] ?: Reference2IntMaps.emptyMap()
}
override fun blockStates(tag: Any): Reference2IntMap<BlockState> {
checkAccess()
return tag2BlockStateViews[tag] ?: Reference2IntMaps.emptyMap()
}
override fun blocks(): Reference2IntMap<Block> {
checkAccess()
return globalBlocksView
}
override fun blockStates(): Reference2IntMap<BlockState> {
checkAccess()
return globalBlockStatesView
}
@ -491,11 +515,19 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
override fun createRemoteState(listener: Runnable): IRemoteState {
return RemoteState(listener)
}
private fun checkAccess() {
if (!isUpdating && activeConfig !== this) {
throw IllegalStateException("ShapedMultiblock configuration leaked! $this of ${this@ShapedMultiblock}")
}
}
}
override var isRemote: Boolean = false
private set
private var isUpdating = false
override fun read(stream: RegistryFriendlyByteBuf) {
isRemote = true
isValid = stream.readBoolean()
@ -543,7 +575,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
override val currentNodes: Map<BlockPos, IMultiblockNode>
get() = activeConfig.parts
override fun <T : BlockEntity> blockEntities(tag: BlockEntityTag<T>): Set<T> {
override fun <T : Any> blockEntities(tag: BlockEntityTag<T>): Set<T> {
if (!isValid) return setOf()
return activeConfig.blockEntities(tag)
}
@ -573,66 +605,78 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
}
fun update(levelAccessor: LevelAccessor): Boolean {
val configurations = LinkedList<Config>()
val configurations0 = ArrayList(this.configurations)
isUpdating = true
while (configurations0.isNotEmpty()) {
val max = configurations0.max()
configurations0.remove(max)
configurations.add(max)
}
try {
val configurations = LinkedList<Config>()
val configurations0 = ArrayList(this.configurations)
isValid = false
while (configurations0.isNotEmpty()) {
val max = configurations0.max()
configurations0.remove(max)
configurations.add(max)
}
while (configurations.isNotEmpty()) {
val config = configurations.removeFirst()
isValid = false
if (config.update(levelAccessor)) {
if (customChecks.all { it.test(config) }) {
activeConfig = config
isValid = true
remotes.forEach { it.listener.run() }
return true
} else {
config.clear()
while (configurations.isNotEmpty()) {
val config = configurations.removeFirst()
if (config.update(levelAccessor)) {
if (customChecks.all { it.test(config) }) {
activeConfig = config
isValid = true
remotes.forEach { it.listener.run() }
return true
} else {
config.clear()
}
}
}
}
return false
return false
} finally {
isUpdating = false
}
}
fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean {
var changes = false
isUpdating = true
if (activeConfig.currentDirection != direction && isValid) {
activeConfig.clear()
isValid = false
changes = true
try {
var changes = false
if (activeConfig.currentDirection != direction && isValid) {
activeConfig.clear()
isValid = false
changes = true
}
val config = when (direction) {
Direction.NORTH -> north
Direction.SOUTH -> south
Direction.WEST -> west
Direction.EAST -> east
else -> throw IllegalArgumentException(direction.name)
}
changes = changes || activeConfig != config
activeConfig = config
isValid = config.update(levelAccessor)
if (isValid) {
isValid = customChecks.all { it.test(config) }
if (!isValid) config.clear()
}
if (changes) {
remotes.forEach { it.listener.run() }
}
return isValid
} finally {
isUpdating = false
}
val config = when (direction) {
Direction.NORTH -> north
Direction.SOUTH -> south
Direction.WEST -> west
Direction.EAST -> east
else -> throw IllegalArgumentException(direction.name)
}
changes = changes || activeConfig != config
activeConfig = config
isValid = config.update(levelAccessor)
if (isValid) {
isValid = customChecks.all { it.test(config) }
if (!isValid) config.clear()
}
if (changes) {
remotes.forEach { it.listener.run() }
}
return isValid
}
override fun close() {

View File

@ -56,7 +56,7 @@ class ShapedMultiblockBuilder {
/**
* Marks this node report its block in [ShapedMultiblock.blockStates] method when called with specified [value]
*
* [value] is searched using "value" semantics (`==`)
* [value] is searched using "value" semantics (`==` / `equals`)
*/
fun tagBlockState(value: Any): T {
blockStateTags.add(value)
@ -74,7 +74,7 @@ class ShapedMultiblockBuilder {
/**
* Marks this node report its block in [ShapedMultiblock.blocks] method when called with specified [value]
*
* [value] is searched for using "value" semantics (`==`)
* [value] is searched for using "value" semantics (`==` / `equals`)
*/
fun tagBlock(value: Any): T {
blockTags.add(value)
@ -92,7 +92,7 @@ class ShapedMultiblockBuilder {
/**
* Marks this node to report block entities put at its position when called [ShapedMultiblock.blockEntities] with specified [value]
*
* [value] is searched for using "identity" semantics (`===`)
* [value] is searched for using "identity" semantics (`===` / Java's `==`)
*/
fun tag(value: BlockEntityTag<*>): T {
blockEntityTags.add(value)

View File

@ -0,0 +1,109 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.JsonArray
import net.minecraft.data.CachedOutput
import net.minecraft.data.DataProvider
import net.minecraft.data.PackOutput
import net.minecraft.tags.TagKey
import net.minecraft.world.level.block.Block
import net.neoforged.neoforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.toJsonStrict
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.matter.AbstractRegistryAction
import ru.dbotthepony.mc.otm.matter.MatterManager
import java.util.concurrent.CompletableFuture
open class FlywheelMaterialDataProvider(val modid: String, val location: String? = null) : DataProvider {
private val entries = ArrayList<FlywheelMaterials.Entry>()
var pathProvider: PackOutput.PathProvider by WriteOnce("You need to call bindPackOutput before registering this data provider")
private set
constructor(output: PackOutput, modid: String, location: String? = null) : this(modid, location) {
bindPackOutput(output)
}
constructor(event: GatherDataEvent, location: String? = null) : this(event.generator.packOutput, event.modContainer.namespace, location)
fun bindPackOutput(output: PackOutput) {
pathProvider = output.createPathProvider(PackOutput.Target.DATA_PACK, "otm_flywheel_materials")
}
@JvmOverloads
fun add(block: Block, storage: Decimal, priority: Int = 0) {
entries.add(FlywheelMaterials.Entry(block, storage, priority))
}
@JvmOverloads
fun add(block: TagKey<Block>, storage: Decimal, priority: Int = 0) {
entries.add(FlywheelMaterials.Entry(block, storage, priority))
}
@JvmName("addBlocks")
@JvmOverloads
fun add(blocks: Collection<Block>, storage: Decimal, priority: Int = 0) {
for (block in blocks)
entries.add(FlywheelMaterials.Entry(block, storage, priority))
}
@JvmName("addBlocks")
@JvmOverloads
fun add(blocks: Array<out Block>, storage: Decimal, priority: Int = 0) {
for (block in blocks)
entries.add(FlywheelMaterials.Entry(block, storage, priority))
}
@JvmName("addTags")
@JvmOverloads
fun add(blocks: Array<out TagKey<Block>>, storage: Decimal, priority: Int = 0) {
for (block in blocks)
entries.add(FlywheelMaterials.Entry(block, storage, priority))
}
@JvmName("addBlocks")
fun add(storage: Decimal, vararg blocks: Block) {
return add(blocks, storage)
}
@JvmName("addBlocks")
fun add(storage: Decimal, priority: Int, vararg blocks: Block) {
return add(blocks, storage, priority)
}
@JvmName("addTags")
fun add(storage: Decimal, vararg blocks: TagKey<Block>) {
return add(blocks, storage)
}
@JvmName("addTags")
fun add(storage: Decimal, priority: Int, vararg blocks: TagKey<Block>) {
return add(blocks, storage, priority)
}
override fun run(output: CachedOutput): CompletableFuture<*> {
if (location == null) {
val futures = ArrayList<CompletableFuture<*>>()
for (entry in entries) {
val path = ResourceLocation(modid, entry.id.map({ "tag/${it.location.namespace}/${it.location.path}" }, { "block/${it.registryName!!.namespace}/${it.registryName!!.path}" }))
futures.add(DataProvider.saveStable(output, FlywheelMaterials.CODEC.toJsonStrict(entry), pathProvider.json(path)))
}
return CompletableFuture.allOf(*futures.toTypedArray())
} else {
val result = JsonArray()
for (entry in entries)
result.add(FlywheelMaterials.CODEC.toJsonStrict(entry))
return DataProvider.saveStable(output, result, pathProvider.json(ResourceLocation(modid, location)))
}
}
override fun getName(): String {
return "Flywheel Materials for $modid"
}
}

View File

@ -0,0 +1,153 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
import net.minecraft.tags.TagKey
import net.minecraft.util.profiling.ProfilerFiller
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.neoforge.event.AddReloadListenerEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.data.codec.minRange
object FlywheelMaterials : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().create(), "otm_flywheel_materials") {
data class Entry(
val id: Either<TagKey<Block>, Block>,
val storage: Decimal,
val priority: Int = 0,
val receiveEfficiency: Decimal = Decimal.ONE,
val momentumLossSpeed: Decimal = Decimal.ONE
) : Comparable<Entry> {
constructor(id: Block, storage: Decimal, priority: Int = 0, windUpEfficiency: Decimal = Decimal.ONE, windDownEfficiency: Decimal = Decimal.ONE) : this(Either.right(id), storage, priority, windUpEfficiency, windDownEfficiency)
constructor(id: TagKey<Block>, storage: Decimal, priority: Int = 0, windUpEfficiency: Decimal = Decimal.ONE, windDownEfficiency: Decimal = Decimal.ONE) : this(Either.left(id), storage, priority, windUpEfficiency, windDownEfficiency)
override fun compareTo(other: Entry): Int {
val selfLeft = id.left().isPresent
val otherLeft = other.id.left().isPresent
if (selfLeft && otherLeft || !selfLeft && !otherLeft) {
val cmp = priority.compareTo(other.priority)
if (cmp == 0) {
if (selfLeft) {
return id.left().get().location.compareTo(other.id.left().get().location)
} else {
return id.right().get().registryName!!.compareTo(other.id.right().get().registryName!!)
}
}
return cmp
} else if (selfLeft) {
return -1
} else {
return 1
}
}
}
private var elements = ArrayList<Entry>()
private var mapped = HashMap<Block, Entry>()
private var mappingChanged = false
private fun mapping(): Map<Block, Entry> {
var mapped = mapped
if (mappingChanged) {
mapped = HashMap()
for (element in elements) {
element.id
.ifLeft {
for (b in BuiltInRegistries.BLOCK.getTagOrEmpty(it)) {
mapped[b.value()] = element
}
}
.ifRight {
mapped[it] = element
}
}
this.mapped = mapped
this.mappingChanged = false
return mapped
}
return mapped
}
operator fun get(index: Block): Entry? {
return mapping()[index]
}
operator fun get(index: BlockState): Entry? {
return this[index.block]
}
operator fun contains(value: Block): Boolean {
return value in mapping()
}
operator fun contains(value: BlockState): Boolean {
return value.block in mapping()
}
override fun apply(
map: MutableMap<ResourceLocation, JsonElement>,
manager: ResourceManager,
profiler: ProfilerFiller
) {
val elements = ArrayList<Entry>()
for ((path, element) in map.entries) {
if (element is JsonObject) {
CODEC.decode(JsonOps.INSTANCE, element)
.ifError { LOGGER.error("Unable to deserialize flywheel material entry at $path: $it") }
.ifSuccess { elements.add(it.first) }
} else if (element is JsonArray) {
for ((i, elem) in element.withIndex()) {
CODEC.decode(JsonOps.INSTANCE, elem)
.ifError { LOGGER.error("Unable to deserialize flywheel material entry at $path, offset $i: $it") }
.ifSuccess { elements.add(it.first) }
}
}
}
elements.sortDescending()
this.elements = elements
this.mappingChanged = true
}
val CODEC: Codec<Entry> = RecordCodecBuilder.create {
it.group(
Codec.either(
TagKey.hashedCodec(Registries.BLOCK),
BuiltInRegistries.BLOCK.byNameCodec()
).fieldOf("id").forGetter(Entry::id),
DecimalCodec.minRange(Decimal.ONE).fieldOf("storage").forGetter(Entry::storage),
Codec.INT.optionalFieldOf("priority", 0).forGetter(Entry::priority),
DecimalCodec.minRange(Decimal.ZERO).optionalFieldOf("receive_efficiency", Decimal.ONE).forGetter(Entry::receiveEfficiency),
DecimalCodec.minRange(Decimal.ZERO).optionalFieldOf("momentum_loss_speed", Decimal.ONE).forGetter(Entry::momentumLossSpeed),
).apply(it, ::Entry)
}
fun reloadEvent(event: AddReloadListenerEvent) {
event.addListener(this)
}
private val LOGGER = LogManager.getLogger()
}

View File

@ -1247,19 +1247,10 @@ open class MatterDataProvider(val modid: String? = null) : DataProvider {
@JvmOverloads
fun insert(name: TagKey<Item>, matterValue: Decimal, complexity: Double, priority: Int, configurator: Consumer<InsertConfiguration> = Consumer { }) = insert(name, matterValue, complexity, priority, configurator::accept)
/**
* Override this if you prefer The Mundane Way instead of calling [insert], [delete] and [update] directly
*
* Called inside [run]
*/
protected open fun addActions() {}
protected val added = ArrayList<AbstractRegistryAction>()
val addedView: List<AbstractRegistryAction> = Collections.unmodifiableList(added)
final override fun run(output: CachedOutput): CompletableFuture<*> {
addActions()
override fun run(output: CachedOutput): CompletableFuture<*> {
val promises = ArrayList<CompletableFuture<*>>()
for ((key, value) in actions) {

View File

@ -17,6 +17,8 @@ object MBlockTags {
val REQUIRES_TRITANIUM_TOOL: TagKey<Block> = BlockTags.create(ResourceLocation("minecraft", "requires_tritanium_tool"))
val TRITANIUM_BLOCKS: TagKey<Block> = BlockTags.create(ResourceLocation("c", "storage_blocks/tritanium"))
val DILITHIUM_ORES: TagKey<Block> = BlockTags.create(ResourceLocation("c", "ores/dilithium"))
val HARDENED_GLASS_PANES: TagKey<Block> = BlockTags.create(ResourceLocation("c", "hardened_glass_panes"))
@ -57,7 +59,6 @@ object MBlockTags {
val HARDENED_GLASS_WHITE: TagKey<Block> = BlockTags.create(ResourceLocation("c", "hardened_glass/white"))
val HARDENED_GLASS_YELLOW: TagKey<Block> = BlockTags.create(ResourceLocation("c", "hardened_glass/yellow"))
val MACHINES: TagKey<Block> = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "machines"))
val MULTIBLOCK_STRUCTURE: TagKey<Block> = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_structure"))
val MULTIBLOCK_HARD_STRUCTURE: TagKey<Block> = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_hard_structure"))
val MULTIBLOCK_SOFT_STRUCTURE: TagKey<Block> = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_soft_structure"))

View File

@ -83,8 +83,6 @@ object MItemTags {
val HARDENED_GLASS_WHITE: TagKey<Item> = ItemTags.create(ResourceLocation("c", "hardened_glass/white"))
val HARDENED_GLASS_YELLOW: TagKey<Item> = ItemTags.create(ResourceLocation("c", "hardened_glass/yellow"))
val MACHINES: TagKey<Item> = ItemTags.create(modLoc("machines"))
val NO_DECOMPOSING: TagKey<Item> = ItemTags.create(modLoc("matter/no_decomposing"))
val NO_REPLICATION: TagKey<Item> = ItemTags.create(modLoc("matter/no_replication"))
val NO_REPAIR: TagKey<Item> = ItemTags.create(modLoc("matter/no_repair"))

View File

@ -23,6 +23,8 @@ object MNames {
const val ITEM_OUTPUT_HATCH = "item_output_hatch"
const val ENERGY_INPUT_HATCH = "energy_input_hatch"
const val ENERGY_OUTPUT_HATCH = "energy_output_hatch"
const val ENERGY_INPUT_INTERFACE = "energy_input_interface"
const val ENERGY_OUTPUT_INTERFACE = "energy_output_interface"
const val MATTER_INPUT_HATCH = "matter_input_hatch"
const val MATTER_OUTPUT_HATCH = "matter_output_hatch"
const val PAINTER = "painter"
@ -56,6 +58,12 @@ object MNames {
const val ESSENCE_STORAGE = "essence_storage"
const val TRITANIUM_ANVIL = "tritanium_anvil"
const val FLYWHEEL_BATTERY = "flywheel_battery"
const val FLYWHEEL_BEARING = "flywheel_bearing"
const val FLYWHEEL_SHAFT = "flywheel_shaft"
const val FLYWHEEL_HOUSING = "flywheel_housing"
const val GENERATOR_BLOCK = "generator_block"
const val STORAGE_CABLE = "storage_cable" // нужен рецепт
const val STORAGE_POWER_SUPPLIER = "storage_power_supplier" // нужен рецепт
const val GRILL = "grill"

View File

@ -92,11 +92,15 @@ object MBlockEntities {
val ENERGY_OUTPUT_HATCH by register(MNames.ENERGY_OUTPUT_HATCH, EnergyHatchBlockEntity::output, MBlocks::ENERGY_OUTPUT_HATCH)
val MATTER_INPUT_HATCH by register(MNames.MATTER_INPUT_HATCH, MatterHatchBlockEntity::input, MBlocks::MATTER_INPUT_HATCH)
val MATTER_OUTPUT_HATCH by register(MNames.MATTER_OUTPUT_HATCH, MatterHatchBlockEntity::output, MBlocks::MATTER_OUTPUT_HATCH)
val ENERGY_INPUT_INTERFACE by register(MNames.ENERGY_INPUT_INTERFACE, EnergyInterfaceBlockEntity::input, MBlocks::ENERGY_INPUT_INTERFACE)
val ENERGY_OUTPUT_INTERFACE by register(MNames.ENERGY_OUTPUT_INTERFACE, EnergyInterfaceBlockEntity::output, MBlocks::ENERGY_OUTPUT_INTERFACE)
val POWERED_FURNACE by register(MNames.POWERED_FURNACE, ::PoweredFurnaceBlockEntity, MBlocks.POWERED_FURNACE)
val POWERED_BLAST_FURNACE by register(MNames.POWERED_BLAST_FURNACE, ::PoweredBlastFurnaceBlockEntity, MBlocks.POWERED_BLAST_FURNACE)
val POWERED_SMOKER by register(MNames.POWERED_SMOKER, ::PoweredSmokerBlockEntity, MBlocks.POWERED_SMOKER)
val FLYWHEEL_BATTERY by register(MNames.FLYWHEEL_BATTERY, ::FlywheelBatteryBlockEntity, MBlocks::FLYWHEEL_BATTERY)
val MULTIBLOCK_TEST by register("multiblock_test", ::MultiblockTestBlockEntity, MBlocks::MULTIBLOCK_TEST)
val ENERGY_CABLES: Map<CablesConfig.E, BlockEntityType<SimpleEnergyCableBlockEntity>> = SupplierMap(CablesConfig.E.entries.map { conf ->

View File

@ -45,6 +45,7 @@ import ru.dbotthepony.mc.otm.block.decorative.TritaniumDoorBlock
import ru.dbotthepony.mc.otm.block.decorative.TritaniumTrapdoorBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.EnergyHatchBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.EnergyInterfaceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.ItemHatchBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.MatterHatchBlockEntity
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
@ -76,6 +77,7 @@ import ru.dbotthepony.mc.otm.block.tech.CobblerBlock
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.tech.EnergyServoBlock
import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock
import ru.dbotthepony.mc.otm.block.tech.FlywheelBatteryBlock
import ru.dbotthepony.mc.otm.block.tech.PhantomAttractorBlock
import ru.dbotthepony.mc.otm.block.tech.PlatePressBlock
import ru.dbotthepony.mc.otm.block.tech.PoweredBlastFurnaceBlock
@ -160,6 +162,13 @@ object MBlocks {
conf to registry.register("${conf.name.lowercase()}_energy_cable") { EnergyCableBlock { a, b -> MBlockEntities.ENERGY_CABLES[conf]!!.create(a, b)!! } }
})
val FLYWHEEL_BATTERY by registry.register(MNames.FLYWHEEL_BATTERY) { FlywheelBatteryBlock() }
val FLYWHEEL_BEARING by registry.register(MNames.FLYWHEEL_BEARING) { MatteryBlock().addSimpleDescription() }
val FLYWHEEL_SHAFT by registry.register(MNames.FLYWHEEL_SHAFT) { MatteryBlock().addSimpleDescription() }
val FLYWHEEL_HOUSING by registry.register(MNames.FLYWHEEL_HOUSING) { MatteryBlock().addSimpleDescription() }
val GENERATOR_BLOCK by registry.register(MNames.GENERATOR_BLOCK) { MatteryBlock().addSimpleDescription() }
val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS, ::StorageBusBlock)
val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER, ::StorageImporterBlock)
val STORAGE_EXPORTER: Block by registry.register(MNames.STORAGE_EXPORTER, ::StorageExporterBlock)
@ -190,6 +199,8 @@ object MBlocks {
val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { HatchBlock(EnergyHatchBlockEntity::output, true) }
val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { HatchBlock(MatterHatchBlockEntity::input, true) }
val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { HatchBlock(MatterHatchBlockEntity::output, true) }
val ENERGY_INPUT_INTERFACE by registry.register(MNames.ENERGY_INPUT_INTERFACE) { HatchBlock(EnergyInterfaceBlockEntity::input, true) }
val ENERGY_OUTPUT_INTERFACE by registry.register(MNames.ENERGY_OUTPUT_INTERFACE) { HatchBlock(EnergyInterfaceBlockEntity::output, true) }
val LIQUID_XP: LiquidBlock by registry.register("liquid_xp") { LiquidBlock(MFluids.LIQUID_XP_FLOWING, BlockBehaviour.Properties.of().mapColor(MapColor.EMERALD).replaceable().noCollission().strength(100.0f).pushReaction(PushReaction.DESTROY).noLootTable().liquid().sound(SoundType.EMPTY)) }

View File

@ -134,12 +134,75 @@ private fun CreativeModeTab.Output.fluids(value: Item) {
private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
with(consumer) {
accept(MItems.ENERGY_CABLES.values)
accept(MItems.MACHINES)
// machines
accept(MItems.TWIN_PLATE_PRESS.values)
accept(MItems.POWERED_FURNACE.values)
accept(MItems.POWERED_BLAST_FURNACE.values)
accept(MItems.POWERED_SMOKER.values)
accept(MItems.ANDROID_STATION.values)
accept(MItems.ANDROID_CHARGER.values)
accept(MItems.BATTERY_BANK.values)
accept(MItems.ENERGY_COUNTER.values)
accept(MItems.CHEMICAL_GENERATOR.values)
accept(MItems.ENERGY_SERVO.values)
accept(MItems.PHANTOM_ATTRACTOR)
accept(MItems.PAINTER)
accept(MItems.COBBLESTONE_GENERATOR.values)
accept(MItems.ESSENCE_STORAGE.values)
accept(MItems.MATTER_DECOMPOSER.values)
accept(MItems.MATTER_CAPACITOR_BANK.values)
accept(MItems.MATTER_CABLE)
accept(MItems.PATTERN_STORAGE)
accept(MItems.MATTER_SCANNER.values)
accept(MItems.MATTER_PANEL.values)
accept(MItems.MATTER_REPLICATOR.values)
accept(MItems.MATTER_BOTTLER.values)
accept(MItems.MATTER_ENTANGLER)
accept(MItems.MATTER_RECYCLER.values)
accept(MItems.MATTER_RECONSTRUCTOR.values)
accept(MItems.GRAVITATION_STABILIZER)
// storage
accept(MItems.STORAGE_BUS)
accept(MItems.STORAGE_IMPORTER)
accept(MItems.STORAGE_EXPORTER)
accept(MItems.DRIVE_VIEWER.values)
accept(MItems.DRIVE_RACK)
accept(MItems.ITEM_MONITOR.values)
accept(MItems.STORAGE_CABLE)
accept(MItems.STORAGE_POWER_SUPPLIER.values)
// multiblock parts
accept(MItems.FLYWHEEL_BATTERY)
accept(MItems.FLYWHEEL_HOUSING)
accept(MItems.FLYWHEEL_SHAFT)
accept(MItems.FLYWHEEL_BEARING)
accept(MItems.GENERATOR_BLOCK)
accept(MItems.BLACK_HOLE_GENERATOR)
accept(MItems.ITEM_INPUT_HATCH)
accept(MItems.ITEM_OUTPUT_HATCH)
accept(MItems.ENERGY_INPUT_HATCH)
accept(MItems.ENERGY_OUTPUT_HATCH)
accept(MItems.ENERGY_INPUT_INTERFACE)
accept(MItems.ENERGY_OUTPUT_INTERFACE)
accept(MItems.MATTER_INPUT_HATCH)
accept(MItems.MATTER_OUTPUT_HATCH)
// upgrades
accept(MItems.MachineUpgrades.Basic.LIST)
accept(MItems.MachineUpgrades.Normal.LIST)
accept(MItems.MachineUpgrades.Advanced.LIST)
accept(MItems.MachineUpgrades.Creative.LIST)
// misc
accept(MRegistry.CARGO_CRATES.item)
accept(MItems.DEV_CHEST)
accept(MItems.HOLO_SIGN)

View File

@ -26,6 +26,9 @@ import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.block.Block
import net.neoforged.bus.api.IEventBus
import net.neoforged.neoforge.common.SimpleTier
import ru.dbotthepony.mc.otm.block.MatteryBlock
import ru.dbotthepony.mc.otm.block.addSimpleDescription
import ru.dbotthepony.mc.otm.block.tech.FlywheelBatteryBlock
import ru.dbotthepony.mc.otm.capability.ITieredUpgradeSet
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.UpgradeType
@ -134,6 +137,7 @@ object MItems {
val PHANTOM_ATTRACTOR: DoubleHighBlockItem by registry.register(MNames.PHANTOM_ATTRACTOR) { DoubleHighBlockItem(
MBlocks.PHANTOM_ATTRACTOR, DEFAULT_PROPERTIES
) }
val ENERGY_SERVO = register(MNames.ENERGY_SERVO, MBlocks.ENERGY_SERVO)
val COBBLESTONE_GENERATOR = register(MNames.COBBLESTONE_GENERATOR, MBlocks.COBBLESTONE_GENERATOR)
@ -141,6 +145,13 @@ object MItems {
val ESSENCE_STORAGE = register(MNames.ESSENCE_STORAGE, MBlocks.ESSENCE_STORAGE)
val MATTER_RECONSTRUCTOR = register(MNames.MATTER_RECONSTRUCTOR, MBlocks.MATTER_RECONSTRUCTOR)
val FLYWHEEL_BATTERY by registry.register(MNames.FLYWHEEL_BATTERY) { BlockItem(MBlocks.FLYWHEEL_BATTERY, DEFAULT_PROPERTIES) }
val FLYWHEEL_BEARING by registry.register(MNames.FLYWHEEL_BEARING) { BlockItem(MBlocks.FLYWHEEL_BEARING, DEFAULT_PROPERTIES) }
val FLYWHEEL_SHAFT by registry.register(MNames.FLYWHEEL_SHAFT) { BlockItem(MBlocks.FLYWHEEL_SHAFT, DEFAULT_PROPERTIES) }
val FLYWHEEL_HOUSING by registry.register(MNames.FLYWHEEL_HOUSING) { BlockItem(MBlocks.FLYWHEEL_HOUSING, DEFAULT_PROPERTIES) }
val GENERATOR_BLOCK by registry.register(MNames.GENERATOR_BLOCK) { BlockItem(MBlocks.GENERATOR_BLOCK, DEFAULT_PROPERTIES) }
val DEV_CHEST: BlockItem by registry.register(MNames.DEV_CHEST) { BlockItem(MBlocks.DEV_CHEST, DEFAULT_PROPERTIES) }
val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) }
val MATTER_ENTANGLER: BlockItem by registry.register(MNames.MATTER_ENTANGLER) { BlockItem(MBlocks.MATTER_ENTANGLER, DEFAULT_PROPERTIES) }
@ -155,62 +166,8 @@ object MItems {
val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { BlockItem(MBlocks.ENERGY_OUTPUT_HATCH, DEFAULT_PROPERTIES) }
val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { BlockItem(MBlocks.MATTER_INPUT_HATCH, DEFAULT_PROPERTIES) }
val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { BlockItem(MBlocks.MATTER_OUTPUT_HATCH, DEFAULT_PROPERTIES) }
val MACHINES: List<BlockItem>
init {
val machines = ArrayList<Supplier<BlockItem>>()
machines.addAll(TWIN_PLATE_PRESS.asSupplierArray())
machines.addAll(POWERED_FURNACE.asSupplierArray())
machines.addAll(POWERED_BLAST_FURNACE.asSupplierArray())
machines.addAll(POWERED_SMOKER.asSupplierArray())
machines.addAll(ANDROID_STATION.asSupplierArray())
machines.addAll(ANDROID_CHARGER.asSupplierArray())
machines.addAll(BATTERY_BANK.asSupplierArray())
machines.addAll(ENERGY_COUNTER.asSupplierArray())
machines.addAll(CHEMICAL_GENERATOR.asSupplierArray())
machines.addAll(ENERGY_SERVO.asSupplierArray())
machines.add(MItems::PHANTOM_ATTRACTOR)
machines.add(MItems::PAINTER)
machines.addAll(COBBLESTONE_GENERATOR.asSupplierArray().iterator())
machines.addAll(ESSENCE_STORAGE.asSupplierArray().iterator())
machines.addAll(MATTER_DECOMPOSER.asSupplierArray().iterator())
machines.addAll(MATTER_CAPACITOR_BANK.asSupplierArray().iterator())
machines.add(MItems::MATTER_CABLE)
machines.add(MItems::PATTERN_STORAGE)
machines.addAll(MATTER_SCANNER.asSupplierArray().iterator())
machines.addAll(MATTER_PANEL.asSupplierArray().iterator())
machines.addAll(MATTER_REPLICATOR.asSupplierArray().iterator())
machines.addAll(MATTER_BOTTLER.asSupplierArray().iterator())
machines.add(MItems::MATTER_ENTANGLER)
machines.addAll(MATTER_RECYCLER.asSupplierArray().iterator())
machines.addAll(MATTER_RECONSTRUCTOR.asSupplierArray().iterator())
machines.add(MItems::GRAVITATION_STABILIZER)
machines.add(MItems::BLACK_HOLE_GENERATOR)
machines.add(MItems::ITEM_INPUT_HATCH)
machines.add(MItems::ITEM_OUTPUT_HATCH)
machines.add(MItems::ENERGY_INPUT_HATCH)
machines.add(MItems::ENERGY_OUTPUT_HATCH)
machines.add(MItems::MATTER_INPUT_HATCH)
machines.add(MItems::MATTER_OUTPUT_HATCH)
machines.add(MItems::STORAGE_BUS)
machines.add(MItems::STORAGE_IMPORTER)
machines.add(MItems::STORAGE_EXPORTER)
machines.addAll(DRIVE_VIEWER.asSupplierArray().iterator())
machines.add(MItems::DRIVE_RACK)
machines.addAll(ITEM_MONITOR.asSupplierArray().iterator())
machines.add(MItems::STORAGE_CABLE)
machines.addAll(STORAGE_POWER_SUPPLIER.asSupplierArray().iterator())
MACHINES = SupplierList(machines)
}
val ENERGY_INPUT_INTERFACE by registry.register(MNames.ENERGY_INPUT_INTERFACE) { BlockItem(MBlocks.ENERGY_INPUT_INTERFACE, DEFAULT_PROPERTIES) }
val ENERGY_OUTPUT_INTERFACE by registry.register(MNames.ENERGY_OUTPUT_INTERFACE) { BlockItem(MBlocks.ENERGY_OUTPUT_INTERFACE, DEFAULT_PROPERTIES) }
val MULTIBLOCK_TEST by registry.register("multiblock_test") { BlockItem(MBlocks.MULTIBLOCK_TEST, Properties().stacksTo(64)) }