Compare commits
2 Commits
aec32ae270
...
2981bdcb07
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 2981bdcb07 | |
Shadowfacts | 03c9c2ab83 |
|
@ -14,6 +14,7 @@ import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
|||
import net.shadowfacts.phycon.network.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.network.component.handleItemStack
|
||||
import net.shadowfacts.phycon.network.packet.*
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -67,8 +68,16 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
|||
|
||||
private fun handleExtractStack(packet: ExtractStackPacket) {
|
||||
getInventory()?.also { inv ->
|
||||
val extracted = inv.extract(packet.stack, packet.amount)
|
||||
sendPacket(ItemStackPacket(extracted, ipAddress, packet.source))
|
||||
var amount = packet.amount
|
||||
while (amount > 0) {
|
||||
val extracted = inv.extract(packet.stack, min(amount, packet.stack.maxCount))
|
||||
if (extracted.isEmpty) {
|
||||
break
|
||||
} else {
|
||||
amount -= extracted.count
|
||||
sendPacket(ItemStackPacket(extracted, ipAddress, packet.source))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
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.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.util.math.MatrixStack
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.text.LiteralText
|
||||
|
@ -13,6 +17,9 @@ import net.minecraft.text.Text
|
|||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import org.lwjgl.glfw.GLFW
|
||||
import java.lang.NumberFormatException
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -20,10 +27,31 @@ import org.lwjgl.glfw.GLFW
|
|||
// todo: translate title
|
||||
class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, title: Text): HandledScreen<TerminalScreenHandler>(handler, playerInv, title) {
|
||||
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 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 {
|
||||
backgroundWidth = 252
|
||||
|
@ -33,6 +61,9 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
|||
override fun init() {
|
||||
super.init()
|
||||
|
||||
children.clear()
|
||||
dialogChildren.clear()
|
||||
|
||||
client!!.keyboard.setRepeatEvents(true)
|
||||
|
||||
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.setEditableColor(0xffffff)
|
||||
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() {
|
||||
super.tick()
|
||||
searchBox.tick()
|
||||
amountBox.tick()
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
val x = (width - backgroundWidth) / 2
|
||||
val y = (height - backgroundHeight) / 2
|
||||
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
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)
|
||||
|
||||
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
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
override fun onMouseClick(slot: Slot?, i: Int, j: Int, slotActionType: SlotActionType?) {
|
||||
super.onMouseClick(slot, i, j, slotActionType)
|
||||
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
|
||||
super.onMouseClick(slot, invSlot, clickData, type)
|
||||
|
||||
// don't unfocus the search box on mouse click
|
||||
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 {
|
||||
val oldText = searchBox.text
|
||||
if (searchBox.charTyped(c, i)) {
|
||||
if (searchBox.text != oldText) {
|
||||
search()
|
||||
if (showingAmountDialog) {
|
||||
return amountBox.charTyped(c, i)
|
||||
} else {
|
||||
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 {
|
||||
val oldText = searchBox.text
|
||||
if (searchBox.keyPressed(key, j, k)) {
|
||||
if (searchBox.text != oldText) {
|
||||
search()
|
||||
if (showingAmountDialog) {
|
||||
return when (key) {
|
||||
GLFW.GLFW_KEY_ESCAPE -> {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
private fun requestItem(player: PlayerEntity, stack: ItemStack, amount: Int) {
|
||||
fun requestItem(player: PlayerEntity, stack: ItemStack, amount: Int) {
|
||||
if (!player.world.isClient) return
|
||||
val handler = (player as ClientPlayerEntity).networkHandler
|
||||
val packet = C2STerminalRequestItem(terminal, stack, amount)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
Loading…
Reference in New Issue