Energy counter limit input using panel instead of widget

This commit is contained in:
DBotThePony 2024-10-08 12:10:46 +07:00
parent 064fbd0f36
commit b80da0e214
Signed by: DBot
GPG Key ID: DCC23B5715498507
6 changed files with 106 additions and 17 deletions

View File

@ -13,6 +13,7 @@ import net.minecraft.client.gui.navigation.ScreenRectangle
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.renderer.Rect2i import net.minecraft.client.renderer.Rect2i
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.util.RandomSource
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.SystemTime import ru.dbotthepony.mc.otm.SystemTime
import ru.dbotthepony.mc.otm.client.CursorType import ru.dbotthepony.mc.otm.client.CursorType
@ -134,6 +135,14 @@ open class EditablePanel<out S : Screen>(
} }
} }
val random: RandomSource by lazy {
if (screen is MatteryScreen<*>) {
screen.menu.random
} else {
RandomSource.create()
}
}
/** /**
* Bigger values means lesser priority while docking, rendering and processing inputs. * Bigger values means lesser priority while docking, rendering and processing inputs.
*/ */

View File

@ -200,6 +200,10 @@ open class TextInputPanel<out S : Screen>(
snapshotTimer = null snapshotTimer = null
redo.clear() redo.clear()
} }
if (!isFocusedThis && snapshotTimer == null) {
idleCallback?.invoke()
}
} }
private fun pushbackSnapshot() { private fun pushbackSnapshot() {
@ -1062,6 +1066,8 @@ open class TextInputPanel<out S : Screen>(
return characterFilter?.acceptsCharacter(codepoint, mods, index) ?: true return characterFilter?.acceptsCharacter(codepoint, mods, index) ?: true
} }
protected var rejectCharacterTimer: Long? = null
override fun charTypedInternal(codepoint: Char, mods: Int): Boolean { override fun charTypedInternal(codepoint: Char, mods: Int): Boolean {
if (!isActive) { if (!isActive) {
killFocus() killFocus()
@ -1087,6 +1093,7 @@ open class TextInputPanel<out S : Screen>(
if (!acceptsCharacter(codepoint, mods, index)) { if (!acceptsCharacter(codepoint, mods, index)) {
playGuiClickSound() playGuiClickSound()
rejectCharacterTimer = milliTime + SHAKE_MILLIS
return true return true
} }
@ -1145,6 +1152,19 @@ open class TextInputPanel<out S : Screen>(
val selectedLine = this[cursorLine] val selectedLine = this[cursorLine]
val shakeX: Float
val shakeY: Float
if (rejectCharacterTimer != null && rejectCharacterTimer!! > milliTime) {
val strength = (rejectCharacterTimer!! - milliTime).toFloat() / SHAKE_MILLIS.toFloat()
shakeX = (random.nextFloat() - 0.5f) * strength
shakeY = (random.nextFloat() - 0.5f) * strength
} else {
rejectCharacterTimer = null
shakeX = 0f
shakeY = 0f
}
if (selectedLine != null) { if (selectedLine != null) {
val w = width(selectedLine, end = cursorRow) - scrollPixels val w = width(selectedLine, end = cursorRow) - scrollPixels
@ -1162,14 +1182,14 @@ open class TextInputPanel<out S : Screen>(
stack.pushPose() stack.pushPose()
stack.translate(-scrollPixels, 0f, 0f) stack.translate(-scrollPixels, 0f, 0f)
var y = topPadding var y = topPadding + shakeY
if (lines.isEmpty() || lines.size == 1 && lines[0] == "") { if (lines.isEmpty() || lines.size == 1 && lines[0] == "") {
graphics.draw( graphics.draw(
font = font, font = font,
text = placeholder, text = placeholder,
gravity = RenderGravity.TOP_LEFT, gravity = RenderGravity.TOP_LEFT,
x = dockPadding.left, x = dockPadding.left + shakeX,
y = y, y = y,
color = placeholderColor color = placeholderColor
) )
@ -1182,7 +1202,7 @@ open class TextInputPanel<out S : Screen>(
graphics.draw( graphics.draw(
text = line, text = line,
gravity = RenderGravity.TOP_LEFT, gravity = RenderGravity.TOP_LEFT,
x = dockPadding.left, x = dockPadding.left + shakeX,
y = y, y = y,
color = textColor color = textColor
) )
@ -1190,7 +1210,7 @@ open class TextInputPanel<out S : Screen>(
if (selection != null && selection.isValid) { if (selection != null && selection.isValid) {
val (before, selected) = selection.sub(line) val (before, selected) = selection.sub(line)
var x = dockPadding.left var x = dockPadding.left + shakeX
if (before.isNotEmpty()) { if (before.isNotEmpty()) {
x += font.width(before).toFloat() x += font.width(before).toFloat()
@ -1233,16 +1253,16 @@ open class TextInputPanel<out S : Screen>(
graphics.draw( graphics.draw(
text = "_", text = "_",
gravity = RenderGravity.TOP_LEFT, gravity = RenderGravity.TOP_LEFT,
x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()), x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()) + shakeX,
y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing) + shakeY,
color = cursorColor color = cursorColor
) )
} else { } else {
graphics.draw( graphics.draw(
text = "|", text = "|",
gravity = RenderGravity.TOP_LEFT, gravity = RenderGravity.TOP_LEFT,
x = dockPadding.left + font.width(activeLine.substring(0, cursorRow)).toFloat() - 1f, x = dockPadding.left + font.width(activeLine.substring(0, cursorRow)).toFloat() - 1f + shakeX,
y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), y = topPadding + shakeY + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing),
color = cursorColor color = cursorColor
) )
} }
@ -1393,11 +1413,16 @@ open class TextInputPanel<out S : Screen>(
} }
protected var changeCallback: ((new: String, old: String) -> Unit)? = null protected var changeCallback: ((new: String, old: String) -> Unit)? = null
protected var idleCallback: (() -> Unit)? = null
fun onTextChange(callback: (new: String, old: String) -> Unit) { fun onTextChange(callback: (new: String, old: String) -> Unit) {
changeCallback = callback changeCallback = callback
} }
fun onIdle(callback: () -> Unit) {
idleCallback = callback
}
private enum class CharType { private enum class CharType {
SPACES { SPACES {
override fun contains(input: Char): Boolean { override fun contains(input: Char): Boolean {
@ -1446,6 +1471,7 @@ open class TextInputPanel<out S : Screen>(
} }
companion object { companion object {
const val SHAKE_MILLIS = 600L
val NEWLINES = Regex("\r?\n") val NEWLINES = Regex("\r?\n")
private val BUFFER = DynamicBufferSource() private val BUFFER = DynamicBufferSource()

View File

@ -34,9 +34,11 @@ import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel
import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.core.RandomSource2Generator
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket
import java.util.* import java.util.*
import java.util.random.RandomGenerator
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.properties.Delegates import kotlin.properties.Delegates
@ -440,8 +442,8 @@ private class AndroidResearchButton(
} }
private enum class PreviewScrollers( private enum class PreviewScrollers(
val init: (EditablePanel<*>, Random) -> Unit, val init: (EditablePanel<*>, RandomGenerator) -> Unit,
val scroll: (EditablePanel<*>, Random) -> Boolean val scroll: (EditablePanel<*>, RandomGenerator) -> Boolean
) { ) {
LEFT_TO_RIGHT( LEFT_TO_RIGHT(
init = { it, random -> init = { it, random ->
@ -499,8 +501,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
val rows = Int2ObjectOpenHashMap<EditablePanel<AndroidStationScreen>>() val rows = Int2ObjectOpenHashMap<EditablePanel<AndroidStationScreen>>()
val canvas = object : DraggableCanvasPanel<AndroidStationScreen>(this@AndroidStationScreen, null) { val canvas = object : DraggableCanvasPanel<AndroidStationScreen>(this@AndroidStationScreen, null) {
private val random = Random() private var scroller: PreviewScrollers = PreviewScrollers.entries.let { it[random.nextInt(it.size)] }
private var scroller: PreviewScrollers = PreviewScrollers.values().let { it[random.nextInt(it.size)] }
private var firstTick = false private var firstTick = false
override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
@ -522,14 +523,14 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
if (isPreview && !layoutInvalidated) { if (isPreview && !layoutInvalidated) {
if (firstTick) { if (firstTick) {
scroller.init.invoke(this, random) scroller.init.invoke(this, RandomSource2Generator(random))
} }
val status = scroller.scroll.invoke(this, random) val status = scroller.scroll.invoke(this, RandomSource2Generator(random))
if (!status) { if (!status) {
scroller = PreviewScrollers.values().let { it[random.nextInt(it.size)] } scroller = PreviewScrollers.entries.let { it[random.nextInt(it.size)] }
scroller.init.invoke(this, random) scroller.init.invoke(this, RandomSource2Generator(random))
} }
} }
} }

View File

@ -13,6 +13,8 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.CheckBoxLabelInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.button.CheckBoxLabelInputPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel
import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
@ -85,9 +87,28 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
it.dockTop = 10f it.dockTop = 10f
} }
NetworkNumberInputPanel(this, limitsTab.canvas, widget = menu.maxIOInput, networkValue = menu::maxIO).also { TextInputPanel(this, limitsTab.canvas).also {
it.dock = Dock.TOP it.dock = Dock.TOP
it.dockTop = 4f it.dockTop = 4f
it.allowNumbersAndSign()
it.onTextChange { new, old ->
try {
var value = Decimal(new)
if (value < Decimal.ZERO)
value = Decimal.MINUS_ONE
if (value != menu.maxIOInput)
menu.maxIOInput.accept(value)
} catch (err: NumberFormatException) {
// do nothing
}
}
it.onIdle {
it.text = menu.maxIO.toString()
}
} }
makeDeviceControls(this, frame, redstoneConfig = menu.redstone) makeDeviceControls(this, frame, redstoneConfig = menu.redstone)

View File

@ -0,0 +1,30 @@
package ru.dbotthepony.mc.otm.core
import net.minecraft.util.RandomSource
import java.util.random.RandomGenerator
class RandomSource2Generator(private val parent: RandomSource) : RandomGenerator {
override fun nextLong(): Long {
return parent.nextLong()
}
override fun nextInt(): Int {
return parent.nextInt()
}
override fun nextFloat(): Float {
return parent.nextFloat()
}
override fun nextDouble(): Double {
return parent.nextDouble()
}
override fun nextBoolean(): Boolean {
return parent.nextBoolean()
}
override fun nextGaussian(): Double {
return parent.nextGaussian()
}
}

View File

@ -13,6 +13,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.protocol.common.custom.CustomPacketPayload import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.util.RandomSource
import net.minecraft.world.Container import net.minecraft.world.Container
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
@ -78,6 +79,7 @@ abstract class MatteryMenu(
val mSynchronizer = Syncher() val mSynchronizer = Syncher()
val synchronizerRemote = mSynchronizer.Remote() val synchronizerRemote = mSynchronizer.Remote()
val player: Player get() = inventory.player val player: Player get() = inventory.player
val random: RandomSource = RandomSource.create()
private val _playerInventorySlots = ArrayList<InventorySlot>() private val _playerInventorySlots = ArrayList<InventorySlot>()
private val _playerHotbarSlots = ArrayList<InventorySlot>() private val _playerHotbarSlots = ArrayList<InventorySlot>()