Compare commits
4 Commits
f375d157b0
...
3e66d7439a
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 3e66d7439a | |
Shadowfacts | 2774cabfcc | |
Shadowfacts | 81ce590231 | |
Shadowfacts | f0fe1e4a3d |
|
@ -19,8 +19,10 @@ object PhyConPlugin: REIPluginV0 {
|
||||||
override fun registerBounds(helper: DisplayHelper) {
|
override fun registerBounds(helper: DisplayHelper) {
|
||||||
BaseBoundsHandler.getInstance().registerExclusionZones(TerminalScreen::class.java) {
|
BaseBoundsHandler.getInstance().registerExclusionZones(TerminalScreen::class.java) {
|
||||||
val screen = MinecraftClient.getInstance().currentScreen as TerminalScreen
|
val screen = MinecraftClient.getInstance().currentScreen as TerminalScreen
|
||||||
|
val button = screen.terminalVC.sortMode
|
||||||
|
val rect = button.convert(button.bounds, to = null)
|
||||||
listOf(
|
listOf(
|
||||||
Rectangle(screen.sortButtonX, screen.sortButtonY, 20, 20)
|
Rectangle(rect.left.toInt(), rect.top.toInt(), 20, 20)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.shadowfacts.cacao
|
package net.shadowfacts.cacao
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
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
|
||||||
|
@ -57,8 +58,17 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onClose() {
|
||||||
|
super.onClose()
|
||||||
|
|
||||||
|
windows.forEach {
|
||||||
|
// todo: VC callbacks
|
||||||
|
|
||||||
|
it.firstResponder = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||||
renderBackground(matrixStack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
||||||
|
@ -67,15 +77,28 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
|
|
||||||
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
val mouse = Point(mouseX, mouseY)
|
val mouse = Point(mouseX, mouseY)
|
||||||
windows.forEachIndexed { index, it ->
|
|
||||||
|
RenderSystem.pushMatrix()
|
||||||
|
RenderSystem.translatef(0f, 0f, -350f)
|
||||||
|
|
||||||
|
for (i in windows.indices) {
|
||||||
|
val it = windows[i]
|
||||||
|
|
||||||
|
if (i == windows.size - 1) {
|
||||||
|
renderBackground(matrixStack)
|
||||||
|
}
|
||||||
|
|
||||||
if (it is ScreenHandlerWindow) {
|
if (it is ScreenHandlerWindow) {
|
||||||
if (index == windows.size - 1) {
|
if (i == windows.size - 1) {
|
||||||
super.render(matrixStack, mouseX, mouseY, delta)
|
super.render(matrixStack, mouseX, mouseY, delta)
|
||||||
} else {
|
} else {
|
||||||
// if the screen handler window is not the frontmost, we fake the mouse x/y to disable the slot mouseover effect
|
// if the screen handler window is not the frontmost, we fake the mouse x/y to disable the slot mouseover effect
|
||||||
super.render(matrixStack, -1, -1, delta)
|
super.render(matrixStack, -1, -1, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderSystem.popMatrix()
|
||||||
}
|
}
|
||||||
|
|
||||||
it.draw(matrixStack, mouse, delta)
|
it.draw(matrixStack, mouse, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +118,38 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||||
|
val window = windows.lastOrNull()
|
||||||
|
val startPoint = Point(mouseX, mouseY)
|
||||||
|
val delta = Point(deltaX, deltaY)
|
||||||
|
val result = window?.mouseDragged(startPoint, delta, MouseButton.fromMC(button))
|
||||||
|
return if (result == true) {
|
||||||
|
true
|
||||||
|
} else if (window is ScreenHandlerWindow) {
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
|
val window = windows.lastOrNull()
|
||||||
|
val result = window?.mouseReleased(Point(mouseX, mouseY), MouseButton.fromMC(button))
|
||||||
|
return if (result == true) {
|
||||||
|
true
|
||||||
|
} else if (window is ScreenHandlerWindow) {
|
||||||
|
super.mouseReleased(mouseX, mouseY, button)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
|
||||||
|
val window = windows.lastOrNull()
|
||||||
|
val result = window?.mouseScrolled(Point(mouseX, mouseY), amount)
|
||||||
|
return result == true
|
||||||
|
}
|
||||||
|
|
||||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||||
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
||||||
|
|
|
@ -119,6 +119,12 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
||||||
return result == true
|
return result == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
|
||||||
|
val window = windows.lastOrNull()
|
||||||
|
val result = window?.mouseScrolled(Point(mouseX, mouseY), amount)
|
||||||
|
return result == true
|
||||||
|
}
|
||||||
|
|
||||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||||
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.shadowfacts.cacao
|
package net.shadowfacts.cacao
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.util.LayoutGuide
|
||||||
import net.shadowfacts.cacao.view.View
|
import net.shadowfacts.cacao.view.View
|
||||||
import no.birkett.kiwi.Variable
|
import no.birkett.kiwi.Variable
|
||||||
|
|
||||||
|
@ -9,10 +10,23 @@ import no.birkett.kiwi.Variable
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class LayoutVariable(val owner: View, val property: String): Variable("LayoutVariable") {
|
class LayoutVariable(
|
||||||
|
val view: View?,
|
||||||
|
val layoutGuide: LayoutGuide?,
|
||||||
|
val property: String,
|
||||||
|
): Variable("LayoutVariable") {
|
||||||
|
|
||||||
override fun getName() = "$owner.$property"
|
constructor(view: View, property: String): this(view, null, property)
|
||||||
|
constructor(layoutGuide: LayoutGuide, property: String): this(null, layoutGuide, property)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if ((view == null) == (layoutGuide == null)) {
|
||||||
|
throw RuntimeException("LayoutVariable must be constructed with either a view or layout guide")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "${view ?: layoutGuide}.$property"
|
||||||
|
|
||||||
override fun toString() = "LayoutVariable(name=$name, value=$value)"
|
override fun toString() = "LayoutVariable(name=$name, value=$value)"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.shadowfacts.cacao.util
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.LayoutVariable
|
||||||
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A layout guide is a non-view object that represents a rectangular area for the purposes of constraint-based layout.
|
||||||
|
* It allows you to define complex layouts without needing empty container views.
|
||||||
|
*
|
||||||
|
* A layout guide is always owned by a view. The owning view's dimensions are not necessarily tied to the layout guide's.
|
||||||
|
*
|
||||||
|
* To create a layout guide, call [View.addLayoutGuide] on the owning view.
|
||||||
|
*
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class LayoutGuide(
|
||||||
|
val owningView: View,
|
||||||
|
) {
|
||||||
|
|
||||||
|
val leftAnchor: LayoutVariable = LayoutVariable(this, "left")
|
||||||
|
val rightAnchor: LayoutVariable = LayoutVariable(this, "right")
|
||||||
|
val topAnchor: LayoutVariable = LayoutVariable(this, "top")
|
||||||
|
val bottomAnchor: LayoutVariable = LayoutVariable(this, "bottom")
|
||||||
|
val widthAnchor: LayoutVariable = LayoutVariable(this, "width")
|
||||||
|
val heightAnchor: LayoutVariable = LayoutVariable(this, "height")
|
||||||
|
val centerXAnchor: LayoutVariable = LayoutVariable(this, "centerX")
|
||||||
|
val centerYAnchor: LayoutVariable = LayoutVariable(this, "centerY")
|
||||||
|
|
||||||
|
val frame: Rect
|
||||||
|
get() = Rect(leftAnchor.value - owningView.leftAnchor.value, topAnchor.value - owningView.topAnchor.value, widthAnchor.value, heightAnchor.value)
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import net.shadowfacts.cacao.geometry.Rect
|
||||||
import net.shadowfacts.cacao.util.texture.NinePatchTexture
|
import net.shadowfacts.cacao.util.texture.NinePatchTexture
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
import net.shadowfacts.cacao.util.properties.ResettableLazyProperty
|
import net.shadowfacts.cacao.util.properties.ResettableLazyProperty
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for drawing a [NinePatchTexture] in a view.
|
* A helper class for drawing a [NinePatchTexture] in a view.
|
||||||
|
@ -91,22 +92,22 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
|
|
||||||
private fun drawEdges(matrixStack: MatrixStack) {
|
private fun drawEdges(matrixStack: MatrixStack) {
|
||||||
// Horizontal
|
// Horizontal
|
||||||
for (i in 0 until (topMiddle.width.toInt() / ninePatch.centerWidth)) {
|
for (i in 0 until (topMiddle.width.roundToInt() / ninePatch.centerWidth)) {
|
||||||
RenderHelper.draw(matrixStack, topMiddle.left + i * ninePatch.centerWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, ninePatch.centerWidth.toDouble(), topMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, topMiddle.left + i * ninePatch.centerWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, ninePatch.centerWidth.toDouble(), topMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
RenderHelper.draw(matrixStack, bottomMiddle.left + i * ninePatch.centerWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, ninePatch.centerWidth.toDouble(), bottomMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, bottomMiddle.left + i * ninePatch.centerWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, ninePatch.centerWidth.toDouble(), bottomMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
}
|
}
|
||||||
val remWidth = topMiddle.width.toInt() % ninePatch.centerWidth
|
val remWidth = topMiddle.width.roundToInt() % ninePatch.centerWidth
|
||||||
if (remWidth > 0) {
|
if (remWidth > 0) {
|
||||||
RenderHelper.draw(matrixStack, topMiddle.right - remWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, topMiddle.right - remWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
RenderHelper.draw(matrixStack, bottomMiddle.right - remWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, bottomMiddle.right - remWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertical
|
// Vertical
|
||||||
for (i in 0 until (leftMiddle.height.toInt() / ninePatch.centerHeight)) {
|
for (i in 0 until (leftMiddle.height.roundToInt() / ninePatch.centerHeight)) {
|
||||||
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.top + i * ninePatch.centerHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.top + i * ninePatch.centerHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.top + i * ninePatch.centerHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.top + i * ninePatch.centerHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
}
|
}
|
||||||
val remHeight = leftMiddle.height.toInt() % ninePatch.centerHeight
|
val remHeight = leftMiddle.height.roundToInt() % ninePatch.centerHeight
|
||||||
if (remHeight > 0) {
|
if (remHeight > 0) {
|
||||||
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.bottom - remHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.bottom - remHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.bottom - remHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.bottom - remHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
@ -114,20 +115,20 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawCenter(matrixStack: MatrixStack) {
|
private fun drawCenter(matrixStack: MatrixStack) {
|
||||||
for (i in 0 until (center.height.toInt() / ninePatch.centerHeight)) {
|
for (i in 0 until (center.height.roundToInt() / ninePatch.centerHeight)) {
|
||||||
drawCenterRow(matrixStack, center.top + i * ninePatch.centerHeight.toDouble(), ninePatch.centerHeight.toDouble())
|
drawCenterRow(matrixStack, center.top + i * ninePatch.centerHeight.toDouble(), ninePatch.centerHeight.toDouble())
|
||||||
}
|
}
|
||||||
val remHeight = center.height.toInt() % ninePatch.centerHeight
|
val remHeight = center.height.roundToInt() % ninePatch.centerHeight
|
||||||
if (remHeight > 0) {
|
if (remHeight > 0) {
|
||||||
drawCenterRow(matrixStack, center.bottom - remHeight, remHeight.toDouble())
|
drawCenterRow(matrixStack, center.bottom - remHeight, remHeight.toDouble())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawCenterRow(matrixStack: MatrixStack, y: Double, height: Double) {
|
private fun drawCenterRow(matrixStack: MatrixStack, y: Double, height: Double) {
|
||||||
for (i in 0 until (center.width.toInt() / ninePatch.centerWidth)) {
|
for (i in 0 until (center.width.roundToInt() / ninePatch.centerWidth)) {
|
||||||
RenderHelper.draw(matrixStack, center.left + i * ninePatch.centerWidth, y, ninePatch.center.u, ninePatch.center.v, ninePatch.centerWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, center.left + i * ninePatch.centerWidth, y, ninePatch.center.u, ninePatch.center.v, ninePatch.centerWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
}
|
}
|
||||||
val remWidth = center.width.toInt() % ninePatch.centerWidth
|
val remWidth = center.width.roundToInt() % ninePatch.centerWidth
|
||||||
if (remWidth > 0) {
|
if (remWidth > 0) {
|
||||||
RenderHelper.draw(matrixStack, center.right - remWidth, y, ninePatch.center.u, ninePatch.center.v, remWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(matrixStack, center.right - remWidth, y, ninePatch.center.u, ninePatch.center.v, remWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import no.birkett.kiwi.Solver
|
||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashSet
|
import kotlin.collections.HashSet
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base Cacao View class. Provides layout anchors, properties, and helper methods.
|
* The base Cacao View class. Provides layout anchors, properties, and helper methods.
|
||||||
|
@ -84,6 +85,17 @@ open class View(): Responder {
|
||||||
*/
|
*/
|
||||||
val centerYAnchor = LayoutVariable(this, "centerY")
|
val centerYAnchor = LayoutVariable(this, "centerY")
|
||||||
|
|
||||||
|
private val _layoutGuides = LinkedList<LayoutGuide>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All the layout guides attached to this view.
|
||||||
|
*
|
||||||
|
* To add a layout guide, call [addLayoutGuide].
|
||||||
|
*
|
||||||
|
* @see LayoutGuide
|
||||||
|
*/
|
||||||
|
val layoutGuides: List<LayoutGuide> = _layoutGuides
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this view uses constraint-based layout.
|
* Whether this view uses constraint-based layout.
|
||||||
* If `false`, the view's `frame` must be set manually and the layout anchors may not be used.
|
* If `false`, the view's `frame` must be set manually and the layout anchors may not be used.
|
||||||
|
@ -229,7 +241,7 @@ open class View(): Responder {
|
||||||
for (b in a + 1 until variables.size) {
|
for (b in a + 1 until variables.size) {
|
||||||
// if the variable views have no common ancestor after the removed view's superview is unset,
|
// if the variable views have no common ancestor after the removed view's superview is unset,
|
||||||
// the constraint crossed the this<->view boundary and should be removed
|
// the constraint crossed the this<->view boundary and should be removed
|
||||||
val ancestor = LowestCommonAncestor.find(variables[a].owner, variables[b].owner, View::superview)
|
val ancestor = LowestCommonAncestor.find(variables[a].viewOrLayoutGuideView, variables[b].viewOrLayoutGuideView, View::superview)
|
||||||
if (ancestor == null) {
|
if (ancestor == null) {
|
||||||
return@filter true
|
return@filter true
|
||||||
}
|
}
|
||||||
|
@ -247,6 +259,18 @@ open class View(): Responder {
|
||||||
// view.wasRemoved()
|
// view.wasRemoved()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a new layout guide with this view as its owner.
|
||||||
|
*/
|
||||||
|
fun addLayoutGuide(): LayoutGuide {
|
||||||
|
val guide = LayoutGuide(this)
|
||||||
|
_layoutGuides.add(guide)
|
||||||
|
if (hasSolver) {
|
||||||
|
guide.attachTo(solver)
|
||||||
|
}
|
||||||
|
return guide
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes this view from its superview, if it has one.
|
* Removes this view from its superview, if it has one.
|
||||||
*/
|
*/
|
||||||
|
@ -283,6 +307,10 @@ open class View(): Responder {
|
||||||
open fun wasAdded() {
|
open fun wasAdded() {
|
||||||
createInternalConstraints()
|
createInternalConstraints()
|
||||||
updateIntrinsicContentSizeConstraints(null, intrinsicContentSize)
|
updateIntrinsicContentSizeConstraints(null, intrinsicContentSize)
|
||||||
|
|
||||||
|
layoutGuides.forEach {
|
||||||
|
it.attachTo(solver)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -341,7 +369,7 @@ open class View(): Responder {
|
||||||
*/
|
*/
|
||||||
open fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
open fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
||||||
RenderHelper.pushMatrix()
|
RenderHelper.pushMatrix()
|
||||||
RenderHelper.translate(frame.left, frame.top)
|
RenderHelper.translate(floor(frame.left), floor(frame.top))
|
||||||
|
|
||||||
RenderHelper.fill(matrixStack, bounds, backgroundColor)
|
RenderHelper.fill(matrixStack, bounds, backgroundColor)
|
||||||
|
|
||||||
|
@ -419,6 +447,23 @@ open class View(): Responder {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun mouseDragEnded(point: Point, mouseButton: MouseButton) {
|
||||||
|
val view = subviewsAtPoint(point).maxByOrNull(View::zIndex)
|
||||||
|
if (view != null) {
|
||||||
|
val pointInView = convert(point, to = view)
|
||||||
|
return view.mouseDragEnded(pointInView, mouseButton)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun mouseScrolled(point: Point, amount: Double): Boolean {
|
||||||
|
val view = subviewsAtPoint(point).maxByOrNull(View::zIndex)
|
||||||
|
if (view != null) {
|
||||||
|
val pointInView = convert(point, to = view)
|
||||||
|
return view.mouseScrolled(pointInView, amount)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given point in this view's coordinate system to the coordinate system of another view or the window.
|
* Converts the given point in this view's coordinate system to the coordinate system of another view or the window.
|
||||||
*
|
*
|
||||||
|
@ -463,3 +508,15 @@ open class View(): Responder {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun LayoutGuide.attachTo(solver: Solver) {
|
||||||
|
solver.dsl {
|
||||||
|
rightAnchor equalTo (leftAnchor + widthAnchor)
|
||||||
|
bottomAnchor equalTo (topAnchor + heightAnchor)
|
||||||
|
centerXAnchor equalTo (leftAnchor + widthAnchor / 2)
|
||||||
|
centerYAnchor equalTo (topAnchor + heightAnchor / 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val LayoutVariable.viewOrLayoutGuideView: View
|
||||||
|
get() = view ?: layoutGuide!!.owningView
|
||||||
|
|
|
@ -41,7 +41,9 @@ class EnumButton<E: Enum<E>>(
|
||||||
value = when (mouseButton) {
|
value = when (mouseButton) {
|
||||||
MouseButton.LEFT -> EnumHelper.next(value)
|
MouseButton.LEFT -> EnumHelper.next(value)
|
||||||
MouseButton.RIGHT -> EnumHelper.previous(value)
|
MouseButton.RIGHT -> EnumHelper.previous(value)
|
||||||
else -> value
|
else -> {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.shadowfacts.cacao.view.textfield
|
package net.shadowfacts.cacao.view.textfield
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.gui.screen.TickableElement
|
||||||
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.text.LiteralText
|
import net.minecraft.text.LiteralText
|
||||||
|
@ -11,6 +12,7 @@ import net.shadowfacts.cacao.util.MouseButton
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
import net.shadowfacts.cacao.view.View
|
import net.shadowfacts.cacao.view.View
|
||||||
import net.shadowfacts.phycon.mixin.client.TextFieldWidgetAccessor
|
import net.shadowfacts.phycon.mixin.client.TextFieldWidgetAccessor
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract text field class. Cannot be constructed directly, use for creating other text fields with more specific
|
* An abstract text field class. Cannot be constructed directly, use for creating other text fields with more specific
|
||||||
|
@ -23,7 +25,7 @@ import net.shadowfacts.phycon.mixin.client.TextFieldWidgetAccessor
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
||||||
initialText: String
|
initialText: String
|
||||||
): View() {
|
): View(), TickableElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that is invoked when the text in this text field changes.
|
* A function that is invoked when the text in this text field changes.
|
||||||
|
@ -159,7 +161,11 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
handler?.invoke(this as Impl)
|
handler?.invoke(this as Impl)
|
||||||
}
|
}
|
||||||
return result
|
return result || (isFirstResponder && keyCode != GLFW.GLFW_KEY_ESCAPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
minecraftWidget.tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: label for the TextFieldWidget?
|
// todo: label for the TextFieldWidget?
|
||||||
|
|
|
@ -3,7 +3,7 @@ package net.shadowfacts.cacao.view.textfield
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class NumberField(
|
open class NumberField(
|
||||||
initialValue: Int,
|
initialValue: Int,
|
||||||
handler: ((NumberField) -> Unit)? = null,
|
handler: ((NumberField) -> Unit)? = null,
|
||||||
): AbstractTextField<NumberField>(initialValue.toString()) {
|
): AbstractTextField<NumberField>(initialValue.toString()) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ package net.shadowfacts.cacao.view.textfield
|
||||||
* @param initialText The initial value of this text field.
|
* @param initialText The initial value of this text field.
|
||||||
* @param handler A function that is invoked when the value of the text field changes.
|
* @param handler A function that is invoked when the value of the text field changes.
|
||||||
*/
|
*/
|
||||||
class TextField(
|
open class TextField(
|
||||||
initialText: String,
|
initialText: String,
|
||||||
handler: ((TextField) -> Unit)? = null
|
handler: ((TextField) -> Unit)? = null
|
||||||
): AbstractTextField<TextField>(initialText) {
|
): AbstractTextField<TextField>(initialText) {
|
||||||
|
|
|
@ -234,7 +234,8 @@ open class Window(
|
||||||
fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
|
fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
|
||||||
val currentlyDraggedView = this.currentDragReceiver
|
val currentlyDraggedView = this.currentDragReceiver
|
||||||
if (currentlyDraggedView != null) {
|
if (currentlyDraggedView != null) {
|
||||||
return currentlyDraggedView.mouseDragged(startPoint, delta, mouseButton)
|
val pointInView = viewController.view.convert(startPoint, to = currentlyDraggedView)
|
||||||
|
return currentlyDraggedView.mouseDragged(pointInView, delta, mouseButton)
|
||||||
} else if (startPoint in viewController.view.frame) {
|
} else if (startPoint in viewController.view.frame) {
|
||||||
val startInView =
|
val startInView =
|
||||||
Point(startPoint.x - viewController.view.frame.left, startPoint.y - viewController.view.frame.top)
|
Point(startPoint.x - viewController.view.frame.left, startPoint.y - viewController.view.frame.top)
|
||||||
|
@ -246,7 +247,12 @@ open class Window(
|
||||||
view = view.subviewsAtPoint(pointInView).maxByOrNull(View::zIndex)
|
view = view.subviewsAtPoint(pointInView).maxByOrNull(View::zIndex)
|
||||||
}
|
}
|
||||||
this.currentDragReceiver = view ?: prevView
|
this.currentDragReceiver = view ?: prevView
|
||||||
return this.currentDragReceiver?.mouseDragged(startPoint, delta, mouseButton) ?: false
|
return if (this.currentDragReceiver != null) {
|
||||||
|
val pointInView = viewController.view.convert(startPoint, to = this.currentDragReceiver!!)
|
||||||
|
this.currentDragReceiver!!.mouseDragged(pointInView, delta, mouseButton)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -254,10 +260,16 @@ open class Window(
|
||||||
fun mouseReleased(point: Point, mouseButton: MouseButton): Boolean {
|
fun mouseReleased(point: Point, mouseButton: MouseButton): Boolean {
|
||||||
val currentlyDraggedView = this.currentDragReceiver
|
val currentlyDraggedView = this.currentDragReceiver
|
||||||
if (currentlyDraggedView != null) {
|
if (currentlyDraggedView != null) {
|
||||||
|
val pointInView = viewController.view.convert(point, to = currentlyDraggedView)
|
||||||
|
currentlyDraggedView.mouseDragEnded(pointInView, mouseButton)
|
||||||
this.currentDragReceiver = null
|
this.currentDragReceiver = null
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun mouseScrolled(point: Point, amount: Double): Boolean {
|
||||||
|
return viewController.view.mouseScrolled(point, amount)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,10 +129,9 @@ class RedstoneEmitterScreen(
|
||||||
inv.leftAnchor equalTo (minX + 8)
|
inv.leftAnchor equalTo (minX + 8)
|
||||||
inv.topAnchor equalTo (minY + 72)
|
inv.topAnchor equalTo (minY + 72)
|
||||||
|
|
||||||
// offset by 1 on each edge to account for MC border
|
|
||||||
field.widthAnchor equalTo 82
|
field.widthAnchor equalTo 82
|
||||||
field.heightAnchor equalTo 11
|
field.heightAnchor equalTo 11
|
||||||
field.leftAnchor equalTo (minX + 56)
|
field.leftAnchor equalTo (minX + 57)
|
||||||
field.topAnchor equalTo (minY + 23)
|
field.topAnchor equalTo (minY + 23)
|
||||||
|
|
||||||
hStack.centerXAnchor equalTo view.centerXAnchor
|
hStack.centerXAnchor equalTo view.centerXAnchor
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.math.MathHelper
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
|
import net.shadowfacts.cacao.util.Color
|
||||||
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ScrollTrackView(
|
||||||
|
val scrollPositionChanged: (ScrollTrackView) -> Unit,
|
||||||
|
): View() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val THUMB = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png"), 52, 230)
|
||||||
|
private const val THUMB_WIDTH = 12.0
|
||||||
|
private const val THUMB_HEIGHT = 15.0
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var thumbView: TextureView
|
||||||
|
|
||||||
|
private var grabbedY: Double? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [0,1] normalized position of the scroll thumb.
|
||||||
|
*/
|
||||||
|
var scrollPosition: Double
|
||||||
|
get() = thumbView.frame.top / (frame.height - THUMB_HEIGHT)
|
||||||
|
set(value) {
|
||||||
|
val newTop = MathHelper.clamp(value, 0.0, 1.0) * (frame.height - THUMB_HEIGHT)
|
||||||
|
thumbView.frame = Rect(0.0, newTop, THUMB_WIDTH, THUMB_HEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
respondsToDragging = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun wasAdded() {
|
||||||
|
super.wasAdded()
|
||||||
|
|
||||||
|
thumbView = addSubview(TextureView(THUMB).apply {
|
||||||
|
usesConstraintBasedLayout = false
|
||||||
|
frame = Rect(0.0, 0.0, THUMB_WIDTH, THUMB_HEIGHT)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseDragged(point: Point, delta: Point, mouseButton: MouseButton): Boolean {
|
||||||
|
if (grabbedY == null && point !in thumbView.frame) {
|
||||||
|
val newCenter = MathHelper.clamp(point.y, THUMB_HEIGHT / 2, frame.height - THUMB_HEIGHT / 2)
|
||||||
|
thumbView.frame = Rect(0.0, newCenter - THUMB_HEIGHT / 2, THUMB_WIDTH, THUMB_HEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grabbedY == null) {
|
||||||
|
grabbedY = point.y - thumbView.frame.top
|
||||||
|
}
|
||||||
|
val newTop = MathHelper.clamp(point.y - grabbedY!!, 0.0, frame.height - THUMB_HEIGHT)
|
||||||
|
thumbView.frame = Rect(0.0, newTop, THUMB_WIDTH, THUMB_HEIGHT)
|
||||||
|
|
||||||
|
scrollPositionChanged(this)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseDragEnded(point: Point, mouseButton: MouseButton) {
|
||||||
|
grabbedY = null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
|
import net.shadowfacts.cacao.util.EnumHelper
|
||||||
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.button.AbstractButton
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class SortModeButton(
|
||||||
|
initialValue: SortMode,
|
||||||
|
): AbstractButton<SortModeButton>(
|
||||||
|
TextureView(TEXTURES[initialValue]!!).apply {
|
||||||
|
intrinsicContentSize = Size(16.0, 16.0)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val ID = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
||||||
|
private val TEXTURES = mapOf(
|
||||||
|
SortMode.COUNT_HIGH_FIRST to Texture(ID, 0, 230),
|
||||||
|
SortMode.COUNT_LOW_FIRST to Texture(ID, 16, 230),
|
||||||
|
SortMode.ALPHABETICAL to Texture(ID, 32, 230),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val textureView: TextureView
|
||||||
|
get() = content as TextureView
|
||||||
|
|
||||||
|
var value: SortMode = initialValue
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
textureView.texture = TEXTURES[value]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
||||||
|
if (!disabled) {
|
||||||
|
value = when (mouseButton) {
|
||||||
|
MouseButton.LEFT -> EnumHelper.next(value)
|
||||||
|
MouseButton.RIGHT -> EnumHelper.previous(value)
|
||||||
|
else -> {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.mouseClicked(point, mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.cacao.util.KeyModifiers
|
||||||
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.button.Button
|
||||||
|
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||||
|
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
import kotlin.math.ceil
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class TerminalRequestAmountViewController(
|
||||||
|
val screen: TerminalScreen,
|
||||||
|
val stack: ItemStack,
|
||||||
|
): ViewController() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val BACKGROUND = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal_amount.png"), 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var field: NumberField
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
val pane = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
pane.widthAnchor equalTo 158
|
||||||
|
pane.heightAnchor equalTo 62
|
||||||
|
pane.centerXAnchor equalTo view.centerXAnchor
|
||||||
|
pane.centerYAnchor equalTo view.centerYAnchor
|
||||||
|
}
|
||||||
|
|
||||||
|
val background = view.addSubview(TextureView(BACKGROUND)).apply {
|
||||||
|
zIndex = -1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
field = view.addSubview(AmountField(this)).apply {
|
||||||
|
drawBackground = false
|
||||||
|
}
|
||||||
|
field.becomeFirstResponder()
|
||||||
|
|
||||||
|
val requestLabel = Label("Request", shadow = true)
|
||||||
|
val request = view.addSubview(Button(requestLabel) {
|
||||||
|
doRequest()
|
||||||
|
})
|
||||||
|
|
||||||
|
val plusOneLabel = Label("+1", shadow = true)
|
||||||
|
val plusOne = view.addSubview(Button(plusOneLabel) {
|
||||||
|
field.number = (field.number ?: 1) + 1
|
||||||
|
})
|
||||||
|
val plusTenLabel = Label("+10", shadow = true)
|
||||||
|
val plusTen = view.addSubview(Button(plusTenLabel) {
|
||||||
|
val old = field.number ?: 1
|
||||||
|
field.number = ceil((old + 1) / 10.0).toInt() * 10
|
||||||
|
})
|
||||||
|
val plusHundredLabel = Label("+100", shadow = true)
|
||||||
|
val plusHundred = view.addSubview(Button(plusHundredLabel) {
|
||||||
|
val old = field.number ?: 1
|
||||||
|
field.number = ceil((old + 1) / 100.0).toInt() * 100
|
||||||
|
})
|
||||||
|
|
||||||
|
val minusOneLabel = Label("-1", shadow = true)
|
||||||
|
val minusOne = view.addSubview(Button(minusOneLabel) {
|
||||||
|
field.number = (field.number ?: 1) - 1
|
||||||
|
})
|
||||||
|
val minusTenLabel = Label("-10", shadow = true)
|
||||||
|
val minusTen = view.addSubview(Button(minusTenLabel) {
|
||||||
|
val old = field.number ?: 1
|
||||||
|
field.number = floor((old - 1) / 10.0).toInt() * 10
|
||||||
|
})
|
||||||
|
val minusHundredLabel = Label("-100", shadow = true)
|
||||||
|
val minusHundred = view.addSubview(Button(minusHundredLabel) {
|
||||||
|
val old = field.number ?: 1
|
||||||
|
field.number = floor((old - 1) / 100.0).toInt() * 100
|
||||||
|
})
|
||||||
|
|
||||||
|
view.solver.dsl {
|
||||||
|
background.leftAnchor equalTo pane.leftAnchor
|
||||||
|
background.rightAnchor equalTo pane.rightAnchor
|
||||||
|
background.topAnchor equalTo pane.topAnchor
|
||||||
|
background.bottomAnchor equalTo pane.bottomAnchor
|
||||||
|
|
||||||
|
field.leftAnchor equalTo (pane.leftAnchor + 8)
|
||||||
|
field.topAnchor equalTo (pane.topAnchor + 27)
|
||||||
|
field.widthAnchor equalTo 80
|
||||||
|
field.heightAnchor equalTo 9
|
||||||
|
|
||||||
|
request.leftAnchor equalTo (pane.leftAnchor + 101)
|
||||||
|
request.centerYAnchor equalTo field.centerYAnchor
|
||||||
|
request.widthAnchor equalTo 50
|
||||||
|
request.heightAnchor equalTo 20
|
||||||
|
|
||||||
|
plusOne.leftAnchor equalTo (pane.leftAnchor + 7)
|
||||||
|
plusTen.leftAnchor equalTo (plusOne.rightAnchor + 3)
|
||||||
|
plusHundred.leftAnchor equalTo (plusTen.rightAnchor + 3)
|
||||||
|
plusHundred.rightAnchor equalTo (pane.leftAnchor + 97)
|
||||||
|
plusOne.widthAnchor equalTo plusTen.widthAnchor
|
||||||
|
plusOne.widthAnchor equalTo plusHundred.widthAnchor
|
||||||
|
|
||||||
|
plusOne.topAnchor equalTo (pane.topAnchor + 7)
|
||||||
|
plusTen.topAnchor equalTo (pane.topAnchor + 7)
|
||||||
|
plusHundred.topAnchor equalTo (pane.topAnchor + 7)
|
||||||
|
plusOne.heightAnchor equalTo 14
|
||||||
|
plusTen.heightAnchor equalTo 14
|
||||||
|
plusHundred.heightAnchor equalTo 14
|
||||||
|
|
||||||
|
minusOne.leftAnchor equalTo (pane.leftAnchor + 7)
|
||||||
|
minusTen.leftAnchor equalTo (minusOne.rightAnchor + 3)
|
||||||
|
minusHundred.leftAnchor equalTo (minusTen.rightAnchor + 3)
|
||||||
|
minusHundred.rightAnchor equalTo (pane.leftAnchor + 97)
|
||||||
|
minusOne.widthAnchor equalTo minusTen.widthAnchor
|
||||||
|
minusOne.widthAnchor equalTo minusHundred.widthAnchor
|
||||||
|
|
||||||
|
minusOne.topAnchor equalTo (pane.topAnchor + 41)
|
||||||
|
minusTen.topAnchor equalTo (pane.topAnchor + 41)
|
||||||
|
minusHundred.topAnchor equalTo (pane.topAnchor + 41)
|
||||||
|
minusOne.heightAnchor equalTo 14
|
||||||
|
minusTen.heightAnchor equalTo 14
|
||||||
|
minusHundred.heightAnchor equalTo 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doRequest() {
|
||||||
|
screen.requestItem(stack, field.number ?: 1)
|
||||||
|
window!!.removeFromScreen()
|
||||||
|
}
|
||||||
|
|
||||||
|
class AmountField(val vc: TerminalRequestAmountViewController): NumberField(1) {
|
||||||
|
override fun keyPressed(keyCode: Int, modifiers: KeyModifiers): Boolean {
|
||||||
|
return if (super.keyPressed(keyCode, modifiers)) {
|
||||||
|
true
|
||||||
|
} else if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
||||||
|
vc.doRequest()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,10 +3,8 @@ package net.shadowfacts.phycon.block.terminal
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import net.minecraft.client.MinecraftClient
|
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.Element
|
||||||
import net.minecraft.client.gui.widget.AbstractButtonWidget
|
import net.minecraft.client.gui.screen.TickableElement
|
||||||
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget
|
|
||||||
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.render.Tessellator
|
import net.minecraft.client.render.Tessellator
|
||||||
import net.minecraft.client.render.VertexConsumerProvider
|
import net.minecraft.client.render.VertexConsumerProvider
|
||||||
|
@ -17,235 +15,67 @@ 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
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.text.TranslatableText
|
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.math.MathHelper
|
import net.shadowfacts.cacao.CacaoHandledScreen
|
||||||
|
import net.shadowfacts.cacao.window.ScreenHandlerWindow
|
||||||
|
import net.shadowfacts.cacao.window.Window
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
||||||
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
|
import net.shadowfacts.phycon.networking.C2STerminalUpdateDisplayedItems
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
import net.shadowfacts.phycon.util.next
|
|
||||||
import net.shadowfacts.phycon.util.prev
|
|
||||||
import org.lwjgl.glfw.GLFW
|
|
||||||
import java.lang.NumberFormatException
|
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
import java.util.LinkedList
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.floor
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
// todo: translate title
|
class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, title: Text): CacaoHandledScreen<TerminalScreenHandler>(handler, playerInv, title) {
|
||||||
class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory, title: Text): HandledScreen<TerminalScreenHandler>(handler, playerInv, title) {
|
|
||||||
companion object {
|
companion object {
|
||||||
private 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
|
val backgroundWidth: Int
|
||||||
private lateinit var sortButton: SortButton
|
get() = backgroundWidth
|
||||||
var sortButtonX: Int = 0
|
val backgroundHeight: Int
|
||||||
private set
|
get() = backgroundHeight
|
||||||
var sortButtonY = 0
|
|
||||||
private set
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
updateFocusedElement()
|
|
||||||
}
|
|
||||||
private var dialogChildren = mutableListOf<AbstractButtonWidget>()
|
|
||||||
|
|
||||||
private var scrollPosition = 0f
|
// val tickableElements = LinkedList<TickableElement>()
|
||||||
private var isDraggingScrollThumb = false
|
|
||||||
private val trackMinY = 18
|
|
||||||
private val trackHeight = 106
|
|
||||||
private val thumbHeight = 15
|
|
||||||
private val thumbWidth = 12
|
|
||||||
private val scrollThumbTop: Int
|
|
||||||
get() = trackMinY + (scrollPosition * (trackHeight - thumbHeight)).roundToInt()
|
|
||||||
|
|
||||||
private val dialogWidth = 158
|
val terminalVC = TerminalViewController(this, handler, handler.terminal)
|
||||||
private val dialogHeight = 62
|
var amountVC: TerminalRequestAmountViewController? = null
|
||||||
|
|
||||||
|
var searchQuery = ""
|
||||||
|
var scrollPosition = 0.0
|
||||||
|
var sortMode = SortMode.COUNT_HIGH_FIRST
|
||||||
|
|
||||||
init {
|
init {
|
||||||
backgroundWidth = 252
|
backgroundWidth = 252
|
||||||
backgroundHeight = 222
|
backgroundHeight = 222
|
||||||
}
|
|
||||||
|
|
||||||
override fun init() {
|
addWindow(ScreenHandlerWindow(handler, terminalVC))
|
||||||
super.init()
|
|
||||||
|
|
||||||
children.clear()
|
|
||||||
dialogChildren.clear()
|
|
||||||
|
|
||||||
client!!.keyboard.setRepeatEvents(true)
|
|
||||||
|
|
||||||
searchBox = TextFieldWidget(textRenderer, x + 138, y + 6, 80, 9, LiteralText("Search"))
|
|
||||||
searchBox.setMaxLength(50)
|
|
||||||
// setHasBorder is actually setDrawsBackground
|
|
||||||
searchBox.setHasBorder(false)
|
|
||||||
searchBox.isVisible = true
|
|
||||||
searchBox.setSelected(true)
|
|
||||||
searchBox.setEditableColor(0xffffff)
|
|
||||||
addChild(searchBox)
|
|
||||||
|
|
||||||
sortButtonX = x + 256
|
|
||||||
sortButtonY = y
|
|
||||||
sortButton = SortButton(sortButtonX, sortButtonY, handler.sortMode, {
|
|
||||||
requestUpdatedItems()
|
|
||||||
}, ::renderTooltip)
|
|
||||||
addButton(sortButton)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
updateFocusedElement()
|
|
||||||
requestUpdatedItems()
|
requestUpdatedItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFocusedElement() {
|
fun requestItem(stack: ItemStack, amount: Int) {
|
||||||
focused = if (showingAmountDialog) {
|
val netHandler = MinecraftClient.getInstance().player!!.networkHandler
|
||||||
amountBox
|
val packet = C2STerminalRequestItem(handler.terminal, stack, amount)
|
||||||
} else if (searchBox.isFocused) {
|
netHandler.sendPacket(packet)
|
||||||
searchBox
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestUpdatedItems() {
|
fun requestUpdatedItems() {
|
||||||
val player = MinecraftClient.getInstance().player!!
|
val player = MinecraftClient.getInstance().player!!
|
||||||
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchBox.text, sortButton.mode, scrollPosition))
|
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchQuery, sortMode, scrollPosition.toFloat()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
private fun showRequestAmountDialog(stack: ItemStack) {
|
||||||
super.tick()
|
val vc = TerminalRequestAmountViewController(this, stack)
|
||||||
searchBox.tick()
|
addWindow(Window(vc))
|
||||||
amountBox.tick()
|
amountVC = vc
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
|
||||||
textRenderer.draw(matrixStack, title, 65f, 6f, 0x404040)
|
|
||||||
textRenderer.draw(matrixStack, playerInventory.displayName, 65f, backgroundHeight - 94f, 0x404040)
|
|
||||||
textRenderer.draw(matrixStack, TranslatableText("gui.phycon.terminal_buffer"), 7f, 6f, 0x404040)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
|
||||||
// if the dialog is open, the background gradient will be drawn in front of the main terminal gui
|
|
||||||
if (!showingAmountDialog) {
|
|
||||||
renderBackground(matrixStack)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
// scroll thumb
|
|
||||||
drawTexture(matrixStack, x + 232, y + scrollThumbTop, 52, 230, thumbWidth, thumbHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
|
||||||
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
|
||||||
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)
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -299,21 +129,29 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
matrixStack.pop()
|
matrixStack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isPointInsScrollThumb(mouseX: Double, mouseY: Double): Boolean {
|
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||||
|
super.drawBackground(matrixStack, delta, mouseX, mouseY)
|
||||||
|
|
||||||
|
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||||
|
client!!.textureManager.bindTexture(BACKGROUND)
|
||||||
val x = (width - backgroundWidth) / 2
|
val x = (width - backgroundWidth) / 2
|
||||||
val y = (height - backgroundHeight) / 2
|
val y = (height - backgroundHeight) / 2
|
||||||
val thumbMinX = x + 232
|
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||||
val thumbMaxX = thumbMinX + thumbWidth
|
}
|
||||||
val thumbMinY = y + scrollThumbTop
|
|
||||||
val thumbMaxY = thumbMinY + thumbHeight
|
override fun tick() {
|
||||||
return mouseX >= thumbMinX && mouseX < thumbMaxX && mouseY >= thumbMinY && mouseY < thumbMaxY
|
super.tick()
|
||||||
|
|
||||||
|
if (amountVC != null) {
|
||||||
|
amountVC!!.field.tick()
|
||||||
|
} else {
|
||||||
|
terminalVC.searchField.tick()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
|
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
|
||||||
super.onMouseClick(slot, invSlot, clickData, type)
|
super.onMouseClick(slot, invSlot, clickData, type)
|
||||||
|
|
||||||
updateFocusedElement()
|
|
||||||
|
|
||||||
if (slot != null && !slot.stack.isEmpty && handler.isNetworkSlot(slot.id)) {
|
if (slot != null && !slot.stack.isEmpty && handler.isNetworkSlot(slot.id)) {
|
||||||
val stack = slot.stack
|
val stack = slot.stack
|
||||||
|
|
||||||
|
@ -325,210 +163,22 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
// right click, request half stack
|
// right click, request half stack
|
||||||
requestItem(stack, ceil(min(stack.count, stack.maxCount) / 2f).toInt())
|
requestItem(stack, ceil(min(stack.count, stack.maxCount) / 2f).toInt())
|
||||||
} else {
|
} else {
|
||||||
dialogStack = stack
|
showRequestAmountDialog(stack)
|
||||||
showingAmountDialog = true
|
// todo
|
||||||
searchBox.setSelected(false)
|
// dialogStack = stack
|
||||||
|
// showingAmountDialog = true
|
||||||
|
// searchBox.setSelected(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
private val fakeFocusedElement = TextFieldWidget(textRenderer, 0, 0, 0, 0, LiteralText(""))
|
||||||
if (showingAmountDialog) {
|
override fun getFocused(): Element? {
|
||||||
for (e in dialogChildren) {
|
return if (windows.last().firstResponder != null) {
|
||||||
if (e.mouseClicked(mouseX, mouseY, button)) {
|
fakeFocusedElement
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
} else {
|
} else {
|
||||||
if (isPointInsScrollThumb(mouseX, mouseY)) {
|
null
|
||||||
isDraggingScrollThumb = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.mouseClicked(mouseX, mouseY, button)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
|
||||||
if (showingAmountDialog) {
|
|
||||||
return false
|
|
||||||
} else if (isDraggingScrollThumb) {
|
|
||||||
scrollPosition = (mouseY.toFloat() - (y + trackMinY) - 7.5f) / (trackHeight - 15)
|
|
||||||
scrollPosition = MathHelper.clamp(scrollPosition, 0f, 1f)
|
|
||||||
requestUpdatedItems()
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
isDraggingScrollThumb = false
|
|
||||||
|
|
||||||
return super.mouseReleased(d, e, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
|
|
||||||
if (showingAmountDialog) {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
var newOffsetInRows = handler.currentScrollOffsetInRows() - amount.toInt()
|
|
||||||
newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, handler.maxScrollOffsetInRows())
|
|
||||||
val newScrollPosition = newOffsetInRows / handler.maxScrollOffsetInRows().toFloat()
|
|
||||||
scrollPosition = newScrollPosition
|
|
||||||
requestUpdatedItems()
|
|
||||||
|
|
||||||
return super.mouseScrolled(mouseX, mouseY, amount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun charTyped(c: Char, i: Int): Boolean {
|
|
||||||
if (showingAmountDialog) {
|
|
||||||
return amountBox.charTyped(c, i)
|
|
||||||
} else {
|
|
||||||
val oldText = searchBox.text
|
|
||||||
if (searchBox.charTyped(c, i)) {
|
|
||||||
if (searchBox.text != oldText) {
|
|
||||||
scrollPosition = 0f
|
|
||||||
requestUpdatedItems()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.charTyped(c, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun keyPressed(key: Int, j: Int, k: Int): Boolean {
|
|
||||||
if (showingAmountDialog) {
|
|
||||||
return when (key) {
|
|
||||||
GLFW.GLFW_KEY_ESCAPE -> {
|
|
||||||
showingAmountDialog = false
|
|
||||||
true
|
|
||||||
}
|
|
||||||
GLFW.GLFW_KEY_ENTER -> {
|
|
||||||
doDialogRequest()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
amountBox.keyPressed(key, j, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val oldText = searchBox.text
|
|
||||||
if (searchBox.keyPressed(key, j, k)) {
|
|
||||||
if (searchBox.text != oldText) {
|
|
||||||
scrollPosition = 0f
|
|
||||||
requestUpdatedItems()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return if (searchBox.isFocused && searchBox.isVisible && key != GLFW.GLFW_KEY_ESCAPE) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
super.keyPressed(key, j, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doDialogRequest() {
|
|
||||||
showingAmountDialog = false
|
|
||||||
requestItem(dialogStack, amountBox.intValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun requestItem(stack: ItemStack, amount: Int) {
|
|
||||||
val netHandler = MinecraftClient.getInstance().player!!.networkHandler
|
|
||||||
val packet = C2STerminalRequestItem(handler.terminal, stack, amount)
|
|
||||||
netHandler.sendPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SortButton(
|
|
||||||
x: Int,
|
|
||||||
y: Int,
|
|
||||||
var mode: SortMode,
|
|
||||||
val onChange: (SortMode) -> Unit,
|
|
||||||
val doRenderTooltip: (MatrixStack, Text, Int, Int) -> Unit
|
|
||||||
): AbstractPressableButtonWidget(x, y, 20, 20, LiteralText("")) {
|
|
||||||
override fun onPress() {}
|
|
||||||
|
|
||||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
|
||||||
if ((button == 0 || button == 1) && clicked(mouseX, mouseY)) {
|
|
||||||
val newVal = if (button == 0) mode.next else mode.prev
|
|
||||||
mode = newVal
|
|
||||||
onChange(mode)
|
|
||||||
|
|
||||||
playDownSound(MinecraftClient.getInstance().soundManager)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renderButton(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
|
||||||
val client = MinecraftClient.getInstance()
|
|
||||||
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
|
||||||
RenderSystem.enableBlend()
|
|
||||||
RenderSystem.defaultBlendFunc()
|
|
||||||
RenderSystem.enableDepthTest()
|
|
||||||
|
|
||||||
client.textureManager.bindTexture(WIDGETS_LOCATION)
|
|
||||||
val k = getYImage(isHovered)
|
|
||||||
drawTexture(matrixStack, x, y, 0, 46 + k * 20, width / 2, height)
|
|
||||||
drawTexture(matrixStack, x + width / 2, y, 200 - width / 2, 46 + k * 20, width / 2, height)
|
|
||||||
|
|
||||||
client.textureManager.bindTexture(BACKGROUND)
|
|
||||||
val u: Int = when (mode) {
|
|
||||||
SortMode.COUNT_HIGH_FIRST -> 0
|
|
||||||
SortMode.COUNT_LOW_FIRST -> 16
|
|
||||||
SortMode.ALPHABETICAL -> 32
|
|
||||||
}
|
|
||||||
drawTexture(matrixStack, x + 2, y + 2, u, 230, 16, 16)
|
|
||||||
|
|
||||||
if (isHovered) {
|
|
||||||
renderToolTip(matrixStack, mouseX, mouseY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun renderToolTip(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
|
||||||
val text = LiteralText("")
|
|
||||||
text.append("Sort by: ")
|
|
||||||
text.append(mode.tooltip)
|
|
||||||
doRenderTooltip(matrixStack, text, mouseX, mouseY)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
private set
|
private set
|
||||||
var totalEntries = 0
|
var totalEntries = 0
|
||||||
private set
|
private set
|
||||||
private var scrollPosition = 0f
|
var scrollPosition = 0f
|
||||||
private var itemEntries = listOf<Entry>()
|
private var itemEntries = listOf<Entry>()
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.text.TranslatableText
|
||||||
|
import net.minecraft.util.math.MathHelper
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.util.Color
|
||||||
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
import net.shadowfacts.cacao.view.textfield.TextField
|
||||||
|
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class TerminalViewController(
|
||||||
|
val screen: TerminalScreen,
|
||||||
|
val handler: TerminalScreenHandler,
|
||||||
|
val terminal: TerminalBlockEntity,
|
||||||
|
): ViewController() {
|
||||||
|
|
||||||
|
private lateinit var scrollTrack: ScrollTrackView
|
||||||
|
lateinit var sortMode: SortModeButton
|
||||||
|
private set
|
||||||
|
lateinit var searchField: TextField
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun loadView() {
|
||||||
|
view = ScrollHandlingView(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
val pane = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
pane.centerXAnchor equalTo view.centerXAnchor
|
||||||
|
pane.centerYAnchor equalTo view.centerYAnchor
|
||||||
|
pane.widthAnchor equalTo screen.backgroundWidth
|
||||||
|
pane.heightAnchor equalTo screen.backgroundHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
val buffer = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
buffer.leftAnchor equalTo (pane.leftAnchor + 7)
|
||||||
|
buffer.topAnchor equalTo (pane.topAnchor + 17)
|
||||||
|
buffer.widthAnchor equalTo (18 * 3)
|
||||||
|
buffer.heightAnchor equalTo (18 * 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
val network = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
network.leftAnchor equalTo (pane.leftAnchor + 65)
|
||||||
|
network.topAnchor equalTo buffer.topAnchor
|
||||||
|
network.widthAnchor equalTo (18 * 9)
|
||||||
|
network.heightAnchor equalTo (18 * 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
val playerInv = view.addLayoutGuide()
|
||||||
|
view.solver.dsl {
|
||||||
|
playerInv.leftAnchor equalTo network.leftAnchor
|
||||||
|
playerInv.topAnchor equalTo (pane.topAnchor + 139)
|
||||||
|
playerInv.widthAnchor equalTo (18 * 9)
|
||||||
|
playerInv.heightAnchor equalTo 76
|
||||||
|
}
|
||||||
|
|
||||||
|
val titleLabel = view.addSubview(Label(screen.title)).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
}
|
||||||
|
val playerInvLabel = view.addSubview(Label(handler.playerInv.displayName)).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
}
|
||||||
|
val bufferLabel = view.addSubview(Label(TranslatableText("gui.phycon.terminal_buffer"))).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
searchField = view.addSubview(TerminalSearchField()).apply {
|
||||||
|
handler = ::searchFieldChanged
|
||||||
|
drawBackground = false
|
||||||
|
}
|
||||||
|
searchField.becomeFirstResponder()
|
||||||
|
|
||||||
|
scrollTrack = view.addSubview(ScrollTrackView(::scrollPositionChanged))
|
||||||
|
|
||||||
|
sortMode = view.addSubview(SortModeButton(SortMode.COUNT_HIGH_FIRST)).apply {
|
||||||
|
handler = ::sortModeChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
view.solver.dsl {
|
||||||
|
titleLabel.leftAnchor equalTo network.leftAnchor
|
||||||
|
titleLabel.topAnchor equalTo (pane.topAnchor + 6)
|
||||||
|
|
||||||
|
bufferLabel.leftAnchor equalTo buffer.leftAnchor
|
||||||
|
bufferLabel.topAnchor equalTo titleLabel.topAnchor
|
||||||
|
|
||||||
|
playerInvLabel.leftAnchor equalTo playerInv.leftAnchor
|
||||||
|
playerInvLabel.topAnchor equalTo (pane.bottomAnchor - 94)
|
||||||
|
|
||||||
|
searchField.leftAnchor equalTo (pane.leftAnchor + 138)
|
||||||
|
searchField.topAnchor equalTo (pane.topAnchor + 5)
|
||||||
|
searchField.widthAnchor equalTo 80
|
||||||
|
searchField.heightAnchor equalTo 9
|
||||||
|
|
||||||
|
scrollTrack.leftAnchor equalTo (pane.leftAnchor + 232)
|
||||||
|
scrollTrack.topAnchor equalTo (network.topAnchor + 1)
|
||||||
|
scrollTrack.bottomAnchor equalTo (network.bottomAnchor - 1)
|
||||||
|
scrollTrack.widthAnchor equalTo 12
|
||||||
|
|
||||||
|
sortMode.leftAnchor equalTo pane.rightAnchor + 4
|
||||||
|
sortMode.topAnchor equalTo pane.topAnchor
|
||||||
|
sortMode.widthAnchor equalTo 20
|
||||||
|
sortMode.heightAnchor equalTo 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun searchFieldChanged(field: TextField) {
|
||||||
|
screen.searchQuery = field.text
|
||||||
|
screen.requestUpdatedItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scrollPositionChanged(track: ScrollTrackView) {
|
||||||
|
val oldOffset = handler.currentScrollOffsetInRows()
|
||||||
|
|
||||||
|
handler.scrollPosition = track.scrollPosition.toFloat()
|
||||||
|
screen.scrollPosition = track.scrollPosition
|
||||||
|
|
||||||
|
if (handler.currentScrollOffsetInRows() != oldOffset) {
|
||||||
|
screen.requestUpdatedItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sortModeChanged(button: SortModeButton) {
|
||||||
|
screen.sortMode = button.value
|
||||||
|
screen.requestUpdatedItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
class TerminalSearchField: TextField("") {
|
||||||
|
override fun resignFirstResponder() {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScrollHandlingView(val vc: TerminalViewController): View() {
|
||||||
|
override fun mouseScrolled(point: Point, amount: Double): Boolean {
|
||||||
|
var newOffsetInRows = vc.handler.currentScrollOffsetInRows() - amount.toInt()
|
||||||
|
newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, vc.handler.maxScrollOffsetInRows())
|
||||||
|
if (newOffsetInRows != vc.handler.currentScrollOffsetInRows()) {
|
||||||
|
val newScrollPosition = newOffsetInRows / vc.handler.maxScrollOffsetInRows().toDouble()
|
||||||
|
vc.screen.scrollPosition = newScrollPosition
|
||||||
|
vc.scrollTrack.scrollPosition = newScrollPosition
|
||||||
|
vc.screen.requestUpdatedItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 2.2 KiB |
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:black_carpet"},
|
"W": {"item": "minecraft:black_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_black",
|
"item": "phycon:cable_black",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:blue_carpet"},
|
"W": {"item": "minecraft:blue_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_blue",
|
"item": "phycon:cable_blue",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:brown_carpet"},
|
"W": {"item": "minecraft:brown_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_brown",
|
"item": "phycon:cable_brown",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:cyan_carpet"},
|
"W": {"item": "minecraft:cyan_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_cyan",
|
"item": "phycon:cable_cyan",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:gray_carpet"},
|
"W": {"item": "minecraft:gray_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_gray",
|
"item": "phycon:cable_gray",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:green_carpet"},
|
"W": {"item": "minecraft:green_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_green",
|
"item": "phycon:cable_green",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:light_blue_carpet"},
|
"W": {"item": "minecraft:light_blue_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_light_blue",
|
"item": "phycon:cable_light_blue",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:light_gray_carpet"},
|
"W": {"item": "minecraft:light_gray_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_light_gray",
|
"item": "phycon:cable_light_gray",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:lime_carpet"},
|
"W": {"item": "minecraft:lime_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_lime",
|
"item": "phycon:cable_lime",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:orange_carpet"},
|
"W": {"item": "minecraft:orange_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_orange",
|
"item": "phycon:cable_orange",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:orange_carpet"},
|
"W": {"item": "minecraft:orange_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_orange",
|
"item": "phycon:cable_orange",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:pink_carpet"},
|
"W": {"item": "minecraft:pink_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_pink",
|
"item": "phycon:cable_pink",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:purple_carpet"},
|
"W": {"item": "minecraft:purple_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_purple",
|
"item": "phycon:cable_purple",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:red_carpet"},
|
"W": {"item": "minecraft:red_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_red",
|
"item": "phycon:cable_red",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:white_carpet"},
|
"W": {"item": "minecraft:white_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_white",
|
"item": "phycon:cable_white",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"CCC",
|
"WWW",
|
||||||
"TRT",
|
"TRT",
|
||||||
"CCC"
|
"WWW"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"C": {"item": "minecraft:yellow_carpet"},
|
"W": {"item": "minecraft:yellow_wool"},
|
||||||
"T": {"item": "phycon:twisted_pair"},
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
"R": {"item": "minecraft:redstone"}
|
"R": {"item": "minecraft:redstone"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:cable_yellow",
|
"item": "phycon:cable_yellow",
|
||||||
"count": 3
|
"count": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"NNN",
|
"III",
|
||||||
" ",
|
" ",
|
||||||
"NNN"
|
"III"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"N": {"tag": "c:copper_nuggets"}
|
"I": {"tag": "c:copper_ingots"}
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"item": "phycon:twisted_pair"
|
"item": "phycon:twisted_pair",
|
||||||
|
"count": 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue