Energy cable tiers, fix some Client -> Server logic leaks in singleplayer

This commit is contained in:
DBotThePony 2023-12-30 20:26:31 +07:00
parent 023081eaaa
commit 1c0cdb8b5b
Signed by: DBot
GPG Key ID: DCC23B5715498507
21 changed files with 487 additions and 37 deletions

View File

@ -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()) }

View File

@ -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,

View File

@ -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();

View File

@ -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 <V> lazyPerServer(fn: (MinecraftServer) -> V): Lazy<V> {
return AtomicallyInvalidatedLazy(serverCounter) {
if (!SERVER_IS_LIVE)

View File

@ -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)
}
}

View File

@ -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<Unit>()
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<T> : Supplier<LazyOptional<T>>, ISubscriptable<LazyOptional<T>>
inner class Side(val side: RelativeSide) {
@ -191,7 +201,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
override fun addListener(listener: Consumer<LazyOptional<T>>): 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()
}
}

View File

@ -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()
}

View File

@ -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 {
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, CableSide>(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
}

View File

@ -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<EnergyCableBlockEntity.Node, EnergyCableGraph>() {
val livelyNodes = ObjectOpenHashSet<EnergyCableBlockEntity.Node>()
private val pathCache = Object2ObjectOpenHashMap<Pair<EnergyCableBlockEntity.Node, EnergyCableBlockEntity.Node>, Decimal?>()
private class SearchNode(val node: EnergyCableBlockEntity.Node, target: EnergyCableBlockEntity.Node, var parent: SearchNode? = null) : Comparable<SearchNode> {
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<SearchNode>()
val seenNodes = ObjectOpenHashSet<EnergyCableBlockEntity.Node>()
openNodes.add(SearchNode(a, b))
while (openNodes.isNotEmpty()) {
val first = openNodes.min()
openNodes.remove(first)
if (first.node === b) {
// solution found
val solution = ArrayList<EnergyCableBlockEntity.Node>()
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,19 +96,24 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
for (side in node.sides.values) {
if (side.isEnabled) {
if (fromNode === node && side.side === fromSide)
continue
side.neighbour.get().ifPresentK {
if (it !is EnergyCableBlockEntity.CableSide) {
val limit = getPath(fromNode, node)
hit = true
val thisReceived = it.receiveEnergy(residue, simulate)
if (limit != null) {
val thisReceived = it.receiveEnergy(residue.coerceAtMost(limit), simulate)
received += thisReceived
residue -= thisReceived
if (!residue.isPositive) return received
}
}
}
}
}
if (!hit) {
itr.remove()

View File

@ -0,0 +1,28 @@
package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object CablesConfig : AbstractConfig("cables") {
enum class E(throughput: Decimal) {
CRUDE(Decimal(160)),
REGULAR(Decimal(1024)),
ADVANCED(Decimal(8192)),
SUPERCONDUCTOR(Decimal.POSITIVE_INFINITY);
init {
builder.push(name)
}
var throughput by builder
.defineDecimal("THROUGHPUT", throughput, Decimal.ZERO)
init {
builder.pop()
}
}
init {
E.SUPERCONDUCTOR
}
}

View File

@ -262,14 +262,14 @@ sealed class Decimal : Number(), Comparable<Decimal> {
}
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")
}

View File

@ -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<N : GraphNode<N, G>, G : GraphNodeList<N, G>>(val graphFactory: () -> G) {
interface Link {
@ -30,6 +32,7 @@ open class GraphNode<N : GraphNode<N, G>, G : GraphNodeList<N, G>>(val graphFact
}
private val neighbours = Object2ObjectOpenHashMap<Link, N>()
val neighboursView: Map<Link, N> = Collections.unmodifiableMap(neighbours)
var graph: G = graphFactory.invoke()
internal set

View File

@ -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<CablesConfig.E, BlockEntityType<*>> = SupplierMap(CablesConfig.E.entries.map { conf ->
var selfFeed: Supplier<BlockEntityType<*>> = Supplier { TODO() }
selfFeed = register("${conf.name.lowercase()}_energy_cable", { a, b -> SimpleEnergyCableBlockEntity(selfFeed.get(), a, b, conf) }) as Supplier<BlockEntityType<*>>
conf to selfFeed::get
})
val POWERED_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> 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<PoweredFurnaceBlockEntity> 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) }

View File

@ -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<CablesConfig.E, EnergyCableBlock> = 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() }

View File

@ -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)

View File

@ -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<CablesConfig.E, BlockItem> = 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) }

View File

@ -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"

View File

@ -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
}
}
]
}

View File

@ -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
}
}
]
}

View File

@ -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
}
}
]
}

View File

@ -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
}
}
]
}