diff --git a/gradle.properties b/gradle.properties index c7a457f8f..bfd304f0e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt index 869892f85..4be8f7178 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -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() } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/FlywheelData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/FlywheelData.kt new file mode 100644 index 000000000..96b07c0d0 --- /dev/null +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/FlywheelData.kt @@ -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)) +} diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index df516019e..e22d4c75b 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -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") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index 7d045f457..2cfb45df4 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -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, "Входной клапан материи") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DecorativeLoot.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DecorativeLoot.kt index ff57f0a8e..37f898079 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DecorativeLoot.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DecorativeLoot.kt @@ -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) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/MachineLoot.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/MachineLoot.kt index bc4260b3a..b3f3e179b 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/MachineLoot.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/MachineLoot.kt @@ -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) } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/MineableTags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/MineableTags.kt index 302f9349b..2e6044545 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/MineableTags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/MineableTags.kt @@ -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( diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index 459ba1e68..882206eb9 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt index b24b84ef8..22c2c4a2b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleGeneratorBlockEntity.kt index ec45e96b0..58f6b4222 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleGeneratorBlockEntity.kt @@ -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() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt index 528f83b3c..4e6dfd6ca 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt @@ -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>() 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) + } + } + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyInterfaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyInterfaceBlockEntity.kt new file mode 100644 index 000000000..0dc83d27e --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyInterfaceBlockEntity.kt @@ -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() + + 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>() + + 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) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/FlywheelBatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/FlywheelBatteryBlockEntity.kt new file mode 100644 index 000000000..5430e2ced --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/FlywheelBatteryBlockEntity.kt @@ -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() + + 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) + } + } + } + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/FlywheelBatteryBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/FlywheelBatteryBlock.kt new file mode 100644 index 000000000..be1965237 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/FlywheelBatteryBlock.kt @@ -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 getTicker( + level: Level, + p_153213_: BlockState, + p_153214_: BlockEntityType + ): BlockEntityTicker? { + if (level.isClientSide) + return null + + return BlockEntityTicker { _, _, _, t -> if (t is FlywheelBatteryBlockEntity) t.tick() } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt index a6c43e04c..e1ee4df84 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -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 Supplier>.iterateProviders(random: RandomGenerator?, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal { +fun Supplier>.iterateProviders(random: RandomSource?, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal { val providers = get() val iteratorProvider: () -> Iterator diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedEnergyStorage.kt index 7cece4a06..1f0a0ac21 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedEnergyStorage.kt @@ -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>, - val random: Supplier = Supplier { null } + val random: Supplier = Supplier { null } ) : IMatteryEnergyStorage { final override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::extractEnergy) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedProfiledEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedProfiledEnergyStorage.kt index 7001566b6..441f918c3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedProfiledEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/CombinedProfiledEnergyStorage.kt @@ -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>>, - random: Supplier = Supplier { null } + random: Supplier = 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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedMatterStorage.kt index cd0c3d7c7..d18c5b298 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedMatterStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedMatterStorage.kt @@ -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>, - val random: Supplier = Supplier { null } + val random: Supplier = Supplier { null } ) : IMatterStorage { final override var storedMatter: Decimal get() = provider.get().map { it.storedMatter }.reduce(Decimal.ZERO, Decimal::plus) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedProfiledMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedProfiledMatterStorage.kt index e870ca7b4..34576bf89 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedProfiledMatterStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/CombinedProfiledMatterStorage.kt @@ -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>>, - random: Supplier = Supplier { null } + random: Supplier = 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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntitySet.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntitySet.kt index fb203ad2c..9e47845f9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntitySet.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntitySet.kt @@ -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(private val listener: GlobalBlockEntityRemovalListener, val tag: BlockEntityTag) { +class BlockEntitySet(private val listener: GlobalBlockEntityRemovalListener, val tag: BlockEntityTag) { private val items = Reference2IntOpenHashMap() val set: Set = Collections.unmodifiableSet(items.keys) @@ -38,7 +38,7 @@ class BlockEntitySet(private val listener: GlobalBlockEntityRem fun clear() { items.keys.forEach { - GlobalBlockEntityRemovalListener.stopListening(it, listener) + GlobalBlockEntityRemovalListener.stopListening(it as BlockEntity, listener) } items.clear() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntityTag.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntityTag.kt index 39f1a0f47..ee723d051 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntityTag.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/BlockEntityTag.kt @@ -13,9 +13,8 @@ inline fun multiblockEntity(): BlockEntityTag { * * Optionally, can have [predicate] specified, which narrows which block entities can be accepted by this tag */ -class BlockEntityTag(val clazz: KClass, val predicate: Predicate = Predicate { true }) : - Predicate { - override fun test(t: BlockEntity): Boolean { +class BlockEntityTag(val clazz: KClass, val predicate: Predicate = Predicate { true }) : Predicate { + override fun test(t: Any?): Boolean { return clazz.isInstance(t) && predicate.test(t as T) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockAccess.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockAccess.kt index 7dc35e643..420c7fa32 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockAccess.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockAccess.kt @@ -45,7 +45,7 @@ interface IMultiblockAccess { return blockStates(GLOBAL_BLOCK_TAG) } - fun blockEntities(tag: BlockEntityTag): Set + fun blockEntities(tag: BlockEntityTag): Set companion object { val GLOBAL_BLOCK_TAG = Any() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockListener.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockListener.kt new file mode 100644 index 000000000..cf751d8d1 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/IMultiblockListener.kt @@ -0,0 +1,6 @@ +package ru.dbotthepony.mc.otm.core.multiblock + +interface IMultiblockListener { + fun onAddedToMultiblock(multiblock: IMultiblockAccess) + fun onRemovedFromMultiblock(multiblock: IMultiblockAccess) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/MultiblockListenerSet.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/MultiblockListenerSet.kt new file mode 100644 index 000000000..1b4050b31 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/MultiblockListenerSet.kt @@ -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() + + 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() + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblock.kt index c12e8fe8b..0316b47d9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblock.kt @@ -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 getBlockEntityList(tag: BlockEntityTag): BlockEntitySet { + private fun getBlockEntityList(tag: BlockEntityTag): BlockEntitySet { 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 blockEntities(tag: BlockEntityTag): Set { + override fun blockEntities(tag: BlockEntityTag): Set { + checkAccess() return (tag2BlockEntity[tag]?.set ?: setOf()) as Set } override fun blocks(tag: Any): Reference2IntMap { + checkAccess() return tag2BlockViews[tag] ?: Reference2IntMaps.emptyMap() } override fun blockStates(tag: Any): Reference2IntMap { + checkAccess() return tag2BlockStateViews[tag] ?: Reference2IntMaps.emptyMap() } override fun blocks(): Reference2IntMap { + checkAccess() return globalBlocksView } override fun blockStates(): Reference2IntMap { + 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 get() = activeConfig.parts - override fun blockEntities(tag: BlockEntityTag): Set { + override fun blockEntities(tag: BlockEntityTag): Set { 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() - val configurations0 = ArrayList(this.configurations) + isUpdating = true - while (configurations0.isNotEmpty()) { - val max = configurations0.max() - configurations0.remove(max) - configurations.add(max) - } + try { + val configurations = LinkedList() + 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() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblockBuilder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblockBuilder.kt index a93484ac9..0fde89cc3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblockBuilder.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/multiblock/ShapedMultiblockBuilder.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterialDataProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterialDataProvider.kt new file mode 100644 index 000000000..13f41ede0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterialDataProvider.kt @@ -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() + + 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, storage: Decimal, priority: Int = 0) { + entries.add(FlywheelMaterials.Entry(block, storage, priority)) + } + + @JvmName("addBlocks") + @JvmOverloads + fun add(blocks: Collection, storage: Decimal, priority: Int = 0) { + for (block in blocks) + entries.add(FlywheelMaterials.Entry(block, storage, priority)) + } + + @JvmName("addBlocks") + @JvmOverloads + fun add(blocks: Array, storage: Decimal, priority: Int = 0) { + for (block in blocks) + entries.add(FlywheelMaterials.Entry(block, storage, priority)) + } + + @JvmName("addTags") + @JvmOverloads + fun add(blocks: Array>, 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) { + return add(blocks, storage) + } + + @JvmName("addTags") + fun add(storage: Decimal, priority: Int, vararg blocks: TagKey) { + return add(blocks, storage, priority) + } + + override fun run(output: CachedOutput): CompletableFuture<*> { + if (location == null) { + val futures = ArrayList>() + + 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" + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterials.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterials.kt new file mode 100644 index 000000000..48a3eceda --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/FlywheelMaterials.kt @@ -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, Block>, + val storage: Decimal, + val priority: Int = 0, + val receiveEfficiency: Decimal = Decimal.ONE, + val momentumLossSpeed: Decimal = Decimal.ONE + ) : Comparable { + 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, 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() + private var mapped = HashMap() + private var mappingChanged = false + + private fun mapping(): Map { + 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, + manager: ResourceManager, + profiler: ProfilerFiller + ) { + val elements = ArrayList() + + 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 = 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() +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterDataProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterDataProvider.kt index e490e82a1..5406c79ad 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterDataProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterDataProvider.kt @@ -1247,19 +1247,10 @@ open class MatterDataProvider(val modid: String? = null) : DataProvider { @JvmOverloads fun insert(name: TagKey, matterValue: Decimal, complexity: Double, priority: Int, configurator: Consumer = 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() val addedView: List = Collections.unmodifiableList(added) - final override fun run(output: CachedOutput): CompletableFuture<*> { - addActions() - + override fun run(output: CachedOutput): CompletableFuture<*> { val promises = ArrayList>() for ((key, value) in actions) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockTags.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockTags.kt index 517b35bbc..876128ac1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockTags.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockTags.kt @@ -17,6 +17,8 @@ object MBlockTags { val REQUIRES_TRITANIUM_TOOL: TagKey = BlockTags.create(ResourceLocation("minecraft", "requires_tritanium_tool")) + val TRITANIUM_BLOCKS: TagKey = BlockTags.create(ResourceLocation("c", "storage_blocks/tritanium")) + val DILITHIUM_ORES: TagKey = BlockTags.create(ResourceLocation("c", "ores/dilithium")) val HARDENED_GLASS_PANES: TagKey = BlockTags.create(ResourceLocation("c", "hardened_glass_panes")) @@ -57,7 +59,6 @@ object MBlockTags { val HARDENED_GLASS_WHITE: TagKey = BlockTags.create(ResourceLocation("c", "hardened_glass/white")) val HARDENED_GLASS_YELLOW: TagKey = BlockTags.create(ResourceLocation("c", "hardened_glass/yellow")) - val MACHINES: TagKey = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "machines")) val MULTIBLOCK_STRUCTURE: TagKey = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_structure")) val MULTIBLOCK_HARD_STRUCTURE: TagKey = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_hard_structure")) val MULTIBLOCK_SOFT_STRUCTURE: TagKey = BlockTags.create(ResourceLocation(OverdriveThatMatters.MOD_ID, "multiblock_soft_structure")) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemTags.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemTags.kt index c8e242df6..a3bd24319 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemTags.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemTags.kt @@ -83,8 +83,6 @@ object MItemTags { val HARDENED_GLASS_WHITE: TagKey = ItemTags.create(ResourceLocation("c", "hardened_glass/white")) val HARDENED_GLASS_YELLOW: TagKey = ItemTags.create(ResourceLocation("c", "hardened_glass/yellow")) - val MACHINES: TagKey = ItemTags.create(modLoc("machines")) - val NO_DECOMPOSING: TagKey = ItemTags.create(modLoc("matter/no_decomposing")) val NO_REPLICATION: TagKey = ItemTags.create(modLoc("matter/no_replication")) val NO_REPAIR: TagKey = ItemTags.create(modLoc("matter/no_repair")) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt index 080cd5bbe..cfd03d438 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -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" diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt index 8bdded89e..41c02d5b1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt @@ -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> = SupplierMap(CablesConfig.E.entries.map { conf -> diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt index f8531e01a..1faf345ee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt @@ -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)) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MCreativeTabs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MCreativeTabs.kt index cc58e4677..3cf74f94a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MCreativeTabs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MCreativeTabs.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt index 4b13cbb79..350019244 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt @@ -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 - - init { - val machines = ArrayList>() - - 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)) }