diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt index 57e16b586..39260fc3e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt @@ -13,6 +13,7 @@ import net.minecraft.client.gui.navigation.ScreenRectangle import net.minecraft.client.gui.screens.Screen import net.minecraft.client.renderer.Rect2i import net.minecraft.network.chat.Component +import net.minecraft.util.RandomSource import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.SystemTime import ru.dbotthepony.mc.otm.client.CursorType @@ -134,6 +135,14 @@ open class EditablePanel( } } + 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. */ diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt index 474c14dbd..fe411fea0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt @@ -200,6 +200,10 @@ open class TextInputPanel( snapshotTimer = null redo.clear() } + + if (!isFocusedThis && snapshotTimer == null) { + idleCallback?.invoke() + } } private fun pushbackSnapshot() { @@ -1062,6 +1066,8 @@ open class TextInputPanel( return characterFilter?.acceptsCharacter(codepoint, mods, index) ?: true } + protected var rejectCharacterTimer: Long? = null + override fun charTypedInternal(codepoint: Char, mods: Int): Boolean { if (!isActive) { killFocus() @@ -1087,6 +1093,7 @@ open class TextInputPanel( if (!acceptsCharacter(codepoint, mods, index)) { playGuiClickSound() + rejectCharacterTimer = milliTime + SHAKE_MILLIS return true } @@ -1145,6 +1152,19 @@ open class TextInputPanel( 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) { val w = width(selectedLine, end = cursorRow) - scrollPixels @@ -1162,14 +1182,14 @@ open class TextInputPanel( stack.pushPose() stack.translate(-scrollPixels, 0f, 0f) - var y = topPadding + var y = topPadding + shakeY if (lines.isEmpty() || lines.size == 1 && lines[0] == "") { graphics.draw( font = font, text = placeholder, gravity = RenderGravity.TOP_LEFT, - x = dockPadding.left, + x = dockPadding.left + shakeX, y = y, color = placeholderColor ) @@ -1182,7 +1202,7 @@ open class TextInputPanel( graphics.draw( text = line, gravity = RenderGravity.TOP_LEFT, - x = dockPadding.left, + x = dockPadding.left + shakeX, y = y, color = textColor ) @@ -1190,7 +1210,7 @@ open class TextInputPanel( if (selection != null && selection.isValid) { val (before, selected) = selection.sub(line) - var x = dockPadding.left + var x = dockPadding.left + shakeX if (before.isNotEmpty()) { x += font.width(before).toFloat() @@ -1233,16 +1253,16 @@ open class TextInputPanel( graphics.draw( text = "_", gravity = RenderGravity.TOP_LEFT, - x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()), - y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), + x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()) + shakeX, + y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing) + shakeY, color = cursorColor ) } else { graphics.draw( text = "|", gravity = RenderGravity.TOP_LEFT, - x = dockPadding.left + font.width(activeLine.substring(0, cursorRow)).toFloat() - 1f, - y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), + x = dockPadding.left + font.width(activeLine.substring(0, cursorRow)).toFloat() - 1f + shakeX, + y = topPadding + shakeY + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), color = cursorColor ) } @@ -1393,11 +1413,16 @@ open class TextInputPanel( } protected var changeCallback: ((new: String, old: String) -> Unit)? = null + protected var idleCallback: (() -> Unit)? = null fun onTextChange(callback: (new: String, old: String) -> Unit) { changeCallback = callback } + fun onIdle(callback: () -> Unit) { + idleCallback = callback + } + private enum class CharType { SPACES { override fun contains(input: Char): Boolean { @@ -1446,6 +1471,7 @@ open class TextInputPanel( } companion object { + const val SHAKE_MILLIS = 600L val NEWLINES = Regex("\r?\n") private val BUFFER = DynamicBufferSource() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt index 7adcf7fd6..c17dac55c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt @@ -34,9 +34,11 @@ import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.kommons.math.RGBAColor 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.network.AndroidResearchRequestPacket import java.util.* +import java.util.random.RandomGenerator import kotlin.collections.ArrayList import kotlin.properties.Delegates @@ -440,8 +442,8 @@ private class AndroidResearchButton( } private enum class PreviewScrollers( - val init: (EditablePanel<*>, Random) -> Unit, - val scroll: (EditablePanel<*>, Random) -> Boolean + val init: (EditablePanel<*>, RandomGenerator) -> Unit, + val scroll: (EditablePanel<*>, RandomGenerator) -> Boolean ) { LEFT_TO_RIGHT( init = { it, random -> @@ -499,8 +501,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I val rows = Int2ObjectOpenHashMap>() val canvas = object : DraggableCanvasPanel(this@AndroidStationScreen, null) { - private val random = Random() - private var scroller: PreviewScrollers = PreviewScrollers.values().let { it[random.nextInt(it.size)] } + private var scroller: PreviewScrollers = PreviewScrollers.entries.let { it[random.nextInt(it.size)] } private var firstTick = false 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 (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) { - scroller = PreviewScrollers.values().let { it[random.nextInt(it.size)] } - scroller.init.invoke(this, random) + scroller = PreviewScrollers.entries.let { it[random.nextInt(it.size)] } + scroller.init.invoke(this, RandomSource2Generator(random)) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt index 479ce6ca2..7a8770f14 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt @@ -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.makeDeviceControls 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.menu.tech.EnergyCounterMenu @@ -85,9 +87,28 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: it.dockTop = 10f } - NetworkNumberInputPanel(this, limitsTab.canvas, widget = menu.maxIOInput, networkValue = menu::maxIO).also { + TextInputPanel(this, limitsTab.canvas).also { it.dock = Dock.TOP 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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/RandomSource2Generator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RandomSource2Generator.kt new file mode 100644 index 000000000..323cd254b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RandomSource2Generator.kt @@ -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() + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt index 5a82ef272..8b559b07f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -13,6 +13,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf import net.minecraft.network.protocol.common.custom.CustomPacketPayload import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer +import net.minecraft.util.RandomSource import net.minecraft.world.Container import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player @@ -78,6 +79,7 @@ abstract class MatteryMenu( val mSynchronizer = Syncher() val synchronizerRemote = mSynchronizer.Remote() val player: Player get() = inventory.player + val random: RandomSource = RandomSource.create() private val _playerInventorySlots = ArrayList() private val _playerHotbarSlots = ArrayList()