Fix opening and closing recipe book not moving exosuit button

This commit is contained in:
DBotThePony 2022-09-09 12:58:38 +07:00
parent ab2862c123
commit 41c8172375
Signed by: DBot
GPG Key ID: DCC23B5715498507
8 changed files with 225 additions and 76 deletions

View File

@ -149,6 +149,9 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onMovementInputUpdate);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onScreenOpen);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::onPostScreenInit);
EVENT_BUS.addListener(EventPriority.LOWEST, ClientEventHandlerKt::onClientTick);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientEventHandlerKt::onClientConnected);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientEventHandlerKt::onClientDisconnected);
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addListener(EventPriority.NORMAL, TooltipsKt::tooltipEvent);

View File

@ -15,6 +15,7 @@ import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.IConditionalTickable
import ru.dbotthepony.mc.otm.core.ITickable
import ru.dbotthepony.mc.otm.core.TickList
import ru.dbotthepony.mc.otm.core.TimerQueue
import java.util.*
private val preServerTick = TickList()
@ -25,72 +26,6 @@ private val postWorldTick = WeakHashMap<Level, TickList>()
private val preServerTickTimers = TimerQueue()
private val postServerTickTimers = TimerQueue()
class TimerQueue {
private var ticks = 0
private var head: Timer? = null
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
val ringAt = ticks + timerTicks
var finished = false
private set
var next: Timer? = null
var prev: Timer? = null
init {
if (head == null) {
head = this
} else {
var next = head
while (next != null) {
if (next.ringAt >= this.ringAt) {
next.prev?.next = this
this.prev = next.prev
next.prev = this
this.next = next
break
} else if (next.next == null) {
next.next = this
this.prev = next
break
} else {
next = next.next
}
}
}
}
fun execute() {
check(!finished) { "Already finished" }
runnable.run()
finished = true
}
}
fun tick() {
ticks++
var head = head
while (head != null) {
if (head.ringAt <= ticks) {
head.execute()
head = head.next
head?.prev = null
this.head = head
} else {
break
}
}
}
fun clear() {
ticks = 0
head = null
}
}
fun addPreTickTimer(inTicks: Int, callback: Runnable): TimerQueue.Timer? {
if (SERVER_IS_DYING) {
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
@ -180,7 +115,7 @@ fun onServerTick(event: ServerTickEvent) {
}
}
fun addPreServerTicker(ticker: IConditionalTickable) {
fun tickServerPre(ticker: IConditionalTickable) {
if (SERVER_IS_DYING) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
@ -189,7 +124,7 @@ fun addPreServerTicker(ticker: IConditionalTickable) {
preServerTick.add(ticker)
}
fun addPostServerTicker(ticker: IConditionalTickable) {
fun tickServer(ticker: IConditionalTickable) {
if (SERVER_IS_DYING) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
@ -198,7 +133,7 @@ fun addPostServerTicker(ticker: IConditionalTickable) {
postServerTick.add(ticker)
}
fun addPreServerTickerOnce(ticker: ITickable) {
fun onceServerPre(ticker: ITickable) {
if (SERVER_IS_DYING) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
@ -207,7 +142,7 @@ fun addPreServerTickerOnce(ticker: ITickable) {
preServerTick.add(ticker)
}
fun addPostServerTickerOnce(ticker: ITickable) {
fun onceServer(ticker: ITickable) {
if (SERVER_IS_DYING) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return

View File

@ -732,7 +732,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
if (mattery.hasExoSuit && !ply.level.gameRules.getBoolean(GameRules.RULE_KEEPINVENTORY)) {
waitingToDie.add(ply to mattery)
addPostServerTickerOnce {
onceServer {
val index = waitingToDie.indexOfFirst { it.first == ply }
if (index != -1) {

View File

@ -2,15 +2,24 @@ package ru.dbotthepony.mc.otm.client
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraftforge.client.event.ClientPlayerNetworkEvent
import net.minecraftforge.client.event.MovementInputUpdateEvent
import net.minecraftforge.client.event.ScreenEvent
import net.minecraftforge.event.TickEvent
import net.minecraftforge.event.TickEvent.ClientTickEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.LargeSquareButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.Panel2Widget
import ru.dbotthepony.mc.otm.core.IConditionalTickable
import ru.dbotthepony.mc.otm.core.ITickable
import ru.dbotthepony.mc.otm.core.TickList
import ru.dbotthepony.mc.otm.core.TimerQueue
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
fun onMovementInputUpdate(event: MovementInputUpdateEvent) {
@ -52,7 +61,7 @@ fun onPostScreenInit(event: ScreenEvent.Init.Post) {
val screen = event.screen as? InventoryScreen ?: return
if (player.hasExoSuit) {
event.addListener(Panel2Widget(LargeSquareButtonPanel(event.screen as InventoryScreen, null,
val widget = Panel2Widget(LargeSquareButtonPanel(screen, null,
x = screen.guiLeft + screen.xSize + 2f,
y = screen.guiTop.toFloat(),
skinElement = Widgets18.RETURN_ARROW_LEFT,
@ -66,7 +75,14 @@ fun onPostScreenInit(event: ScreenEvent.Init.Post) {
minecraft.setScreen(ExoSuitInventoryScreen(player.exoSuitMenu))
InputConstants.grabOrReleaseMouse(minecraft.window.window, 212993, mouseX, mouseY)
}).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") }))
}).also { it.tooltip = TranslatableComponent("otm.gui.exosuit.go_in") })
event.addListener(widget)
whileClient({ minecraft.screen == screen }) {
widget.panel.x = screen.guiLeft + screen.xSize + 2f
widget.panel.y = screen.guiTop.toFloat()
}
}
}
@ -81,3 +97,77 @@ fun onScreenOpen(event: ScreenEvent.Opening) {
event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu)
}
}
private val preTickList = TickList()
private val postTickList = TickList()
private val preTimerList = TimerQueue()
private val postTimerList = TimerQueue()
private var LOGGED_IN = false
private val LOGGER = LogManager.getLogger()
fun onceClient(ticker: ITickable) {
check(isClient) { "Illegal side" }
postTickList.add(ticker, LOGGED_IN, "Not logged in")
}
fun onceClientPre(ticker: ITickable) {
check(isClient) { "Illegal side" }
preTickList.add(ticker, LOGGED_IN, "Not logged in")
}
fun tickClient(ticker: IConditionalTickable) {
check(isClient) { "Illegal side" }
postTickList.add(ticker, LOGGED_IN, "Not logged in")
}
fun tickClientPre(ticker: IConditionalTickable) {
check(isClient) { "Illegal side" }
preTickList.add(ticker, LOGGED_IN, "Not logged in")
}
fun untilClient(ticker: () -> Boolean) {
tickClient(IConditionalTickable.wrap(ticker))
}
fun untilClientPre(ticker: () -> Boolean) {
tickClientPre(IConditionalTickable.wrap(ticker))
}
fun whileClient(condition: () -> Boolean, ticker: () -> Unit) {
tickClient(IConditionalTickable.wrap(condition, ticker))
}
fun whileClientPre(condition: () -> Boolean, ticker: () -> Unit) {
tickClientPre(IConditionalTickable.wrap(condition, ticker))
}
fun onClientTick(event: ClientTickEvent) {
if (event.phase == TickEvent.Phase.START) {
preTimerList.tick()
preTickList.tick()
} else {
postTimerList.tick()
postTickList.tick()
}
}
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()
}

View File

@ -17,7 +17,7 @@ import net.minecraftforge.event.AttachCapabilitiesEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import ru.dbotthepony.mc.otm.core.ITickable
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.addPostServerTickerOnce
import ru.dbotthepony.mc.otm.onceServer
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.core.isPositive
@ -285,7 +285,7 @@ fun attachCapabilities(event: AttachCapabilitiesEvent<BlockEntity>) {
val capability = QIOStorage(event.`object` as TileEntityQIODriveArray)
event.addCapability(QIO_LOCATION, capability)
addPostServerTickerOnce {
onceServer {
if (!event.`object`.isRemoved && event.`object`.level?.isClientSide == false) {
StorageNetworkGraph.discoverFull(event.`object`, capability.cell.storageNode)
}

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.core
import org.apache.logging.log4j.LogManager
import java.util.*
import kotlin.ConcurrentModificationException
@ -28,6 +29,32 @@ class TickList {
}
}
fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) {
if (!condition) {
LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason))
return
}
if (inTicker) {
conditionalValveTime.add(ticker)
} else {
conditional.addFirst(ticker)
}
}
fun add(ticker: ITickable, condition: Boolean, reason: String) {
if (!condition) {
LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason))
return
}
if (inTicker) {
onceValveTime.add(ticker)
} else {
once.addFirst(ticker)
}
}
fun tick() {
if (inTicker) {
throw ConcurrentModificationException("Already ticking")
@ -68,6 +95,10 @@ class TickList {
conditional.clear()
once.clear()
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}
fun interface ITickable {
@ -81,4 +112,27 @@ interface IConditionalTickable : ITickable {
* If it suddenly turns true after being false, result is undefined.
*/
val canTick: Boolean
companion object {
fun wrap(ticker: () -> Boolean): IConditionalTickable {
return object : IConditionalTickable {
override var canTick: Boolean = true
private set
override fun tick() {
canTick = !ticker.invoke()
}
}
}
fun wrap(condition: () -> Boolean, ticker: () -> Unit): IConditionalTickable {
return object : IConditionalTickable {
override val canTick: Boolean get() = condition.invoke()
override fun tick() {
ticker.invoke()
}
}
}
}
}

View File

@ -0,0 +1,67 @@
package ru.dbotthepony.mc.otm.core
class TimerQueue {
private var ticks = 0
private var head: Timer? = null
inner class Timer(val timerTicks: Int, val runnable: Runnable) {
val ringAt = ticks + timerTicks
var finished = false
private set
var next: Timer? = null
var prev: Timer? = null
init {
if (head == null) {
head = this
} else {
var next = head
while (next != null) {
if (next.ringAt >= this.ringAt) {
next.prev?.next = this
this.prev = next.prev
next.prev = this
this.next = next
break
} else if (next.next == null) {
next.next = this
this.prev = next
break
} else {
next = next.next
}
}
}
}
fun execute() {
check(!finished) { "Already finished" }
runnable.run()
finished = true
}
}
fun tick() {
ticks++
var head = head
while (head != null) {
if (head.ringAt <= ticks) {
head.execute()
head = head.next
head?.prev = null
this.head = head
} else {
break
}
}
}
fun clear() {
ticks = 0
head = null
}
}

View File

@ -3,7 +3,7 @@ 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.TimerQueue
import ru.dbotthepony.mc.otm.core.TimerQueue
object TimerQueueTests {
@Test