Merge TimerQueue into TickList
This commit is contained in:
parent
a289d9d1c1
commit
8511c2c01b
@ -19,7 +19,6 @@ import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
|
||||
import ru.dbotthepony.mc.otm.core.util.ITickable
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
import ru.dbotthepony.mc.otm.core.util.TimerQueue
|
||||
import java.util.*
|
||||
|
||||
private val preServerTick = TickList()
|
||||
@ -27,25 +26,22 @@ private val postServerTick = TickList()
|
||||
private val preWorldTick = WeakHashMap<Level, TickList>()
|
||||
private val postWorldTick = WeakHashMap<Level, TickList>()
|
||||
|
||||
private val preServerTickTimers = TimerQueue()
|
||||
private val postServerTickTimers = TimerQueue()
|
||||
|
||||
fun onceServerPre(inTicks: Int, callback: Runnable): TimerQueue.Timer? {
|
||||
fun onceServerPre(inTicks: Int, callback: Runnable): TickList.Timer? {
|
||||
if (!SERVER_IS_LIVE) {
|
||||
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
||||
return null
|
||||
}
|
||||
|
||||
return preServerTickTimers.Timer(inTicks, callback)
|
||||
return preServerTick.Timer(inTicks, callback)
|
||||
}
|
||||
|
||||
fun onceServer(inTicks: Int, callback: Runnable): TimerQueue.Timer? {
|
||||
fun onceServer(inTicks: Int, callback: Runnable): TickList.Timer? {
|
||||
if (!SERVER_IS_LIVE) {
|
||||
LOGGER.error("Refusing to add ticker $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
||||
return null
|
||||
}
|
||||
|
||||
return postServerTickTimers.Timer(inTicks, callback)
|
||||
return postServerTick.Timer(inTicks, callback)
|
||||
}
|
||||
|
||||
private var _server: MinecraftServer? = null
|
||||
@ -146,10 +142,8 @@ private val LOGGER = LogManager.getLogger()
|
||||
|
||||
fun onServerTick(event: ServerTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
preServerTickTimers.tick()
|
||||
preServerTick.tick()
|
||||
} else {
|
||||
postServerTickTimers.tick()
|
||||
postServerTick.tick()
|
||||
}
|
||||
}
|
||||
@ -259,8 +253,6 @@ fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) {
|
||||
}
|
||||
|
||||
private fun clear() {
|
||||
preServerTickTimers.clear()
|
||||
postServerTickTimers.clear()
|
||||
preServerTick.clear()
|
||||
postServerTick.clear()
|
||||
preWorldTick.clear()
|
||||
|
@ -5,13 +5,11 @@ import net.minecraftforge.event.TickEvent
|
||||
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
|
||||
import ru.dbotthepony.mc.otm.core.util.ITickable
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
import ru.dbotthepony.mc.otm.core.util.TimerQueue
|
||||
import ru.dbotthepony.mc.otm.isClient
|
||||
|
||||
private val preTickList = TickList()
|
||||
private val postTickList = TickList()
|
||||
private val preTimerList = TimerQueue()
|
||||
private val postTimerList = TimerQueue()
|
||||
|
||||
var LOGGED_IN = false
|
||||
private set
|
||||
|
||||
@ -27,12 +25,12 @@ fun onceClientPre(ticker: ITickable) {
|
||||
|
||||
fun onceClient(inTicks: Int, ticker: Runnable) {
|
||||
check(isClient) { "Illegal side" }
|
||||
postTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||
postTickList.timer(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||
}
|
||||
|
||||
fun onceClientPre(inTicks: Int, ticker: Runnable) {
|
||||
check(isClient) { "Illegal side" }
|
||||
preTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||
preTickList.timer(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||
}
|
||||
|
||||
fun tickClient(ticker: IConditionalTickable) {
|
||||
@ -63,10 +61,8 @@ fun tickWhileClientPre(condition: () -> Boolean, ticker: () -> Unit) {
|
||||
|
||||
fun onClientTick(event: TickEvent.ClientTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START) {
|
||||
preTimerList.tick()
|
||||
preTickList.tick()
|
||||
} else {
|
||||
postTimerList.tick()
|
||||
postTickList.tick()
|
||||
}
|
||||
}
|
||||
@ -74,17 +70,13 @@ fun onClientTick(event: TickEvent.ClientTickEvent) {
|
||||
fun onClientDisconnected(event: ClientPlayerNetworkEvent.LoggingOut) {
|
||||
LOGGED_IN = false
|
||||
|
||||
preTimerList.clear()
|
||||
preTickList.clear()
|
||||
postTimerList.clear()
|
||||
postTickList.clear()
|
||||
}
|
||||
|
||||
fun onClientConnected(event: ClientPlayerNetworkEvent.LoggingIn) {
|
||||
LOGGED_IN = true
|
||||
|
||||
preTimerList.clear()
|
||||
preTickList.clear()
|
||||
postTimerList.clear()
|
||||
postTickList.clear()
|
||||
}
|
||||
|
@ -2,16 +2,66 @@ package ru.dbotthepony.mc.otm.core.util
|
||||
|
||||
import org.apache.logging.log4j.LogManager
|
||||
|
||||
class TickList {
|
||||
class TickList : ITickable {
|
||||
private val conditional = ArrayDeque<IConditionalTickable>()
|
||||
private val conditionalValveTime = ArrayList<IConditionalTickable>()
|
||||
|
||||
private val once = ArrayDeque<ITickable>()
|
||||
private val onceValveTime = ArrayList<ITickable>()
|
||||
|
||||
private val always = ArrayList<ITickable>()
|
||||
private val alwaysValveTime = ArrayList<ITickable>()
|
||||
|
||||
private val conditionalValveTime = ArrayList<IConditionalTickable>()
|
||||
private val onceValveTime = ArrayList<ITickable>()
|
||||
private val timers = ArrayDeque<Timer>()
|
||||
|
||||
private var inTicker = false
|
||||
var inTicker = false
|
||||
private set
|
||||
var ticks = 0
|
||||
private set
|
||||
|
||||
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
|
||||
val ringAt = ticks + timerTicks
|
||||
|
||||
var finished = false
|
||||
private set
|
||||
|
||||
init {
|
||||
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
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
timers.addLast(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun execute() {
|
||||
if (finished) return
|
||||
runnable.run()
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
fun add(ticker: IConditionalTickable) {
|
||||
if (inTicker) {
|
||||
@ -21,22 +71,6 @@ class TickList {
|
||||
}
|
||||
}
|
||||
|
||||
fun once(ticker: ITickable) {
|
||||
if (inTicker) {
|
||||
onceValveTime.add(ticker)
|
||||
} else {
|
||||
once.addFirst(ticker)
|
||||
}
|
||||
}
|
||||
|
||||
fun always(ticker: ITickable) {
|
||||
if (inTicker) {
|
||||
alwaysValveTime.add(ticker)
|
||||
} else {
|
||||
always.add(ticker)
|
||||
}
|
||||
}
|
||||
|
||||
fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) {
|
||||
if (!condition) {
|
||||
LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason))
|
||||
@ -46,6 +80,14 @@ class TickList {
|
||||
return add(ticker)
|
||||
}
|
||||
|
||||
fun once(ticker: ITickable) {
|
||||
if (inTicker) {
|
||||
onceValveTime.add(ticker)
|
||||
} else {
|
||||
once.addFirst(ticker)
|
||||
}
|
||||
}
|
||||
|
||||
fun once(ticker: ITickable, condition: Boolean, reason: String) {
|
||||
if (!condition) {
|
||||
LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason))
|
||||
@ -55,6 +97,27 @@ class TickList {
|
||||
return once(ticker)
|
||||
}
|
||||
|
||||
fun always(ticker: ITickable) {
|
||||
if (inTicker) {
|
||||
alwaysValveTime.add(ticker)
|
||||
} else {
|
||||
always.add(ticker)
|
||||
}
|
||||
}
|
||||
|
||||
fun timer(timerTicks: Int, action: Runnable, condition: Boolean, reason: String): Timer? {
|
||||
if (!condition) {
|
||||
LOGGER.error("Refusing to add timer $action in $timerTicks ticks because we $reason", IllegalStateException(reason))
|
||||
return null
|
||||
}
|
||||
|
||||
return Timer(timerTicks, action)
|
||||
}
|
||||
|
||||
fun timer(timerTicks: Int, action: Runnable): Timer {
|
||||
return Timer(timerTicks, action)
|
||||
}
|
||||
|
||||
fun until(ticker: () -> Boolean) = add(IConditionalTickable.wrap(ticker))
|
||||
fun `while`(tickerCondition: () -> Boolean, ticker: () -> Unit) = add(
|
||||
IConditionalTickable.wrap(
|
||||
@ -67,66 +130,90 @@ class TickList {
|
||||
fun `while`(tickerCondition: () -> Boolean, ticker: () -> Unit, condition: Boolean, reason: String) = add(
|
||||
IConditionalTickable.wrap(tickerCondition, ticker), condition, reason)
|
||||
|
||||
fun tick() {
|
||||
override fun tick() {
|
||||
if (inTicker) {
|
||||
throw ConcurrentModificationException("Already ticking")
|
||||
}
|
||||
|
||||
ticks++
|
||||
inTicker = true
|
||||
|
||||
if (conditional.isNotEmpty()) {
|
||||
val iterator = conditional.iterator()
|
||||
try {
|
||||
if (conditional.isNotEmpty()) {
|
||||
val iterator = conditional.iterator()
|
||||
|
||||
for (ticker in iterator) {
|
||||
if (!ticker.canTick) {
|
||||
iterator.remove()
|
||||
} else {
|
||||
for (ticker in iterator) {
|
||||
if (!ticker.canTick) {
|
||||
iterator.remove()
|
||||
} else {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (once.isNotEmpty()) {
|
||||
for (ticker in once) {
|
||||
ticker.tick()
|
||||
}
|
||||
|
||||
once.clear()
|
||||
}
|
||||
|
||||
if (always.isNotEmpty()) {
|
||||
for (ticker in always) {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (once.isNotEmpty()) {
|
||||
for (ticker in once) {
|
||||
ticker.tick()
|
||||
if (alwaysValveTime.isNotEmpty()) {
|
||||
always.addAll(alwaysValveTime)
|
||||
alwaysValveTime.clear()
|
||||
}
|
||||
|
||||
once.clear()
|
||||
}
|
||||
if (conditionalValveTime.isNotEmpty()) {
|
||||
for (ticker in conditionalValveTime) {
|
||||
conditional.addFirst(ticker)
|
||||
}
|
||||
|
||||
if (always.isNotEmpty()) {
|
||||
for (ticker in always) {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
|
||||
if (alwaysValveTime.isNotEmpty()) {
|
||||
always.addAll(alwaysValveTime)
|
||||
alwaysValveTime.clear()
|
||||
}
|
||||
|
||||
if (conditionalValveTime.isNotEmpty()) {
|
||||
for (ticker in conditionalValveTime) {
|
||||
conditional.addFirst(ticker)
|
||||
conditionalValveTime.clear()
|
||||
}
|
||||
|
||||
conditionalValveTime.clear()
|
||||
}
|
||||
if (onceValveTime.isNotEmpty()) {
|
||||
for (ticker in onceValveTime) {
|
||||
once.addFirst(ticker)
|
||||
}
|
||||
|
||||
if (onceValveTime.isNotEmpty()) {
|
||||
for (ticker in onceValveTime) {
|
||||
once.addFirst(ticker)
|
||||
onceValveTime.clear()
|
||||
}
|
||||
|
||||
onceValveTime.clear()
|
||||
}
|
||||
while (timers.isNotEmpty()) {
|
||||
val head = timers.first()
|
||||
|
||||
inTicker = false
|
||||
if (head.ringAt <= ticks) {
|
||||
head.execute()
|
||||
timers.removeFirst()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
inTicker = false
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
if (inTicker) throw ConcurrentModificationException()
|
||||
|
||||
conditional.clear()
|
||||
conditionalValveTime.clear()
|
||||
|
||||
once.clear()
|
||||
onceValveTime.clear()
|
||||
|
||||
always.clear()
|
||||
alwaysValveTime.clear()
|
||||
|
||||
timers.clear()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -1,85 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.core.util
|
||||
|
||||
import org.apache.logging.log4j.LogManager
|
||||
|
||||
class TimerQueue {
|
||||
private var ticks = 0
|
||||
private val list = ArrayDeque<Timer>()
|
||||
|
||||
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
|
||||
val ringAt = ticks + timerTicks
|
||||
|
||||
var finished = false
|
||||
private set
|
||||
|
||||
init {
|
||||
if (list.isEmpty()) {
|
||||
list.addLast(this)
|
||||
} else {
|
||||
val iterator = list.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 {
|
||||
list.addFirst(this)
|
||||
}
|
||||
|
||||
hit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
list.addLast(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun execute() {
|
||||
if (finished) return
|
||||
runnable.run()
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
fun add(timerTicks: Int, ticker: Runnable, condition: Boolean, reason: String): Timer? {
|
||||
if (!condition) {
|
||||
LOGGER.error("Refusing to add timer $ticker in $timerTicks ticks because we $reason", IllegalStateException(reason))
|
||||
return null
|
||||
}
|
||||
|
||||
return Timer(timerTicks, ticker)
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
ticks++
|
||||
|
||||
while (list.isNotEmpty()) {
|
||||
val head = list.first()
|
||||
|
||||
if (head.ringAt <= ticks) {
|
||||
head.execute()
|
||||
list.removeFirst()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
ticks = 0
|
||||
list.clear()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
}
|
||||
}
|
@ -3,13 +3,13 @@ package ru.dbotthepony.mc.otm.tests
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import ru.dbotthepony.mc.otm.core.util.TimerQueue
|
||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||
|
||||
object TimerQueueTests {
|
||||
@Test
|
||||
@DisplayName("TimerQueue test")
|
||||
fun test() {
|
||||
val queue = TimerQueue()
|
||||
val queue = TickList()
|
||||
|
||||
var state = 0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user