From 1c0cdb8b5bd427c9f953716c7d0d02cb9c8fdf44 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 30 Dec 2023 20:26:31 +0700 Subject: [PATCH] Energy cable tiers, fix some Client -> Server logic leaks in singleplayer --- .../mc/otm/datagen/loot/LootTablesData.kt | 1 + .../dbotthepony/mc/otm/datagen/tags/Tags.kt | 1 + .../mc/otm/OverdriveThatMatters.java | 2 + .../dbotthepony/mc/otm/GlobalEventHandler.kt | 3 + .../ru/dbotthepony/mc/otm/block/Cables.kt | 6 +- .../mc/otm/block/entity/MatteryBlockEntity.kt | 16 +++- .../block/entity/MatteryDeviceBlockEntity.kt | 6 +- .../entity/cable/EnergyCableBlockEntity.kt | 42 +++++---- .../block/entity/cable/EnergyCableGraph.kt | 86 +++++++++++++++++-- .../dbotthepony/mc/otm/config/CablesConfig.kt | 28 ++++++ .../dbotthepony/mc/otm/core/math/Decimal.kt | 6 +- .../ru/dbotthepony/mc/otm/graph/GraphNode.kt | 3 + .../mc/otm/registry/MBlockEntities.kt | 12 ++- .../ru/dbotthepony/mc/otm/registry/MBlocks.kt | 7 +- .../mc/otm/registry/MCreativeTabs.kt | 2 +- .../ru/dbotthepony/mc/otm/registry/MItems.kt | 6 +- .../ru/dbotthepony/mc/otm/registry/MNames.kt | 1 - .../blockstates/advanced_energy_cable.json | 74 ++++++++++++++++ .../blockstates/crude_energy_cable.json | 74 ++++++++++++++++ .../blockstates/regular_energy_cable.json | 74 ++++++++++++++++ .../superconductor_energy_cable.json | 74 ++++++++++++++++ 21 files changed, 487 insertions(+), 37 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/config/CablesConfig.kt create mode 100644 src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json create mode 100644 src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json create mode 100644 src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json create mode 100644 src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt index f3a46e108..afea9c71a 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt @@ -50,6 +50,7 @@ fun addLootTables(lootTables: LootTables) { lootTables.dropsSelf(MBlocks.METAL_BEAM) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_BARS) { condition(ExplosionCondition.survivesExplosion()) } + lootTables.dropsSelf(MBlocks.ENERGY_CABLES.values) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.INFINITE_WATER_SOURCE) { condition(ExplosionCondition.survivesExplosion()) } 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 ad9a24614..e70e7c839 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 @@ -176,6 +176,7 @@ fun addTags(tagsProvider: TagsProvider) { tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.PAINTER, Tiers.STONE) + tagsProvider.requiresPickaxe(MBlocks.ENERGY_CABLES.values, Tiers.STONE) tagsProvider.requiresPickaxe(listOf( MBlocks.ANDROID_STATION, diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index cbb6c61c9..424e15699 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -39,6 +39,7 @@ import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer import ru.dbotthepony.mc.otm.compat.adastra.AdAstraCompatKt; import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt; import ru.dbotthepony.mc.otm.config.AndroidConfig; +import ru.dbotthepony.mc.otm.config.CablesConfig; import ru.dbotthepony.mc.otm.config.ClientConfig; import ru.dbotthepony.mc.otm.config.ExopackConfig; import ru.dbotthepony.mc.otm.config.ItemsConfig; @@ -142,6 +143,7 @@ public final class OverdriveThatMatters { ClientConfig.INSTANCE.register(); ServerConfig.INSTANCE.register(); + CablesConfig.INSTANCE.register(); ServerCompatConfig.INSTANCE.register(); AndroidConfig.INSTANCE.register(); ExopackConfig.INSTANCE.register(); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 7e8d4de0f..a8f8c9096 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -40,6 +40,9 @@ private val serverCounter = AtomicInteger() private var _server: MinecraftServer? = null val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT } +val UNIVERSE_TICKS get() = postServerTick.ticks +val Level.ticksPassed get() = postWorldTick.computeIfAbsent(this) { TickList() }.ticks + fun lazyPerServer(fn: (MinecraftServer) -> V): Lazy { return AtomicallyInvalidatedLazy(serverCounter) { if (!SERVER_IS_LIVE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/Cables.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/Cables.kt index e17fe4714..d0405c814 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/Cables.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/Cables.kt @@ -129,8 +129,8 @@ class StorageCableBlock : CableBlock(Properties.of().mapColor(MapColor.METAL).re } } -class EnergyCableBlock : CableBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().sound(SoundType.METAL).strength(1.0f, 6.0f)), EntityBlock { - private val shapes = generateShapes(0.125) +class EnergyCableBlock(val factory: (blockPos: BlockPos, blockState: BlockState) -> BlockEntity) : CableBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().sound(SoundType.METAL).strength(1.0f, 6.0f)), EntityBlock { + private val shapes = generateShapes(0.185) @Suppress("OVERRIDE_DEPRECATION") override fun getShape(blockState: BlockState, accessor: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape { @@ -138,6 +138,6 @@ class EnergyCableBlock : CableBlock(Properties.of().mapColor(MapColor.METAL).req } override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { - return EnergyCableBlockEntity(blockPos, blockState) + return factory(blockPos, blockState) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index fd6ae1e0f..bfbb8955c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -62,6 +62,7 @@ import java.util.function.Consumer import java.util.function.Predicate import java.util.function.Supplier import java.util.stream.Stream +import kotlin.collections.ArrayList import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -109,6 +110,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc protected val tickList = TickList() protected val blockStateChangesCounter = IntCounter() protected val dirtyListeners = ISubscriptable.Impl() + private val waitForServerLevel = ArrayList<() -> Unit>() /** * Shared savetables, written both to level storage and to item tag @@ -166,6 +168,14 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } + protected fun waitForServerLevel(lambda: () -> Unit) { + if (level is ServerLevel) { + lambda.invoke() + } else if (level == null) { + waitForServerLevel.add(lambda) + } + } + interface SideListener : Supplier>, ISubscriptable> inner class Side(val side: RelativeSide) { @@ -191,7 +201,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc override fun addListener(listener: Consumer>): ISubscriptable.L { val l = listeners.addListener(listener) - listener.accept(value) + if (level is ServerLevel) listener.accept(value) return l } @@ -521,6 +531,10 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } } + + waitForServerLevel.forEach { it.invoke() } + } else { + waitForServerLevel.clear() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt index 744da7694..9eeab72a6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt @@ -179,7 +179,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo } init { - tickList.once { + waitForServerLevel { redstoneControl.addListener { updateTickerState() } @@ -388,7 +388,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo updateTickerState() } - tickList.once { + waitForServerLevel { redstoneControl.addListener { updateTickerState() } @@ -670,7 +670,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo savetables.bool(::automatePush, "itemhandler_${side}_automatePush") savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf) - tickList.once { + waitForServerLevel { redstoneControl.addListener { updateTickerState() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt index aeeb47cf8..23b852c37 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt @@ -2,8 +2,10 @@ package ru.dbotthepony.mc.otm.block.entity.cable import net.minecraft.core.BlockPos import net.minecraft.core.Direction +import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.ForgeCapabilities import ru.dbotthepony.mc.otm.SERVER_IS_LIVE @@ -12,13 +14,12 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage -import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.config.CablesConfig import ru.dbotthepony.mc.otm.core.math.BlockRotation import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.graph.GraphNode import ru.dbotthepony.mc.otm.onceServer -import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.util.Collections import java.util.EnumMap @@ -27,7 +28,7 @@ import java.util.EnumMap // this allows simpler implementation and faster code, while also reducing possibility of duplication exploits -class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.ENERGY_CABLE, blockPos, blockState) { +abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(type, blockPos, blockState) { inner class CableSide(val side: RelativeSide) : IMatteryEnergyStorage { var isEnabled = true set(value) { @@ -47,19 +48,17 @@ class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte val neighbour = sides[side]!!.trackEnergy() init { - neighbour.addListener { - if (isEnabled) { - if (it.isPresent) { - if (it.resolve().get() !is CableSide) { - node.graph.livelyNodes.add(node) + waitForServerLevel { + neighbour.addListener { + if (isEnabled) { + if (it.isPresent) { + if (it.resolve().get() !is CableSide) { + node.graph.livelyNodes.add(node) + } } onceServer { - updateBlockState(blockRotation.side2Dir(side), true) - } - } else { - onceServer { - updateBlockState(blockRotation.side2Dir(side), false) + updateBlockState(blockRotation.side2Dir(side), it.isPresent || node.neighboursView[GraphNode.link(blockRotation.side2Dir(side))] != null) } } } @@ -71,7 +70,7 @@ class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte } override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { - return node.graph.receiveEnergy(howMuch, simulate) + return node.graph.receiveEnergy(howMuch, simulate, node, side) } override var batteryLevel: Decimal @@ -103,6 +102,11 @@ class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte updateBlockState(link.direction, false) } } + + val blockEntity get() = this@EnergyCableBlockEntity + val canTraverse get() = energyThroughput > Decimal.ZERO + val energyThroughput get() = this@EnergyCableBlockEntity.energyThroughput + val position: BlockPos get() = this@EnergyCableBlockEntity.blockPos } private fun updateBlockState(side: Direction, status: Boolean) { @@ -112,7 +116,10 @@ class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS) } - override val blockRotation: BlockRotation + // whenever this changes, graph#invalidatePathCache() MUST be called + abstract val energyThroughput: Decimal + + final override val blockRotation: BlockRotation get() = BlockRotation.NORTH private val energySidesInternal = EnumMap(RelativeSide::class.java) @@ -134,3 +141,8 @@ class EnergyCableBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte exposeGlobally(MatteryCapability.ENERGY_CABLE_NODE, node) } } + +class SimpleEnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState, val config: CablesConfig.E) : EnergyCableBlockEntity(type, blockPos, blockState) { + override val energyThroughput: Decimal + get() = config.throughput +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt index c5e25be5b..db8a71f7a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableGraph.kt @@ -1,23 +1,92 @@ package ru.dbotthepony.mc.otm.block.entity.cable +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import ru.dbotthepony.mc.otm.capability.receiveEnergy import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.graph.GraphNodeList +import kotlin.math.ln class EnergyCableGraph : GraphNodeList() { val livelyNodes = ObjectOpenHashSet() + private val pathCache = Object2ObjectOpenHashMap, Decimal?>() + + private class SearchNode(val node: EnergyCableBlockEntity.Node, target: EnergyCableBlockEntity.Node, var parent: SearchNode? = null) : Comparable { + var heuristics: Double = node.position.distSqr(target.position) * 0.0001 - ln(node.energyThroughput.coerceAtMost(Decimal.LONG_MAX_VALUE).toDouble()) + + override fun compareTo(other: SearchNode): Int { + return heuristics.compareTo(other.heuristics) + } + } + + fun invalidatePathCache() { + pathCache.clear() + } + + private fun getPath(a: EnergyCableBlockEntity.Node, b: EnergyCableBlockEntity.Node): Decimal? { + if (!a.canTraverse || !b.canTraverse) + return null + + val key = a to b + + if (key in pathCache) + return pathCache[key] + + // no free paths available, try to find extra one + // while this use A* algorithm, this is done purely for biasing search towards end point (to speed up search), + // on small cable networks simple flooding will do just fine, if we consider overloaded cables as closed flood gates + val openNodes = ArrayList() + val seenNodes = ObjectOpenHashSet() + + openNodes.add(SearchNode(a, b)) + + while (openNodes.isNotEmpty()) { + val first = openNodes.min() + openNodes.remove(first) + + if (first.node === b) { + // solution found + val solution = ArrayList() + + var last = first.parent + solution.add(first.node) + + while (last != null) { + solution.add(last.node) + last = last.parent + } + + val calc = solution.minOf { it.energyThroughput } + pathCache[key] = calc + return calc + } else { + for (neighbour in first.node.neighboursView.values) { + if (!seenNodes.add(neighbour) || !neighbour.canTraverse) continue + openNodes.add(SearchNode(neighbour, b, first)) + } + } + } + + // solution does not exist + pathCache[key] = null + return null + } + override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) { livelyNodes.remove(node) + invalidatePathCache() } override fun onNodeAdded(node: EnergyCableBlockEntity.Node) { livelyNodes.add(node) + invalidatePathCache() } - fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal { + fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal { val itr = livelyNodes.iterator() var received = Decimal.ZERO var residue = howMuch @@ -27,15 +96,20 @@ class EnergyCableGraph : GraphNodeList { } override fun compareTo(other: Decimal): Int { - return if (other is Regular) + return if (other === Zero) + signum() + else if (other is Regular) mag.compareTo(other.mag) else if (other === PositiveInfinity) -1 else if (other === NegativeInfinity) 1 - else if (other === Zero) - signum() else throw RuntimeException("unreachable code") } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphNode.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphNode.kt index 05899b77f..e6b2b754e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphNode.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphNode.kt @@ -13,6 +13,8 @@ import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.core.util.IConditionalTickable import ru.dbotthepony.mc.otm.core.util.ITickable +import java.util.* +import kotlin.collections.ArrayList open class GraphNode, G : GraphNodeList>(val graphFactory: () -> G) { interface Link { @@ -30,6 +32,7 @@ open class GraphNode, G : GraphNodeList>(val graphFact } private val neighbours = Object2ObjectOpenHashMap() + val neighboursView: Map = Collections.unmodifiableMap(neighbours) var graph: G = graphFactory.invoke() internal set diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt index a0697f9c7..9036fc742 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt @@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.* import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityExplosionDebugger import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntitySphereDebugger -import ru.dbotthepony.mc.otm.block.entity.cable.EnergyCableBlockEntity +import ru.dbotthepony.mc.otm.block.entity.cable.SimpleEnergyCableBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.DevChestBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity @@ -30,6 +30,9 @@ import ru.dbotthepony.mc.otm.block.entity.tech.EnergyServoBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity import ru.dbotthepony.mc.otm.client.render.blockentity.* +import ru.dbotthepony.mc.otm.config.CablesConfig +import ru.dbotthepony.mc.otm.core.collect.SupplierMap +import ru.dbotthepony.mc.otm.core.getValue import java.util.function.Supplier @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // Type<*> is unused in BlockEntityType.Builder @@ -74,7 +77,12 @@ object MBlockEntities { val DEV_CHEST by register(MNames.DEV_CHEST, ::DevChestBlockEntity, MBlocks::DEV_CHEST) val PAINTER by register(MNames.PAINTER, ::PainterBlockEntity, MBlocks::PAINTER) val MATTER_ENTANGLER by register(MNames.MATTER_ENTANGLER, ::MatterEntanglerBlockEntity, MBlocks::MATTER_ENTANGLER) - val ENERGY_CABLE by register(MNames.ENERGY_CABLE, ::EnergyCableBlockEntity, MBlocks::ENERGY_CABLE) + + val ENERGY_CABLES: Map> = SupplierMap(CablesConfig.E.entries.map { conf -> + var selfFeed: Supplier> = Supplier { TODO() } + selfFeed = register("${conf.name.lowercase()}_energy_cable", { a, b -> SimpleEnergyCableBlockEntity(selfFeed.get(), a, b, conf) }) as Supplier> + conf to selfFeed::get + }) val POWERED_FURNACE: BlockEntityType by registry.register(MNames.POWERED_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_FURNACE).build(null) } val POWERED_BLAST_FURNACE: BlockEntityType by registry.register(MNames.POWERED_BLAST_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_BLAST_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_BLAST_FURNACE).build(null) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt index 266a98416..bb75430c5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -77,9 +77,11 @@ import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock import ru.dbotthepony.mc.otm.block.tech.PhantomAttractorBlock import ru.dbotthepony.mc.otm.block.tech.PlatePressBlock import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock +import ru.dbotthepony.mc.otm.config.CablesConfig import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.collect.SupplierList +import ru.dbotthepony.mc.otm.core.collect.SupplierMap import ru.dbotthepony.mc.otm.shapes.BlockShapes object MBlocks { @@ -115,7 +117,10 @@ object MBlocks { val MATTER_RECONSTRUCTOR: MatterReconstructorBlock by registry.register(MNames.MATTER_RECONSTRUCTOR) { MatterReconstructorBlock() } val PAINTER: PainterBlock by registry.register(MNames.PAINTER) { PainterBlock() } val MATTER_ENTANGLER: MatterEntanglerBlock by registry.register(MNames.MATTER_ENTANGLER) { MatterEntanglerBlock() } - val ENERGY_CABLE: EnergyCableBlock by registry.register(MNames.ENERGY_CABLE) { EnergyCableBlock() } + + val ENERGY_CABLES: Map = SupplierMap(CablesConfig.E.entries.map { conf -> + conf to registry.register("${conf.name.lowercase()}_energy_cable") { EnergyCableBlock { a, b -> MBlockEntities.ENERGY_CABLES[conf]!!.create(a, b)!! } }::get + }) val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() } val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt index 66ef9f405..258ca4ed1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt @@ -129,7 +129,7 @@ private fun CreativeModeTab.Output.fluids(value: Item) { private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) { with(consumer) { - accept(MItems.ENERGY_CABLE) + accept(MItems.ENERGY_CABLES.values) accept(MItems.MACHINES) accept(MItems.MachineUpgrades.Basic.LIST) accept(MItems.MachineUpgrades.Normal.LIST) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt index 4c50272dc..0d3611aaa 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -17,9 +17,11 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.capability.ITieredUpgradeSet import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.UpgradeType +import ru.dbotthepony.mc.otm.config.CablesConfig import ru.dbotthepony.mc.otm.config.ItemsConfig import ru.dbotthepony.mc.otm.core.collect.SupplierList import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.collect.SupplierMap import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.item.* import ru.dbotthepony.mc.otm.item.exopack.ExopackProbeItem @@ -46,7 +48,9 @@ object MItems { registry.register(bus) } - val ENERGY_CABLE: BlockItem by registry.register(MNames.ENERGY_CABLE) { BlockItem(MBlocks.ENERGY_CABLE, DEFAULT_PROPERTIES) } + val ENERGY_CABLES: Map = SupplierMap(CablesConfig.E.entries.map { conf -> + conf to registry.register("${conf.name.lowercase()}_energy_cable") { BlockItem(MBlocks.ENERGY_CABLES[conf]!!, DEFAULT_PROPERTIES) }::get + }) val ANDROID_STATION: BlockItem by registry.register(MNames.ANDROID_STATION) { BlockItem(MBlocks.ANDROID_STATION, DEFAULT_PROPERTIES) } val ANDROID_CHARGER: BlockItem by registry.register(MNames.ANDROID_CHARGER) { BlockItem(MBlocks.ANDROID_CHARGER, DEFAULT_PROPERTIES) } 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 43316e325..258cc69c5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -17,7 +17,6 @@ object MNames { const val DEV_CHEST = "dev_chest" const val PAINTER = "painter" const val MATTER_ENTANGLER = "matter_entangler" - const val ENERGY_CABLE = "energy_cable" // blocks const val ANDROID_STATION = "android_station" diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json new file mode 100644 index 000000000..ae8a815be --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/blockstates/advanced_energy_cable.json @@ -0,0 +1,74 @@ +{ + "multipart": [ + { + "apply": { + "model": "overdrive_that_matters:block/storage_cable_core" + } + }, + + { + "when": { + "connect_south": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection" + } + }, + + { + "when": { + "connect_west": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 90 + } + }, + + { + "when": { + "connect_north": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 180 + } + }, + + { + "when": { + "connect_east": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 270 + } + }, + + { + "when": { + "connect_up": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 90 + } + }, + + { + "when": { + "connect_down": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 270 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json new file mode 100644 index 000000000..ae8a815be --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/blockstates/crude_energy_cable.json @@ -0,0 +1,74 @@ +{ + "multipart": [ + { + "apply": { + "model": "overdrive_that_matters:block/storage_cable_core" + } + }, + + { + "when": { + "connect_south": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection" + } + }, + + { + "when": { + "connect_west": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 90 + } + }, + + { + "when": { + "connect_north": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 180 + } + }, + + { + "when": { + "connect_east": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 270 + } + }, + + { + "when": { + "connect_up": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 90 + } + }, + + { + "when": { + "connect_down": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 270 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json new file mode 100644 index 000000000..ae8a815be --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/blockstates/regular_energy_cable.json @@ -0,0 +1,74 @@ +{ + "multipart": [ + { + "apply": { + "model": "overdrive_that_matters:block/storage_cable_core" + } + }, + + { + "when": { + "connect_south": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection" + } + }, + + { + "when": { + "connect_west": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 90 + } + }, + + { + "when": { + "connect_north": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 180 + } + }, + + { + "when": { + "connect_east": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 270 + } + }, + + { + "when": { + "connect_up": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 90 + } + }, + + { + "when": { + "connect_down": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 270 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json b/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json new file mode 100644 index 000000000..ae8a815be --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/blockstates/superconductor_energy_cable.json @@ -0,0 +1,74 @@ +{ + "multipart": [ + { + "apply": { + "model": "overdrive_that_matters:block/storage_cable_core" + } + }, + + { + "when": { + "connect_south": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection" + } + }, + + { + "when": { + "connect_west": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 90 + } + }, + + { + "when": { + "connect_north": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 180 + } + }, + + { + "when": { + "connect_east": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "y": 270 + } + }, + + { + "when": { + "connect_up": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 90 + } + }, + + { + "when": { + "connect_down": true + }, + + "apply": { + "model": "overdrive_that_matters:block/storage_cable_connection", + "x": 270 + } + } + ] +} \ No newline at end of file