Compare commits
12 Commits
385e36918f
...
c9bcfd29d5
Author | SHA1 | Date |
---|---|---|
Shadowfacts | c9bcfd29d5 | |
Shadowfacts | 2198b5e10d | |
Shadowfacts | 1c405f8623 | |
Shadowfacts | 89e91796a5 | |
Shadowfacts | 219033476c | |
Shadowfacts | 32d87fbd9d | |
Shadowfacts | 72b8435834 | |
Shadowfacts | 5542f088f9 | |
Shadowfacts | 7cc96d78ad | |
Shadowfacts | da8b600f31 | |
Shadowfacts | 74aae99b36 | |
Shadowfacts | f321b2a06a |
|
@ -35,7 +35,7 @@ data class Rect(val left: Double, val top: Double, val width: Double, val height
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun contains(point: Point): Boolean {
|
operator fun contains(point: Point): Boolean {
|
||||||
return point.x in left..right && point.y in top..bottom
|
return point.x >= left && point.x < right && point.y >= top && point.y < bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.geometry.Size
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple View that displays text. Allows for controlling the color and shadow of the text. Label cannot be used
|
* A simple View that displays text. Allows for controlling the color and shadow of the text. Label cannot be used
|
||||||
|
@ -26,10 +27,10 @@ import net.shadowfacts.cacao.util.RenderHelper
|
||||||
*/
|
*/
|
||||||
class Label(
|
class Label(
|
||||||
text: Text,
|
text: Text,
|
||||||
val shadow: Boolean = false,
|
var shadow: Boolean = false,
|
||||||
val maxLines: Int = 0,
|
val maxLines: Int = 0,
|
||||||
val wrappingMode: WrappingMode = WrappingMode.WRAP,
|
val wrappingMode: WrappingMode = WrappingMode.WRAP,
|
||||||
val textAlignment: TextAlignment = TextAlignment.LEFT
|
var textAlignment: TextAlignment = TextAlignment.LEFT
|
||||||
): View() {
|
): View() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -59,7 +60,8 @@ class Label(
|
||||||
var text: Text = text
|
var text: Text = text
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
updateIntrinsicContentSize()
|
// todo: uhhhh
|
||||||
|
updateIntrinsicContentSize(true)
|
||||||
// todo: setNeedsLayout instead of force unwrapping window
|
// todo: setNeedsLayout instead of force unwrapping window
|
||||||
window!!.layout()
|
window!!.layout()
|
||||||
}
|
}
|
||||||
|
@ -75,15 +77,23 @@ class Label(
|
||||||
override fun wasAdded() {
|
override fun wasAdded() {
|
||||||
super.wasAdded()
|
super.wasAdded()
|
||||||
|
|
||||||
updateIntrinsicContentSize()
|
updateIntrinsicContentSize(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateIntrinsicContentSize() {
|
private fun updateIntrinsicContentSize(canWrap: Boolean): Boolean {
|
||||||
if (RenderHelper.disabled) return
|
if (RenderHelper.disabled) return false
|
||||||
|
|
||||||
val width = textRenderer.getWidth(text)
|
val oldSize = intrinsicContentSize
|
||||||
val height = textRenderer.fontHeight
|
if (wrappingMode == WrappingMode.WRAP && canWrap && hasSolver) {
|
||||||
intrinsicContentSize = Size(width.toDouble(), height.toDouble())
|
val lines = textRenderer.wrapLines(text, bounds.width.toInt())
|
||||||
|
val height = (if (maxLines == 0) lines.size else min(lines.size, maxLines)) * textRenderer.fontHeight
|
||||||
|
intrinsicContentSize = Size(bounds.width, height.toDouble())
|
||||||
|
} else {
|
||||||
|
val width = textRenderer.getWidth(text)
|
||||||
|
val height = textRenderer.fontHeight
|
||||||
|
intrinsicContentSize = Size(width.toDouble(), height.toDouble())
|
||||||
|
}
|
||||||
|
return oldSize != intrinsicContentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
||||||
|
@ -110,14 +120,22 @@ class Label(
|
||||||
super.didLayout()
|
super.didLayout()
|
||||||
|
|
||||||
computeLines()
|
computeLines()
|
||||||
|
if (updateIntrinsicContentSize(true)) {
|
||||||
|
// if the intrinsic content size changes, relayout
|
||||||
|
window!!.layout()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeLines() {
|
private fun computeLines() {
|
||||||
var lines = textRenderer.wrapLines(text, bounds.width.toInt())
|
if (wrappingMode == WrappingMode.WRAP) {
|
||||||
if (maxLines > 0 && maxLines < lines.size) {
|
var lines = textRenderer.wrapLines(text, bounds.width.toInt())
|
||||||
lines = lines.dropLast(lines.size - maxLines)
|
if (maxLines > 0 && maxLines < lines.size) {
|
||||||
|
lines = lines.dropLast(lines.size - maxLines)
|
||||||
|
}
|
||||||
|
this.lines = lines
|
||||||
|
} else {
|
||||||
|
this.lines = listOf(text.asOrderedText())
|
||||||
}
|
}
|
||||||
this.lines = lines
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ open class View(): Responder {
|
||||||
*/
|
*/
|
||||||
var solver: Solver by solverDelegate
|
var solver: Solver by solverDelegate
|
||||||
|
|
||||||
|
val hasSolver: Boolean
|
||||||
|
get() = solverDelegate.isInitialized
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the left edge of this view in the window's coordinate system.
|
* Layout anchor for the left edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
|
@ -92,17 +95,22 @@ open class View(): Responder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The rectangle for this view in the coordinate system of its superview view (or the window, if there is no superview).
|
* The rectangle for this view in the coordinate system of its superview view (or the window, if there is no superview).
|
||||||
* If using constraint based layout, this property is not initialized until [didLayout] called.
|
* If using constraint based layout, this property has zero dimensions until [didLayout] called.
|
||||||
* Otherwise, this must be set manually.
|
* Otherwise, this must be set manually.
|
||||||
* Setting this property updates the [bounds].
|
* Setting this property updates the [bounds].
|
||||||
*/
|
*/
|
||||||
var frame: Rect by ObservableLateInitProperty { this.bounds = Rect(Point.ORIGIN, it.size) }
|
var frame = Rect(0.0, 0.0, 0.0, 0.0)
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
bounds = Rect(Point.ORIGIN, value.size)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The rectangle for this view in its own coordinate system.
|
* The rectangle for this view in its own coordinate system.
|
||||||
* If using constraint based layout, this property is not initialized until [didLayout] called.
|
* If using constraint based layout, this property has zero dimensions until [didLayout] called.
|
||||||
* Otherwise, this will be initialized when [frame] is set.
|
* Otherwise, this will be initialized when [frame] is set.
|
||||||
*/
|
*/
|
||||||
lateinit var bounds: Rect
|
var bounds = Rect(0.0, 0.0, 0.0, 0.0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The position on the Z-axis of this view.
|
* The position on the Z-axis of this view.
|
||||||
|
@ -114,7 +122,7 @@ open class View(): Responder {
|
||||||
* The intrinsic size of this view's content. May be null if the view doesn't have any content or there is no
|
* The intrinsic size of this view's content. May be null if the view doesn't have any content or there is no
|
||||||
* intrinsic size.
|
* intrinsic size.
|
||||||
*
|
*
|
||||||
* Setting this creates/updates [no.birkett.kiwi.Strength.WEAK] constraints on this view's width/height using
|
* Setting this creates/updates [no.birkett.kiwi.Strength.MEDIUM] constraints on this view's width/height using
|
||||||
* the size.
|
* the size.
|
||||||
*/
|
*/
|
||||||
var intrinsicContentSize: Size? = null
|
var intrinsicContentSize: Size? = null
|
||||||
|
@ -182,7 +190,7 @@ open class View(): Responder {
|
||||||
subviewsSortedByZIndex = subviews.sortedBy(View::zIndex)
|
subviewsSortedByZIndex = subviews.sortedBy(View::zIndex)
|
||||||
|
|
||||||
view.superview = this
|
view.superview = this
|
||||||
if (solverDelegate.isInitialized) {
|
if (hasSolver) {
|
||||||
view.solver = solver
|
view.solver = solver
|
||||||
}
|
}
|
||||||
view.window = window
|
view.window = window
|
||||||
|
@ -293,7 +301,7 @@ open class View(): Responder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateIntrinsicContentSizeConstraints(old: Size?, new: Size?) {
|
private fun updateIntrinsicContentSizeConstraints(old: Size?, new: Size?) {
|
||||||
if (!usesConstraintBasedLayout || !solverDelegate.isInitialized) return
|
if (!usesConstraintBasedLayout || !hasSolver) return
|
||||||
|
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
solver.removeConstraint(intrinsicContentSizeWidthConstraint!!)
|
solver.removeConstraint(intrinsicContentSizeWidthConstraint!!)
|
||||||
|
|
|
@ -1,25 +1,31 @@
|
||||||
package net.shadowfacts.cacao.view.button
|
package net.shadowfacts.cacao.view.button
|
||||||
|
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.cacao.geometry.Point
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.geometry.Size
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
import net.shadowfacts.cacao.util.texture.Texture
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
import net.shadowfacts.cacao.view.TextureView
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A button for toggling between on/off states.
|
* A button for toggling between on/off states.
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
* @param initialState Whether the button starts as on or off.
|
* @param initialState Whether the button starts as on or off.
|
||||||
|
* @param handler The handler function to invoke when this button is pressed.
|
||||||
*/
|
*/
|
||||||
class ToggleButton(initialState: Boolean): AbstractButton<ToggleButton>(TextureView(if (initialState) ON else OFF).apply {
|
class ToggleButton(
|
||||||
intrinsicContentSize = Size(19.0, 19.0)
|
initialState: Boolean,
|
||||||
}, padding = 0.0) {
|
handler: ((ToggleButton) -> Unit)? = null,
|
||||||
|
): AbstractButton<ToggleButton>(TextureView(if (initialState) ON else OFF), padding = 0.0) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ON = Texture(Identifier("asmr", "textures/gui/toggle.png"), 0, 0)
|
val OFF = Texture(Identifier("textures/gui/checkbox.png"), 0, 0, 64, 64)
|
||||||
val OFF = Texture(Identifier("asmr", "textures/gui/toggle.png"), 0, 19)
|
val OFF_HOVERED = Texture(Identifier("textures/gui/checkbox.png"), 20, 0, 64, 64)
|
||||||
|
val ON = Texture(Identifier("textures/gui/checkbox.png"), 0, 20, 64, 64)
|
||||||
|
val ON_HOVERED = Texture(Identifier("textures/gui/checkbox.png"), 20, 20, 64, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val textureView: TextureView
|
private val textureView: TextureView
|
||||||
|
@ -30,10 +36,15 @@ class ToggleButton(initialState: Boolean): AbstractButton<ToggleButton>(TextureV
|
||||||
* Updating this property updates the button's texture.
|
* Updating this property updates the button's texture.
|
||||||
*/
|
*/
|
||||||
var state: Boolean = initialState
|
var state: Boolean = initialState
|
||||||
set(value) {
|
|
||||||
field = value
|
init {
|
||||||
textureView.texture = if (value) ON else OFF
|
this.handler = handler
|
||||||
}
|
intrinsicContentSize = Size(20.0, 20.0)
|
||||||
|
|
||||||
|
background = null
|
||||||
|
disabledBackground = null
|
||||||
|
hoveredBackground = null
|
||||||
|
}
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
||||||
if (!disabled && (mouseButton == MouseButton.LEFT || mouseButton == MouseButton.RIGHT)) {
|
if (!disabled && (mouseButton == MouseButton.LEFT || mouseButton == MouseButton.RIGHT)) {
|
||||||
|
@ -43,4 +54,17 @@ class ToggleButton(initialState: Boolean): AbstractButton<ToggleButton>(TextureV
|
||||||
return super.mouseClicked(point, mouseButton)
|
return super.mouseClicked(point, mouseButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
||||||
|
val hovered = mouse in bounds
|
||||||
|
textureView.texture = if (state) {
|
||||||
|
if (hovered) ON_HOVERED else ON
|
||||||
|
} else {
|
||||||
|
if (hovered) OFF_HOVERED else OFF
|
||||||
|
}
|
||||||
|
|
||||||
|
super.draw(matrixStack, mouse, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCurrentBackground(mouse: Point) = null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import net.shadowfacts.cacao.geometry.Axis
|
||||||
import net.shadowfacts.cacao.geometry.Point
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.geometry.Rect
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
import net.shadowfacts.cacao.geometry.Size
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
import net.shadowfacts.cacao.util.texture.NinePatchTexture
|
import net.shadowfacts.cacao.util.texture.NinePatchTexture
|
||||||
import net.shadowfacts.cacao.util.texture.Texture
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
@ -97,6 +98,7 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
|
|
||||||
private lateinit var outerStack: StackView
|
private lateinit var outerStack: StackView
|
||||||
private lateinit var tabStack: StackView
|
private lateinit var tabStack: StackView
|
||||||
|
private lateinit var currentTabController: ViewController
|
||||||
// todo: this shouldn't be public, use layout guides
|
// todo: this shouldn't be public, use layout guides
|
||||||
lateinit var tabVCContainer: View
|
lateinit var tabVCContainer: View
|
||||||
private set
|
private set
|
||||||
|
@ -121,7 +123,11 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
tabVCContainer.zIndex = 1.0
|
tabVCContainer.zIndex = 1.0
|
||||||
view.addSubview(tabVCContainer)
|
view.addSubview(tabVCContainer)
|
||||||
|
|
||||||
embedChild(currentTab.controller, tabVCContainer)
|
currentTabController = currentTab.controller
|
||||||
|
currentTabController.willMoveTo(this)
|
||||||
|
embedChild(currentTabController, tabVCContainer)
|
||||||
|
currentTabController.didMoveTo(this)
|
||||||
|
// will/did appear events for the initial VC are provided by this class' implementations of those
|
||||||
|
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
outerStack.leftAnchor equalTo view.leftAnchor
|
outerStack.leftAnchor equalTo view.leftAnchor
|
||||||
|
@ -136,6 +142,26 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun viewWillAppear() {
|
||||||
|
super.viewWillAppear()
|
||||||
|
currentTabController.viewWillAppear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun viewDidAppear() {
|
||||||
|
super.viewDidAppear()
|
||||||
|
currentTabController.viewDidAppear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun viewWillDisappear() {
|
||||||
|
super.viewWillDisappear()
|
||||||
|
currentTabController.viewWillDisappear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun viewDidDisappear() {
|
||||||
|
super.viewDidDisappear()
|
||||||
|
currentTabController.viewDidDisappear()
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateTabButtons() {
|
private fun updateTabButtons() {
|
||||||
while (tabStack.arrangedSubviews.isNotEmpty()) tabStack.removeArrangedSubview(tabStack.arrangedSubviews.first())
|
while (tabStack.arrangedSubviews.isNotEmpty()) tabStack.removeArrangedSubview(tabStack.arrangedSubviews.first())
|
||||||
|
|
||||||
|
@ -186,8 +212,20 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
tabButtons.forEach {
|
tabButtons.forEach {
|
||||||
it.setSelected(it.tab === tab)
|
it.setSelected(it.tab === tab)
|
||||||
}
|
}
|
||||||
oldTab.controller.removeFromParent()
|
currentTabController.viewWillDisappear()
|
||||||
embedChild(currentTab.controller, tabVCContainer)
|
currentTabController.view.removeFromSuperview()
|
||||||
|
currentTabController.viewDidDisappear()
|
||||||
|
currentTabController.willMoveTo(null)
|
||||||
|
currentTabController.removeFromParent()
|
||||||
|
currentTabController.didMoveTo(null)
|
||||||
|
|
||||||
|
currentTabController = currentTab.controller
|
||||||
|
|
||||||
|
currentTabController.willMoveTo(this)
|
||||||
|
embedChild(currentTabController, tabVCContainer)
|
||||||
|
currentTabController.didMoveTo(this)
|
||||||
|
currentTabController.viewWillAppear()
|
||||||
|
currentTabController.viewDidAppear()
|
||||||
|
|
||||||
onTabChange?.invoke(currentTab)
|
onTabChange?.invoke(currentTab)
|
||||||
|
|
||||||
|
@ -202,7 +240,7 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
padding = 2.0
|
padding = 2.0
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val BACKGROUND = Identifier("textures/gui/container/creative_inventory/tabs.png")
|
val BACKGROUND = Identifier("phycon:textures/gui/tabs.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
private var selected = false
|
private var selected = false
|
||||||
|
@ -256,7 +294,7 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
val u = when {
|
val u = when {
|
||||||
superview == null -> 0
|
superview == null -> 0
|
||||||
frame.left == 0.0 -> 0
|
frame.left == 0.0 -> 0
|
||||||
frame.right == superview!!.bounds.right -> 140
|
frame.right == superview!!.bounds.right -> 56
|
||||||
else -> 28
|
else -> 28
|
||||||
}
|
}
|
||||||
backgroundView.texture = Texture(BACKGROUND, u, v)
|
backgroundView.texture = Texture(BACKGROUND, u, v)
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package net.shadowfacts.phycon
|
package net.shadowfacts.phycon
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer
|
import net.fabricmc.api.ClientModInitializer
|
||||||
|
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
||||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry
|
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry
|
||||||
import net.shadowfacts.phycon.block.inserter.InserterScreen
|
import net.shadowfacts.phycon.block.inserter.InserterScreen
|
||||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreen
|
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreen
|
||||||
import net.shadowfacts.phycon.init.PhyScreens
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalScreen
|
import net.shadowfacts.phycon.block.terminal.TerminalScreen
|
||||||
|
import net.shadowfacts.phycon.client.PhyModelProvider
|
||||||
import net.shadowfacts.phycon.networking.ClientReceiver
|
import net.shadowfacts.phycon.networking.ClientReceiver
|
||||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||||
|
|
||||||
|
@ -16,6 +18,8 @@ import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
object PhysicalConnectivityClient: ClientModInitializer {
|
||||||
|
|
||||||
override fun onInitializeClient() {
|
override fun onInitializeClient() {
|
||||||
|
ModelLoadingRegistry.INSTANCE.registerResourceProvider(::PhyModelProvider)
|
||||||
|
|
||||||
ScreenRegistry.register(PhyScreens.TERMINAL, ::TerminalScreen)
|
ScreenRegistry.register(PhyScreens.TERMINAL, ::TerminalScreen)
|
||||||
ScreenRegistry.register(PhyScreens.INSERTER, ::InserterScreen)
|
ScreenRegistry.register(PhyScreens.INSERTER, ::InserterScreen)
|
||||||
ScreenRegistry.register(PhyScreens.REDSTONE_EMITTER, ::RedstoneEmitterScreen)
|
ScreenRegistry.register(PhyScreens.REDSTONE_EMITTER, ::RedstoneEmitterScreen)
|
||||||
|
|
|
@ -119,10 +119,11 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type),
|
||||||
|
|
||||||
open fun findDestination(): Interface? {
|
open fun findDestination(): Interface? {
|
||||||
val sides = (cachedState.block as NetworkComponentBlock).getNetworkConnectedSides(cachedState, world!!, pos)
|
val sides = (cachedState.block as NetworkComponentBlock).getNetworkConnectedSides(cachedState, world!!, pos)
|
||||||
if (sides.size != 1) {
|
return when (sides.size) {
|
||||||
throw RuntimeException("DeviceBlockEntity.findDestination must be overridden by devices which have more than 1 network connected side")
|
0 -> null
|
||||||
|
1 -> NetworkUtil.findConnectedInterface(world!!, pos, sides.first())
|
||||||
|
else -> throw RuntimeException("DeviceBlockEntity.findDestination must be overridden by devices which have more than 1 network connected side")
|
||||||
}
|
}
|
||||||
return NetworkUtil.findConnectedInterface(world!!, pos, sides.first())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraft.item.ItemPlacementContext
|
||||||
import net.minecraft.state.StateManager
|
import net.minecraft.state.StateManager
|
||||||
import net.minecraft.state.property.EnumProperty
|
import net.minecraft.state.property.EnumProperty
|
||||||
import net.minecraft.state.property.Properties
|
import net.minecraft.state.property.Properties
|
||||||
|
import net.minecraft.util.StringIdentifiable
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.Direction
|
import net.minecraft.util.math.Direction
|
||||||
import net.minecraft.util.shape.VoxelShape
|
import net.minecraft.util.shape.VoxelShape
|
||||||
|
@ -26,7 +27,36 @@ import java.util.*
|
||||||
abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): DeviceBlock<T>(settings) {
|
abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): DeviceBlock<T>(settings) {
|
||||||
companion object {
|
companion object {
|
||||||
val FACING = Properties.FACING
|
val FACING = Properties.FACING
|
||||||
val CABLE_CONNECTION = EnumProperty.of("cable_connection", Direction::class.java)
|
val CABLE_CONNECTION = EnumProperty.of("cable_connection", FaceCableConnection::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FaceCableConnection : StringIdentifiable {
|
||||||
|
NONE, DOWN, UP, NORTH, SOUTH, WEST, EAST;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(dir: Direction?) = when (dir) {
|
||||||
|
null -> NONE
|
||||||
|
Direction.DOWN -> DOWN
|
||||||
|
Direction.UP -> UP
|
||||||
|
Direction.NORTH -> NORTH
|
||||||
|
Direction.SOUTH -> SOUTH
|
||||||
|
Direction.WEST -> WEST
|
||||||
|
Direction.EAST -> EAST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val direction: Direction?
|
||||||
|
get() = when (this) {
|
||||||
|
NONE -> null
|
||||||
|
DOWN -> Direction.DOWN
|
||||||
|
UP -> Direction.UP
|
||||||
|
NORTH -> Direction.NORTH
|
||||||
|
SOUTH -> Direction.SOUTH
|
||||||
|
WEST -> Direction.WEST
|
||||||
|
EAST -> Direction.EAST
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun asString() = name.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract val faceThickness: Double
|
protected abstract val faceThickness: Double
|
||||||
|
@ -41,20 +71,21 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
Direction.EAST to createCuboidShape(6.0, 6.0, 6.0, 16.0 - faceThickness, 10.0, 10.0)
|
Direction.EAST to createCuboidShape(6.0, 6.0, 6.0, 16.0 - faceThickness, 10.0, 10.0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
private val shapeCache = mutableMapOf<Pair<Direction, Direction>, VoxelShape>()
|
private val shapeCache = mutableMapOf<Pair<Direction, FaceCableConnection>, VoxelShape>()
|
||||||
|
|
||||||
fun getShape(facing: Direction, cableConnection: Direction): VoxelShape {
|
private fun getShape(facing: Direction, cableConnection: FaceCableConnection): VoxelShape {
|
||||||
return shapeCache.getOrPut(facing to cableConnection) {
|
return shapeCache.getOrPut(facing to cableConnection) {
|
||||||
VoxelShapes.union(
|
if (cableConnection == FaceCableConnection.NONE) {
|
||||||
faceShapes[facing],
|
VoxelShapes.union(faceShapes[facing], centerShapes[facing])
|
||||||
centerShapes[facing],
|
} else {
|
||||||
CableBlock.SIDE_SHAPES[cableConnection]
|
VoxelShapes.union(faceShapes[facing], centerShapes[facing], CableBlock.SIDE_SHAPES[cableConnection.direction])
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
||||||
return EnumSet.of(state[CABLE_CONNECTION])
|
val direction = state[CABLE_CONNECTION].direction
|
||||||
|
return if (direction != null) EnumSet.of(direction) else setOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
||||||
|
@ -73,13 +104,13 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
|
|
||||||
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
||||||
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
|
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
|
||||||
val cableConnection = getCableConnectedSide(context.world, context.blockPos, facing) ?: facing.opposite
|
val cableConnection = FaceCableConnection.from(getCableConnectedSide(context.world, context.blockPos, facing))
|
||||||
return defaultState
|
return defaultState
|
||||||
.with(FACING, facing)
|
.with(FACING, facing)
|
||||||
.with(CABLE_CONNECTION, cableConnection)
|
.with(CABLE_CONNECTION, cableConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getCableConnectedSide(world: World, pos: BlockPos, facing: Direction): Direction? {
|
private fun getCableConnectedSide(world: WorldAccess, pos: BlockPos, facing: Direction): Direction? {
|
||||||
for (side in Direction.values()) {
|
for (side in Direction.values()) {
|
||||||
if (side == facing) {
|
if (side == facing) {
|
||||||
continue
|
continue
|
||||||
|
@ -95,10 +126,21 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||||
if (neighborState.block is NetworkComponentBlock && world.getBlockState(pos.offset(state[CABLE_CONNECTION])).block !is NetworkComponentBlock) {
|
val current = state[CABLE_CONNECTION]
|
||||||
return state.with(CABLE_CONNECTION, side)
|
var newConnection = current
|
||||||
|
|
||||||
|
if (current == FaceCableConnection.NONE) {
|
||||||
|
if (neighborState.block is NetworkComponentBlock) {
|
||||||
|
newConnection = FaceCableConnection.from(side)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val currentConnectedPos = pos.offset(current.direction)
|
||||||
|
if (neighborPos == currentConnectedPos && neighborState.block !is NetworkComponentBlock) {
|
||||||
|
// the old cable connection is no longer correct, try to find another
|
||||||
|
newConnection = FaceCableConnection.from(getCableConnectedSide(world, pos, state[FACING]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state.with(CABLE_CONNECTION, newConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||||
import net.shadowfacts.phycon.component.ActivationController
|
import net.shadowfacts.phycon.component.ActivationController
|
||||||
import net.shadowfacts.phycon.component.NetworkStackDispatcher
|
import net.shadowfacts.phycon.component.NetworkStackDispatcher
|
||||||
|
import net.shadowfacts.phycon.component.finishTimedOutPendingInsertions
|
||||||
import net.shadowfacts.phycon.component.handleItemStack
|
import net.shadowfacts.phycon.component.handleItemStack
|
||||||
import net.shadowfacts.phycon.packet.CapacityPacket
|
import net.shadowfacts.phycon.packet.CapacityPacket
|
||||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||||
|
@ -84,6 +85,8 @@ class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
|
||||||
|
|
||||||
if (!world!!.isClient) {
|
if (!world!!.isClient) {
|
||||||
controller.tick()
|
controller.tick()
|
||||||
|
|
||||||
|
finishTimedOutPendingInsertions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
||||||
|
|
||||||
override var providerPriority = 0
|
override var providerPriority = 0
|
||||||
override var receiverPriority = 0
|
override var receiverPriority = 0
|
||||||
|
var syncPriorities = true
|
||||||
|
|
||||||
// todo: should this be a weak ref?
|
// todo: should this be a weak ref?
|
||||||
private var inventory: GroupedItemInv? = null
|
private var inventory: GroupedItemInv? = null
|
||||||
|
@ -121,11 +122,13 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
||||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||||
tag.putInt("ProviderPriority", providerPriority)
|
tag.putInt("ProviderPriority", providerPriority)
|
||||||
tag.putInt("ReceiverPriority", receiverPriority)
|
tag.putInt("ReceiverPriority", receiverPriority)
|
||||||
|
tag.putBoolean("SyncPriorities", syncPriorities)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||||
providerPriority = tag.getInt("ProviderPriority")
|
providerPriority = tag.getInt("ProviderPriority")
|
||||||
receiverPriority = tag.getInt("ReceiverPriority")
|
receiverPriority = tag.getInt("ReceiverPriority")
|
||||||
|
syncPriorities = tag.getBoolean("SyncPriorities")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,24 @@ package net.shadowfacts.phycon.block.netswitch
|
||||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
import net.minecraft.block.entity.BlockEntity
|
import net.minecraft.block.entity.BlockEntity
|
||||||
import net.minecraft.entity.ItemEntity
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.util.Tickable
|
import net.minecraft.util.Tickable
|
||||||
import net.minecraft.util.math.Direction
|
import net.minecraft.util.math.Direction
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.api.Interface
|
import net.shadowfacts.phycon.api.Interface
|
||||||
import net.shadowfacts.phycon.api.frame.EthernetFrame
|
import net.shadowfacts.phycon.api.frame.EthernetFrame
|
||||||
import net.shadowfacts.phycon.api.frame.PacketFrame
|
import net.shadowfacts.phycon.api.frame.PacketFrame
|
||||||
|
import net.shadowfacts.phycon.api.util.IPAddress
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
|
import net.shadowfacts.phycon.frame.BasePacketFrame
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.util.NetworkUtil
|
|
||||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||||
|
import net.shadowfacts.phycon.util.NetworkUtil
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import java.util.Deque
|
||||||
|
import java.util.LinkedList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -25,13 +30,14 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
|
||||||
Tickable {
|
Tickable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var SWITCHING_CAPACITY = 256 // 256 items/tick
|
var SWITCHING_CAPACITY = 256 // 256 packets/tick
|
||||||
}
|
}
|
||||||
|
|
||||||
val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) }
|
val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) }
|
||||||
|
|
||||||
private val macTable = mutableMapOf<MACAddress, Direction>()
|
private val macTable = mutableMapOf<MACAddress, Direction>()
|
||||||
private var itemsHandledThisTick = 0
|
private var packetsHandledThisTick = 0
|
||||||
|
private var delayedPackets: Deque<Pair<PacketFrame, SwitchInterface>> = LinkedList()
|
||||||
|
|
||||||
fun interfaceForSide(side: Direction): SwitchInterface {
|
fun interfaceForSide(side: Direction): SwitchInterface {
|
||||||
return interfaces.find { it.side == side }!!
|
return interfaces.find { it.side == side }!!
|
||||||
|
@ -40,18 +46,20 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
|
||||||
private fun handle(frame: EthernetFrame, fromItf: SwitchInterface) {
|
private fun handle(frame: EthernetFrame, fromItf: SwitchInterface) {
|
||||||
macTable[frame.source] = fromItf.side
|
macTable[frame.source] = fromItf.side
|
||||||
|
|
||||||
if (frame is PacketFrame && frame.packet is ItemStackPacket) {
|
if (frame is PacketFrame) {
|
||||||
val packet = frame.packet as ItemStackPacket
|
if (packetsHandledThisTick > SWITCHING_CAPACITY) {
|
||||||
if (itemsHandledThisTick + packet.stack.count > SWITCHING_CAPACITY) {
|
PhysicalConnectivity.NETWORK_LOGGER.debug("{} reached capacity, delaying forwarding {}", this, frame)
|
||||||
// todo: calculate entity spawn point by finding non-obstructed location
|
delayedPackets.addLast(frame to fromItf)
|
||||||
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
|
|
||||||
world!!.spawnEntity(entity)
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
itemsHandledThisTick += packet.stack.count
|
packetsHandledThisTick++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resend(frame, fromItf)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resend(frame: EthernetFrame, fromItf: SwitchInterface) {
|
||||||
if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) {
|
if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) {
|
||||||
val dir = macTable[frame.destination]!!
|
val dir = macTable[frame.destination]!!
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir)
|
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir)
|
||||||
|
@ -75,11 +83,30 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
itemsHandledThisTick = 0
|
packetsHandledThisTick = 0
|
||||||
|
|
||||||
|
while (delayedPackets.isNotEmpty() && packetsHandledThisTick <= SWITCHING_CAPACITY) {
|
||||||
|
val (frame, fromItf) = delayedPackets.pop()
|
||||||
|
resend(frame, fromItf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||||
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
|
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
|
||||||
|
val list = ListTag()
|
||||||
|
for ((frame, fromItf) in delayedPackets) {
|
||||||
|
val packet = frame.packet
|
||||||
|
if (packet !is ItemStackPacket) continue
|
||||||
|
val compound = CompoundTag()
|
||||||
|
compound.putInt("FromItfSide", fromItf.side.ordinal)
|
||||||
|
compound.putInt("SourceIP", packet.source.address)
|
||||||
|
compound.putInt("DestinationIP", packet.destination.address)
|
||||||
|
compound.putLong("SourceMAC", frame.source.address)
|
||||||
|
compound.putLong("DestinationMAC", frame.destination.address)
|
||||||
|
compound.put("Stack", packet.stack.toTag(CompoundTag()))
|
||||||
|
list.add(compound)
|
||||||
|
}
|
||||||
|
tag.put("DelayedStackPackets", list)
|
||||||
return super.toTag(tag)
|
return super.toTag(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +115,21 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
|
||||||
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
|
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
|
||||||
interfaces[i].macAddress = MACAddress(l)
|
interfaces[i].macAddress = MACAddress(l)
|
||||||
}
|
}
|
||||||
|
tag.getList("DelayedStackPackets", 10).forEach { it ->
|
||||||
|
val compound = it as CompoundTag
|
||||||
|
val fromItfSide = Direction.values()[compound.getInt("FromItfSide")]
|
||||||
|
val fromItf = interfaces.find { it.side == fromItfSide }!!
|
||||||
|
val sourceIP = IPAddress(compound.getInt("SourceIP"))
|
||||||
|
val destinationIP = IPAddress(compound.getInt("DestinationIP"))
|
||||||
|
val sourceMAC = MACAddress(compound.getLong("SourceMAC"))
|
||||||
|
val destinationMAC = MACAddress(compound.getLong("DestinationMAC"))
|
||||||
|
val stack = ItemStack.fromTag(compound.getCompound("Stack"))
|
||||||
|
if (!stack.isEmpty) {
|
||||||
|
val packet = ItemStackPacket(stack, sourceIP, destinationIP)
|
||||||
|
val frame = BasePacketFrame(packet, sourceMAC, destinationMAC)
|
||||||
|
delayedPackets.addLast(frame to fromItf)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||||
|
|
|
@ -2,13 +2,20 @@ package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
import alexiil.mc.lib.attributes.AttributeList
|
import alexiil.mc.lib.attributes.AttributeList
|
||||||
import alexiil.mc.lib.attributes.AttributeProvider
|
import alexiil.mc.lib.attributes.AttributeProvider
|
||||||
|
import net.minecraft.block.Block
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
import net.minecraft.block.Material
|
import net.minecraft.block.Material
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.server.world.ServerWorld
|
||||||
import net.minecraft.sound.BlockSoundGroup
|
import net.minecraft.sound.BlockSoundGroup
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.Properties
|
||||||
import net.minecraft.util.ActionResult
|
import net.minecraft.util.ActionResult
|
||||||
import net.minecraft.util.Hand
|
import net.minecraft.util.Hand
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.ItemScatterer
|
||||||
import net.minecraft.util.hit.BlockHitResult
|
import net.minecraft.util.hit.BlockHitResult
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.Direction
|
import net.minecraft.util.math.Direction
|
||||||
|
@ -18,7 +25,7 @@ import net.minecraft.world.WorldAccess
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||||
import net.shadowfacts.phycon.block.DeviceBlock
|
import net.shadowfacts.phycon.block.DeviceBlock
|
||||||
import java.util.*
|
import java.util.EnumSet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -33,10 +40,22 @@ class TerminalBlock: DeviceBlock<TerminalBlockEntity>(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
|
val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
|
||||||
|
val FACING = Properties.FACING
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
||||||
return EnumSet.allOf(Direction::class.java)
|
val set = EnumSet.allOf(Direction::class.java)
|
||||||
|
set.remove(state[FACING])
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
super.appendProperties(builder)
|
||||||
|
builder.add(FACING)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
||||||
|
return defaultState.with(FACING, context.playerLookDirection.opposite)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity()
|
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity()
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package net.shadowfacts.phycon.client
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.client.model.ModelProviderContext
|
||||||
|
import net.fabricmc.fabric.api.client.model.ModelResourceProvider
|
||||||
|
import net.minecraft.client.render.model.UnbakedModel
|
||||||
|
import net.minecraft.resource.ResourceManager
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.client.model.RedstoneControllerModel
|
||||||
|
import net.shadowfacts.phycon.client.model.SimpleFaceDeviceModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class PhyModelProvider(resourceManager: ResourceManager) : ModelResourceProvider {
|
||||||
|
companion object {
|
||||||
|
val INTERFACE = Identifier(PhysicalConnectivity.MODID, "block/network_interface")
|
||||||
|
val INTERFACE_SIDE = Identifier(PhysicalConnectivity.MODID, "block/interface_side")
|
||||||
|
val REDSTONE_CONTROLLER = Identifier(PhysicalConnectivity.MODID, "block/redstone_controller")
|
||||||
|
val REDSTONE_EMITTER = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter")
|
||||||
|
val REDSTONE_EMITTER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/redstone_emitter_side")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadModelResource(resourceId: Identifier, context: ModelProviderContext): UnbakedModel? {
|
||||||
|
return when (resourceId) {
|
||||||
|
INTERFACE -> SimpleFaceDeviceModel(INTERFACE_SIDE)
|
||||||
|
REDSTONE_CONTROLLER -> RedstoneControllerModel
|
||||||
|
REDSTONE_EMITTER -> SimpleFaceDeviceModel(REDSTONE_EMITTER_SIDE)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
package net.shadowfacts.phycon.client.model
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.client.render.model.*
|
||||||
|
import net.minecraft.client.texture.Sprite
|
||||||
|
import net.minecraft.client.util.SpriteIdentifier
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.math.Direction
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
|
import net.shadowfacts.phycon.block.FaceDeviceBlock.FaceCableConnection
|
||||||
|
import java.util.Random
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
|
|
||||||
|
private val interfaceCableStraightID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_straight")
|
||||||
|
private val interfaceCableCornerID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner")
|
||||||
|
private val interfaceCableCorner2ID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner_2")
|
||||||
|
private val interfaceCableCapID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_cap")
|
||||||
|
private var interfaceCableStraight = Array<BakedModel?>(6) { null }
|
||||||
|
private var interfaceCableCap = Array<BakedModel?>(6) { null }
|
||||||
|
private var interfaceCableCorner = mutableMapOf<ModelRotation, BakedModel>()
|
||||||
|
private var interfaceCableCorner2 = mutableMapOf<ModelRotation, BakedModel>()
|
||||||
|
|
||||||
|
protected val defaultRotations = listOf(
|
||||||
|
ModelRotation.X0_Y0,
|
||||||
|
ModelRotation.X180_Y0,
|
||||||
|
ModelRotation.X270_Y0,
|
||||||
|
ModelRotation.X90_Y0,
|
||||||
|
ModelRotation.X90_Y90,
|
||||||
|
ModelRotation.X90_Y270,
|
||||||
|
)
|
||||||
|
|
||||||
|
abstract fun getSideModelIDs(): Collection<Identifier>
|
||||||
|
abstract fun bakeSideModels(loader: ModelLoader)
|
||||||
|
abstract fun getSideModel(state: BlockState): BakedModel?
|
||||||
|
|
||||||
|
override fun getModelDependencies(): Collection<Identifier> {
|
||||||
|
return getSideModelIDs() + listOf(
|
||||||
|
interfaceCableStraightID,
|
||||||
|
interfaceCableCornerID,
|
||||||
|
interfaceCableCorner2ID,
|
||||||
|
interfaceCableCapID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTextureDependencies(
|
||||||
|
unbakedModelGetter: Function<Identifier, UnbakedModel>,
|
||||||
|
unresolvedTextureReferences: MutableSet<com.mojang.datafixers.util.Pair<String, String>>
|
||||||
|
): Collection<SpriteIdentifier> {
|
||||||
|
return modelDependencies.map(unbakedModelGetter::apply).flatMap { it.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bake(loader: ModelLoader, textureGetter: Function<SpriteIdentifier, Sprite>, rotationContainer: ModelBakeSettings, modelId: Identifier): BakedModel {
|
||||||
|
bakeSideModels(loader)
|
||||||
|
|
||||||
|
defaultRotations.forEachIndexed { i, rot ->
|
||||||
|
interfaceCableStraight[i] = loader.bake(interfaceCableStraightID, rot)
|
||||||
|
interfaceCableCap[i] = loader.bake(interfaceCableCapID, rot)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapOf(
|
||||||
|
interfaceCableCorner to interfaceCableCornerID to ModelRotation.values().toList(),
|
||||||
|
interfaceCableCorner2 to interfaceCableCorner2ID to listOf(
|
||||||
|
ModelRotation.X0_Y0,
|
||||||
|
ModelRotation.X0_Y90,
|
||||||
|
ModelRotation.X0_Y180,
|
||||||
|
ModelRotation.X0_Y270,
|
||||||
|
ModelRotation.X180_Y0,
|
||||||
|
ModelRotation.X180_Y90,
|
||||||
|
ModelRotation.X180_Y180,
|
||||||
|
ModelRotation.X180_Y270,
|
||||||
|
),
|
||||||
|
).forEach { (k, rotations) ->
|
||||||
|
val (map, id) = k
|
||||||
|
map.clear()
|
||||||
|
rotations.forEach { rot ->
|
||||||
|
val model = loader.bake(id, rot)
|
||||||
|
if (model == null) map.remove(rot)
|
||||||
|
else map[rot] = model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getQuads(state: BlockState?, face: Direction?, random: Random): List<BakedQuad> {
|
||||||
|
if (state == null) return listOf()
|
||||||
|
val facing = state[FaceDeviceBlock.FACING]
|
||||||
|
val connection = state[FaceDeviceBlock.CABLE_CONNECTION]
|
||||||
|
|
||||||
|
val sideQuads = getSideModel(state)?.getQuads(state, face, random) ?: listOf()
|
||||||
|
val cableQuads = if (connection.direction == facing.opposite) {
|
||||||
|
interfaceCableStraight[facing.ordinal]?.getQuads(state, face, random) ?: listOf()
|
||||||
|
} else if (connection == FaceCableConnection.NONE) {
|
||||||
|
interfaceCableCap[facing.ordinal]?.getQuads(state, face, random) ?: listOf()
|
||||||
|
} else {
|
||||||
|
val model = when (facing) {
|
||||||
|
Direction.DOWN -> when (connection) {
|
||||||
|
FaceCableConnection.NORTH -> interfaceCableCorner[ModelRotation.X0_Y0]
|
||||||
|
FaceCableConnection.EAST -> interfaceCableCorner[ModelRotation.X0_Y90]
|
||||||
|
FaceCableConnection.SOUTH -> interfaceCableCorner[ModelRotation.X0_Y180]
|
||||||
|
FaceCableConnection.WEST -> interfaceCableCorner[ModelRotation.X0_Y270]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Direction.UP -> when (connection) {
|
||||||
|
FaceCableConnection.NORTH -> interfaceCableCorner[ModelRotation.X180_Y180]
|
||||||
|
FaceCableConnection.EAST -> interfaceCableCorner[ModelRotation.X180_Y270]
|
||||||
|
FaceCableConnection.SOUTH -> interfaceCableCorner[ModelRotation.X180_Y0]
|
||||||
|
FaceCableConnection.WEST -> interfaceCableCorner[ModelRotation.X180_Y90]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Direction.NORTH -> when (connection) {
|
||||||
|
FaceCableConnection.UP -> interfaceCableCorner[ModelRotation.X270_Y0]
|
||||||
|
FaceCableConnection.EAST -> interfaceCableCorner2[ModelRotation.X180_Y180]
|
||||||
|
FaceCableConnection.DOWN -> interfaceCableCorner[ModelRotation.X90_Y180]
|
||||||
|
FaceCableConnection.WEST -> interfaceCableCorner2[ModelRotation.X0_Y0]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Direction.SOUTH -> when (connection) {
|
||||||
|
FaceCableConnection.UP -> interfaceCableCorner[ModelRotation.X270_Y180]
|
||||||
|
FaceCableConnection.WEST -> interfaceCableCorner2[ModelRotation.X180_Y0]
|
||||||
|
FaceCableConnection.DOWN -> interfaceCableCorner[ModelRotation.X90_Y0]
|
||||||
|
FaceCableConnection.EAST -> interfaceCableCorner2[ModelRotation.X0_Y180]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Direction.WEST -> when (connection) {
|
||||||
|
FaceCableConnection.UP -> interfaceCableCorner[ModelRotation.X270_Y270]
|
||||||
|
FaceCableConnection.NORTH -> interfaceCableCorner2[ModelRotation.X180_Y90]
|
||||||
|
FaceCableConnection.DOWN -> interfaceCableCorner[ModelRotation.X90_Y90]
|
||||||
|
FaceCableConnection.SOUTH -> interfaceCableCorner2[ModelRotation.X0_Y270]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Direction.EAST -> when (connection) {
|
||||||
|
FaceCableConnection.UP -> interfaceCableCorner[ModelRotation.X270_Y90]
|
||||||
|
FaceCableConnection.SOUTH -> interfaceCableCorner2[ModelRotation.X180_Y270]
|
||||||
|
FaceCableConnection.DOWN -> interfaceCableCorner[ModelRotation.X90_Y270]
|
||||||
|
FaceCableConnection.NORTH -> interfaceCableCorner2[ModelRotation.X0_Y90]
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
model?.getQuads(state, face, random) ?: listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
return sideQuads + cableQuads
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun useAmbientOcclusion() = true
|
||||||
|
|
||||||
|
override fun hasDepth() = false
|
||||||
|
|
||||||
|
override fun isSideLit() = false
|
||||||
|
|
||||||
|
override fun isBuiltin() = false
|
||||||
|
|
||||||
|
abstract override fun getSprite(): Sprite
|
||||||
|
|
||||||
|
override fun getTransformation() = null
|
||||||
|
|
||||||
|
override fun getOverrides() = null
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package net.shadowfacts.phycon.client.model
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.client.render.model.BakedModel
|
||||||
|
import net.minecraft.client.render.model.ModelLoader
|
||||||
|
import net.minecraft.client.texture.Sprite
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
|
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object RedstoneControllerModel: FaceDeviceModel() {
|
||||||
|
|
||||||
|
private val ON = Identifier(PhysicalConnectivity.MODID, "block/redstone_controller_side_on")
|
||||||
|
private val OFF = Identifier(PhysicalConnectivity.MODID, "block/redstone_controller_side_off")
|
||||||
|
private val onModels = Array<BakedModel?>(6) { null }
|
||||||
|
private val offModels = Array<BakedModel?>(6) { null }
|
||||||
|
|
||||||
|
override fun getSideModelIDs(): Collection<Identifier> {
|
||||||
|
return listOf(ON, OFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bakeSideModels(loader: ModelLoader) {
|
||||||
|
defaultRotations.forEachIndexed { i, rot ->
|
||||||
|
onModels[i] = loader.bake(ON, rot)
|
||||||
|
offModels[i] = loader.bake(OFF, rot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSideModel(state: BlockState): BakedModel? {
|
||||||
|
return if (state[RedstoneControllerBlock.POWERED]) {
|
||||||
|
onModels[state[FaceDeviceBlock.FACING].ordinal]
|
||||||
|
} else {
|
||||||
|
offModels[state[FaceDeviceBlock.FACING].ordinal]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSprite(): Sprite {
|
||||||
|
return offModels.first()!!.sprite
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package net.shadowfacts.phycon.client.model
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.client.render.model.BakedModel
|
||||||
|
import net.minecraft.client.render.model.ModelLoader
|
||||||
|
import net.minecraft.client.texture.Sprite
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class SimpleFaceDeviceModel(
|
||||||
|
private val sideModelID: Identifier,
|
||||||
|
): FaceDeviceModel() {
|
||||||
|
private val sideModels = Array<BakedModel?>(6) { null }
|
||||||
|
|
||||||
|
override fun getSideModelIDs(): Collection<Identifier> {
|
||||||
|
return listOf(sideModelID)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bakeSideModels(loader: ModelLoader) {
|
||||||
|
defaultRotations.forEachIndexed { i, rot ->
|
||||||
|
sideModels[i] = loader.bake(sideModelID, rot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSideModel(state: BlockState): BakedModel? {
|
||||||
|
return sideModels[state[FaceDeviceBlock.FACING].ordinal]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSprite(): Sprite {
|
||||||
|
return sideModels.first()!!.sprite
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import net.minecraft.item.BlockItem
|
||||||
import net.minecraft.item.Item
|
import net.minecraft.item.Item
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.item.ConsoleItem
|
import net.shadowfacts.phycon.item.ConsoleItem
|
||||||
import net.shadowfacts.phycon.item.ScrewdriverItem
|
import net.shadowfacts.phycon.item.ScrewdriverItem
|
||||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||||
|
@ -34,6 +35,7 @@ object PhyItems {
|
||||||
|
|
||||||
val SCREWDRIVER = ScrewdriverItem()
|
val SCREWDRIVER = ScrewdriverItem()
|
||||||
val CONSOLE = ConsoleItem()
|
val CONSOLE = ConsoleItem()
|
||||||
|
val TWISTED_PAIR = Item(Item.Settings())
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
register(InterfaceBlock.ID, INTERFACE)
|
register(InterfaceBlock.ID, INTERFACE)
|
||||||
|
@ -48,6 +50,7 @@ object PhyItems {
|
||||||
|
|
||||||
register(ScrewdriverItem.ID, SCREWDRIVER)
|
register(ScrewdriverItem.ID, SCREWDRIVER)
|
||||||
register(ConsoleItem.ID, CONSOLE)
|
register(ConsoleItem.ID, CONSOLE)
|
||||||
|
register(Identifier(PhysicalConnectivity.MODID, "twisted_pair"), TWISTED_PAIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun register(id: Identifier, item: Item) {
|
private fun register(id: Identifier, item: Item) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import net.minecraft.util.ActionResult
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.block.DeviceBlock
|
import net.shadowfacts.phycon.block.DeviceBlock
|
||||||
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -35,6 +36,11 @@ class ScrewdriverItem: Item(Settings()) {
|
||||||
beTag.remove("y")
|
beTag.remove("y")
|
||||||
beTag.remove("z")
|
beTag.remove("z")
|
||||||
|
|
||||||
|
if (block === PhyBlocks.TERMINAL) {
|
||||||
|
// remove the terminal's internal buffer since it drops its items
|
||||||
|
beTag.remove("InternalBuffer")
|
||||||
|
}
|
||||||
|
|
||||||
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
|
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
|
||||||
context.world.spawnEntity(entity)
|
context.world.spawnEntity(entity)
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,16 @@ package net.shadowfacts.phycon.screen.console
|
||||||
import net.minecraft.block.entity.BlockEntity
|
import net.minecraft.block.entity.BlockEntity
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.text.TranslatableText
|
import net.minecraft.text.TranslatableText
|
||||||
|
import net.shadowfacts.cacao.geometry.Axis
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.view.Label
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.StackView
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
import net.shadowfacts.cacao.view.button.ToggleButton
|
||||||
import net.shadowfacts.cacao.view.textfield.NumberField
|
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
import net.shadowfacts.kiwidsl.dsl
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import net.shadowfacts.phycon.block.netinterface.InterfaceBlockEntity
|
||||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||||
|
|
||||||
|
@ -18,6 +23,9 @@ class ProviderViewController<T>(
|
||||||
private val device: T
|
private val device: T
|
||||||
): ViewController() where T: BlockEntity, T: NetworkStackProvider {
|
): ViewController() where T: BlockEntity, T: NetworkStackProvider {
|
||||||
|
|
||||||
|
private lateinit var field: NumberField
|
||||||
|
private var syncButton: ToggleButton? = null
|
||||||
|
|
||||||
override fun viewDidLoad() {
|
override fun viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
@ -26,9 +34,14 @@ class ProviderViewController<T>(
|
||||||
}
|
}
|
||||||
view.addSubview(label)
|
view.addSubview(label)
|
||||||
|
|
||||||
val field = NumberField(device.providerPriority) {
|
field = NumberField(device.providerPriority) {
|
||||||
if (it.number != null) {
|
if (it.number != null) {
|
||||||
device.providerPriority = it.number!!
|
device.providerPriority = it.number!!
|
||||||
|
|
||||||
|
if (device is InterfaceBlockEntity && device.syncPriorities) {
|
||||||
|
device.receiverPriority = it.number!!
|
||||||
|
}
|
||||||
|
|
||||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +52,30 @@ class ProviderViewController<T>(
|
||||||
}
|
}
|
||||||
view.addSubview(desc)
|
view.addSubview(desc)
|
||||||
|
|
||||||
|
if (device is InterfaceBlockEntity) {
|
||||||
|
val syncLabel = Label(TranslatableText("gui.phycon.console.provider.sync")).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
textAlignment = Label.TextAlignment.RIGHT
|
||||||
|
}
|
||||||
|
view.addSubview(syncLabel)
|
||||||
|
|
||||||
|
val syncButton = ToggleButton(device.syncPriorities) {
|
||||||
|
device.syncPriorities = it.state
|
||||||
|
device.receiverPriority = device.providerPriority
|
||||||
|
}
|
||||||
|
this.syncButton = syncButton
|
||||||
|
view.addSubview(syncButton)
|
||||||
|
|
||||||
|
view.solver.dsl {
|
||||||
|
syncButton.topAnchor equalTo (desc.bottomAnchor + 4)
|
||||||
|
syncButton.leftAnchor equalTo field.leftAnchor
|
||||||
|
|
||||||
|
syncLabel.centerYAnchor equalTo syncButton.centerYAnchor
|
||||||
|
syncLabel.leftAnchor equalTo view.leftAnchor
|
||||||
|
syncLabel.rightAnchor equalTo (syncButton.leftAnchor - 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
field.widthAnchor equalTo 100
|
field.widthAnchor equalTo 100
|
||||||
field.heightAnchor equalTo 20
|
field.heightAnchor equalTo 20
|
||||||
|
@ -54,4 +91,13 @@ class ProviderViewController<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun viewWillAppear() {
|
||||||
|
super.viewWillAppear()
|
||||||
|
|
||||||
|
field.number = device.providerPriority
|
||||||
|
if (device is InterfaceBlockEntity) {
|
||||||
|
syncButton!!.state = device.syncPriorities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.text.TranslatableText
|
import net.minecraft.text.TranslatableText
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.view.Label
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.button.ToggleButton
|
||||||
import net.shadowfacts.cacao.view.textfield.NumberField
|
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
import net.shadowfacts.kiwidsl.dsl
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import net.shadowfacts.phycon.block.netinterface.InterfaceBlockEntity
|
||||||
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
||||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||||
|
|
||||||
|
@ -18,6 +20,9 @@ class ReceiverViewController<T>(
|
||||||
private val device: T
|
private val device: T
|
||||||
): ViewController() where T: BlockEntity, T: NetworkStackReceiver {
|
): ViewController() where T: BlockEntity, T: NetworkStackReceiver {
|
||||||
|
|
||||||
|
private lateinit var field: NumberField
|
||||||
|
private var syncButton: ToggleButton? = null
|
||||||
|
|
||||||
override fun viewDidLoad() {
|
override fun viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
@ -26,9 +31,14 @@ class ReceiverViewController<T>(
|
||||||
}
|
}
|
||||||
view.addSubview(label)
|
view.addSubview(label)
|
||||||
|
|
||||||
val field = NumberField(device.receiverPriority) {
|
field = NumberField(device.receiverPriority) {
|
||||||
if (it.number != null) {
|
if (it.number != null) {
|
||||||
device.receiverPriority = it.number!!
|
device.receiverPriority = it.number!!
|
||||||
|
|
||||||
|
if (device is InterfaceBlockEntity && device.syncPriorities) {
|
||||||
|
device.providerPriority = it.number!!
|
||||||
|
}
|
||||||
|
|
||||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +49,30 @@ class ReceiverViewController<T>(
|
||||||
}
|
}
|
||||||
view.addSubview(desc)
|
view.addSubview(desc)
|
||||||
|
|
||||||
|
if (device is InterfaceBlockEntity) {
|
||||||
|
val syncLabel = Label(TranslatableText("gui.phycon.console.receiver.sync")).apply {
|
||||||
|
textColor = Color.TEXT
|
||||||
|
textAlignment = Label.TextAlignment.RIGHT
|
||||||
|
}
|
||||||
|
view.addSubview(syncLabel)
|
||||||
|
|
||||||
|
val syncButton = ToggleButton(device.syncPriorities) {
|
||||||
|
device.syncPriorities = it.state
|
||||||
|
device.providerPriority = device.receiverPriority
|
||||||
|
}
|
||||||
|
this.syncButton = syncButton
|
||||||
|
view.addSubview(syncButton)
|
||||||
|
|
||||||
|
view.solver.dsl {
|
||||||
|
syncButton.topAnchor equalTo (desc.bottomAnchor + 4)
|
||||||
|
syncButton.leftAnchor equalTo field.leftAnchor
|
||||||
|
|
||||||
|
syncLabel.centerYAnchor equalTo syncButton.centerYAnchor
|
||||||
|
syncLabel.leftAnchor equalTo view.leftAnchor
|
||||||
|
syncLabel.rightAnchor equalTo (syncButton.leftAnchor - 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
field.widthAnchor equalTo 100
|
field.widthAnchor equalTo 100
|
||||||
field.heightAnchor equalTo 20
|
field.heightAnchor equalTo 20
|
||||||
|
@ -54,4 +88,13 @@ class ReceiverViewController<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun viewWillAppear() {
|
||||||
|
super.viewWillAppear()
|
||||||
|
|
||||||
|
field.number = device.receiverPriority
|
||||||
|
if (device is InterfaceBlockEntity) {
|
||||||
|
syncButton!!.state = device.syncPriorities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,159 +1,8 @@
|
||||||
{
|
{
|
||||||
"multipart": [
|
"multipart": [
|
||||||
{
|
{
|
||||||
"apply": { "model": "phycon:block/cable_center" }
|
"_comment": "see SimpleFaceDeviceModel",
|
||||||
},
|
"apply": { "model": "phycon:block/network_interface" }
|
||||||
{
|
|
||||||
"when": { "facing": "down" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "up" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "north" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "south" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "west" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "east" },
|
|
||||||
"apply": { "model": "phycon:block/interface_side", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "up", "facing": "down" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "down", "facing": "up" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "north", "facing": "south" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "south", "facing": "north" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "west", "facing": "east" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "east", "facing": "west" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"when": {"cable_connection": "down", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 270 }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,183 +1,8 @@
|
||||||
{
|
{
|
||||||
"multipart": [
|
"multipart": [
|
||||||
{
|
{
|
||||||
"apply": { "model": "phycon:block/cable_center" }
|
"_comment": "see RedstoneControllerModel",
|
||||||
},
|
"apply": { "model": "phycon:block/redstone_controller" }
|
||||||
{
|
|
||||||
"when": { "facing": "down", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "up", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "north", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "south", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "west", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "east", "powered": "false" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "down", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "up", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "north", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "south", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "west", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "east", "powered": "true" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "up", "facing": "down" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "down", "facing": "up" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "north", "facing": "south" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "south", "facing": "north" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "west", "facing": "east" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "east", "facing": "west" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"when": {"cable_connection": "down", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 270 }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,159 +1,7 @@
|
||||||
{
|
{
|
||||||
"multipart": [
|
"multipart": [
|
||||||
{
|
{
|
||||||
"apply": { "model": "phycon:block/cable_center" }
|
"apply": { "model": "phycon:block/redstone_emitter" }
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "down" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "up" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "north" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "south" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "west" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "facing": "east" },
|
|
||||||
"apply": { "model": "phycon:block/redstone_emitter_side", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "up", "facing": "down" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "down", "facing": "up" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "north", "facing": "south" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "south", "facing": "north" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "west", "facing": "east" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": { "cable_connection": "east", "facing": "west" },
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_straight", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "down"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "up"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 180, "y": 90 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "north"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 180 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "west", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "east", "facing": "south"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 180 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"when": {"cable_connection": "down", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "west"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_3", "x": 180, "y": 270 }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "down", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 90, "y": 270 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "up", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner", "x": 270, "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "north", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "y": 90 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"when": {"cable_connection": "south", "facing": "east"},
|
|
||||||
"apply": { "model": "phycon:block/interface_cable_corner_2", "x": 180, "y": 270 }
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
"item.phycon.screwdriver": "Screwdriver",
|
"item.phycon.screwdriver": "Screwdriver",
|
||||||
"item.phycon.console": "Console",
|
"item.phycon.console": "Console",
|
||||||
|
"item.phycon.twisted_pair": "Twisted Pair",
|
||||||
|
|
||||||
"gui.phycon.terminal_buffer": "Buffer",
|
"gui.phycon.terminal_buffer": "Buffer",
|
||||||
"gui.phycon.console.details": "Device Details",
|
"gui.phycon.console.details": "Device Details",
|
||||||
|
@ -24,9 +25,11 @@
|
||||||
"gui.phycon.console.provider": "Item Provider",
|
"gui.phycon.console.provider": "Item Provider",
|
||||||
"gui.phycon.console.provider.priority": "Provider Priority",
|
"gui.phycon.console.provider.priority": "Provider Priority",
|
||||||
"gui.phycon.console.provider.priority_desc": "When a device requests items from the network, it send requests to providers (e.g., interfaces) with higher priorities first. Priorities can be negative.",
|
"gui.phycon.console.provider.priority_desc": "When a device requests items from the network, it send requests to providers (e.g., interfaces) with higher priorities first. Priorities can be negative.",
|
||||||
|
"gui.phycon.console.provider.sync": "Sync with Receiver Priority",
|
||||||
"gui.phycon.console.receiver": "Item Receiver",
|
"gui.phycon.console.receiver": "Item Receiver",
|
||||||
"gui.phycon.console.receiver.priority": "Receiver Priority",
|
"gui.phycon.console.receiver.priority": "Receiver Priority",
|
||||||
"gui.phycon.console.receiver.priority_desc": "When a device puts items into the network, it starts with receiver (e.g., interfaces) with higher priorities. Priorities can be negative.",
|
"gui.phycon.console.receiver.priority_desc": "When a device puts items into the network, it starts with receiver (e.g., interfaces) with higher priorities. Priorities can be negative.",
|
||||||
|
"gui.phycon.console.receiver.sync": "Sync with Provider Priority",
|
||||||
"gui.phycon.redstone_mode.high": "High",
|
"gui.phycon.redstone_mode.high": "High",
|
||||||
"gui.phycon.redstone_mode.low": "Low",
|
"gui.phycon.redstone_mode.low": "Low",
|
||||||
"gui.phycon.redstone_mode.toggle": "Toggle",
|
"gui.phycon.redstone_mode.toggle": "Toggle",
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"textures": {
|
||||||
|
"cap": "phycon:block/cable_cap_end",
|
||||||
|
"straight": "phycon:block/cable_straight"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [6, 6, 6],
|
||||||
|
"to": [10, 9, 10],
|
||||||
|
"faces": {
|
||||||
|
"north": {"texture": "#straight"},
|
||||||
|
"south": {"texture": "#straight"},
|
||||||
|
"west": {"texture": "#straight"},
|
||||||
|
"east": {"texture": "#straight"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [6, 9, 6],
|
||||||
|
"to": [10, 10, 10],
|
||||||
|
"faces": {
|
||||||
|
"up": {"texture": "#cap"},
|
||||||
|
"north": {"texture": "#cap"},
|
||||||
|
"south": {"texture": "#cap"},
|
||||||
|
"west": {"texture": "#cap"},
|
||||||
|
"east": {"texture": "#cap"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"textures": {
|
|
||||||
"straight": "phycon:block/cable_straight_rotated",
|
|
||||||
"cap": "phycon:block/cable_cap_end",
|
|
||||||
"corner_down": "phycon:block/interface_cable_corner_l_up",
|
|
||||||
"corner_up": "phycon:block/interface_cable_corner_r"
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"from": [0, 6, 6],
|
|
||||||
"to": [10, 10, 10],
|
|
||||||
"faces": {
|
|
||||||
"down": {"texture": "#corner_down"},
|
|
||||||
"up": {"texture": "#corner_up"},
|
|
||||||
"north": {"texture": "#straight"},
|
|
||||||
"south": {"texture": "#straight"},
|
|
||||||
"west": {"texture": "#cap", "cullface": "west"},
|
|
||||||
"east": {"texture": "#straight"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -4,7 +4,8 @@
|
||||||
"cable": "phycon:block/cable_straight",
|
"cable": "phycon:block/cable_straight",
|
||||||
"front": "phycon:block/redstone_controller_front_off",
|
"front": "phycon:block/redstone_controller_front_off",
|
||||||
"back": "phycon:block/redstone_controller_back",
|
"back": "phycon:block/redstone_controller_back",
|
||||||
"side": "phycon:block/redstone_controller_back"
|
"side": "phycon:block/redstone_controller_back",
|
||||||
|
"particle": "#front"
|
||||||
},
|
},
|
||||||
"elements": [
|
"elements": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
"cable": "phycon:block/cable_straight",
|
"cable": "phycon:block/cable_straight",
|
||||||
"front": "phycon:block/redstone_controller_front_on",
|
"front": "phycon:block/redstone_controller_front_on",
|
||||||
"back": "phycon:block/redstone_controller_back",
|
"back": "phycon:block/redstone_controller_back",
|
||||||
"side": "phycon:block/redstone_controller_back"
|
"side": "phycon:block/redstone_controller_back",
|
||||||
|
"particle": "#front"
|
||||||
},
|
},
|
||||||
"elements": [
|
"elements": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "phycon:item/twisted_pair"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 709 B |
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"phycon:cable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"has_twisted_pair": {
|
||||||
|
"trigger": "minecraft:inventory_changed",
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"item": "phycon:twisted_pair"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"trigger": "minecraft:recipe_unlocked",
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "phycon:cable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_twisted_pair",
|
||||||
|
"has_the_recipe"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:recipes/root",
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"phycon:twisted_pair"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"has_copper_nuggets": {
|
||||||
|
"trigger": "minecraft:inventory_changed",
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"tag": "c:copper_nuggets"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has_the_recipe": {
|
||||||
|
"trigger": "minecraft:recipe_unlocked",
|
||||||
|
"conditions": {
|
||||||
|
"recipe": "phycon:twisted_pair"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[
|
||||||
|
"has_copper_nuggets",
|
||||||
|
"has_the_recipe"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"CCC",
|
||||||
|
"TRT",
|
||||||
|
"CCC"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"C": {"tag": "minecraft:carpets"},
|
||||||
|
"T": {"item": "phycon:twisted_pair"},
|
||||||
|
"R": {"item": "minecraft:redstone"}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "phycon:cable",
|
||||||
|
"count": 3
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"NNN",
|
||||||
|
" ",
|
||||||
|
"NNN"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"N": {"tag": "c:copper_nuggets"}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "phycon:twisted_pair"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue