Reimplement "open/close" capability state
This commit is contained in:
parent
9fb57259bd
commit
5a6a88e65b
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.booleans.BooleanConsumer
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
|
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
||||||
@ -57,6 +58,7 @@ import ru.dbotthepony.mc.otm.registry.MBlocks
|
|||||||
import ru.dbotthepony.mc.otm.sometimeServer
|
import ru.dbotthepony.mc.otm.sometimeServer
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.function.BooleanSupplier
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
@ -71,7 +73,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
|
|
||||||
private val sidelessCaps = Reference2ObjectOpenHashMap<BlockCapability<*, *>, Any>()
|
private val sidelessCaps = Reference2ObjectOpenHashMap<BlockCapability<*, *>, Any>()
|
||||||
private val sidedCaps = Array(RelativeSide.entries.size) {
|
private val sidedCaps = Array(RelativeSide.entries.size) {
|
||||||
Reference2ObjectOpenHashMap<BlockCapability<*, *>, Any>()
|
Reference2ObjectOpenHashMap<BlockCapability<*, *>, ControllableCapability<*>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val tickList = TickList()
|
protected val tickList = TickList()
|
||||||
@ -121,6 +123,68 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
tickList.tick()
|
tickList.tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CapabilityControl : BooleanSupplier, BooleanConsumer {
|
||||||
|
var isEnabled: Boolean
|
||||||
|
|
||||||
|
fun doDispatchInvalidation()
|
||||||
|
fun dontDispatchInvalidation()
|
||||||
|
|
||||||
|
override fun getAsBoolean(): Boolean {
|
||||||
|
return isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun accept(t: Boolean) {
|
||||||
|
isEnabled = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class ControllableCapability<T : Any>(val capability: T) : CapabilityControl {
|
||||||
|
override var isEnabled: Boolean = true
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
if (dispatchInvalidation) level?.invalidateCapabilities(blockPos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dispatchInvalidation = true
|
||||||
|
|
||||||
|
override fun doDispatchInvalidation() {
|
||||||
|
dispatchInvalidation = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dontDispatchInvalidation() {
|
||||||
|
dispatchInvalidation = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrNull(): T? {
|
||||||
|
return if (isEnabled) capability else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class ControllableCapabilitySet(val capabilities: List<CapabilityControl>) : CapabilityControl {
|
||||||
|
override var isEnabled: Boolean
|
||||||
|
get() = capabilities.all { it.isEnabled }
|
||||||
|
set(value) {
|
||||||
|
capabilities.forEach { it.dontDispatchInvalidation() }
|
||||||
|
|
||||||
|
try {
|
||||||
|
capabilities.forEach { it.isEnabled = value }
|
||||||
|
} finally {
|
||||||
|
capabilities.forEach { it.doDispatchInvalidation() }
|
||||||
|
level?.invalidateCapabilities(blockPos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doDispatchInvalidation() {
|
||||||
|
capabilities.forEach { it.doDispatchInvalidation() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dontDispatchInvalidation() {
|
||||||
|
capabilities.forEach { it.dontDispatchInvalidation() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exposes capability when no side is specified
|
* exposes capability when no side is specified
|
||||||
*/
|
*/
|
||||||
@ -132,24 +196,24 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
level?.invalidateCapabilities(blockPos)
|
level?.invalidateCapabilities(blockPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun <T : Any> exposeSided(side: RelativeSide, capability: BlockCapability<T, *>, value: T) {
|
protected fun <T : Any> exposeSided(side: RelativeSide, capability: BlockCapability<T, *>, value: T): CapabilityControl {
|
||||||
val map = sidedCaps[side.ordinal]
|
val map = sidedCaps[side.ordinal]
|
||||||
check(!map.containsKey(capability)) { "Already has exposed $capability on $side!" }
|
check(!map.containsKey(capability)) { "Already has exposed $capability on $side!" }
|
||||||
MBlocks.ensureCapabilityIsKnown(capability)
|
MBlocks.ensureCapabilityIsKnown(capability)
|
||||||
map[capability] = value
|
val wrapper = ControllableCapability(value)
|
||||||
|
map[capability] = wrapper
|
||||||
setChanged()
|
setChanged()
|
||||||
level?.invalidateCapabilities(blockPos)
|
level?.invalidateCapabilities(blockPos)
|
||||||
|
return wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposes capability unconditionally, on all sides and sideless
|
* Exposes capability unconditionally, on all sides and sideless
|
||||||
*/
|
*/
|
||||||
protected fun <T : Any> exposeGlobally(capability: BlockCapability<T, *>, value: T, predicate: Predicate<RelativeSide> = Predicate { true }) {
|
protected fun <T : Any> exposeGlobally(capability: BlockCapability<T, *>, value: T, predicate: Predicate<RelativeSide> = Predicate { true }): CapabilityControl {
|
||||||
exposeSideless(capability, value)
|
exposeSideless(capability, value)
|
||||||
|
|
||||||
for (side in RelativeSide.entries)
|
return ControllableCapabilitySet(RelativeSide.entries.stream().filter(predicate).map { exposeSided(it, capability, value) }.toList())
|
||||||
if (predicate.test(side))
|
|
||||||
exposeSided(side, capability, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun exposeEnergySideless(value: IMatteryEnergyStorage) {
|
protected fun exposeEnergySideless(value: IMatteryEnergyStorage) {
|
||||||
@ -157,14 +221,22 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
exposeSideless(MatteryCapability.BLOCK_ENERGY, value)
|
exposeSideless(MatteryCapability.BLOCK_ENERGY, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage) {
|
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage): CapabilityControl {
|
||||||
exposeGlobally(Capabilities.EnergyStorage.BLOCK, value)
|
return ControllableCapabilitySet(
|
||||||
exposeGlobally(MatteryCapability.BLOCK_ENERGY, value)
|
listOf(
|
||||||
|
exposeGlobally(Capabilities.EnergyStorage.BLOCK, value),
|
||||||
|
exposeGlobally(MatteryCapability.BLOCK_ENERGY, value)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun exposeEnergySided(side: RelativeSide, value: IMatteryEnergyStorage) {
|
protected fun exposeEnergySided(side: RelativeSide, value: IMatteryEnergyStorage): CapabilityControl {
|
||||||
exposeSided(side, Capabilities.EnergyStorage.BLOCK, value)
|
return ControllableCapabilitySet(
|
||||||
exposeSided(side, MatteryCapability.BLOCK_ENERGY, value)
|
listOf(
|
||||||
|
exposeSided(side, Capabilities.EnergyStorage.BLOCK, value),
|
||||||
|
exposeSided(side, MatteryCapability.BLOCK_ENERGY, value)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun waitForServerLevel(lambda: () -> Unit) {
|
protected fun waitForServerLevel(lambda: () -> Unit) {
|
||||||
@ -177,7 +249,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
|
|
||||||
fun <T : Any> getCapability(cap: BlockCapability<T, *>, side: Direction?): T? {
|
fun <T : Any> getCapability(cap: BlockCapability<T, *>, side: Direction?): T? {
|
||||||
if (side != null) {
|
if (side != null) {
|
||||||
return sidedCaps[blockRotation.dir2Side(side).ordinal][cap] as T?
|
return sidedCaps[blockRotation.dir2Side(side).ordinal][cap]?.getOrNull() as T?
|
||||||
}
|
}
|
||||||
|
|
||||||
return sidelessCaps[cap] as T?
|
return sidelessCaps[cap] as T?
|
||||||
|
@ -147,10 +147,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
inner class Piece(val side: RelativeSide) : IFluidHandler, ITickable {
|
inner class Piece(val side: RelativeSide) : IFluidHandler, ITickable {
|
||||||
private val ticker = tickList.Ticker(this)
|
private val ticker = tickList.Ticker(this)
|
||||||
private val neighbour = CapabilityCache(side, Capabilities.FluidHandler.BLOCK)
|
private val neighbour = CapabilityCache(side, Capabilities.FluidHandler.BLOCK)
|
||||||
|
private val control = exposeSided(side, Capabilities.FluidHandler.BLOCK, this)
|
||||||
init {
|
|
||||||
exposeSided(side, Capabilities.FluidHandler.BLOCK, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateTickerState() {
|
private fun updateTickerState() {
|
||||||
ticker.isEnabled =
|
ticker.isEnabled =
|
||||||
@ -174,7 +171,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
access.accept(value)
|
access.accept(value)
|
||||||
markDirtyFast()
|
markDirtyFast()
|
||||||
updateTickerState()
|
updateTickerState()
|
||||||
level?.invalidateCapabilities(blockPos)
|
control.isEnabled = value != FlowDirection.NONE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -273,6 +270,12 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
return FluidStack.EMPTY
|
return FluidStack.EMPTY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (flow == FlowDirection.NONE) {
|
||||||
|
control.isEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,10 +353,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
|
|
||||||
inner class Piece(val side: RelativeSide, val possibleModes: FlowDirection) : IMatteryEnergyStorage, ITickable {
|
inner class Piece(val side: RelativeSide, val possibleModes: FlowDirection) : IMatteryEnergyStorage, ITickable {
|
||||||
private val neighbour = CapabilityCache(side, Capabilities.EnergyStorage.BLOCK)
|
private val neighbour = CapabilityCache(side, Capabilities.EnergyStorage.BLOCK)
|
||||||
|
private val control = exposeEnergySided(side, this)
|
||||||
init {
|
|
||||||
exposeEnergySided(side, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override var batteryLevel: Decimal by energy::batteryLevel
|
override var batteryLevel: Decimal by energy::batteryLevel
|
||||||
override val maxBatteryLevel: Decimal by energy::maxBatteryLevel
|
override val maxBatteryLevel: Decimal by energy::maxBatteryLevel
|
||||||
@ -453,9 +453,15 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
access.accept(value)
|
access.accept(value)
|
||||||
markDirtyFast()
|
markDirtyFast()
|
||||||
updateTickerState()
|
updateTickerState()
|
||||||
level?.invalidateCapabilities(blockPos)
|
control.isEnabled = value != FlowDirection.NONE
|
||||||
}
|
}
|
||||||
}).delegate
|
}).delegate
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (energyFlow == FlowDirection.NONE) {
|
||||||
|
control.isEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,10 +572,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
|
|
||||||
private val neighbour = CapabilityCache(side, Capabilities.ItemHandler.BLOCK)
|
private val neighbour = CapabilityCache(side, Capabilities.ItemHandler.BLOCK)
|
||||||
private val ticker = tickList.Ticker(this)
|
private val ticker = tickList.Ticker(this)
|
||||||
|
private val control = exposeSided(side, Capabilities.ItemHandler.BLOCK, this)
|
||||||
init {
|
|
||||||
exposeSided(side, Capabilities.ItemHandler.BLOCK, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var innerSlotPull = 0
|
private var innerSlotPull = 0
|
||||||
private var outerSlotPull = 0
|
private var outerSlotPull = 0
|
||||||
@ -601,7 +604,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
ItemHandlerMode.BATTERY -> battery!!
|
ItemHandlerMode.BATTERY -> battery!!
|
||||||
}
|
}
|
||||||
|
|
||||||
level?.invalidateCapabilities(blockPos)
|
control.isEnabled = value != ItemHandlerMode.DISABLED
|
||||||
}
|
}
|
||||||
}).delegate
|
}).delegate
|
||||||
|
|
||||||
@ -705,6 +708,12 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
override fun isItemValid(slot: Int, stack: ItemStack): Boolean {
|
override fun isItemValid(slot: Int, stack: ItemStack): Boolean {
|
||||||
return currentHandler.isItemValid(slot, stack)
|
return currentHandler.isItemValid(slot, stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (mode == ItemHandlerMode.DISABLED) {
|
||||||
|
control.isEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user