Holo sign block is now barely functional
This commit is contained in:
parent
c7e086e9ae
commit
f279bcd3d6
@ -6,15 +6,33 @@ import ru.dbotthepony.mc.otm.client.screen.panels.Dock
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.TextInputPanel
|
||||
import ru.dbotthepony.mc.otm.menu.HoloSignMenu
|
||||
import ru.dbotthepony.mc.otm.milliTime
|
||||
|
||||
class HoloSignScreen(menu: HoloSignMenu, inventory: Inventory, title: Component) : MatteryScreen<HoloSignMenu>(menu, title) {
|
||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||
val frame = FramePanel(this, null, 0f, 0f, 200f, 200f, getTitle())
|
||||
|
||||
val textbox = TextInputPanel(this, frame)
|
||||
textbox.dock = Dock.FILL
|
||||
textbox.multiLine = true
|
||||
textbox.text = "МОГУС\nБОНУС\n\nСУС"
|
||||
object : TextInputPanel<HoloSignScreen>(this@HoloSignScreen, frame) {
|
||||
init {
|
||||
dock = Dock.FILL
|
||||
multiLine = true
|
||||
}
|
||||
|
||||
private var lastChanges = 0L
|
||||
|
||||
override fun onTextChanged(old: String, new: String) {
|
||||
lastChanges = milliTime + 1000L
|
||||
menu.textInput.input(new)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (milliTime >= lastChanges) {
|
||||
text = menu.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frame
|
||||
}
|
||||
|
@ -80,14 +80,24 @@ open class TextInputPanel<out S : Screen>(
|
||||
private val cursorLine = this@TextInputPanel.cursorLine
|
||||
private val cursorCharacter = this@TextInputPanel.cursorCharacter
|
||||
private val selections = Int2ObjectAVLTreeMap(this@TextInputPanel.selections)
|
||||
private val multiLine = this@TextInputPanel.multiLine
|
||||
|
||||
fun apply() {
|
||||
this@TextInputPanel.lines.clear()
|
||||
|
||||
if (this@TextInputPanel.multiLine)
|
||||
this@TextInputPanel.lines.addAll(lines)
|
||||
else
|
||||
this@TextInputPanel.lines.add(lines.joinToString(""))
|
||||
|
||||
|
||||
this@TextInputPanel.selections.clear()
|
||||
if (this@TextInputPanel.multiLine && multiLine)
|
||||
this@TextInputPanel.selections.putAll(selections)
|
||||
|
||||
this@TextInputPanel.cursorCharacter = cursorCharacter
|
||||
this@TextInputPanel.cursorLine = cursorLine
|
||||
triggerChangeCallback()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@ -114,18 +124,41 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
var debugDraw = false
|
||||
var multiLine = false
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
|
||||
if (!value && lines.size > 1) {
|
||||
val merge = lines.joinToString("")
|
||||
lines.clear()
|
||||
lines.add(merge)
|
||||
triggerChangeCallback()
|
||||
}
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
var cursorLine = 0
|
||||
var cursorCharacter = 0
|
||||
var textColor = RGBAColor.WHITE
|
||||
var cursorColor = RGBAColor.GREEN
|
||||
var backgroundColor = RGBAColor.BLACK
|
||||
|
||||
private var oldText = ArrayList<String>()
|
||||
private var textCache: String? = null
|
||||
private val lines = ArrayList<String>()
|
||||
private val selections = Int2ObjectAVLTreeMap<TextSelection>()
|
||||
private val undo = ArrayDeque<Snapshot>()
|
||||
private val redo = ArrayDeque<Snapshot>()
|
||||
|
||||
private fun triggerChangeCallback() {
|
||||
if (oldText != lines) {
|
||||
textCache = null
|
||||
val old = oldText.joinToString("\n")
|
||||
oldText = ArrayList(lines)
|
||||
onTextChanged(old, textCache())
|
||||
}
|
||||
}
|
||||
|
||||
private var snapshotTimer: Long? = null
|
||||
|
||||
override fun tick() {
|
||||
@ -214,9 +247,11 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
operator fun set(index: Int, value: String) {
|
||||
if (index < 0) {
|
||||
if (index < 0)
|
||||
throw IndexOutOfBoundsException("negative index $index")
|
||||
}
|
||||
|
||||
if (!multiLine && index != 0)
|
||||
throw IllegalStateException("Not accepting newlines")
|
||||
|
||||
lines.ensureCapacity(index)
|
||||
|
||||
@ -241,6 +276,9 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
fun insertLine(index: Int, value: String = "") {
|
||||
if (!multiLine && lines.isNotEmpty())
|
||||
throw IllegalStateException("Not accepting newlines")
|
||||
|
||||
lines.ensureCapacity(index)
|
||||
|
||||
while (lines.size < index) {
|
||||
@ -262,9 +300,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
fun removeLine(index: Int): Boolean {
|
||||
if (index < 0 || index >= lines.size) {
|
||||
if (index < 0 || index >= lines.size)
|
||||
return false
|
||||
}
|
||||
|
||||
if (cursorLine == index) {
|
||||
if (index != 0)
|
||||
@ -363,6 +400,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
cursorCharacter = selection.start
|
||||
}
|
||||
}
|
||||
|
||||
triggerChangeCallback()
|
||||
}
|
||||
|
||||
private fun textCache(): String {
|
||||
@ -391,6 +430,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
undo.clear()
|
||||
cursorLine = 0
|
||||
cursorCharacter = 0
|
||||
textCache = null
|
||||
|
||||
if (multiLine) {
|
||||
lines.addAll(value.split(NEWLINES))
|
||||
@ -636,9 +676,12 @@ open class TextInputPanel<out S : Screen>(
|
||||
cursorCharacter = 0
|
||||
}
|
||||
|
||||
triggerChangeCallback()
|
||||
|
||||
return true
|
||||
} else {
|
||||
killFocus()
|
||||
triggerChangeCallback()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -718,6 +761,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
recordHistory()
|
||||
triggerChangeCallback()
|
||||
}
|
||||
} else {
|
||||
if (line != null) {
|
||||
@ -728,13 +772,14 @@ open class TextInputPanel<out S : Screen>(
|
||||
val newLine = line.substring(0, line.length - 1)
|
||||
moveCursors(cursorLine, cursorCharacter, -1)
|
||||
this[cursorLine] = newLine
|
||||
recordHistory()
|
||||
} else {
|
||||
val newLine = line.substring(0, cursorCharacter - 1) + line.substring(cursorCharacter)
|
||||
moveCursors(cursorLine, cursorCharacter, -1)
|
||||
this[cursorLine] = newLine
|
||||
recordHistory()
|
||||
}
|
||||
|
||||
recordHistory()
|
||||
triggerChangeCallback()
|
||||
} else if (cursorLine > 0) {
|
||||
cursorLine--
|
||||
recordHistory()
|
||||
@ -751,7 +796,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
if (cursorLine !in 0 until lines.size) {
|
||||
cursorLine = lines.size - 1
|
||||
cursorLine = (lines.size - 1).coerceAtLeast(0)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -764,6 +809,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
cursorCharacter = 0
|
||||
recordHistory(true)
|
||||
triggerChangeCallback()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -780,8 +826,6 @@ open class TextInputPanel<out S : Screen>(
|
||||
cursorCharacter = line.length
|
||||
this[cursorLine] = line + bottomLine
|
||||
removeLine(cursorLine + 1)
|
||||
|
||||
recordHistory()
|
||||
} else {
|
||||
pushbackSnapshotIfNoTimer()
|
||||
|
||||
@ -791,10 +835,10 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
if (cursorCharacter != 0)
|
||||
this.cursorCharacter++
|
||||
|
||||
recordHistory()
|
||||
}
|
||||
|
||||
recordHistory()
|
||||
triggerChangeCallback()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -860,6 +904,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
pushbackSnapshot()
|
||||
triggerChangeCallback()
|
||||
return true
|
||||
}
|
||||
|
||||
@ -924,6 +969,10 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
override fun charTypedInternal(codepoint: Char, mods: Int): Boolean {
|
||||
wipeSelection()
|
||||
|
||||
if (!multiLine)
|
||||
cursorLine = 0
|
||||
|
||||
var line = this[cursorLine]
|
||||
|
||||
if (line == null) {
|
||||
@ -942,6 +991,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
set(cursorLine, line)
|
||||
moveCursors(cursorLine, cursorCharacter, 1)
|
||||
recordHistory()
|
||||
triggerChangeCallback()
|
||||
|
||||
return true
|
||||
}
|
||||
@ -1171,6 +1221,16 @@ open class TextInputPanel<out S : Screen>(
|
||||
return true
|
||||
}
|
||||
|
||||
protected open fun onTextChanged(old: String, new: String) {
|
||||
changeCallback?.invoke(old, new)
|
||||
}
|
||||
|
||||
protected var changeCallback: ((old: String, new: String) -> Unit)? = null
|
||||
|
||||
fun onTextChange(callback: (old: String, new: String) -> Unit) {
|
||||
changeCallback = callback
|
||||
}
|
||||
|
||||
private enum class CharType {
|
||||
SPACES {
|
||||
override fun contains(input: Char): Boolean {
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.menu
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity
|
||||
import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec
|
||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||
|
||||
class HoloSignMenu @JvmOverloads constructor(
|
||||
@ -12,6 +13,11 @@ class HoloSignMenu @JvmOverloads constructor(
|
||||
) : MatteryMenu(MMenus.HOLO_SIGN, containerId, inventory, tile) {
|
||||
var text by mSynchronizer.string(name = "text")
|
||||
|
||||
val textInput = PlayerInput(BinaryStringCodec) {
|
||||
if (tile is HoloSignBlockEntity)
|
||||
tile.text = it
|
||||
}
|
||||
|
||||
override val storageSlots: Collection<Slot>
|
||||
get() = listOf()
|
||||
|
||||
|
@ -2,7 +2,10 @@ package ru.dbotthepony.mc.otm.menu
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
|
||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.Container
|
||||
@ -12,17 +15,26 @@ import net.minecraft.world.inventory.*
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper.hasBindingCurse
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
|
||||
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
|
||||
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
|
||||
import ru.dbotthepony.mc.otm.core.util.IStreamCodec
|
||||
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
|
||||
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.network.MenuFieldPacket
|
||||
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.network.packetHandled
|
||||
import ru.dbotthepony.mc.otm.network.sender
|
||||
import java.io.DataInputStream
|
||||
import java.io.DataOutputStream
|
||||
import java.util.*
|
||||
import java.util.function.Supplier
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
menuType: MenuType<*>?,
|
||||
@ -43,6 +55,45 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
|
||||
private val _playerExoSuitSlots = ArrayList<MatterySlot>()
|
||||
private val _playerCombinedInventorySlots = ArrayList<MatterySlot>()
|
||||
|
||||
private val playerInputs = ArrayList<PlayerInput<*>>()
|
||||
|
||||
class PlayerInputPacket(val containerId: Int, val inputId: Int, val payload: ByteArray) : MatteryPacket {
|
||||
constructor(buff: FriendlyByteBuf) : this(buff.readVarInt(), buff.readVarInt(), ByteArray(buff.readableBytes()).also { buff.readBytes(it) })
|
||||
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeVarInt(containerId)
|
||||
buff.writeVarInt(inputId)
|
||||
buff.writeBytes(payload)
|
||||
}
|
||||
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.packetHandled = true
|
||||
val menu = context.sender?.containerMenu as? MatteryMenu ?: return
|
||||
if (menu.containerId != containerId) return
|
||||
val input = menu.playerInputs.getOrNull(inputId) ?: return
|
||||
if (!input.allowSpectators && context.sender!!.isSpectator) return
|
||||
input.invoke(input.codec.read(DataInputStream(FastByteArrayInputStream(payload))))
|
||||
}
|
||||
}
|
||||
|
||||
inner class PlayerInput<V>(val codec: IStreamCodec<V>, val allowSpectators: Boolean = false, val handler: (V) -> Unit) {
|
||||
val id = playerInputs.size
|
||||
|
||||
init {
|
||||
playerInputs.add(this)
|
||||
}
|
||||
|
||||
fun input(value: V) {
|
||||
val stream = FastByteArrayOutputStream()
|
||||
codec.write(DataOutputStream(stream), value)
|
||||
MenuNetworkChannel.sendToServer(PlayerInputPacket(containerId, id, stream.array.copyOfRange(0, stream.length)))
|
||||
}
|
||||
|
||||
internal fun invoke(value: Any?) {
|
||||
handler.invoke(value as V)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* inventory + exosuit + hotbar (in this order)
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ class SetCarriedPacket(val item: ItemStack) : MatteryPacket {
|
||||
}
|
||||
|
||||
object MenuNetworkChannel : MatteryNetworkChannel(
|
||||
version = "1",
|
||||
version = "2",
|
||||
name = "menu"
|
||||
) {
|
||||
fun register() {
|
||||
@ -86,6 +86,7 @@ object MenuNetworkChannel : MatteryNetworkChannel(
|
||||
add(NumberPlayerInputPacket::class.java, NumberPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
|
||||
add(OneWayPlayerInputPacket::class.java, OneWayPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
|
||||
add(BooleanPlayerInputPacket::class.java, BooleanPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER)
|
||||
add(MatteryMenu.PlayerInputPacket::class.java, MatteryMenu::PlayerInputPacket, NetworkDirection.PLAY_TO_SERVER)
|
||||
|
||||
// menu specific
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user