Add request specific amount dialog to terminal GUI
This commit is contained in:
parent
03c9c2ab83
commit
2981bdcb07
|
@ -1,11 +1,15 @@
|
||||||
package net.shadowfacts.phycon.network.block.terminal
|
package net.shadowfacts.phycon.network.block.terminal
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.gui.DrawableHelper
|
import net.minecraft.client.gui.DrawableHelper
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
|
import net.minecraft.client.gui.widget.AbstractButtonWidget
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget
|
||||||
import net.minecraft.client.gui.widget.TextFieldWidget
|
import net.minecraft.client.gui.widget.TextFieldWidget
|
||||||
import net.minecraft.client.util.math.MatrixStack
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
import net.minecraft.entity.player.PlayerInventory
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.screen.slot.Slot
|
import net.minecraft.screen.slot.Slot
|
||||||
import net.minecraft.screen.slot.SlotActionType
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
import net.minecraft.text.LiteralText
|
import net.minecraft.text.LiteralText
|
||||||
|
@ -13,6 +17,9 @@ import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
|
import java.lang.NumberFormatException
|
||||||
|
import kotlin.math.ceil
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -20,10 +27,31 @@ import org.lwjgl.glfw.GLFW
|
||||||
// todo: translate title
|
// todo: translate title
|
||||||
class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, title: Text): HandledScreen<TerminalScreenHandler>(handler, playerInv, title) {
|
class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, title: Text): HandledScreen<TerminalScreenHandler>(handler, playerInv, title) {
|
||||||
companion object {
|
companion object {
|
||||||
val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
private val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
||||||
|
private val DIALOG = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal_amount.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var searchBox: TextFieldWidget
|
private lateinit var searchBox: TextFieldWidget
|
||||||
|
private lateinit var amountBox: TextFieldWidget
|
||||||
|
private var dialogStack = ItemStack.EMPTY
|
||||||
|
private var showingAmountDialog = false
|
||||||
|
set(value) {
|
||||||
|
val oldValue = field
|
||||||
|
field = value
|
||||||
|
for (e in dialogChildren) {
|
||||||
|
e.visible = value
|
||||||
|
}
|
||||||
|
amountBox.isVisible
|
||||||
|
searchBox.setSelected(!value)
|
||||||
|
amountBox.setSelected(value)
|
||||||
|
if (value && !oldValue) {
|
||||||
|
amountBox.text = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var dialogChildren = mutableListOf<AbstractButtonWidget>()
|
||||||
|
|
||||||
|
private val dialogWidth = 158
|
||||||
|
private val dialogHeight = 62
|
||||||
|
|
||||||
init {
|
init {
|
||||||
backgroundWidth = 252
|
backgroundWidth = 252
|
||||||
|
@ -33,6 +61,9 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
override fun init() {
|
override fun init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
children.clear()
|
||||||
|
dialogChildren.clear()
|
||||||
|
|
||||||
client!!.keyboard.setRepeatEvents(true)
|
client!!.keyboard.setRepeatEvents(true)
|
||||||
|
|
||||||
searchBox = TextFieldWidget(textRenderer, x + 138, y + 6, 80, 9, LiteralText("Search"))
|
searchBox = TextFieldWidget(textRenderer, x + 138, y + 6, 80, 9, LiteralText("Search"))
|
||||||
|
@ -43,11 +74,68 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
searchBox.setSelected(true)
|
searchBox.setSelected(true)
|
||||||
searchBox.setEditableColor(0xffffff)
|
searchBox.setEditableColor(0xffffff)
|
||||||
children.add(searchBox)
|
children.add(searchBox)
|
||||||
|
|
||||||
|
val dialogMinX = width / 2 - dialogWidth / 2
|
||||||
|
val dialogMinY = height / 2 - dialogHeight / 2
|
||||||
|
amountBox = TextFieldWidget(textRenderer, dialogMinX + 8, dialogMinY + 27, 80, 9, LiteralText("Amount"))
|
||||||
|
amountBox.setHasBorder(false)
|
||||||
|
amountBox.isVisible = false
|
||||||
|
amountBox.setSelected(false)
|
||||||
|
amountBox.setEditableColor(0xffffff)
|
||||||
|
amountBox.setTextPredicate {
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Integer.parseInt(it) > 0
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialogChildren.add(amountBox)
|
||||||
|
|
||||||
|
val plusOne = SmallButton(dialogMinX + 7, dialogMinY + 7, 28, LiteralText("+1")) {
|
||||||
|
amountBox.intValue += 1
|
||||||
|
}
|
||||||
|
dialogChildren.add(plusOne)
|
||||||
|
|
||||||
|
val plusTen = SmallButton(dialogMinX + 7 + 28 + 3, dialogMinY + 7, 28, LiteralText("+10")) {
|
||||||
|
amountBox.intValue = ceil((amountBox.intValue + 1) / 10.0).toInt() * 10
|
||||||
|
}
|
||||||
|
dialogChildren.add(plusTen)
|
||||||
|
|
||||||
|
val plusHundred = SmallButton(dialogMinX + 7 + (28 + 3) * 2, dialogMinY + 7, 28, LiteralText("+100")) {
|
||||||
|
amountBox.intValue = ceil((amountBox.intValue + 1) / 100.0).toInt() * 100
|
||||||
|
}
|
||||||
|
dialogChildren.add(plusHundred)
|
||||||
|
|
||||||
|
val minusOne = SmallButton(dialogMinX + 7, dialogMinY + 39, 28, LiteralText("-1")) {
|
||||||
|
amountBox.intValue -= 1
|
||||||
|
}
|
||||||
|
dialogChildren.add(minusOne)
|
||||||
|
|
||||||
|
val minusTen = SmallButton(dialogMinX + 7 + 28 + 3, dialogMinY + 39, 28, LiteralText("-10")) {
|
||||||
|
amountBox.intValue = floor((amountBox.intValue - 1) / 10.0).toInt() * 10
|
||||||
|
}
|
||||||
|
dialogChildren.add(minusTen)
|
||||||
|
|
||||||
|
val minusHundred = SmallButton(dialogMinX + 7 + (28 + 3) * 2, dialogMinY + 39, 28, LiteralText("-100")) {
|
||||||
|
amountBox.intValue = floor((amountBox.intValue - 1) / 100.0).toInt() * 100
|
||||||
|
}
|
||||||
|
dialogChildren.add(minusHundred)
|
||||||
|
|
||||||
|
// 101,25
|
||||||
|
val request = ButtonWidget(dialogMinX + 101, dialogMinY + 21, 50, 20, LiteralText("Request")) {
|
||||||
|
doDialogRequest()
|
||||||
|
}
|
||||||
|
dialogChildren.add(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
super.tick()
|
||||||
searchBox.tick()
|
searchBox.tick()
|
||||||
|
amountBox.tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
||||||
|
@ -58,21 +146,50 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||||
renderBackground(matrixStack)
|
// if the dialog is open, the background gradient will be drawn in front of the main terminal gui
|
||||||
|
if (!showingAmountDialog) {
|
||||||
|
renderBackground(matrixStack)
|
||||||
|
}
|
||||||
|
|
||||||
GlStateManager.color4f(1f, 1f, 1f, 1f)
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
client!!.textureManager.bindTexture(BACKGROUND)
|
client!!.textureManager.bindTexture(BACKGROUND)
|
||||||
val x = (width - backgroundWidth) / 2
|
val x = (width - backgroundWidth) / 2
|
||||||
val y = (height - backgroundHeight) / 2
|
val y = (height - backgroundHeight) / 2
|
||||||
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
super.render(matrixStack, mouseX, mouseY, delta)
|
if (showingAmountDialog) {
|
||||||
|
RenderSystem.pushMatrix()
|
||||||
|
// items are rendered at some stupidly high z offset. item amounts at an even higher one
|
||||||
|
RenderSystem.translatef(0f, 0f, -350f)
|
||||||
|
|
||||||
|
// fake the mouse x/y while showing a dialog so slot mouseover highlights aren't drawn
|
||||||
|
super.render(matrixStack, -1, -1, delta)
|
||||||
|
|
||||||
|
RenderSystem.popMatrix()
|
||||||
|
} else {
|
||||||
|
super.render(matrixStack, mouseX, mouseY, delta)
|
||||||
|
}
|
||||||
|
|
||||||
searchBox.render(matrixStack, mouseX, mouseY, delta)
|
searchBox.render(matrixStack, mouseX, mouseY, delta)
|
||||||
|
|
||||||
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
|
if (showingAmountDialog) {
|
||||||
|
renderBackground(matrixStack)
|
||||||
|
|
||||||
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
|
client!!.textureManager.bindTexture(DIALOG)
|
||||||
|
val dialogMinX = width / 2 - dialogWidth / 2
|
||||||
|
val dialogMinY = height / 2 - dialogHeight / 2
|
||||||
|
drawTexture(matrixStack, dialogMinX, dialogMinY, 0, 0, dialogWidth, dialogHeight)
|
||||||
|
|
||||||
|
for (e in dialogChildren) {
|
||||||
|
e.render(matrixStack, mouseX, mouseY, delta)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
|
@ -90,37 +207,107 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt())
|
DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseClick(slot: Slot?, i: Int, j: Int, slotActionType: SlotActionType?) {
|
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
|
||||||
super.onMouseClick(slot, i, j, slotActionType)
|
super.onMouseClick(slot, invSlot, clickData, type)
|
||||||
|
|
||||||
// don't unfocus the search box on mouse click
|
// don't unfocus the search box on mouse click
|
||||||
searchBox.setSelected(true)
|
searchBox.setSelected(true)
|
||||||
|
|
||||||
|
if (type == SlotActionType.PICKUP && clickData == 0 && slot != null && handler.isNetworkSlot(slot.id) && !slot.stack.isEmpty) {
|
||||||
|
dialogStack = slot.stack
|
||||||
|
showingAmountDialog = true
|
||||||
|
searchBox.setSelected(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
|
if (showingAmountDialog) {
|
||||||
|
for (e in dialogChildren) {
|
||||||
|
if (e.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return super.mouseClicked(mouseX, mouseY, button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean {
|
||||||
|
if (showingAmountDialog) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return super.mouseDragged(d, e, i, f, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseMoved(d: Double, e: Double) {
|
||||||
|
if (showingAmountDialog) {
|
||||||
|
} else {
|
||||||
|
super.mouseMoved(d, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseReleased(d: Double, e: Double, i: Int): Boolean {
|
||||||
|
if (showingAmountDialog) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return super.mouseReleased(d, e, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseScrolled(d: Double, e: Double, f: Double): Boolean {
|
||||||
|
if (showingAmountDialog) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return super.mouseScrolled(d, e, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun charTyped(c: Char, i: Int): Boolean {
|
override fun charTyped(c: Char, i: Int): Boolean {
|
||||||
val oldText = searchBox.text
|
if (showingAmountDialog) {
|
||||||
if (searchBox.charTyped(c, i)) {
|
return amountBox.charTyped(c, i)
|
||||||
if (searchBox.text != oldText) {
|
} else {
|
||||||
search()
|
val oldText = searchBox.text
|
||||||
|
if (searchBox.charTyped(c, i)) {
|
||||||
|
if (searchBox.text != oldText) {
|
||||||
|
search()
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.charTyped(c, i)
|
return super.charTyped(c, i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyPressed(key: Int, j: Int, k: Int): Boolean {
|
override fun keyPressed(key: Int, j: Int, k: Int): Boolean {
|
||||||
val oldText = searchBox.text
|
if (showingAmountDialog) {
|
||||||
if (searchBox.keyPressed(key, j, k)) {
|
return when (key) {
|
||||||
if (searchBox.text != oldText) {
|
GLFW.GLFW_KEY_ESCAPE -> {
|
||||||
search()
|
showingAmountDialog = false
|
||||||
|
true
|
||||||
|
}
|
||||||
|
GLFW.GLFW_KEY_ENTER -> {
|
||||||
|
doDialogRequest()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
amountBox.keyPressed(key, j, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
return if (searchBox.isFocused && searchBox.isVisible && key != GLFW.GLFW_KEY_ESCAPE) {
|
|
||||||
true
|
|
||||||
} else {
|
} else {
|
||||||
super.keyPressed(key, j, k)
|
val oldText = searchBox.text
|
||||||
|
if (searchBox.keyPressed(key, j, k)) {
|
||||||
|
if (searchBox.text != oldText) {
|
||||||
|
search()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return if (searchBox.isFocused && searchBox.isVisible && key != GLFW.GLFW_KEY_ESCAPE) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
super.keyPressed(key, j, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,4 +315,32 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
screenHandler.search(searchBox.text)
|
screenHandler.search(searchBox.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun doDialogRequest() {
|
||||||
|
showingAmountDialog = false
|
||||||
|
handler.requestItem(client!!.player!!, dialogStack, amountBox.intValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var TextFieldWidget.intValue: Int
|
||||||
|
get() = if (text.isEmpty()) 0 else Integer.parseInt(text)
|
||||||
|
set(value) {
|
||||||
|
text = value.toString()
|
||||||
|
setSelected(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
class SmallButton(x: Int, y: Int, width: Int, title: Text, action: PressAction): ButtonWidget(x, y, width, 14, title, action) {
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
override fun renderButton(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
val client = MinecraftClient.getInstance()
|
||||||
|
client.textureManager.bindTexture(DIALOG)
|
||||||
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
|
val v = if (isHovered) 142 else 128
|
||||||
|
RenderSystem.enableBlend()
|
||||||
|
RenderSystem.defaultBlendFunc()
|
||||||
|
RenderSystem.enableDepthTest()
|
||||||
|
drawTexture(matrixStack, x, y, 0, v, width / 2, height)
|
||||||
|
drawTexture(matrixStack, x + width / 2, y, 200 - width / 2, v, width / 2, height)
|
||||||
|
drawCenteredText(matrixStack, client.textRenderer, message, x + width / 2, y + (height - 8) / 2, 0xffffffffu.toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ class TerminalScreenHandler(syncId: Int, playerInv: PlayerInventory, val termina
|
||||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestItem(player: PlayerEntity, stack: ItemStack, amount: Int) {
|
fun requestItem(player: PlayerEntity, stack: ItemStack, amount: Int) {
|
||||||
if (!player.world.isClient) return
|
if (!player.world.isClient) return
|
||||||
val handler = (player as ClientPlayerEntity).networkHandler
|
val handler = (player as ClientPlayerEntity).networkHandler
|
||||||
val packet = C2STerminalRequestItem(terminal, stack, amount)
|
val packet = C2STerminalRequestItem(terminal, stack, amount)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
Loading…
Reference in New Issue