The fastest code is code which doesn't execute
Side automation no longer ticks if it doesn't automate
This commit is contained in:
parent
c08e262638
commit
20d478cbfb
@ -180,22 +180,6 @@ fun tickServer(ticker: IConditionalTickable) {
|
|||||||
postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping")
|
postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tickUntilServerPre(ticker: () -> Boolean) {
|
|
||||||
preServerTick.until(ticker, SERVER_IS_LIVE, "Server is stopping")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tickUntilServer(ticker: () -> Boolean) {
|
|
||||||
postServerTick.until(ticker, SERVER_IS_LIVE, "Server is stopping")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tickWhileServerPre(condition: () -> Boolean, ticker: () -> Unit) {
|
|
||||||
preServerTick.`while`(condition, ticker, SERVER_IS_LIVE, "Server is stopping")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tickWhileServer(condition: () -> Boolean, ticker: () -> Unit) {
|
|
||||||
postServerTick.`while`(condition, ticker, SERVER_IS_LIVE, "Server is stopping")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Level.once(ticker: ITickable) {
|
fun Level.once(ticker: ITickable) {
|
||||||
if (this.isClientSide) return
|
if (this.isClientSide) return
|
||||||
|
|
||||||
|
@ -129,18 +129,21 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class Piece(val side: RelativeSide) : IFluidHandler, ITickable {
|
inner class Piece(val side: RelativeSide) : IFluidHandler, ITickable {
|
||||||
init {
|
private val ticker = tickList.Ticker(this)
|
||||||
tickList.always(this)
|
private val controller = sides[side]!!.Cap(ForgeCapabilities.FLUID_HANDLER, this)
|
||||||
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.FLUID_HANDLER)
|
||||||
|
|
||||||
|
private fun updateTickerState() {
|
||||||
|
ticker.isEnabled = (automatePull || automatePush) && flow != FlowDirection.NONE && !redstoneControl.isBlockedByRedstone
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
// https://tenor.com/view/simp-metal-gear-liquid-snake-running-gif-16717852
|
// https://tenor.com/view/simp-metal-gear-liquid-snake-running-gif-16717852
|
||||||
savetables.enum(::flow, "fluid_${side}_flow", FlowDirection::valueOf)
|
savetables.enum(::flow, "fluid_${side}_flow", FlowDirection::valueOf)
|
||||||
savetables.bool(::automatePull, "fluid_${side}_pull")
|
savetables.bool(::automatePull, "fluid_${side}_pull")
|
||||||
savetables.bool(::automatePush, "fluid_${side}_push")
|
savetables.bool(::automatePush, "fluid_${side}_push")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val controller = sides[side]!!.Cap(ForgeCapabilities.FLUID_HANDLER, this)
|
|
||||||
private val neighbour by sides[side]!!.track(ForgeCapabilities.FLUID_HANDLER)
|
|
||||||
|
|
||||||
var flow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
|
var flow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
|
||||||
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
|
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
|
||||||
|
|
||||||
@ -154,6 +157,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
controller.close()
|
controller.close()
|
||||||
controller.expose()
|
controller.expose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -162,12 +167,25 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
setChangedLight()
|
setChangedLight()
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// var automatePush by synchronizer.bool().property
|
// var automatePush by synchronizer.bool().property
|
||||||
var automatePush = false
|
var automatePush = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
setChangedLight()
|
setChangedLight()
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
tickList.once {
|
||||||
|
redstoneControl.addListener {
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
@ -324,25 +342,40 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
|
|
||||||
override val canSetBatteryLevel: Boolean by energy::canSetBatteryLevel
|
override val canSetBatteryLevel: Boolean by energy::canSetBatteryLevel
|
||||||
|
|
||||||
|
private val ticker = tickList.Ticker(this)
|
||||||
|
|
||||||
|
private fun updateTickerState() {
|
||||||
|
ticker.isEnabled = (automatePull || automatePush) && energyFlow != FlowDirection.NONE && !redstoneControl.isBlockedByRedstone
|
||||||
|
}
|
||||||
|
|
||||||
// var automatePull by synchronizer.bool().property
|
// var automatePull by synchronizer.bool().property
|
||||||
var automatePull = false
|
var automatePull = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
setChangedLight()
|
setChangedLight()
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// var automatePush by synchronizer.bool().property
|
// var automatePush by synchronizer.bool().property
|
||||||
var automatePush = false
|
var automatePush = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
setChangedLight()
|
setChangedLight()
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
tickList.always(this)
|
|
||||||
|
|
||||||
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
|
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
|
||||||
savetables.bool(::automatePull, "energy_${side}_pull")
|
savetables.bool(::automatePull, "energy_${side}_pull")
|
||||||
savetables.bool(::automatePush, "energy_${side}_push")
|
savetables.bool(::automatePush, "energy_${side}_push")
|
||||||
|
|
||||||
|
tickList.once {
|
||||||
|
redstoneControl.addListener {
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
@ -406,6 +439,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
controller.expose()
|
controller.expose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -533,11 +568,26 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
|
|
||||||
inner class Piece(val side: RelativeSide) : IItemHandler, ITickable {
|
inner class Piece(val side: RelativeSide) : IItemHandler, ITickable {
|
||||||
private var currentHandler: IItemHandler = EmptyItemHandler
|
private var currentHandler: IItemHandler = EmptyItemHandler
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
updateTickerState()
|
||||||
|
}
|
||||||
|
|
||||||
private val capController = sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
private val capController = sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
||||||
private val neighbour by sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
||||||
|
private val ticker = tickList.Ticker(this)
|
||||||
|
|
||||||
|
private var innerSlotPull = 0
|
||||||
|
private var outerSlotPull = 0
|
||||||
|
|
||||||
|
private var innerSlotPush = 0
|
||||||
|
private var outerSlotPush = 0
|
||||||
|
|
||||||
|
private fun updateTickerState() {
|
||||||
|
ticker.isEnabled = (automatePull || automatePush) && mode != ItemHandlerMode.DISABLED && !redstoneControl.isBlockedByRedstone && currentHandler.slots != 0
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
tickList.always(this)
|
|
||||||
capController.close()
|
capController.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,28 +615,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/*var automatePull by synchronizer.bool(setter = { value, access, _ ->
|
|
||||||
if (access.readBoolean() != value) {
|
|
||||||
access.write(value)
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
innerSlotPush = 0
|
|
||||||
outerSlotPush = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).property
|
|
||||||
|
|
||||||
var automatePush by synchronizer.bool(setter = { value, access, _ ->
|
|
||||||
if (access.readBoolean() != value) {
|
|
||||||
access.write(value)
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
innerSlotPush = 0
|
|
||||||
outerSlotPush = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).property*/
|
|
||||||
|
|
||||||
var automatePull = false
|
var automatePull = false
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field != value) {
|
if (field != value) {
|
||||||
@ -597,6 +625,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
innerSlotPush = 0
|
innerSlotPush = 0
|
||||||
outerSlotPush = 0
|
outerSlotPush = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,6 +640,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
innerSlotPush = 0
|
innerSlotPush = 0
|
||||||
outerSlotPush = 0
|
outerSlotPush = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,13 +649,15 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
||||||
savetables.bool(::automatePush, "itemhandler_${side}_automatePush")
|
savetables.bool(::automatePush, "itemhandler_${side}_automatePush")
|
||||||
savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf)
|
savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf)
|
||||||
|
|
||||||
|
tickList.once {
|
||||||
|
redstoneControl.addListener {
|
||||||
|
updateTickerState()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var innerSlotPull = 0
|
updateTickerState()
|
||||||
private var outerSlotPull = 0
|
}
|
||||||
|
}
|
||||||
private var innerSlotPush = 0
|
|
||||||
private var outerSlotPush = 0
|
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
if (mode == ItemHandlerMode.DISABLED || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone || currentHandler.slots == 0)
|
if (mode == ItemHandlerMode.DISABLED || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone || currentHandler.slots == 0)
|
||||||
|
@ -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 net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||||
@ -13,9 +14,14 @@ interface IRedstoneControlled {
|
|||||||
abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?> {
|
abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?> {
|
||||||
abstract var redstoneSetting: RedstoneSetting
|
abstract var redstoneSetting: RedstoneSetting
|
||||||
abstract var redstoneSignal: Int
|
abstract var redstoneSignal: Int
|
||||||
|
protected val listeners = ArrayList<BooleanConsumer>()
|
||||||
|
|
||||||
val isBlockedByRedstone: Boolean get() = !redstoneSetting.test(redstoneSignal)
|
val isBlockedByRedstone: Boolean get() = !redstoneSetting.test(redstoneSignal)
|
||||||
|
|
||||||
|
fun addListener(callback: BooleanConsumer) {
|
||||||
|
listeners.add(callback)
|
||||||
|
}
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
override fun serializeNBT(): CompoundTag {
|
||||||
return CompoundTag().also {
|
return CompoundTag().also {
|
||||||
it[SETTING_KEY] = redstoneSetting.toString()
|
it[SETTING_KEY] = redstoneSetting.toString()
|
||||||
@ -47,7 +53,11 @@ class RedstoneControl(private val valueChanges: (new: Boolean, old: Boolean) ->
|
|||||||
val old = isBlockedByRedstone
|
val old = isBlockedByRedstone
|
||||||
field = level
|
field = level
|
||||||
val state = isBlockedByRedstone
|
val state = isBlockedByRedstone
|
||||||
|
|
||||||
|
if (state != old) {
|
||||||
valueChanges.invoke(state, old)
|
valueChanges.invoke(state, old)
|
||||||
|
listeners.forEach { it.accept(state) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override var redstoneSignal: Int = 0
|
override var redstoneSignal: Int = 0
|
||||||
@ -56,7 +66,11 @@ class RedstoneControl(private val valueChanges: (new: Boolean, old: Boolean) ->
|
|||||||
val old = isBlockedByRedstone
|
val old = isBlockedByRedstone
|
||||||
field = setting
|
field = setting
|
||||||
val state = isBlockedByRedstone
|
val state = isBlockedByRedstone
|
||||||
|
|
||||||
|
if (state != old) {
|
||||||
valueChanges.invoke(state, old)
|
valueChanges.invoke(state, old)
|
||||||
|
listeners.forEach { it.accept(state) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +86,11 @@ class SynchronizedRedstoneControl(
|
|||||||
val old = isBlockedByRedstone
|
val old = isBlockedByRedstone
|
||||||
access.write(value)
|
access.write(value)
|
||||||
val state = isBlockedByRedstone
|
val state = isBlockedByRedstone
|
||||||
|
|
||||||
|
if (state != old) {
|
||||||
valueChanges.invoke(state, old)
|
valueChanges.invoke(state, old)
|
||||||
|
listeners.forEach { it.accept(state) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -84,7 +102,11 @@ class SynchronizedRedstoneControl(
|
|||||||
val old = isBlockedByRedstone
|
val old = isBlockedByRedstone
|
||||||
access.write(value)
|
access.write(value)
|
||||||
val state = isBlockedByRedstone
|
val state = isBlockedByRedstone
|
||||||
|
|
||||||
|
if (state != old) {
|
||||||
valueChanges.invoke(state, old)
|
valueChanges.invoke(state, old)
|
||||||
|
listeners.forEach { it.accept(state) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).property
|
}).property
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableSet
|
|||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectComparators
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.NbtAccounter
|
import net.minecraft.nbt.NbtAccounter
|
||||||
@ -417,3 +418,12 @@ fun <E> List<E>.searchInsertionIndex(element: E, comparator: Comparator<E>, from
|
|||||||
fun <E> MutableList<E>.addSorted(element: E, comparator: Comparator<E>) {
|
fun <E> MutableList<E>.addSorted(element: E, comparator: Comparator<E>) {
|
||||||
add(searchInsertionIndex(element, comparator), element)
|
add(searchInsertionIndex(element, comparator), element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts [element] into [MutableList] at index determined by comparing values themselves
|
||||||
|
*
|
||||||
|
* If [MutableList] is not sorted, result of this function is undefined
|
||||||
|
*/
|
||||||
|
fun <E : Comparable<E>> MutableList<E>.addSorted(element: E) {
|
||||||
|
add(searchInsertionIndex(element, ObjectComparators.NATURAL_COMPARATOR), element)
|
||||||
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.util
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
|
import ru.dbotthepony.mc.otm.core.addSorted
|
||||||
|
|
||||||
class TickList : ITickable {
|
class TickList : ITickable {
|
||||||
private val conditional = ArrayDeque<IConditionalTickable>()
|
private val conditional = ArrayDeque<IConditionalTickable>()
|
||||||
private val conditionalValveTime = ArrayList<IConditionalTickable>()
|
private val conditionalQueued = ArrayList<IConditionalTickable>()
|
||||||
|
|
||||||
private val once = ArrayDeque<ITickable>()
|
private val once = ArrayDeque<ITickable>()
|
||||||
private val onceValveTime = ArrayList<ITickable>()
|
private val onceQueued = ArrayList<ITickable>()
|
||||||
|
|
||||||
private val always = ArrayList<ITickable>()
|
private val always = ArrayList<ITickable>()
|
||||||
private val alwaysValveTime = ArrayList<ITickable>()
|
private val alwaysQueued = ArrayList<ITickable>()
|
||||||
|
private val toRemoveFromAlways = ArrayList<ITickable>()
|
||||||
|
|
||||||
private val timers = ArrayDeque<Timer>()
|
private val timers = ArrayDeque<Timer>()
|
||||||
|
|
||||||
@ -19,45 +21,18 @@ class TickList : ITickable {
|
|||||||
var ticks = 0
|
var ticks = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private var nothingToDo = true
|
inner class Timer(val timerTicks: Int, val runnable: Runnable) : Comparable<Timer> {
|
||||||
|
|
||||||
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
|
|
||||||
val ringAt = ticks + timerTicks
|
val ringAt = ticks + timerTicks
|
||||||
|
|
||||||
var finished = false
|
var finished = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
nothingToDo = false
|
timers.addSorted(this)
|
||||||
|
|
||||||
if (timers.isEmpty()) {
|
|
||||||
timers.addLast(this)
|
|
||||||
} else {
|
|
||||||
val iterator = timers.listIterator()
|
|
||||||
var hit = false
|
|
||||||
|
|
||||||
for (value in iterator) {
|
|
||||||
if (value.ringAt == ringAt) {
|
|
||||||
hit = true
|
|
||||||
iterator.add(this)
|
|
||||||
break
|
|
||||||
} else if (value.ringAt > ringAt) {
|
|
||||||
if (iterator.hasPrevious()) {
|
|
||||||
iterator.previous()
|
|
||||||
iterator.add(this)
|
|
||||||
} else {
|
|
||||||
timers.addFirst(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hit = true
|
override fun compareTo(other: Timer): Int {
|
||||||
break
|
return ringAt.compareTo(other.ringAt)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hit) {
|
|
||||||
timers.addLast(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun execute() {
|
fun execute() {
|
||||||
@ -67,13 +42,49 @@ class TickList : ITickable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(ticker: IConditionalTickable) {
|
inner class Ticker(parent: ITickable) : ITickable by parent {
|
||||||
if (inTicker) {
|
init {
|
||||||
conditionalValveTime.add(ticker)
|
add(this, always, alwaysQueued)
|
||||||
} else {
|
|
||||||
conditional.addFirst(ticker)
|
|
||||||
nothingToDo = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isEnabled = true
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
add(this, always, alwaysQueued)
|
||||||
|
} else {
|
||||||
|
alwaysQueued.remove(this)
|
||||||
|
|
||||||
|
if (inTicker) {
|
||||||
|
toRemoveFromAlways.add(this)
|
||||||
|
} else {
|
||||||
|
always.remove(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disable() {
|
||||||
|
isEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enable() {
|
||||||
|
isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : Any> add(value: T, regular: MutableList<T>, queue: MutableList<T>) {
|
||||||
|
if (inTicker) {
|
||||||
|
queue.add(value)
|
||||||
|
} else {
|
||||||
|
regular.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(ticker: IConditionalTickable) {
|
||||||
|
add(ticker, conditional, conditionalQueued)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) {
|
fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) {
|
||||||
@ -86,12 +97,7 @@ class TickList : ITickable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun once(ticker: ITickable) {
|
fun once(ticker: ITickable) {
|
||||||
if (inTicker) {
|
add(ticker, once, onceQueued)
|
||||||
onceValveTime.add(ticker)
|
|
||||||
} else {
|
|
||||||
once.addFirst(ticker)
|
|
||||||
nothingToDo = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun once(ticker: ITickable, condition: Boolean, reason: String) {
|
fun once(ticker: ITickable, condition: Boolean, reason: String) {
|
||||||
@ -104,12 +110,7 @@ class TickList : ITickable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun always(ticker: ITickable) {
|
fun always(ticker: ITickable) {
|
||||||
if (inTicker) {
|
add(ticker, always, alwaysQueued)
|
||||||
alwaysValveTime.add(ticker)
|
|
||||||
} else {
|
|
||||||
always.add(ticker)
|
|
||||||
nothingToDo = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun timer(timerTicks: Int, action: Runnable, condition: Boolean, reason: String): Timer? {
|
fun timer(timerTicks: Int, action: Runnable, condition: Boolean, reason: String): Timer? {
|
||||||
@ -125,23 +126,7 @@ class TickList : ITickable {
|
|||||||
return Timer(timerTicks, action)
|
return Timer(timerTicks, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun until(ticker: () -> Boolean) = add(IConditionalTickable.wrap(ticker))
|
|
||||||
fun `while`(tickerCondition: () -> Boolean, ticker: () -> Unit) = add(
|
|
||||||
IConditionalTickable.wrap(
|
|
||||||
tickerCondition,
|
|
||||||
ticker
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
fun until(ticker: () -> Boolean, condition: Boolean, reason: String) = add(IConditionalTickable.wrap(ticker), condition, reason)
|
|
||||||
fun `while`(tickerCondition: () -> Boolean, ticker: () -> Unit, condition: Boolean, reason: String) = add(
|
|
||||||
IConditionalTickable.wrap(tickerCondition, ticker), condition, reason)
|
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
if (nothingToDo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inTicker) {
|
if (inTicker) {
|
||||||
throw ConcurrentModificationException("Already ticking")
|
throw ConcurrentModificationException("Already ticking")
|
||||||
}
|
}
|
||||||
@ -150,23 +135,12 @@ class TickList : ITickable {
|
|||||||
inTicker = true
|
inTicker = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var nothingToDo = true
|
|
||||||
val conditional = conditional
|
|
||||||
val once = once
|
|
||||||
val always = always
|
|
||||||
val alwaysValveTime = alwaysValveTime
|
|
||||||
val conditionalValveTime = conditionalValveTime
|
|
||||||
val onceValveTime = onceValveTime
|
|
||||||
val timers = timers
|
|
||||||
|
|
||||||
if (conditional.isNotEmpty()) {
|
if (conditional.isNotEmpty()) {
|
||||||
val iterator = conditional.iterator()
|
val iterator = conditional.iterator()
|
||||||
|
|
||||||
for (ticker in iterator) {
|
for (ticker in iterator) {
|
||||||
if (!ticker.tick()) {
|
if (!ticker.tick()) {
|
||||||
iterator.remove()
|
iterator.remove()
|
||||||
} else {
|
|
||||||
nothingToDo = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,40 +153,40 @@ class TickList : ITickable {
|
|||||||
once.clear()
|
once.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toRemoveFromAlways.isNotEmpty()) {
|
||||||
|
for (v in toRemoveFromAlways) always.remove(v)
|
||||||
|
toRemoveFromAlways.clear()
|
||||||
|
}
|
||||||
|
|
||||||
if (always.isNotEmpty()) {
|
if (always.isNotEmpty()) {
|
||||||
for (ticker in always) {
|
for (ticker in always) {
|
||||||
ticker.tick()
|
ticker.tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
nothingToDo = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alwaysValveTime.isNotEmpty()) {
|
if (alwaysQueued.isNotEmpty()) {
|
||||||
always.addAll(alwaysValveTime)
|
always.ensureCapacity(always.size + alwaysQueued.size)
|
||||||
alwaysValveTime.clear()
|
for (v in alwaysQueued) always.add(v) // avoid toArray()
|
||||||
nothingToDo = false
|
alwaysQueued.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conditionalValveTime.isNotEmpty()) {
|
if (conditionalQueued.isNotEmpty()) {
|
||||||
for (ticker in conditionalValveTime) {
|
for (ticker in conditionalQueued) {
|
||||||
conditional.addFirst(ticker)
|
conditional.addFirst(ticker)
|
||||||
}
|
}
|
||||||
|
|
||||||
conditionalValveTime.clear()
|
conditionalQueued.clear()
|
||||||
nothingToDo = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onceValveTime.isNotEmpty()) {
|
if (onceQueued.isNotEmpty()) {
|
||||||
for (ticker in onceValveTime) {
|
for (ticker in onceQueued) {
|
||||||
once.addFirst(ticker)
|
once.addFirst(ticker)
|
||||||
}
|
}
|
||||||
|
|
||||||
onceValveTime.clear()
|
onceQueued.clear()
|
||||||
nothingToDo = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (timers.isNotEmpty()) {
|
while (timers.isNotEmpty()) {
|
||||||
nothingToDo = false
|
|
||||||
val head = timers.first()
|
val head = timers.first()
|
||||||
|
|
||||||
if (head.ringAt <= ticks) {
|
if (head.ringAt <= ticks) {
|
||||||
@ -222,8 +196,6 @@ class TickList : ITickable {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.nothingToDo = nothingToDo
|
|
||||||
} finally {
|
} finally {
|
||||||
inTicker = false
|
inTicker = false
|
||||||
}
|
}
|
||||||
@ -233,13 +205,13 @@ class TickList : ITickable {
|
|||||||
if (inTicker) throw ConcurrentModificationException()
|
if (inTicker) throw ConcurrentModificationException()
|
||||||
|
|
||||||
conditional.clear()
|
conditional.clear()
|
||||||
conditionalValveTime.clear()
|
conditionalQueued.clear()
|
||||||
|
|
||||||
once.clear()
|
once.clear()
|
||||||
onceValveTime.clear()
|
onceQueued.clear()
|
||||||
|
|
||||||
always.clear()
|
always.clear()
|
||||||
alwaysValveTime.clear()
|
alwaysQueued.clear()
|
||||||
|
|
||||||
timers.clear()
|
timers.clear()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user