Compare commits
No commits in common. "385e36918f719a405fa5b37c704a57692bc144a6" and "2c19b8456b949d86077bd913e88354a9f682efe2" have entirely different histories.
385e36918f
...
2c19b8456b
|
@ -3,7 +3,7 @@ package net.shadowfacts.phycon.mixin.client;
|
|||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalScreen;
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
|
|
@ -7,7 +7,6 @@ import net.minecraft.screen.ScreenHandler
|
|||
import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.text.Text
|
||||
import net.shadowfacts.cacao.geometry.Point
|
||||
import net.shadowfacts.cacao.util.KeyModifiers
|
||||
import net.shadowfacts.cacao.util.MouseButton
|
||||
import net.shadowfacts.cacao.util.RenderHelper
|
||||
import net.shadowfacts.cacao.window.ScreenHandlerWindow
|
||||
|
@ -17,7 +16,7 @@ import java.util.*
|
|||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||
class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||
handler: Handler,
|
||||
playerInv: PlayerInventory,
|
||||
title: Text,
|
||||
|
@ -58,16 +57,15 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
|||
}
|
||||
|
||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
renderBackground(matrixStack)
|
||||
}
|
||||
|
||||
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
renderBackground(matrixStack)
|
||||
|
||||
val mouse = Point(mouseX, mouseY)
|
||||
windows.forEachIndexed { index, it ->
|
||||
it.draw(matrixStack, mouse, delta)
|
||||
if (it is ScreenHandlerWindow) {
|
||||
if (index == windows.size - 1) {
|
||||
super.render(matrixStack, mouseX, mouseY, delta)
|
||||
|
@ -76,10 +74,7 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
|||
super.render(matrixStack, -1, -1, delta)
|
||||
}
|
||||
}
|
||||
it.draw(matrixStack, mouse, delta)
|
||||
}
|
||||
|
||||
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
|
@ -95,20 +90,4 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
|||
}
|
||||
}
|
||||
|
||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
||||
return true
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
override fun charTyped(char: Char, modifiers: Int): Boolean {
|
||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||
if (findResponder { it.charTyped(char, modifiersSet) }) {
|
||||
return true
|
||||
}
|
||||
return super.charTyped(char, modifiers)
|
||||
}
|
||||
|
||||
}
|
|
@ -139,15 +139,15 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
|||
return super.charTyped(char, modifiers)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun AbstractCacaoScreen.findResponder(fn: (Responder) -> Boolean): Boolean {
|
||||
var responder = windows.lastOrNull()?.firstResponder
|
||||
while (responder != null) {
|
||||
if (fn(responder)) {
|
||||
return true
|
||||
private fun findResponder(fn: (Responder) -> Boolean): Boolean {
|
||||
var responder = windows.lastOrNull()?.firstResponder
|
||||
while (responder != null) {
|
||||
if (fn(responder)) {
|
||||
return true
|
||||
}
|
||||
responder = responder.nextResponder
|
||||
}
|
||||
responder = responder.nextResponder
|
||||
return false
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ data class Color(val red: Int, val green: Int, val blue: Int, val alpha: Int = 2
|
|||
val RED = Color(0xff0000)
|
||||
val GREEN = Color(0x00ff00)
|
||||
val BLUE = Color(0x0000ff)
|
||||
val MAGENTA = Color(0xfc46e4)
|
||||
|
||||
val TEXT = Color(0x404040)
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ class Label(
|
|||
for (i in 0 until lines.size) {
|
||||
val x = when (textAlignment) {
|
||||
TextAlignment.LEFT -> 0.0
|
||||
TextAlignment.CENTER -> (bounds.width - textRenderer.getWidth(lines[i])) / 2
|
||||
TextAlignment.CENTER -> (bounds.width + textRenderer.getWidth(lines[i])) / 2
|
||||
TextAlignment.RIGHT -> bounds.width - textRenderer.getWidth(lines[i])
|
||||
}
|
||||
val y = i * textRenderer.fontHeight
|
||||
|
|
|
@ -6,7 +6,6 @@ import net.shadowfacts.cacao.geometry.Axis
|
|||
import net.shadowfacts.cacao.geometry.AxisPosition
|
||||
import net.shadowfacts.cacao.geometry.AxisPosition.*
|
||||
import no.birkett.kiwi.Constraint
|
||||
import java.lang.RuntimeException
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
|
@ -19,7 +18,6 @@ import java.util.*
|
|||
* @param axis The primary axis that this stack lays out its children along.
|
||||
* @param distribution The mode by which this stack lays out its children along the axis perpendicular to the
|
||||
* primary [axis].
|
||||
* @param spacing The distance between arranged subviews along the primary axis.
|
||||
*/
|
||||
open class StackView(
|
||||
val axis: Axis,
|
||||
|
@ -27,7 +25,7 @@ open class StackView(
|
|||
val spacing: Double = 0.0
|
||||
): View() {
|
||||
|
||||
// the internal, mutable list of arranged subviews
|
||||
// the internal mutable, list of arranged subviews
|
||||
private val _arrangedSubviews = LinkedList<View>()
|
||||
/**
|
||||
* The list of arranged subviews belonging to this stack view.
|
||||
|
@ -59,64 +57,6 @@ open class StackView(
|
|||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given arranged subview from this stack view's arranged subviews.
|
||||
*/
|
||||
fun removeArrangedSubview(view: View) {
|
||||
val index = arrangedSubviews.indexOf(view)
|
||||
if (index < 0) {
|
||||
throw RuntimeException("Cannot remove view that is not arranged subview")
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
solver.removeConstraint(leadingConnection)
|
||||
val next = arrangedSubviews.getOrNull(1)
|
||||
if (next != null) {
|
||||
solver.dsl {
|
||||
leadingConnection = anchor(LEADING) equalTo anchor(LEADING, next)
|
||||
}
|
||||
} else {
|
||||
leadingConnection = null
|
||||
}
|
||||
}
|
||||
if (index == arrangedSubviews.size - 1) {
|
||||
solver.removeConstraint(trailingConnection)
|
||||
val prev = arrangedSubviews.getOrNull(arrangedSubviews.size - 2)
|
||||
if (prev != null) {
|
||||
solver.dsl {
|
||||
trailingConnection = anchor(TRAILING) equalTo anchor(TRAILING, prev)
|
||||
}
|
||||
} else {
|
||||
trailingConnection = null
|
||||
}
|
||||
}
|
||||
|
||||
// if the removed view is in the middle
|
||||
if (arrangedSubviews.size >= 3 && index > 0 && index < arrangedSubviews.size - 1) {
|
||||
val prev = arrangedSubviews[index - 1]
|
||||
val next = arrangedSubviews[index + 1]
|
||||
solver.dsl {
|
||||
solver.removeConstraint(arrangedSubviewConnections[index - 1])
|
||||
solver.removeConstraint(arrangedSubviewConnections[index])
|
||||
|
||||
// todo: double check me
|
||||
arrangedSubviewConnections[index - 1] = anchor(TRAILING, prev) equalTo anchor(LEADING, next)
|
||||
arrangedSubviewConnections.removeAt(index)
|
||||
}
|
||||
}
|
||||
|
||||
_arrangedSubviews.remove(view)
|
||||
removeSubview(view)
|
||||
}
|
||||
|
||||
override fun removeSubview(view: View) {
|
||||
if (arrangedSubviews.contains(view)) {
|
||||
removeArrangedSubview(view)
|
||||
} else {
|
||||
super.removeSubview(view)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addConstraintsForArrangedView(view: View, index: Int) {
|
||||
if (index == 0) {
|
||||
if (leadingConnection != null) {
|
||||
|
|
|
@ -197,13 +197,10 @@ open class View(): Responder {
|
|||
* its children (recursively) to a view outside of the subview's hierarchy. Constraints internal to the subview's
|
||||
* hierarchy (e.g., one between the subview and its child) will be left in place.
|
||||
*
|
||||
* This method may be overridden by layout-providing views (such as [StackView]) to update its layout when a managed
|
||||
* subview is removed.
|
||||
*
|
||||
* @param view The view to removed as a child of this view.
|
||||
* @throws RuntimeException If the given [view] is not a subview of this view.
|
||||
*/
|
||||
open fun removeSubview(view: View) {
|
||||
fun removeSubview(view: View) {
|
||||
if (view.superview !== this) {
|
||||
throw RuntimeException("Cannot remove subview whose superview is not this view")
|
||||
}
|
||||
|
|
|
@ -62,22 +62,12 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
|||
minecraftWidget.setMaxLength(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the Minecraft builtin black background and border are drawn. Defaults to true.
|
||||
*/
|
||||
var drawBackground = true
|
||||
set(value) {
|
||||
field = value
|
||||
minecraftWidget.setHasBorder(value)
|
||||
}
|
||||
|
||||
private lateinit var originInWindow: Point
|
||||
private var minecraftWidget = ProxyWidget()
|
||||
|
||||
init {
|
||||
minecraftWidget.text = initialText
|
||||
minecraftWidget.setTextPredicate { this.validate(it) }
|
||||
minecraftWidget.setHasBorder(drawBackground)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package net.shadowfacts.cacao.view.textfield
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class NumberField(
|
||||
initialValue: Int,
|
||||
handler: ((NumberField) -> Unit)? = null,
|
||||
): AbstractTextField<NumberField>(initialValue.toString()) {
|
||||
|
||||
var number: Int?
|
||||
get() {
|
||||
return if (isTextTemporarilyAllowed(text)) {
|
||||
null
|
||||
} else {
|
||||
try {
|
||||
Integer.parseInt(text)
|
||||
} catch (e: NumberFormatException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
text = value?.toString() ?: ""
|
||||
}
|
||||
|
||||
var validator: ((Int) -> Boolean)? = null
|
||||
|
||||
init {
|
||||
this.handler = handler
|
||||
}
|
||||
|
||||
override fun validate(proposedText: String): Boolean {
|
||||
return isTextTemporarilyAllowed(proposedText) || try {
|
||||
val value = Integer.parseInt(proposedText)
|
||||
validator?.invoke(value) ?: true
|
||||
} catch (e: NumberFormatException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTextTemporarilyAllowed(s: String): Boolean {
|
||||
return s.isEmpty() || s == "-"
|
||||
}
|
||||
|
||||
}
|
|
@ -61,13 +61,6 @@ class TabViewController<T: TabViewController.Tab>(
|
|||
* may be reused or created from scratch each time.
|
||||
*/
|
||||
val controller: ViewController
|
||||
|
||||
/**
|
||||
* Used by the tab view controller to determine whether the button for this tab should be displayed.
|
||||
* If the conditions that control this change, call [TabViewController.visibleTabsChanged].
|
||||
*/
|
||||
val isVisible: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,17 +68,12 @@ class TabViewController<T: TabViewController.Tab>(
|
|||
* @param tabView The view to display on the tab's button.
|
||||
* @param tooltip The tooltip to display when the tab's button is hovered (or `null`, if none).
|
||||
* @param controller The content view controller for this tab.
|
||||
* @param visible A function that determines if the tab should currently be visible.
|
||||
*/
|
||||
class SimpleTab(
|
||||
override val tabView: View,
|
||||
override val tooltip: Text? = null,
|
||||
override val controller: ViewController,
|
||||
private val visible: (() -> Boolean)? = null
|
||||
): Tab {
|
||||
override val isVisible: Boolean
|
||||
get() = visible?.invoke() ?: true
|
||||
}
|
||||
): Tab
|
||||
|
||||
/**
|
||||
* The currently selected tab.
|
||||
|
@ -112,7 +100,20 @@ class TabViewController<T: TabViewController.Tab>(
|
|||
tabStack = StackView(Axis.HORIZONTAL, StackView.Distribution.FILL)
|
||||
tabStack.zIndex = 1.0
|
||||
outerStack.addArrangedSubview(tabStack)
|
||||
updateTabButtons()
|
||||
|
||||
tabButtons = tabs.mapIndexed { index, tab ->
|
||||
val btn = TabButton(tab)
|
||||
btn.handler = { selectTab(it.tab) }
|
||||
if (tab == currentTab) {
|
||||
btn.setSelected(true)
|
||||
}
|
||||
btn
|
||||
}
|
||||
// todo: batch calls to addArrangedSubview
|
||||
tabButtons.forEach(tabStack::addArrangedSubview)
|
||||
|
||||
// spacer
|
||||
tabStack.addArrangedSubview(View())
|
||||
|
||||
val background = NinePatchView(NinePatchTexture.PANEL_BG)
|
||||
outerStack.addArrangedSubview(background)
|
||||
|
@ -136,37 +137,6 @@ class TabViewController<T: TabViewController.Tab>(
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateTabButtons() {
|
||||
while (tabStack.arrangedSubviews.isNotEmpty()) tabStack.removeArrangedSubview(tabStack.arrangedSubviews.first())
|
||||
|
||||
tabButtons = tabs.mapNotNull { tab ->
|
||||
if (!tab.isVisible) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
val btn = TabButton(tab)
|
||||
btn.handler = { selectTab(it.tab) }
|
||||
if (tab == currentTab) {
|
||||
btn.setSelected(true)
|
||||
}
|
||||
btn
|
||||
}
|
||||
// todo: batch calls to addArrangedSubview
|
||||
tabButtons.forEach(tabStack::addArrangedSubview)
|
||||
|
||||
// spacer
|
||||
tabStack.addArrangedSubview(View())
|
||||
|
||||
window!!.layout()
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when the conditions that make the configured tabs visible change.
|
||||
*/
|
||||
fun visibleTabsChanged() {
|
||||
updateTabButtons()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the provided tab as the currently active tab for this controller. Updates the state of tab bar buttons and
|
||||
* swaps the content view controller.
|
||||
|
|
|
@ -26,7 +26,8 @@ object PhysicalConnectivity: ModInitializer {
|
|||
|
||||
registerGlobalReceiver(C2STerminalRequestItem)
|
||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||
registerGlobalReceiver(C2SConfigureDevice)
|
||||
registerGlobalReceiver(C2SConfigureActivationMode)
|
||||
registerGlobalReceiver(C2SConfigureRedstoneController)
|
||||
}
|
||||
|
||||
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package net.shadowfacts.phycon
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer
|
||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry
|
||||
import net.shadowfacts.phycon.block.inserter.InserterScreen
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreen
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.init.PhyScreens
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalScreen
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen
|
||||
import net.shadowfacts.phycon.networking.ClientReceiver
|
||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||
|
||||
|
@ -16,9 +17,9 @@ import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
|||
object PhysicalConnectivityClient: ClientModInitializer {
|
||||
|
||||
override fun onInitializeClient() {
|
||||
ScreenRegistry.register(PhyScreens.TERMINAL, ::TerminalScreen)
|
||||
ScreenRegistry.register(PhyScreens.INSERTER, ::InserterScreen)
|
||||
ScreenRegistry.register(PhyScreens.REDSTONE_EMITTER, ::RedstoneEmitterScreen)
|
||||
BlockRenderLayerMap.INSTANCE.putBlock(PhyBlocks.CABLE, RenderLayer.getTranslucent())
|
||||
|
||||
ScreenRegistry.register(PhyScreens.TERMINAL_SCREEN_HANDLER, ::TerminalScreen)
|
||||
|
||||
registerGlobalReceiver(S2CTerminalUpdateDisplayedItems)
|
||||
}
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.inserter
|
||||
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.block.ShapeContext
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class InserterBlock: DeviceBlock<InserterBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
||||
val FACING = Properties.FACING
|
||||
private val INSERTER_SHAPES = mutableMapOf<Direction, VoxelShape>()
|
||||
|
||||
init {
|
||||
val components = arrayOf(
|
||||
doubleArrayOf(4.0, 0.0, 4.0, 12.0, 2.0, 12.0),
|
||||
doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0),
|
||||
doubleArrayOf(0.0, 4.0, 0.0, 16.0, 6.0, 16.0),
|
||||
doubleArrayOf(6.0, 6.0, 6.0, 10.0, 16.0, 10.0)
|
||||
)
|
||||
val directions = arrayOf(
|
||||
Triple(Direction.DOWN, null, false),
|
||||
Triple(Direction.UP, null, true),
|
||||
Triple(Direction.NORTH, 2, false),
|
||||
Triple(Direction.SOUTH, 2, true),
|
||||
Triple(Direction.WEST, 1, false),
|
||||
Triple(Direction.EAST, 1, true),
|
||||
)
|
||||
for ((dir, rotate, flip) in directions) {
|
||||
val shapes = components.map { it ->
|
||||
val arr = it.copyOf()
|
||||
if (rotate != null) {
|
||||
for (i in 0 until 3) {
|
||||
arr[i] = it[(i + rotate) % 3]
|
||||
arr[3 + i] = it[3 + ((i + rotate) % 3)]
|
||||
}
|
||||
}
|
||||
if (flip) {
|
||||
for (i in arr.indices) {
|
||||
arr[i] = 16.0 - arr[i]
|
||||
}
|
||||
}
|
||||
createCuboidShape(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5])
|
||||
}
|
||||
INSERTER_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
|
||||
return EnumSet.of(state[FACING].opposite)
|
||||
}
|
||||
|
||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
||||
return if (side == state[FACING].opposite) {
|
||||
getBlockEntity(world, pos)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
super.appendProperties(builder)
|
||||
builder.add(FACING)
|
||||
}
|
||||
|
||||
override fun createBlockEntity(world: BlockView) = InserterBlockEntity()
|
||||
|
||||
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
||||
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
|
||||
return defaultState.with(FACING, facing)
|
||||
}
|
||||
|
||||
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||
return INSERTER_SHAPES[state[FACING]]!!
|
||||
}
|
||||
|
||||
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
|
||||
if (!world.isClient) {
|
||||
getBlockEntity(world, pos)!!.updateInventory()
|
||||
}
|
||||
}
|
||||
|
||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
|
||||
if (!world.isClient) {
|
||||
getBlockEntity(world, pos)!!.updateInventory()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
|
||||
if (!world.isClient) {
|
||||
val be = getBlockEntity(world, pos)!!
|
||||
|
||||
be.sync()
|
||||
|
||||
val factory = object: ExtendedScreenHandlerFactory {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||
return InserterScreenHandler(syncId, playerInv, be)
|
||||
}
|
||||
|
||||
override fun getDisplayName() = this@InserterBlock.name
|
||||
|
||||
override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
|
||||
buf.writeBlockPos(be.pos)
|
||||
}
|
||||
}
|
||||
player.openHandledScreen(factory)
|
||||
}
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.inserter
|
||||
|
||||
import alexiil.mc.lib.attributes.SearchOptions
|
||||
import alexiil.mc.lib.attributes.Simulation
|
||||
import alexiil.mc.lib.attributes.item.ItemAttributes
|
||||
import alexiil.mc.lib.attributes.item.ItemInsertable
|
||||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
import net.shadowfacts.phycon.component.ItemStackPacketHandler
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.component.handleItemStack
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.packet.*
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class InserterBlockEntity: DeviceBlockEntity(PhyBlockEntities.INSERTER),
|
||||
ItemStackPacketHandler,
|
||||
ActivationController.ActivatableDevice,
|
||||
ClientConfigurableDevice {
|
||||
|
||||
companion object {
|
||||
val SLEEP_TIME = 40L
|
||||
val REQUEST_TIMEOUT = 40
|
||||
}
|
||||
|
||||
private val facing: Direction
|
||||
get() = cachedState[InserterBlock.FACING]
|
||||
|
||||
private var inventory: ItemInsertable? = null
|
||||
private var currentRequest: PendingExtractRequest? = null
|
||||
var stackToExtract: ItemStack = ItemStack.EMPTY
|
||||
var amountToExtract = 1
|
||||
override val controller = ActivationController(SLEEP_TIME, this)
|
||||
|
||||
fun updateInventory() {
|
||||
val offsetPos = pos.offset(facing)
|
||||
val option = SearchOptions.inDirection(facing)
|
||||
inventory = ItemAttributes.INSERTABLE.getFirstOrNull(world, offsetPos, option)
|
||||
}
|
||||
|
||||
private fun getInventory(): ItemInsertable? {
|
||||
if (inventory == null) updateInventory()
|
||||
return inventory
|
||||
}
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is RemoteActivationPacket -> controller.handleRemoteActivation(packet)
|
||||
is StackLocationPacket -> handleStackLocation(packet)
|
||||
is ItemStackPacket -> handleItemStack(packet)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
||||
val inventory = getInventory()
|
||||
return if (inventory != null) {
|
||||
inventory.attemptInsertion(packet.stack, Simulation.ACTION)
|
||||
} else {
|
||||
// no inventory, entire stack remains
|
||||
packet.stack
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleStackLocation(packet: StackLocationPacket) {
|
||||
val request = currentRequest
|
||||
if (request != null && ItemStackUtil.areEqualIgnoreAmounts(request.stack, packet.stack)) {
|
||||
request.results.add(packet.amount to packet.stackProvider)
|
||||
if (request.isFinishable(counter)) {
|
||||
finishRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (!world!!.isClient) {
|
||||
controller.tick()
|
||||
|
||||
val request = currentRequest
|
||||
if (request != null) {
|
||||
if (request.isFinishable(counter)) {
|
||||
finishRequest()
|
||||
} else if (counter - request.timestamp >= REQUEST_TIMEOUT && request.totalAmount == 0) {
|
||||
currentRequest = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun activate(): Boolean {
|
||||
if (currentRequest != null || stackToExtract.isEmpty) {
|
||||
return false
|
||||
}
|
||||
|
||||
// todo: configure me
|
||||
currentRequest = PendingExtractRequest(stackToExtract, counter)
|
||||
sendPacket(LocateStackPacket(stackToExtract, ipAddress))
|
||||
return true
|
||||
}
|
||||
|
||||
private fun finishRequest() {
|
||||
val request = currentRequest ?: return
|
||||
|
||||
// todo: dedup with TerminalBlockEntity.stackLocateRequestCompleted
|
||||
val actualAmount = min(min(request.stack.maxCount, request.totalAmount), amountToExtract)
|
||||
val sortedResults = request.results.sortedByDescending { it.first }.toMutableList()
|
||||
var amountRequested = 0
|
||||
while (amountRequested < actualAmount && sortedResults.isNotEmpty()) {
|
||||
val (sourceAmount, source) = sortedResults.removeAt(0)
|
||||
val amountToRequest = min(sourceAmount, actualAmount - amountRequested)
|
||||
amountRequested += amountToRequest
|
||||
sendPacket(ExtractStackPacket(request.stack, amountToRequest, ipAddress, source.ipAddress))
|
||||
}
|
||||
|
||||
currentRequest = null
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
tag.put("StackToExtract", stackToExtract.toTag(CompoundTag()))
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
stackToExtract = ItemStack.fromTag(tag.getCompound("StackToExtract"))
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
tag.putString("ActivationMode", controller.activationMode.name)
|
||||
tag.putInt("AmountToExtract", amountToExtract)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||
amountToExtract = tag.getInt("AmountToExtract")
|
||||
}
|
||||
|
||||
class PendingExtractRequest(
|
||||
val stack: ItemStack,
|
||||
val timestamp: Long,
|
||||
var results: MutableSet<Pair<Int, NetworkStackProvider>> = mutableSetOf()
|
||||
) {
|
||||
val totalAmount: Int
|
||||
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
||||
|
||||
fun isFinishable(currentTimestamp: Long): Boolean {
|
||||
return totalAmount >= stack.maxCount || (currentTimestamp - timestamp >= REQUEST_TIMEOUT && totalAmount > 0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.inserter
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.text.LiteralText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
import java.lang.NumberFormatException
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class InserterScreen(
|
||||
handler: InserterScreenHandler,
|
||||
playerInv: PlayerInventory,
|
||||
title: Text,
|
||||
): HandledScreen<InserterScreenHandler>(
|
||||
handler,
|
||||
playerInv,
|
||||
title
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/inserter.png")
|
||||
}
|
||||
|
||||
private lateinit var amountField: TextFieldWidget
|
||||
|
||||
init {
|
||||
backgroundWidth = 176
|
||||
backgroundHeight = 133
|
||||
playerInventoryTitleY = backgroundHeight - 94
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
amountField = TextFieldWidget(textRenderer, x + 57, y + 24, 80, 9, LiteralText("Amount"))
|
||||
amountField.text = handler.inserter.amountToExtract.toString()
|
||||
amountField.setHasBorder(false)
|
||||
amountField.isVisible = true
|
||||
amountField.setSelected(true)
|
||||
amountField.setEditableColor(0xffffff)
|
||||
amountField.setTextPredicate {
|
||||
if (it.isEmpty()) {
|
||||
true
|
||||
} else {
|
||||
try {
|
||||
val value = Integer.parseInt(it)
|
||||
value in 1..64
|
||||
} catch (e: NumberFormatException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
addChild(amountField)
|
||||
}
|
||||
|
||||
fun amountUpdated() {
|
||||
if (amountField.text.isNotEmpty()) {
|
||||
handler.inserter.amountToExtract = Integer.parseInt(amountField.text)
|
||||
client!!.player!!.networkHandler.sendPacket(C2SConfigureDevice(handler.inserter))
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
amountField.tick()
|
||||
}
|
||||
|
||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
renderBackground(matrixStack)
|
||||
|
||||
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||
client!!.textureManager.bindTexture(BACKGROUND)
|
||||
val x = (width - backgroundWidth) / 2
|
||||
val y = (height - backgroundHeight) / 2
|
||||
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||
}
|
||||
|
||||
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
super.render(matrixStack, mouseX, mouseY, delta)
|
||||
|
||||
amountField.render(matrixStack, mouseX, mouseY, delta)
|
||||
|
||||
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
|
||||
}
|
||||
|
||||
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, slotActionType: SlotActionType?) {
|
||||
super.onMouseClick(slot, invSlot, clickData, slotActionType)
|
||||
|
||||
amountField.setSelected(true)
|
||||
}
|
||||
|
||||
override fun charTyped(c: Char, i: Int): Boolean {
|
||||
val oldText = amountField.text
|
||||
if (amountField.charTyped(c, i)) {
|
||||
if (oldText != amountField.text) {
|
||||
amountUpdated()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return super.charTyped(c, i)
|
||||
}
|
||||
|
||||
override fun keyPressed(i: Int, j: Int, k: Int): Boolean {
|
||||
val oldText = amountField.text
|
||||
if (amountField.keyPressed(i, j, k)) {
|
||||
if (oldText != amountField.text) {
|
||||
amountUpdated()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return super.keyPressed(i, j, k)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.inserter
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.init.PhyScreens
|
||||
import net.shadowfacts.phycon.util.GhostSlot
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class InserterScreenHandler(
|
||||
syncId: Int,
|
||||
playerInv: PlayerInventory,
|
||||
val inserter: InserterBlockEntity,
|
||||
): ScreenHandler(PhyScreens.INSERTER, syncId) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
||||
}
|
||||
|
||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
||||
this(
|
||||
syncId,
|
||||
playerInv,
|
||||
PhyBlocks.INSERTER.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||
)
|
||||
|
||||
init {
|
||||
// fake slot
|
||||
addSlot(GhostSlot(inserter::stackToExtract, 31, 20))
|
||||
|
||||
// player inv
|
||||
for (y in 0 until 3) {
|
||||
for (x in 0 until 9) {
|
||||
addSlot(Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 51 + y * 18))
|
||||
}
|
||||
}
|
||||
|
||||
// hotbar
|
||||
for (x in 0 until 9) {
|
||||
addSlot(Slot(playerInv, x, 8 + x * 18, 109))
|
||||
}
|
||||
}
|
||||
|
||||
private fun stackToExtractChanged() {
|
||||
inserter.amountToExtract = min(inserter.stackToExtract.maxCount, inserter.amountToExtract)
|
||||
}
|
||||
|
||||
override fun canUse(player: PlayerEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||
// fake slot
|
||||
if (slotId == 0) {
|
||||
if (player.inventory.cursorStack.isEmpty) {
|
||||
inserter.stackToExtract = ItemStack.EMPTY
|
||||
} else {
|
||||
inserter.stackToExtract = player.inventory.cursorStack.copyWithCount(1)
|
||||
}
|
||||
stackToExtractChanged()
|
||||
}
|
||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||
}
|
||||
|
||||
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
||||
val slot = slots[slotId]
|
||||
inserter.stackToExtract = slot.stack.copyWithCount(1)
|
||||
stackToExtractChanged()
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.redstone_emitter
|
||||
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "redstone_emitter")
|
||||
}
|
||||
|
||||
// todo: don't just copy the redstone controller
|
||||
override val faceThickness = 3.0
|
||||
override val faceShapes = mapOf(
|
||||
Direction.DOWN to createCuboidShape(0.0, 0.0, 0.0, 16.0, 3.0, 16.0),
|
||||
Direction.UP to createCuboidShape(0.0, 13.0, 0.0, 16.0, 16.0, 16.0),
|
||||
Direction.NORTH to createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 3.0),
|
||||
Direction.SOUTH to createCuboidShape(0.0, 0.0, 13.0, 16.0, 16.0, 16.0),
|
||||
Direction.WEST to createCuboidShape(0.0, 0.0, 0.0, 3.0, 16.0, 16.0),
|
||||
Direction.EAST to createCuboidShape(13.0, 0.0, 0.0, 16.0, 16.0, 16.0)
|
||||
)
|
||||
|
||||
override fun createBlockEntity(world: BlockView) = RedstoneEmitterBlockEntity()
|
||||
|
||||
override fun emitsRedstonePower(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getStrongRedstonePower(state: BlockState, world: BlockView, pos: BlockPos, receivingSide: Direction): Int {
|
||||
return if (receivingSide.opposite == state[FACING]) {
|
||||
getBlockEntity(world, pos)!!.cachedEmittedPower
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWeakRedstonePower(state: BlockState, world: BlockView, pos: BlockPos, receivingSide: Direction): Int {
|
||||
return getStrongRedstonePower(state, world, pos, receivingSide)
|
||||
}
|
||||
|
||||
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, result: BlockHitResult): ActionResult {
|
||||
if (!world.isClient) {
|
||||
val be = getBlockEntity(world, pos)!!
|
||||
|
||||
be.sync()
|
||||
|
||||
val factory = object: ExtendedScreenHandlerFactory {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||
return RedstoneEmitterScreenHandler(syncId, playerInv, be)
|
||||
}
|
||||
|
||||
override fun getDisplayName() = this@RedstoneEmitterBlock.name
|
||||
|
||||
override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
|
||||
buf.writeBlockPos(be.pos)
|
||||
}
|
||||
}
|
||||
player.openHandledScreen(factory)
|
||||
}
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.redstone_emitter
|
||||
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.packet.DeviceRemovedPacket
|
||||
import net.shadowfacts.phycon.packet.ReadInventoryPacket
|
||||
import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import kotlin.math.round
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneEmitterBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER),
|
||||
ClientConfigurableDevice {
|
||||
|
||||
private val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>()
|
||||
var cachedEmittedPower: Int = 0
|
||||
private set
|
||||
|
||||
var stackToMonitor: ItemStack = ItemStack.EMPTY
|
||||
var maxAmount = 64
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is ReadInventoryPacket -> handleReadInventory(packet)
|
||||
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
||||
inventoryCache[packet.source] = packet.inventory
|
||||
recalculateRedstone()
|
||||
}
|
||||
|
||||
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
|
||||
inventoryCache.remove(packet.source)
|
||||
recalculateRedstone()
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (!world!!.isClient && counter % 20 == 0L) {
|
||||
if (counter % 80 == 0L) {
|
||||
updateInventories()
|
||||
} else if (counter % 20 == 0L) {
|
||||
recalculateRedstone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateInventories() {
|
||||
sendPacket(RequestInventoryPacket(ipAddress))
|
||||
}
|
||||
|
||||
private fun recalculateRedstone() {
|
||||
if (stackToMonitor.isEmpty) {
|
||||
cachedEmittedPower = 0
|
||||
updateWorld()
|
||||
return
|
||||
}
|
||||
val networkAmount = inventoryCache.values.fold(0) { acc, inv ->
|
||||
acc + inv.getAmount(stackToMonitor)
|
||||
}
|
||||
cachedEmittedPower =
|
||||
if (networkAmount == 0) {
|
||||
0
|
||||
} else {
|
||||
1 + round(networkAmount / maxAmount.toDouble() * 14).toInt()
|
||||
}
|
||||
updateWorld()
|
||||
}
|
||||
|
||||
private fun updateWorld() {
|
||||
world!!.updateNeighborsAlways(pos, cachedState.block)
|
||||
world!!.updateNeighborsAlways(pos.offset(cachedState[FaceDeviceBlock.FACING]), cachedState.block)
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
tag.putInt("CachedEmittedPower", cachedEmittedPower)
|
||||
tag.put("StackToMonitor", stackToMonitor.toTag(CompoundTag()))
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
cachedEmittedPower = tag.getInt("CachedEmittedPower")
|
||||
stackToMonitor = ItemStack.fromTag(tag.getCompound("StackToMonitor"))
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
tag.putInt("MaxAmount", maxAmount)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
maxAmount = tag.getInt("MaxAmount")
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.redstone_emitter
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.cacao.CacaoHandledScreen
|
||||
import net.shadowfacts.cacao.geometry.Axis
|
||||
import net.shadowfacts.cacao.util.Color
|
||||
import net.shadowfacts.cacao.view.Label
|
||||
import net.shadowfacts.cacao.view.StackView
|
||||
import net.shadowfacts.cacao.view.View
|
||||
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||
import net.shadowfacts.cacao.window.ScreenHandlerWindow
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
import no.birkett.kiwi.Variable
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneEmitterScreen(
|
||||
handler: RedstoneEmitterScreenHandler,
|
||||
playerInv: PlayerInventory,
|
||||
title: Text
|
||||
): CacaoHandledScreen<RedstoneEmitterScreenHandler>(
|
||||
handler,
|
||||
playerInv,
|
||||
title
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val BACKGROUND = Identifier(PhysicalConnectivity.MODID, "textures/gui/redstone_emitter.png")
|
||||
}
|
||||
|
||||
init {
|
||||
backgroundWidth = 176
|
||||
backgroundHeight = 166
|
||||
|
||||
addWindow(ScreenHandlerWindow(handler, ViewController(handler.emitter)))
|
||||
}
|
||||
|
||||
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
super.drawBackground(matrixStack, delta, mouseX, mouseY)
|
||||
|
||||
RenderSystem.color4f(1f, 1f, 1f, 1f)
|
||||
client!!.textureManager.bindTexture(BACKGROUND)
|
||||
val x = (width - backgroundWidth) / 2
|
||||
val y = (height - backgroundHeight) / 2
|
||||
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||
}
|
||||
|
||||
class ViewController(
|
||||
private val emitter: RedstoneEmitterBlockEntity,
|
||||
): net.shadowfacts.cacao.viewcontroller.ViewController() {
|
||||
|
||||
lateinit var halfLabel: Label
|
||||
lateinit var fullLabel: Label
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val title = Label(PhyBlocks.REDSTONE_EMITTER.name)
|
||||
title.textColor = Color.TEXT
|
||||
view.addSubview(title)
|
||||
|
||||
val inv = Label(MinecraftClient.getInstance().player!!.inventory.displayName)
|
||||
inv.textColor = Color.TEXT
|
||||
view.addSubview(inv)
|
||||
|
||||
val field = NumberField(emitter.maxAmount) {
|
||||
if (it.number != null) {
|
||||
emitter.maxAmount = it.number!!
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(emitter))
|
||||
}
|
||||
updateLabelTexts()
|
||||
}
|
||||
field.validator = { it >= 0 }
|
||||
field.drawBackground = false
|
||||
view.addSubview(field)
|
||||
|
||||
val hStack = StackView(Axis.HORIZONTAL, StackView.Distribution.FILL, spacing = 2.0)
|
||||
view.addSubview(hStack)
|
||||
|
||||
val zeroStack = hStack.addArrangedSubview(StackView(Axis.VERTICAL))
|
||||
zeroStack.addArrangedSubview(Label(TranslatableText("gui.phycon.emitter.count", 0), textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
zeroStack.addArrangedSubview(View())
|
||||
zeroStack.addArrangedSubview(Label("0", textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.RED
|
||||
}
|
||||
|
||||
val halfStack = hStack.addArrangedSubview(StackView(Axis.VERTICAL))
|
||||
halfLabel = halfStack.addArrangedSubview(Label("half", textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
halfStack.addArrangedSubview(View())
|
||||
halfStack.addArrangedSubview(Label("8", textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.RED
|
||||
}
|
||||
|
||||
val fullStack = hStack.addArrangedSubview(StackView(Axis.VERTICAL))
|
||||
fullLabel = fullStack.addArrangedSubview(Label("full", textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
fullStack.addArrangedSubview(View())
|
||||
fullStack.addArrangedSubview(Label("15", textAlignment = Label.TextAlignment.CENTER)).apply {
|
||||
textColor = Color.RED
|
||||
}
|
||||
|
||||
updateLabelTexts()
|
||||
|
||||
view.solver.dsl {
|
||||
val minX = Variable("minX")
|
||||
val minY = Variable("minY")
|
||||
minX equalTo ((view.widthAnchor - 176) / 2)
|
||||
minY equalTo ((view.heightAnchor - 166) / 2)
|
||||
|
||||
title.leftAnchor equalTo (minX + 8)
|
||||
title.topAnchor equalTo (minY + 6)
|
||||
|
||||
inv.leftAnchor equalTo (minX + 8)
|
||||
inv.topAnchor equalTo (minY + 72)
|
||||
|
||||
// offset by 1 on each edge to account for MC border
|
||||
field.widthAnchor equalTo 82
|
||||
field.heightAnchor equalTo 11
|
||||
field.leftAnchor equalTo (minX + 56)
|
||||
field.topAnchor equalTo (minY + 23)
|
||||
|
||||
hStack.centerXAnchor equalTo view.centerXAnchor
|
||||
hStack.widthAnchor equalTo (176 - 4)
|
||||
hStack.topAnchor equalTo (field.bottomAnchor + 8)
|
||||
hStack.bottomAnchor equalTo inv.topAnchor
|
||||
|
||||
zeroStack.widthAnchor equalTo halfStack.widthAnchor
|
||||
halfStack.widthAnchor equalTo fullStack.widthAnchor
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLabelTexts() {
|
||||
halfLabel.text = TranslatableText("gui.phycon.emitter.count", ceil(emitter.maxAmount / 2.0).toInt())
|
||||
fullLabel.text = TranslatableText("gui.phycon.emitter.count", emitter.maxAmount)
|
||||
window!!.layout()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package net.shadowfacts.phycon.block.redstone_emitter
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.init.PhyScreens
|
||||
import net.shadowfacts.phycon.util.GhostSlot
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneEmitterScreenHandler(
|
||||
syncId: Int,
|
||||
playerInv: PlayerInventory,
|
||||
val emitter: RedstoneEmitterBlockEntity,
|
||||
): ScreenHandler(PhyScreens.REDSTONE_EMITTER, syncId) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "redstone_emitter")
|
||||
}
|
||||
|
||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
||||
this(
|
||||
syncId,
|
||||
playerInv,
|
||||
PhyBlocks.REDSTONE_EMITTER.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||
)
|
||||
|
||||
init {
|
||||
// fake slot
|
||||
addSlot(GhostSlot(emitter::stackToMonitor, 31, 20))
|
||||
|
||||
// player inv
|
||||
for (y in 0 until 3) {
|
||||
for (x in 0 until 9) {
|
||||
addSlot(Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 84 + y * 18))
|
||||
}
|
||||
}
|
||||
|
||||
// hotbar
|
||||
for (x in 0 until 9) {
|
||||
addSlot(Slot(playerInv, x, 8 + x * 18, 142))
|
||||
}
|
||||
}
|
||||
|
||||
override fun canUse(player: PlayerEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSlotClick(slotId: Int, clickData: Int, slotActionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||
// fake slot
|
||||
if (slotId == 0) {
|
||||
if (player.inventory.cursorStack.isEmpty) {
|
||||
emitter.stackToMonitor = ItemStack.EMPTY
|
||||
} else {
|
||||
emitter.stackToMonitor = player.inventory.cursorStack.copyWithCount(1)
|
||||
}
|
||||
}
|
||||
return super.onSlotClick(slotId, clickData, slotActionType, player)
|
||||
}
|
||||
|
||||
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
||||
val slot = slots[slotId]
|
||||
emitter.stackToMonitor = slot.stack.copyWithCount(1)
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package net.shadowfacts.phycon.component
|
||||
|
||||
import net.shadowfacts.phycon.api.NetworkDevice
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
interface NetworkStackProvider: NetworkDevice, ClientConfigurableDevice {
|
||||
|
||||
var providerPriority: Int
|
||||
|
||||
fun canConfigureProviderPriority(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package net.shadowfacts.phycon.component
|
||||
|
||||
import net.shadowfacts.phycon.api.NetworkDevice
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
interface NetworkStackReceiver: NetworkDevice, ClientConfigurableDevice {
|
||||
|
||||
var receiverPriority: Int
|
||||
|
||||
}
|
|
@ -5,22 +5,22 @@ import net.minecraft.block.entity.BlockEntity
|
|||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.registry.Registry
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlockEntity
|
||||
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||
import net.shadowfacts.phycon.block.inserter.InserterBlockEntity
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlockEntity
|
||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlockEntity
|
||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlockEntity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.network.block.extractor.ExtractorBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.network.block.miner.MinerBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.test.DestBlock
|
||||
import net.shadowfacts.phycon.network.block.test.DestBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.test.SourceBlock
|
||||
import net.shadowfacts.phycon.network.block.test.SourceBlockEntity
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -31,10 +31,11 @@ object PhyBlockEntities {
|
|||
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
|
||||
val SWITCH = create(::SwitchBlockEntity, PhyBlocks.SWITCH)
|
||||
val EXTRACTOR = create(::ExtractorBlockEntity, PhyBlocks.EXTRACTOR)
|
||||
val INSERTER = create(::InserterBlockEntity, PhyBlocks.INSERTER)
|
||||
val MINER = create(::MinerBlockEntity, PhyBlocks.MINER)
|
||||
val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER)
|
||||
val REDSTONE_EMITTER = create(::RedstoneEmitterBlockEntity, PhyBlocks.REDSTONE_EMITTER)
|
||||
|
||||
val SOURCE = create(::SourceBlockEntity, PhyBlocks.SOURCE)
|
||||
val DEST = create(::DestBlockEntity, PhyBlocks.DEST)
|
||||
|
||||
private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> {
|
||||
return BlockEntityType.Builder.create(builder, block).build(null)
|
||||
|
@ -45,10 +46,11 @@ object PhyBlockEntities {
|
|||
register(TerminalBlock.ID, TERMINAL)
|
||||
register(SwitchBlock.ID, SWITCH)
|
||||
register(ExtractorBlock.ID, EXTRACTOR)
|
||||
register(InserterBlock.ID, INSERTER)
|
||||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
|
||||
register(SourceBlock.ID, SOURCE)
|
||||
register(DestBlock.ID, DEST)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, type: BlockEntityType<*>) {
|
||||
|
|
|
@ -3,15 +3,15 @@ package net.shadowfacts.phycon.init
|
|||
import net.minecraft.block.Block
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.registry.Registry
|
||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.network.block.cable.CableBlock
|
||||
import net.shadowfacts.phycon.network.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.network.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.network.block.test.DestBlock
|
||||
import net.shadowfacts.phycon.network.block.test.SourceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -23,10 +23,11 @@ object PhyBlocks {
|
|||
val SWITCH = SwitchBlock()
|
||||
val CABLE = CableBlock()
|
||||
val EXTRACTOR = ExtractorBlock()
|
||||
val INSERTER = InserterBlock()
|
||||
val MINER = MinerBlock()
|
||||
val REDSTONE_CONTROLLER = RedstoneControllerBlock()
|
||||
val REDSTONE_EMITTER = RedstoneEmitterBlock()
|
||||
|
||||
val SOURCE = SourceBlock()
|
||||
val DEST = DestBlock()
|
||||
|
||||
fun init() {
|
||||
register(InterfaceBlock.ID, INTERFACE)
|
||||
|
@ -34,10 +35,11 @@ object PhyBlocks {
|
|||
register(SwitchBlock.ID, SWITCH)
|
||||
register(CableBlock.ID, CABLE)
|
||||
register(ExtractorBlock.ID, EXTRACTOR)
|
||||
register(InserterBlock.ID, INSERTER)
|
||||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
|
||||
register(SourceBlock.ID, SOURCE)
|
||||
register(DestBlock.ID, DEST)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, block: Block) {
|
||||
|
|
|
@ -6,31 +6,31 @@ import net.minecraft.util.Identifier
|
|||
import net.minecraft.util.registry.Registry
|
||||
import net.shadowfacts.phycon.item.ConsoleItem
|
||||
import net.shadowfacts.phycon.item.ScrewdriverItem
|
||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.block.inserter.InserterBlock
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.item.DeviceBlockItem
|
||||
import net.shadowfacts.phycon.network.block.cable.CableBlock
|
||||
import net.shadowfacts.phycon.network.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.network.block.miner.MinerBlock
|
||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
|
||||
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.network.block.test.DestBlock
|
||||
import net.shadowfacts.phycon.network.block.test.SourceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
object PhyItems {
|
||||
|
||||
val INTERFACE = DeviceBlockItem(PhyBlocks.INTERFACE, Item.Settings())
|
||||
val TERMINAL = DeviceBlockItem(PhyBlocks.TERMINAL, Item.Settings())
|
||||
val INTERFACE = BlockItem(PhyBlocks.INTERFACE, Item.Settings())
|
||||
val TERMINAL = BlockItem(PhyBlocks.TERMINAL, Item.Settings())
|
||||
val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings())
|
||||
val CABLE = BlockItem(PhyBlocks.CABLE, Item.Settings())
|
||||
val EXTRACTOR = DeviceBlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
||||
val INSERTER = DeviceBlockItem(PhyBlocks.INSERTER, Item.Settings())
|
||||
val MINER = DeviceBlockItem(PhyBlocks.MINER, Item.Settings())
|
||||
val REDSTONE_CONTROLLER = DeviceBlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
|
||||
val REDSTONE_EMITTER = DeviceBlockItem(PhyBlocks.REDSTONE_EMITTER, Item.Settings())
|
||||
val EXTRACTOR = BlockItem(PhyBlocks.EXTRACTOR, Item.Settings())
|
||||
val MINER = BlockItem(PhyBlocks.MINER, Item.Settings())
|
||||
val REDSTONE_CONTROLLER = BlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
|
||||
|
||||
val SOURCE = BlockItem(PhyBlocks.SOURCE, Item.Settings())
|
||||
val DEST = BlockItem(PhyBlocks.DEST , Item.Settings())
|
||||
|
||||
val SCREWDRIVER = ScrewdriverItem()
|
||||
val CONSOLE = ConsoleItem()
|
||||
|
@ -41,10 +41,11 @@ object PhyItems {
|
|||
register(SwitchBlock.ID, SWITCH)
|
||||
register(CableBlock.ID, CABLE)
|
||||
register(ExtractorBlock.ID, EXTRACTOR)
|
||||
register(InserterBlock.ID, INSERTER)
|
||||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
|
||||
register(SourceBlock.ID, SOURCE)
|
||||
register(DestBlock.ID, DEST)
|
||||
|
||||
register(ScrewdriverItem.ID, SCREWDRIVER)
|
||||
register(ConsoleItem.ID, CONSOLE)
|
||||
|
|
|
@ -2,23 +2,17 @@ package net.shadowfacts.phycon.init
|
|||
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry
|
||||
import net.minecraft.screen.ScreenHandlerType
|
||||
import net.shadowfacts.phycon.block.inserter.InserterScreenHandler
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterScreenHandler
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreenHandler
|
||||
|
||||
object PhyScreens {
|
||||
|
||||
lateinit var TERMINAL: ScreenHandlerType<TerminalScreenHandler>
|
||||
private set
|
||||
lateinit var INSERTER: ScreenHandlerType<InserterScreenHandler>
|
||||
private set
|
||||
lateinit var REDSTONE_EMITTER: ScreenHandlerType<RedstoneEmitterScreenHandler>
|
||||
lateinit var TERMINAL_SCREEN_HANDLER: ScreenHandlerType<TerminalScreenHandler>
|
||||
private set
|
||||
|
||||
fun init() {
|
||||
TERMINAL = ScreenHandlerRegistry.registerExtended(TerminalScreenHandler.ID, ::TerminalScreenHandler)
|
||||
INSERTER = ScreenHandlerRegistry.registerExtended(InserterScreenHandler.ID, ::InserterScreenHandler)
|
||||
REDSTONE_EMITTER = ScreenHandlerRegistry.registerExtended(RedstoneEmitterScreenHandler.ID, ::RedstoneEmitterScreenHandler)
|
||||
TERMINAL_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(Identifier(PhysicalConnectivity.MODID, "terminal"), ::TerminalScreenHandler)
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,8 @@ import net.minecraft.item.ItemUsageContext
|
|||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.screen.console.DeviceConsoleScreen
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
package net.shadowfacts.phycon.item
|
||||
|
||||
import net.minecraft.client.item.TooltipContext
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.world.World
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.util.text
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) {
|
||||
|
||||
override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) {
|
||||
val beTag = stack.getSubTag("BlockEntityTag")
|
||||
if (beTag != null) {
|
||||
val ip = IPAddress(beTag.getInt("IPAddress"))
|
||||
list.add(text {
|
||||
withStyle(lightPurple) {
|
||||
+translate("tooltip.phycon.device.configured")
|
||||
}
|
||||
+" ("
|
||||
+translate("tooltip.phycon.device.ip")
|
||||
withStyle(darkPurple) {
|
||||
+ip.toString()
|
||||
}
|
||||
+")"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,8 @@
|
|||
package net.shadowfacts.phycon.item
|
||||
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.entity.ItemEntity
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.ItemUsageContext
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -19,33 +11,4 @@ class ScrewdriverItem: Item(Settings()) {
|
|||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "screwdriver")
|
||||
}
|
||||
|
||||
override fun useOnBlock(context: ItemUsageContext): ActionResult {
|
||||
val state = context.world.getBlockState(context.blockPos)
|
||||
val block = state.block
|
||||
if (block is DeviceBlock<*>) {
|
||||
if (!context.world.isClient) {
|
||||
val be = block.getBlockEntity(context.world, context.blockPos)!!
|
||||
|
||||
val stack = ItemStack(block)
|
||||
val beTag = stack.getOrCreateSubTag("BlockEntityTag")
|
||||
be.toTag(beTag)
|
||||
// remove x, y, z entries for stacking purposes
|
||||
beTag.remove("x")
|
||||
beTag.remove("y")
|
||||
beTag.remove("z")
|
||||
|
||||
val entity = ItemEntity(context.world, context.blockPos.x.toDouble(), context.blockPos.y.toDouble(), context.blockPos.z.toDouble(), stack)
|
||||
context.world.spawnEntity(entity)
|
||||
|
||||
context.world.setBlockState(context.blockPos, Blocks.AIR.defaultState, 3, 512)
|
||||
}
|
||||
|
||||
context.world.playSound(context.player, context.blockPos, SoundEvents.BLOCK_METAL_PLACE, SoundCategory.BLOCKS, 0.8f, 0.65f)
|
||||
|
||||
return ActionResult.SUCCESS
|
||||
} else {
|
||||
return ActionResult.PASS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block
|
||||
package net.shadowfacts.phycon.network
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
|
@ -8,6 +8,7 @@ import net.minecraft.world.World
|
|||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||
import net.shadowfacts.phycon.block.BlockWithEntity
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block
|
||||
package net.shadowfacts.phycon.network
|
||||
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
||||
import net.minecraft.block.BlockState
|
||||
|
@ -16,11 +16,10 @@ import net.shadowfacts.phycon.api.frame.PacketFrame
|
|||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.api.util.MACAddress
|
||||
import net.shadowfacts.phycon.util.NetworkUtil
|
||||
import net.shadowfacts.phycon.frame.ARPQueryFrame
|
||||
import net.shadowfacts.phycon.frame.ARPResponseFrame
|
||||
import net.shadowfacts.phycon.frame.BasePacketFrame
|
||||
import net.shadowfacts.phycon.packet.*
|
||||
import net.shadowfacts.phycon.network.frame.ARPQueryFrame
|
||||
import net.shadowfacts.phycon.network.frame.ARPResponseFrame
|
||||
import net.shadowfacts.phycon.network.frame.BasePacketFrame
|
||||
import net.shadowfacts.phycon.network.packet.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
|
@ -147,33 +146,27 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type),
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun toCommonTag(tag: CompoundTag) {
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
tag.putInt("IPAddress", ipAddress.address)
|
||||
tag.putLong("MACAddress", macAddress.address)
|
||||
}
|
||||
|
||||
protected open fun fromCommonTag(tag: CompoundTag) {
|
||||
ipAddress = IPAddress(tag.getInt("IPAddress"))
|
||||
macAddress = MACAddress(tag.getLong("MACAddress"))
|
||||
}
|
||||
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
toCommonTag(tag)
|
||||
return super.toTag(tag)
|
||||
}
|
||||
|
||||
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||
super.fromTag(state, tag)
|
||||
fromCommonTag(tag)
|
||||
ipAddress = IPAddress(tag.getInt("IPAddress"))
|
||||
macAddress = MACAddress(tag.getLong("MACAddress"))
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
toCommonTag(tag)
|
||||
tag.putInt("IPAddress", ipAddress.address)
|
||||
tag.putLong("MACAddress", macAddress.address)
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
fromCommonTag(tag)
|
||||
ipAddress = IPAddress(tag.getInt("IPAddress"))
|
||||
macAddress = MACAddress(tag.getLong("MACAddress"))
|
||||
}
|
||||
|
||||
fun onBreak() {
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block
|
||||
package net.shadowfacts.phycon.network
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
|
@ -16,7 +16,7 @@ import net.minecraft.world.World
|
|||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||
import net.shadowfacts.phycon.block.cable.CableBlock
|
||||
import net.shadowfacts.phycon.network.block.cable.CableBlock
|
||||
import java.util.*
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.util
|
||||
package net.shadowfacts.phycon.network
|
||||
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.cable
|
||||
package net.shadowfacts.phycon.network.block.cable
|
||||
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.piston.PistonBehavior
|
||||
|
@ -31,7 +31,6 @@ import java.util.*
|
|||
*/
|
||||
class CableBlock: Block(
|
||||
Settings.of(CABLE_MATERIAL)
|
||||
.strength(1f)
|
||||
.nonOpaque()
|
||||
), NetworkCableBlock {
|
||||
companion object {
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.extractor
|
||||
package net.shadowfacts.phycon.network.block.extractor
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
|
@ -7,7 +7,6 @@ import net.minecraft.block.ShapeContext
|
|||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.util.Identifier
|
||||
|
@ -20,17 +19,13 @@ import net.minecraft.world.World
|
|||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(Settings.of(Material.METAL)) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "extractor")
|
||||
|
@ -93,7 +88,7 @@ class ExtractorBlock: DeviceBlock<ExtractorBlockEntity>(
|
|||
override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity()
|
||||
|
||||
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.playerFacing.opposite
|
||||
return defaultState.with(FACING, facing)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.extractor
|
||||
package net.shadowfacts.phycon.network.block.extractor
|
||||
|
||||
import alexiil.mc.lib.attributes.SearchOptions
|
||||
import alexiil.mc.lib.attributes.Simulation
|
||||
|
@ -11,15 +11,14 @@ import net.minecraft.nbt.CompoundTag
|
|||
import net.minecraft.util.math.Direction
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
import net.shadowfacts.phycon.component.NetworkStackDispatcher
|
||||
import net.shadowfacts.phycon.component.handleItemStack
|
||||
import net.shadowfacts.phycon.packet.CapacityPacket
|
||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||
import net.shadowfacts.phycon.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.component.ActivationController
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackDispatcher
|
||||
import net.shadowfacts.phycon.network.component.handleItemStack
|
||||
import net.shadowfacts.phycon.network.packet.CapacityPacket
|
||||
import net.shadowfacts.phycon.network.packet.ItemStackPacket
|
||||
import net.shadowfacts.phycon.network.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
|
@ -27,8 +26,7 @@ import kotlin.properties.Delegates
|
|||
*/
|
||||
class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
|
||||
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
|
||||
ActivationController.ActivatableDevice,
|
||||
ClientConfigurableDevice {
|
||||
ActivationController.ActivatableDevice {
|
||||
|
||||
companion object {
|
||||
val SLEEP_TIME = 40L
|
||||
|
@ -39,7 +37,7 @@ class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
|
|||
|
||||
private var inventory: FixedItemInv? = null
|
||||
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
||||
override val dispatchStackTimeout = 1L
|
||||
override val dispatchStackTimeout = 40L
|
||||
override val controller = ActivationController(SLEEP_TIME, this)
|
||||
|
||||
fun updateInventory() {
|
||||
|
@ -101,21 +99,23 @@ class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
|
|||
return false
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
tag.putString("ActivationMode", controller.activationMode.name)
|
||||
return super.toTag(tag)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||
super.fromTag(state, tag)
|
||||
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
tag.putString("ActivationMode", controller.activationMode.name)
|
||||
return super.toClientTag(tag)
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
super.fromClientTag(tag)
|
||||
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.miner
|
||||
package net.shadowfacts.phycon.network.block.miner
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
|
@ -6,7 +6,6 @@ import net.minecraft.block.Material
|
|||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.util.Identifier
|
||||
|
@ -17,18 +16,14 @@ import net.minecraft.world.World
|
|||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import net.shadowfacts.phycon.network.block.extractor.ExtractorBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class MinerBlock: DeviceBlock<MinerBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
class MinerBlock: DeviceBlock<MinerBlockEntity>(Settings.of(Material.METAL)) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "miner")
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.miner
|
||||
package net.shadowfacts.phycon.network.block.miner
|
||||
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
|
@ -6,25 +6,20 @@ import alexiil.mc.lib.attributes.item.filter.ItemFilter
|
|||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.World
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
import net.shadowfacts.phycon.component.NetworkStackDispatcher
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.component.handleItemStack
|
||||
import net.shadowfacts.phycon.packet.*
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackDispatcher
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.network.component.handleItemStack
|
||||
import net.shadowfacts.phycon.network.component.spawnItemStack
|
||||
import net.shadowfacts.phycon.network.packet.*
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
|
@ -32,9 +27,7 @@ import kotlin.math.min
|
|||
*/
|
||||
class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||
NetworkStackProvider,
|
||||
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion>,
|
||||
ActivationController.ActivatableDevice,
|
||||
ClientConfigurableDevice {
|
||||
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion> {
|
||||
|
||||
private val facing: Direction
|
||||
get() = cachedState[MinerBlock.FACING]
|
||||
|
@ -43,10 +36,6 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
|
||||
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
||||
override val dispatchStackTimeout = TerminalBlockEntity.INSERTION_TIMEOUT
|
||||
override val controller = ActivationController(40L, this)
|
||||
override var providerPriority = 0
|
||||
|
||||
var minerMode = MinerMode.ON_DEMAND
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
|
@ -59,16 +48,10 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
}
|
||||
|
||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
||||
if (minerMode != MinerMode.ON_DEMAND) {
|
||||
return
|
||||
}
|
||||
sendPacket(ReadInventoryPacket(invProxy, ipAddress, packet.source))
|
||||
}
|
||||
|
||||
private fun handleLocateStack(packet: LocateStackPacket) {
|
||||
if (minerMode != MinerMode.ON_DEMAND) {
|
||||
return
|
||||
}
|
||||
val amount = invProxy.getAmount(packet.stack)
|
||||
if (amount > 0) {
|
||||
sendPacket(StackLocationPacket(packet.stack, amount, this, ipAddress, packet.source))
|
||||
|
@ -76,10 +59,6 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
}
|
||||
|
||||
private fun handleExtractStack(packet: ExtractStackPacket) {
|
||||
if (minerMode != MinerMode.ON_DEMAND) {
|
||||
return
|
||||
}
|
||||
|
||||
// always recalculate immediately before breaking
|
||||
val drops = invProxy.getDrops(recalculate = true)
|
||||
if (invProxy.getAmount(packet.stack) > 0) {
|
||||
|
@ -94,13 +73,14 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
if (!ItemStackUtil.areEqualIgnoreAmounts(droppedStack, packet.stack)) {
|
||||
continue
|
||||
}
|
||||
val copy = droppedStack.copy()
|
||||
|
||||
val toDecr = min(droppedStack.count, remaining)
|
||||
val copy = droppedStack.copyWithCount(toDecr)
|
||||
droppedStack.decrement(toDecr)
|
||||
remaining -= toDecr
|
||||
|
||||
// todo: should this try to combine stacks and send as few packets as possible?
|
||||
copy.count = toDecr
|
||||
sendPacket(ItemStackPacket(copy, ipAddress, packet.source))
|
||||
}
|
||||
|
||||
|
@ -119,76 +99,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
|
||||
override fun createPendingInsertion(stack: ItemStack) = PendingInsertion(stack, counter)
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (!world!!.isClient && minerMode == MinerMode.AUTOMATIC) {
|
||||
|
||||
controller.tick()
|
||||
}
|
||||
}
|
||||
|
||||
override fun activate(): Boolean {
|
||||
if (minerMode == MinerMode.ON_DEMAND) {
|
||||
return false
|
||||
}
|
||||
|
||||
val drops = invProxy.getDrops(recalculate = true)
|
||||
if (!world!!.getBlockState(pos.offset(facing)).isAir) {
|
||||
world!!.breakBlock(pos.offset(facing), false)
|
||||
|
||||
for (stack in drops) {
|
||||
if (stack.isEmpty) continue
|
||||
dispatchItemStack(stack)
|
||||
}
|
||||
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun canConfigureActivationController(): Boolean {
|
||||
return minerMode == MinerMode.AUTOMATIC
|
||||
}
|
||||
|
||||
override fun canConfigureProviderPriority(): Boolean {
|
||||
return minerMode == MinerMode.ON_DEMAND
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
tag.putString("MinerMode", minerMode.name)
|
||||
tag.putString("ActivationMode", controller.activationMode.name)
|
||||
tag.putInt("ProviderPriority", providerPriority)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
minerMode = MinerMode.valueOf(tag.getString("MinerMode"))
|
||||
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||
providerPriority = tag.getInt("ProviderPriority")
|
||||
}
|
||||
|
||||
enum class MinerMode {
|
||||
ON_DEMAND, AUTOMATIC;
|
||||
|
||||
val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.toLowerCase()}")
|
||||
}
|
||||
|
||||
class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView {
|
||||
companion object {
|
||||
val TOOL = ItemStack(Items.DIAMOND_PICKAXE)
|
||||
}
|
||||
|
||||
private var cachedState: BlockState? = null
|
||||
private var cachedDrops: List<ItemStack>? = null
|
||||
|
||||
|
@ -206,15 +117,12 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
if (cachedDrops == null || realState != cachedState || recalculate) {
|
||||
cachedState = realState
|
||||
val be = if (realState.block.hasBlockEntity()) world.getBlockEntity(targetPos) else null
|
||||
cachedDrops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be, null, TOOL)
|
||||
cachedDrops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be)
|
||||
}
|
||||
return cachedDrops!!
|
||||
}
|
||||
|
||||
override fun getStoredStacks(): Set<ItemStack> {
|
||||
if (miner.minerMode != MinerMode.ON_DEMAND) {
|
||||
return setOf()
|
||||
}
|
||||
return getDrops().toSet()
|
||||
}
|
||||
|
||||
|
@ -224,7 +132,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
|||
|
||||
override fun getStatistics(filter: ItemFilter): GroupedItemInvView.ItemInvStatistic {
|
||||
var totalCount = 0
|
||||
for (s in storedStacks) {
|
||||
for (s in getDrops()) {
|
||||
if (filter.matches(s)) {
|
||||
totalCount += s.count
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package net.shadowfacts.phycon.block.netinterface
|
||||
package net.shadowfacts.phycon.network.block.netinterface
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList
|
||||
import alexiil.mc.lib.attributes.AttributeProvider
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
|
@ -13,16 +12,12 @@ import net.minecraft.world.BlockView
|
|||
import net.minecraft.world.World
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.network.FaceDeviceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
),
|
||||
class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(Settings.of(Material.METAL)),
|
||||
NetworkComponentBlock,
|
||||
AttributeProvider {
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
package net.shadowfacts.phycon.block.netinterface
|
||||
package net.shadowfacts.phycon.network.block.netinterface
|
||||
|
||||
import alexiil.mc.lib.attributes.SearchOptions
|
||||
import alexiil.mc.lib.attributes.Simulation
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
||||
import alexiil.mc.lib.attributes.item.ItemAttributes
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.component.ItemStackPacketHandler
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.component.handleItemStack
|
||||
import net.shadowfacts.phycon.packet.*
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.network.component.ItemStackPacketHandler
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.network.component.handleItemStack
|
||||
import net.shadowfacts.phycon.network.packet.*
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
|
@ -26,15 +23,11 @@ import kotlin.math.min
|
|||
class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
||||
ItemStackPacketHandler,
|
||||
NetworkStackProvider,
|
||||
NetworkStackReceiver,
|
||||
ClientConfigurableDevice {
|
||||
NetworkStackReceiver {
|
||||
|
||||
private val facing: Direction
|
||||
get() = cachedState[FaceDeviceBlock.FACING]
|
||||
|
||||
override var providerPriority = 0
|
||||
override var receiverPriority = 0
|
||||
|
||||
// todo: should this be a weak ref?
|
||||
private var inventory: GroupedItemInv? = null
|
||||
|
||||
|
@ -108,24 +101,4 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
|
|||
}
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
tag.putInt("ProviderPriority", providerPriority)
|
||||
tag.putInt("ReceiverPriority", receiverPriority)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
providerPriority = tag.getInt("ProviderPriority")
|
||||
receiverPriority = tag.getInt("ReceiverPriority")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package net.shadowfacts.phycon.block.netswitch
|
||||
package net.shadowfacts.phycon.network.block.netswitch
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList
|
||||
import alexiil.mc.lib.attributes.AttributeProvider
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
|
@ -20,11 +19,7 @@ import java.util.*
|
|||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
),
|
||||
class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(Settings.of(Material.METAL)),
|
||||
NetworkComponentBlock,
|
||||
AttributeProvider {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.netswitch
|
||||
package net.shadowfacts.phycon.network.block.netswitch
|
||||
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
||||
import net.minecraft.block.BlockState
|
||||
|
@ -13,8 +13,8 @@ import net.shadowfacts.phycon.api.frame.EthernetFrame
|
|||
import net.shadowfacts.phycon.api.frame.PacketFrame
|
||||
import net.shadowfacts.phycon.api.util.MACAddress
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.util.NetworkUtil
|
||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||
import net.shadowfacts.phycon.network.NetworkUtil
|
||||
import net.shadowfacts.phycon.network.packet.ItemStackPacket
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
|
@ -1,10 +1,10 @@
|
|||
package net.shadowfacts.phycon.block.redstone_controller
|
||||
package net.shadowfacts.phycon.network.block.redstone
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.util.Identifier
|
||||
|
@ -12,23 +12,22 @@ import net.minecraft.util.math.BlockPos
|
|||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.network.FaceDeviceBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(Settings.of(Material.METAL)) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "redstone_controller")
|
||||
val POWERED = Properties.POWERED
|
||||
val LIT = Properties.LIT
|
||||
}
|
||||
|
||||
// todo: don't just copy this from the Interface block
|
||||
override val faceThickness = 3.0
|
||||
override val faceShapes = mapOf(
|
||||
Direction.DOWN to createCuboidShape(0.0, 0.0, 0.0, 16.0, 3.0, 16.0),
|
||||
|
@ -41,20 +40,20 @@ class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
|||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
super.appendProperties(builder)
|
||||
builder.add(POWERED)
|
||||
builder.add(LIT)
|
||||
}
|
||||
|
||||
override fun createBlockEntity(world: BlockView) = RedstoneControllerBlockEntity()
|
||||
|
||||
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
||||
val state = super.getPlacementState(context)
|
||||
return state.with(POWERED, isPowered(context.world, context.blockPos, state[FACING]))
|
||||
return state.with(LIT, isPowered(context.world, context.blockPos, state[FACING]))
|
||||
}
|
||||
|
||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
|
||||
// this can't be done in getStateForNeighborUpdate because getEmittedRedstonePower is defined in World not WorldAccess
|
||||
if (!world.isClient) {
|
||||
val wasLit = state[POWERED]
|
||||
val wasLit = state[LIT]
|
||||
val isLit = isPowered(world, pos, state[FACING])
|
||||
if (wasLit != isLit) {
|
||||
toggleLit(state, world, pos)
|
||||
|
@ -68,7 +67,7 @@ class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
|||
}
|
||||
|
||||
private fun toggleLit(state: BlockState, world: World, pos: BlockPos) {
|
||||
world.setBlockState(pos, state.cycle(POWERED), 2)
|
||||
world.setBlockState(pos, state.cycle(LIT), 2)
|
||||
getBlockEntity(world, pos)!!.redstoneStateChanged()
|
||||
}
|
||||
|
|
@ -1,19 +1,18 @@
|
|||
package net.shadowfacts.phycon.block.redstone_controller
|
||||
package net.shadowfacts.phycon.network.block.redstone
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.util.RedstoneMode
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_CONTROLLER),
|
||||
ClientConfigurableDevice {
|
||||
class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_CONTROLLER) {
|
||||
|
||||
var managedDevices = Array<IPAddress?>(5) { null }
|
||||
var redstoneMode = RedstoneMode.HIGH
|
||||
|
@ -25,7 +24,7 @@ class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE
|
|||
|
||||
fun redstoneStateChanged() {
|
||||
val oldPowered = redstonePowered
|
||||
redstonePowered = cachedState[RedstoneControllerBlock.POWERED]
|
||||
redstonePowered = cachedState[RedstoneControllerBlock.LIT]
|
||||
|
||||
val mode: RemoteActivationPacket.Mode? = when (redstoneMode) {
|
||||
RedstoneMode.TOGGLE -> if (oldPowered != redstonePowered) RemoteActivationPacket.Mode.SINGLE else null
|
||||
|
@ -47,22 +46,27 @@ class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE
|
|||
}
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: CompoundTag) {
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
tag.putIntArray("ManagedDevices", managedDevices.mapNotNull { it?.address })
|
||||
tag.putString("RedstoneMode", redstoneMode.name)
|
||||
return super.toTag(tag)
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
||||
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||
super.fromTag(state, tag)
|
||||
val addresses = tag.getIntArray("ManagedDevices")
|
||||
managedDevices = (0..4).map { if (it >= addresses.size) null else IPAddress(addresses[it]) }.toTypedArray()
|
||||
redstoneMode = RedstoneMode.valueOf(tag.getString("RedstoneMode"))
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
tag.putIntArray("ManagedDevices", managedDevices.mapNotNull { it?.address })
|
||||
tag.putString("RedstoneMode", redstoneMode.name)
|
||||
return super.toClientTag(tag)
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
super.fromClientTag(tag)
|
||||
val addresses = tag.getIntArray("ManagedDevices")
|
||||
managedDevices = (0..4).map { if (it >= addresses.size) null else IPAddress(addresses[it]) }.toTypedArray()
|
||||
redstoneMode = RedstoneMode.valueOf(tag.getString("RedstoneMode"))
|
|
@ -1,11 +1,10 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import alexiil.mc.lib.attributes.AttributeList
|
||||
import alexiil.mc.lib.attributes.AttributeProvider
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
|
@ -17,17 +16,13 @@ import net.minecraft.world.World
|
|||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||
import net.shadowfacts.phycon.block.DeviceBlock
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class TerminalBlock: DeviceBlock<TerminalBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
),
|
||||
class TerminalBlock: DeviceBlock<TerminalBlockEntity>(Settings.of(Material.METAL)),
|
||||
NetworkComponentBlock,
|
||||
AttributeProvider {
|
||||
|
||||
|
@ -46,15 +41,6 @@ class TerminalBlock: DeviceBlock<TerminalBlockEntity>(
|
|||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
override fun onStateReplaced(state: BlockState, world: World, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.isOf(newState.block)) {
|
||||
val be = getBlockEntity(world, pos)!!
|
||||
ItemScatterer.spawn(world, pos, be.internalBuffer)
|
||||
|
||||
super.onStateReplaced(state, world, pos, newState, moved)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) {
|
||||
to.offer(getBlockEntity(world, pos))
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||
import alexiil.mc.lib.attributes.item.ItemStackCollections
|
||||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.Inventory
|
||||
import net.minecraft.inventory.InventoryChangedListener
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
@ -21,10 +23,10 @@ import net.shadowfacts.phycon.api.Interface
|
|||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.util.NetworkUtil
|
||||
import net.shadowfacts.phycon.component.*
|
||||
import net.shadowfacts.phycon.packet.*
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.NetworkUtil
|
||||
import net.shadowfacts.phycon.network.component.*
|
||||
import net.shadowfacts.phycon.network.packet.*
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
@ -41,10 +43,8 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
|||
NetworkStackDispatcher<TerminalBlockEntity.PendingInsertion> {
|
||||
|
||||
companion object {
|
||||
// the locate/insertion timeouts are only 1 tick because that's long enough to hear from every device on the network
|
||||
// in a degraded state (when there's latency in the network), not handling interface priorities correctly is acceptable
|
||||
val LOCATE_REQUEST_TIMEOUT: Long = 1 // ticks
|
||||
val INSERTION_TIMEOUT: Long = 1
|
||||
val LOCATE_REQUEST_TIMEOUT: Long = 40 // ticks
|
||||
val INSERTION_TIMEOUT: Long = 40
|
||||
}
|
||||
|
||||
private val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>()
|
||||
|
@ -164,15 +164,14 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
|||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (!world!!.isClient) {
|
||||
finishPendingRequests()
|
||||
finishTimedOutPendingInsertions()
|
||||
}
|
||||
if (counter % 20 == 0L) {
|
||||
if (!world!!.isClient) {
|
||||
finishPendingRequests()
|
||||
beginInsertions()
|
||||
finishTimedOutPendingInsertions()
|
||||
}
|
||||
|
||||
if (counter % 20 == 0L && !world!!.isClient) {
|
||||
beginInsertions()
|
||||
|
||||
if (observers > 0) {
|
||||
if (observers > 0 && !world!!.isClient) {
|
||||
updateAndSync()
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +184,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
|||
inventoryCache.clear()
|
||||
sendPacket(RequestInventoryPacket(ipAddress))
|
||||
val factory = object: ExtendedScreenHandlerFactory {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler? {
|
||||
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
||||
}
|
||||
|
||||
|
@ -211,15 +210,8 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
|||
private fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
||||
pendingRequests.remove(request)
|
||||
|
||||
val sortedResults = request.results.toMutableList()
|
||||
sortedResults.sortWith { a, b ->
|
||||
// sort results first by provider priority, and then by the count that it can provide
|
||||
if (a.second.providerPriority == b.second.providerPriority) {
|
||||
b.first - a.first
|
||||
} else {
|
||||
b.second.providerPriority - a.second.providerPriority
|
||||
}
|
||||
}
|
||||
// todo: also sort results by interface priority
|
||||
val sortedResults = request.results.sortedByDescending { it.first }.toMutableList()
|
||||
var amountRequested = 0
|
||||
while (amountRequested < request.amount && sortedResults.isNotEmpty()) {
|
||||
val (sourceAmount, sourceInterface) = sortedResults.removeAt(0)
|
||||
|
@ -248,15 +240,25 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
|||
}
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: CompoundTag) {
|
||||
super.toCommonTag(tag)
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
tag.put("InternalBuffer", internalBuffer.toTag())
|
||||
return super.toTag(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: CompoundTag) {
|
||||
super.fromCommonTag(tag)
|
||||
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||
super.fromTag(state, tag)
|
||||
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
tag.put("InternalBuffer", internalBuffer.toTag())
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
||||
}
|
||||
|
||||
interface NetItemObserver {
|
||||
fun netItemsChanged()
|
||||
}
|
||||
|
@ -277,8 +279,6 @@ data class StackLocateRequest(
|
|||
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
||||
|
||||
fun isFinishable(currentTimestamp: Long): Boolean {
|
||||
// we can't check totalResultAmount >= amount because we need to hear back from all network stack providers to
|
||||
// correctly sort by priority
|
||||
return currentTimestamp - timestamp >= TerminalBlockEntity.LOCATE_REQUEST_TIMEOUT
|
||||
return totalResultAmount >= amount || currentTimestamp - timestamp >= TerminalBlockEntity.LOCATE_REQUEST_TIMEOUT
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
import net.minecraft.inventory.SimpleInventory
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.entity.player.PlayerEntity
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import net.minecraft.client.MinecraftClient
|
|
@ -1,5 +1,6 @@
|
|||
package net.shadowfacts.phycon.block.terminal
|
||||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import net.minecraft.client.network.ClientPlayerEntity
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
|
@ -13,16 +14,17 @@ import net.minecraft.util.registry.Registry
|
|||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.init.PhyScreens
|
||||
import net.shadowfacts.phycon.networking.C2STerminalRequestItem
|
||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||
import net.shadowfacts.phycon.util.SortMode
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val terminal: TerminalBlockEntity): ScreenHandler(PhyScreens.TERMINAL, syncId),
|
||||
class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val terminal: TerminalBlockEntity): ScreenHandler(PhyScreens.TERMINAL_SCREEN_HANDLER, syncId),
|
||||
TerminalBlockEntity.NetItemObserver {
|
||||
|
||||
companion object {
|
||||
|
@ -38,7 +40,9 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
|||
field = value
|
||||
if (terminal.world!!.isClient) {
|
||||
itemsForDisplay = value.map {
|
||||
it.stack.copyWithCount(it.amount)
|
||||
val stack = it.stack.copy()
|
||||
stack.count = it.amount
|
||||
stack
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package net.shadowfacts.phycon.network.block.test
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class DestBlock: DeviceBlock<DestBlockEntity>(Settings.of(Material.METAL)) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "dest")
|
||||
}
|
||||
|
||||
override fun createBlockEntity(world: BlockView): DestBlockEntity {
|
||||
return DestBlockEntity()
|
||||
}
|
||||
|
||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): MutableCollection<Direction> {
|
||||
return EnumSet.allOf(Direction::class.java)
|
||||
}
|
||||
|
||||
override fun onUse(
|
||||
blockState: BlockState?,
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
playerEntity: PlayerEntity?,
|
||||
hand: Hand?,
|
||||
blockHitResult: BlockHitResult?
|
||||
): ActionResult {
|
||||
println("dest IP: ${getBlockEntity(world, pos)!!.ipAddress}")
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.shadowfacts.phycon.network.block.test
|
||||
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.NetworkUtil
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class DestBlockEntity: DeviceBlockEntity(PhyBlockEntities.DEST) {
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
println("$this ($ipAddress) received packet: $packet")
|
||||
}
|
||||
|
||||
override fun findDestination(): Interface? {
|
||||
for (dir in Direction.values()) {
|
||||
val itf = NetworkUtil.findConnectedInterface(world!!, pos, dir)
|
||||
if (itf != null) {
|
||||
return itf
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.shadowfacts.phycon.network.block.test
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.network.DeviceBlock
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class SourceBlock: DeviceBlock<SourceBlockEntity>(Settings.of(Material.METAL)) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "source")
|
||||
}
|
||||
|
||||
override fun createBlockEntity(world: BlockView): SourceBlockEntity {
|
||||
return SourceBlockEntity()
|
||||
}
|
||||
|
||||
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): MutableCollection<Direction> {
|
||||
return EnumSet.allOf(Direction::class.java)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package net.shadowfacts.phycon.network.block.test
|
||||
|
||||
import net.minecraft.util.Tickable
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.shadowfacts.phycon.api.Interface
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.NetworkUtil
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class SourceBlockEntity: DeviceBlockEntity(PhyBlockEntities.SOURCE), Tickable {
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
if (!world!!.isClient && counter % 40 == 0L) {
|
||||
sendPacket(TestPacket(ipAddress, IPAddress(170, 171, 101, 168)))
|
||||
}
|
||||
}
|
||||
|
||||
override fun findDestination(): Interface? {
|
||||
for (dir in Direction.values()) {
|
||||
val itf = NetworkUtil.findConnectedInterface(world!!, pos, dir)
|
||||
if (itf != null) {
|
||||
return itf
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.shadowfacts.phycon.network.block.test
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.network.packet.BasePacket
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class TestPacket(source: IPAddress, destination: IPAddress): BasePacket(source, destination) {
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
package net.shadowfacts.phycon.component
|
||||
package net.shadowfacts.phycon.network.component
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.shadowfacts.phycon.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.network.packet.RemoteActivationPacket
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -51,15 +50,11 @@ class ActivationController<T>(
|
|||
}
|
||||
}
|
||||
|
||||
interface ActivatableDevice: ClientConfigurableDevice {
|
||||
interface ActivatableDevice {
|
||||
val controller: ActivationController<*>
|
||||
|
||||
val counter: Long
|
||||
|
||||
fun activate(): Boolean
|
||||
|
||||
fun canConfigureActivationController(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package net.shadowfacts.phycon.component
|
||||
package net.shadowfacts.phycon.network.component
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.entity.ItemEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.PacketSink
|
||||
import net.shadowfacts.phycon.api.PacketSource
|
||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||
import net.shadowfacts.phycon.network.packet.ItemStackPacket
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
|
@ -1,14 +1,12 @@
|
|||
package net.shadowfacts.phycon.component
|
||||
package net.shadowfacts.phycon.network.component
|
||||
|
||||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.packet.CapacityPacket
|
||||
import net.shadowfacts.phycon.packet.CheckCapacityPacket
|
||||
import net.shadowfacts.phycon.packet.ItemStackPacket
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
import kotlin.math.min
|
||||
import net.shadowfacts.phycon.network.packet.CapacityPacket
|
||||
import net.shadowfacts.phycon.network.packet.CheckCapacityPacket
|
||||
import net.shadowfacts.phycon.network.packet.ItemStackPacket
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -29,10 +27,10 @@ interface NetworkStackDispatcher<Insertion: NetworkStackDispatcher.PendingInsert
|
|||
}
|
||||
|
||||
fun handleCapacity(packet: CapacityPacket) {
|
||||
pendingInsertions.firstOrNull { insertion ->
|
||||
ItemStackUtil.areEqualIgnoreAmounts(packet.stack, insertion.stack) &&
|
||||
insertion.results.none { it.second.ipAddress == packet.source }
|
||||
}?.also { insertion ->
|
||||
val insertion = pendingInsertions.firstOrNull {
|
||||
ItemStackUtil.areEqualIgnoreAmounts(packet.stack, it.stack)
|
||||
}
|
||||
if (insertion != null) {
|
||||
insertion.results.add(packet.capacity to packet.stackReceiver)
|
||||
if (insertion.isFinishable(this)) {
|
||||
val remaining = finishInsertion(insertion)
|
||||
|
@ -44,22 +42,14 @@ interface NetworkStackDispatcher<Insertion: NetworkStackDispatcher.PendingInsert
|
|||
fun finishInsertion(insertion: Insertion): ItemStack {
|
||||
pendingInsertions.remove(insertion)
|
||||
|
||||
val sortedResults = insertion.results.toMutableList()//.sortedBy { it.first }.toMutableList()
|
||||
sortedResults.sortWith { a, b ->
|
||||
// sort results first by receiver priority, and then by capacity
|
||||
if (a.second.receiverPriority == b.second.receiverPriority) {
|
||||
b.first - a.first
|
||||
} else {
|
||||
b.second.receiverPriority - a.second.receiverPriority
|
||||
}
|
||||
}
|
||||
// todo: also sort results by interface priority
|
||||
val sortedResults = insertion.results.sortedBy { it.first }.toMutableList()
|
||||
// copy the insertion stack so subclasses that override this method can still see the originally dispatched stack after the super call
|
||||
val remaining = insertion.stack.copy()
|
||||
while (!remaining.isEmpty && sortedResults.isNotEmpty()) {
|
||||
val (capacity, receivingInterface) = sortedResults.removeFirst()
|
||||
if (capacity <= 0) continue
|
||||
val copy = remaining.copyWithCount(min(capacity, remaining.count))
|
||||
sendPacket(ItemStackPacket(copy, ipAddress, receivingInterface.ipAddress))
|
||||
sendPacket(ItemStackPacket(remaining.copy(), ipAddress, receivingInterface.ipAddress))
|
||||
// todo: the destination should confirm how much was actually inserted, in case of race condition
|
||||
remaining.count -= capacity
|
||||
}
|
||||
|
@ -77,8 +67,7 @@ interface NetworkStackDispatcher<Insertion: NetworkStackDispatcher.PendingInsert
|
|||
get() = results.fold(0) { acc, (amount, _) -> acc + amount }
|
||||
|
||||
fun isFinishable(owner: NetworkStackDispatcher<Self>): Boolean {
|
||||
// can't check totalCapacity >= stack.count because we need to wait for all responses to correctly sort by priority
|
||||
return owner.counter - timestamp >= owner.dispatchStackTimeout
|
||||
return totalCapacity >= stack.count || owner.counter - timestamp >= owner.dispatchStackTimeout
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package net.shadowfacts.phycon.network.component
|
||||
|
||||
import net.shadowfacts.phycon.api.NetworkDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
interface NetworkStackProvider: NetworkDevice {
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package net.shadowfacts.phycon.network.component
|
||||
|
||||
import net.shadowfacts.phycon.api.NetworkDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
interface NetworkStackReceiver: NetworkDevice {
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.frame
|
||||
package net.shadowfacts.phycon.network.frame
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.api.util.MACAddress
|
|
@ -1,6 +1,8 @@
|
|||
package net.shadowfacts.phycon.frame
|
||||
package net.shadowfacts.phycon.network.frame
|
||||
|
||||
import net.shadowfacts.phycon.api.frame.EthernetFrame
|
||||
import net.shadowfacts.phycon.api.frame.PacketFrame
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.MACAddress
|
||||
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.frame
|
||||
package net.shadowfacts.phycon.network.frame
|
||||
|
||||
import net.shadowfacts.phycon.api.frame.PacketFrame
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,8 +1,8 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackReceiver
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,7 +1,7 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
package net.shadowfacts.phycon.network.packet
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
|
@ -2,31 +2,31 @@ package net.shadowfacts.phycon.networking
|
|||
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketSender
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.Packet
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.registry.Registry
|
||||
import net.minecraft.util.registry.RegistryKey
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.component.ActivationController
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
object C2SConfigureDevice: ServerReceiver {
|
||||
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "configure_device")
|
||||
object C2SConfigureActivationMode: ServerReceiver {
|
||||
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "configure_activation_mode")
|
||||
|
||||
operator fun <T> invoke(be: T): Packet<*> where T: BlockEntity, T: ClientConfigurableDevice {
|
||||
operator fun <T> invoke(be: T): Packet<*> where T: DeviceBlockEntity, T: ActivationController.ActivatableDevice {
|
||||
val buf = PacketByteBufs.create()
|
||||
|
||||
buf.writeIdentifier(be.world!!.registryKey.value)
|
||||
buf.writeBlockPos(be.pos)
|
||||
val tag = CompoundTag()
|
||||
be.writeDeviceConfiguration(tag)
|
||||
buf.writeCompoundTag(tag)
|
||||
buf.writeString(be.controller.activationMode.name)
|
||||
|
||||
return createPacket(buf)
|
||||
}
|
||||
|
@ -34,16 +34,16 @@ object C2SConfigureDevice: ServerReceiver {
|
|||
override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
|
||||
val dimID = buf.readIdentifier()
|
||||
val pos = buf.readBlockPos()
|
||||
val tag = buf.readCompoundTag() ?: return
|
||||
val mode = ActivationMode.valueOf(buf.readString())
|
||||
|
||||
server.execute {
|
||||
// todo: check if the player is close enough
|
||||
val world = player.world
|
||||
if (world.registryKey.value != dimID) return@execute
|
||||
val be = world.getBlockEntity(pos) ?: return@execute
|
||||
val device = be as? ClientConfigurableDevice ?: return@execute
|
||||
device.loadDeviceConfiguration(tag)
|
||||
be.markDirty()
|
||||
// todo: check the player is close enough
|
||||
val key = RegistryKey.of(Registry.DIMENSION, dimID)
|
||||
val world = server.getWorld(key) ?: return@execute
|
||||
val device = world.getBlockEntity(pos) ?: return@execute
|
||||
if (device !is ActivationController.ActivatableDevice) return@execute
|
||||
device.controller.activationMode = mode
|
||||
device.markDirty()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.shadowfacts.phycon.networking
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketSender
|
||||
import net.minecraft.network.Packet
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.registry.Registry
|
||||
import net.minecraft.util.registry.RegistryKey
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.util.RedstoneMode
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
object C2SConfigureRedstoneController: ServerReceiver {
|
||||
// todo: it would be nice if there wasn't so much duplication with C2SConfigureActivationMode
|
||||
|
||||
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "configure_redstone_controller")
|
||||
|
||||
operator fun invoke(be: RedstoneControllerBlockEntity): Packet<*> {
|
||||
val buf = PacketByteBufs.create()
|
||||
|
||||
buf.writeIdentifier(be.world!!.registryKey.value)
|
||||
buf.writeBlockPos(be.pos)
|
||||
buf.writeString(be.redstoneMode.name)
|
||||
be.managedDevices.forEach {
|
||||
buf.writeInt(it?.address ?: 0)
|
||||
}
|
||||
|
||||
return createPacket(buf)
|
||||
}
|
||||
|
||||
override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
|
||||
val dimID = buf.readIdentifier()
|
||||
val pos = buf.readBlockPos()
|
||||
val mode = RedstoneMode.valueOf(buf.readString())
|
||||
val managedDevices = Array<IPAddress?>(5) { null }
|
||||
(0..4).map {
|
||||
val v = buf.readInt()
|
||||
managedDevices[it] = if (v == 0) null else IPAddress(v)
|
||||
}
|
||||
|
||||
server.execute {
|
||||
// todo: check if the player is close enough
|
||||
val key = RegistryKey.of(Registry.DIMENSION, dimID)
|
||||
val world = server.getWorld(key) ?: return@execute
|
||||
val device = world.getBlockEntity(pos) as? RedstoneControllerBlockEntity ?: return@execute
|
||||
device.redstoneMode = mode
|
||||
device.managedDevices = managedDevices
|
||||
device.markDirty()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,8 +13,7 @@ import net.minecraft.util.Identifier
|
|||
import net.minecraft.util.registry.Registry
|
||||
import net.minecraft.util.registry.RegistryKey
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.util.copyWithCount
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -31,7 +30,9 @@ object C2STerminalRequestItem: ServerReceiver {
|
|||
// Force the count of the stack to be 1 before serializing for the network because
|
||||
// PacketByteBuf serializes the stack count as a byte. Otherwise counts > 127 will result in
|
||||
// an overflow and be negative on the receiving side.
|
||||
buf.writeItemStack(stack.copyWithCount(1))
|
||||
val stackCopy = stack.copy()
|
||||
stackCopy.count = 1
|
||||
buf.writeItemStack(stackCopy)
|
||||
|
||||
buf.writeVarInt(amount)
|
||||
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
||||
|
|
|
@ -10,8 +10,8 @@ import net.minecraft.server.network.ServerPlayNetworkHandler
|
|||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreenHandler
|
||||
import net.shadowfacts.phycon.util.SortMode
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,8 +7,8 @@ import net.minecraft.client.MinecraftClient
|
|||
import net.minecraft.client.network.ClientPlayNetworkHandler
|
||||
import net.minecraft.network.Packet
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreenHandler
|
||||
import net.shadowfacts.phycon.util.SortMode
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,14 +2,16 @@ package net.shadowfacts.phycon.screen.console
|
|||
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.shadowfacts.cacao.geometry.Axis
|
||||
import net.shadowfacts.cacao.util.Color
|
||||
import net.shadowfacts.cacao.view.Label
|
||||
import net.shadowfacts.cacao.view.StackView
|
||||
import net.shadowfacts.cacao.view.button.EnumButton
|
||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.component.ActivationController
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureActivationMode
|
||||
import net.shadowfacts.phycon.util.ActivationMode
|
||||
|
||||
/**
|
||||
|
@ -30,7 +32,7 @@ class ActivatableDeviceViewController<T>(
|
|||
val mode = EnumButton(device.controller.activationMode, ActivationMode::friendlyName)
|
||||
mode.handler = {
|
||||
device.controller.activationMode = it.value
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureActivationMode(device))
|
||||
}
|
||||
view.addSubview(mode)
|
||||
|
||||
|
|
|
@ -12,12 +12,9 @@ import net.shadowfacts.cacao.viewcontroller.TabViewController
|
|||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.cacao.window.Window
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.network.component.ActivationController
|
||||
import org.lwjgl.glfw.GLFW
|
||||
|
||||
/**
|
||||
|
@ -43,8 +40,7 @@ class DeviceConsoleScreen(
|
|||
intrinsicContentSize = Size(16.0, 16.0)
|
||||
},
|
||||
TranslatableText("gui.phycon.console.remote"),
|
||||
ActivatableDeviceViewController(device),
|
||||
device::canConfigureActivationController
|
||||
ActivatableDeviceViewController(device)
|
||||
))
|
||||
}
|
||||
if (device is RedstoneControllerBlockEntity) {
|
||||
|
@ -56,30 +52,7 @@ class DeviceConsoleScreen(
|
|||
RedstoneControllerViewController(device)
|
||||
))
|
||||
}
|
||||
if (device is MinerBlockEntity) {
|
||||
tabs.add(TabViewController.SimpleTab(
|
||||
TextureView(Texture(Identifier("textures/item/diamond_pickaxe.png"), 0, 0, 16, 16)).apply {
|
||||
intrinsicContentSize = Size(16.0, 16.0)
|
||||
},
|
||||
TranslatableText("block.phycon.miner"),
|
||||
MinerViewController(device)
|
||||
))
|
||||
}
|
||||
if (device is NetworkStackProvider) {
|
||||
tabs.add(TabViewController.SimpleTab(
|
||||
Label("P").apply { textColor = Color.TEXT },
|
||||
TranslatableText("gui.phycon.console.provider"),
|
||||
ProviderViewController(device),
|
||||
device::canConfigureProviderPriority
|
||||
))
|
||||
}
|
||||
if (device is NetworkStackReceiver) {
|
||||
tabs.add(TabViewController.SimpleTab(
|
||||
Label("R").apply { textColor = Color.TEXT },
|
||||
TranslatableText("gui.phycon.console.receiver"),
|
||||
ReceiverViewController(device),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
tabController = TabViewController(tabs)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import net.shadowfacts.cacao.view.Label
|
|||
import net.shadowfacts.cacao.view.StackView
|
||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
package net.shadowfacts.phycon.screen.console
|
||||
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.shadowfacts.cacao.util.Color
|
||||
import net.shadowfacts.cacao.view.Label
|
||||
import net.shadowfacts.cacao.view.button.EnumButton
|
||||
import net.shadowfacts.cacao.viewcontroller.TabViewController
|
||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.block.miner.MinerBlockEntity
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class MinerViewController(
|
||||
val device: MinerBlockEntity,
|
||||
): ViewController() {
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val label = Label(TranslatableText("gui.phycon.console.miner.mode")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(label)
|
||||
|
||||
val mode = EnumButton(device.minerMode, MinerBlockEntity.MinerMode::friendlyName)
|
||||
mode.handler = {
|
||||
device.minerMode = it.value
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
|
||||
(parent as TabViewController<TabViewController.SimpleTab>).visibleTabsChanged()
|
||||
}
|
||||
view.addSubview(mode)
|
||||
|
||||
view.solver.dsl {
|
||||
mode.widthAnchor equalTo 100
|
||||
mode.heightAnchor equalTo 20
|
||||
mode.topAnchor equalTo view.topAnchor
|
||||
mode.rightAnchor equalTo view.rightAnchor
|
||||
|
||||
label.centerYAnchor equalTo mode.centerYAnchor
|
||||
label.rightAnchor equalTo (mode.leftAnchor - 4)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package net.shadowfacts.phycon.screen.console
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.shadowfacts.cacao.util.Color
|
||||
import net.shadowfacts.cacao.view.Label
|
||||
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.component.NetworkStackProvider
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class ProviderViewController<T>(
|
||||
private val device: T
|
||||
): ViewController() where T: BlockEntity, T: NetworkStackProvider {
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val label = Label(TranslatableText("gui.phycon.console.provider.priority")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(label)
|
||||
|
||||
val field = NumberField(device.providerPriority) {
|
||||
if (it.number != null) {
|
||||
device.providerPriority = it.number!!
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
}
|
||||
}
|
||||
view.addSubview(field)
|
||||
|
||||
val desc = Label(TranslatableText("gui.phycon.console.provider.priority_desc")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(desc)
|
||||
|
||||
view.solver.dsl {
|
||||
field.widthAnchor equalTo 100
|
||||
field.heightAnchor equalTo 20
|
||||
field.rightAnchor equalTo view.rightAnchor
|
||||
field.topAnchor equalTo view.topAnchor
|
||||
|
||||
label.centerYAnchor equalTo field.centerYAnchor
|
||||
label.rightAnchor equalTo (field.leftAnchor - 4)
|
||||
|
||||
desc.topAnchor equalTo (field.bottomAnchor + 4)
|
||||
desc.leftAnchor equalTo view.leftAnchor
|
||||
desc.rightAnchor equalTo view.rightAnchor
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package net.shadowfacts.phycon.screen.console
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.shadowfacts.cacao.util.Color
|
||||
import net.shadowfacts.cacao.view.Label
|
||||
import net.shadowfacts.cacao.view.textfield.NumberField
|
||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.component.NetworkStackReceiver
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class ReceiverViewController<T>(
|
||||
private val device: T
|
||||
): ViewController() where T: BlockEntity, T: NetworkStackReceiver {
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val label = Label(TranslatableText("gui.phycon.console.receiver.priority")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(label)
|
||||
|
||||
val field = NumberField(device.receiverPriority) {
|
||||
if (it.number != null) {
|
||||
device.receiverPriority = it.number!!
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
}
|
||||
}
|
||||
view.addSubview(field)
|
||||
|
||||
val desc = Label(TranslatableText("gui.phycon.console.receiver.priority_desc")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(desc)
|
||||
|
||||
view.solver.dsl {
|
||||
field.widthAnchor equalTo 100
|
||||
field.heightAnchor equalTo 20
|
||||
field.rightAnchor equalTo view.rightAnchor
|
||||
field.topAnchor equalTo view.topAnchor
|
||||
|
||||
label.centerYAnchor equalTo field.centerYAnchor
|
||||
label.rightAnchor equalTo (field.leftAnchor - 4)
|
||||
|
||||
desc.topAnchor equalTo (field.bottomAnchor + 4)
|
||||
desc.leftAnchor equalTo view.leftAnchor
|
||||
desc.rightAnchor equalTo view.rightAnchor
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,8 +11,8 @@ import net.shadowfacts.cacao.view.textfield.TextField
|
|||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||
import net.shadowfacts.kiwidsl.dsl
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
import net.shadowfacts.phycon.network.block.redstone.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureRedstoneController
|
||||
import net.shadowfacts.phycon.util.RedstoneMode
|
||||
|
||||
/**
|
||||
|
@ -39,14 +39,14 @@ class RedstoneControllerViewController(val device: RedstoneControllerBlockEntity
|
|||
val mode = EnumButton(device.redstoneMode, RedstoneMode::friendlyName)
|
||||
mode.handler = {
|
||||
device.redstoneMode = it.value
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureRedstoneController(device))
|
||||
}
|
||||
controls.addArrangedSubview(mode)
|
||||
|
||||
val textFields = (0 until 5).map { i ->
|
||||
TextField(device.managedDevices[i]?.toString() ?: "") {
|
||||
device.managedDevices[i] = IPAddress.parse(it.text)
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureRedstoneController(device))
|
||||
}
|
||||
}
|
||||
textFields.forEach(controls::addArrangedSubview)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
package net.shadowfacts.phycon.util
|
||||
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
interface ClientConfigurableDevice {
|
||||
|
||||
fun writeDeviceConfiguration(tag: CompoundTag)
|
||||
|
||||
fun loadDeviceConfiguration(tag: CompoundTag)
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package net.shadowfacts.phycon.util
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.inventory.Inventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import kotlin.reflect.KMutableProperty
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class GhostSlot(prop: KMutableProperty<ItemStack>, x: Int, y: Int): Slot(GhostInv(prop), 0, x, y) {
|
||||
|
||||
override fun canInsert(stack: ItemStack) = false
|
||||
|
||||
override fun setStack(itemStack: ItemStack?) {
|
||||
}
|
||||
|
||||
override fun canTakeItems(player: PlayerEntity) = false
|
||||
|
||||
class GhostInv(private val prop: KMutableProperty<ItemStack>): Inventory {
|
||||
override fun clear() {
|
||||
prop.setter.call(ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
override fun size() = 1
|
||||
|
||||
override fun isEmpty() = prop.getter.call().isEmpty
|
||||
|
||||
override fun getStack(i: Int): ItemStack {
|
||||
return if (i == 0) prop.getter.call()
|
||||
else ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun removeStack(i: Int, j: Int) = ItemStack.EMPTY
|
||||
|
||||
override fun removeStack(i: Int) = ItemStack.EMPTY
|
||||
|
||||
override fun setStack(i: Int, itemStack: ItemStack) {}
|
||||
|
||||
override fun markDirty() {}
|
||||
|
||||
override fun canPlayerUse(playerEntity: PlayerEntity?) = true
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package net.shadowfacts.phycon.util
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
fun ItemStack.copyWithCount(count: Int): ItemStack {
|
||||
return copy().also { it.count = count }
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
package net.shadowfacts.phycon.util
|
||||
|
||||
import net.minecraft.text.*
|
||||
import net.minecraft.util.Formatting
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
fun text(build: TextContext.() -> Unit): Text {
|
||||
val context = TextContext()
|
||||
context.build()
|
||||
return context.toText()
|
||||
}
|
||||
|
||||
class TextContext(
|
||||
private val texts: MutableList<Text> = mutableListOf(),
|
||||
private val styles: Deque<Style> = LinkedList()
|
||||
) {
|
||||
|
||||
fun toText(): MutableText {
|
||||
val text = LiteralText("")
|
||||
texts.forEach(text::append)
|
||||
return text
|
||||
}
|
||||
|
||||
operator fun String.unaryPlus() {
|
||||
+LiteralText(this)
|
||||
}
|
||||
|
||||
operator fun MutableText.unaryPlus() {
|
||||
if (styles.isNotEmpty()) {
|
||||
texts.add(this.setStyle(styles.peek()))
|
||||
} else {
|
||||
texts.add(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun translate(key: String, vararg parameters: Any): TranslatableText {
|
||||
return TranslatableText(key, *parameters)
|
||||
}
|
||||
|
||||
fun withStyle(style: Style, build: TextContext.() -> Unit) {
|
||||
styles.push(style)
|
||||
build()
|
||||
styles.pop()
|
||||
}
|
||||
|
||||
fun withStyle(style: Style.() -> Style, build: TextContext.() -> Unit) {
|
||||
withStyle(Style.EMPTY.style(), build)
|
||||
}
|
||||
|
||||
fun withStyle(formatting: Formatting, build: TextContext.() -> Unit) {
|
||||
withStyle(Style.EMPTY.withFormatting(formatting), build)
|
||||
}
|
||||
|
||||
val bold = Formatting.BOLD
|
||||
fun Style.bold(): Style = withBold(true)
|
||||
|
||||
val italic = Formatting.ITALIC
|
||||
fun Style.italic(): Style = withItalic(true)
|
||||
|
||||
val strikethrough = Formatting.STRIKETHROUGH
|
||||
fun Style.strikethrough(): Style = withFormatting(strikethrough)
|
||||
|
||||
val underline = Formatting.UNDERLINE
|
||||
fun Style.underline(): Style = withFormatting(underline)
|
||||
|
||||
val obfuscated = Formatting.OBFUSCATED
|
||||
fun Style.obfuscated(): Style = withFormatting(obfuscated)
|
||||
|
||||
val black = Formatting.BLACK
|
||||
fun Style.black(): Style = withFormatting(black)
|
||||
|
||||
val darkBlue = Formatting.DARK_BLUE
|
||||
fun Style.darkBlue(): Style = withFormatting(darkBlue)
|
||||
|
||||
val darkGreen = Formatting.DARK_GREEN
|
||||
fun Style.darkGreen(): Style = withFormatting(darkGreen)
|
||||
|
||||
val darkAqua = Formatting.DARK_AQUA
|
||||
fun Style.darkAqua(): Style = withFormatting(darkAqua)
|
||||
|
||||
val darkRed = Formatting.DARK_RED
|
||||
fun Style.darkRed(): Style = withFormatting(darkRed)
|
||||
|
||||
val darkPurple = Formatting.DARK_PURPLE
|
||||
fun Style.darkPurple(): Style = withFormatting(darkPurple)
|
||||
|
||||
val gold = Formatting.GOLD
|
||||
fun Style.gold(): Style = withFormatting(gold)
|
||||
|
||||
val gray = Formatting.GRAY
|
||||
fun Style.gray(): Style = withFormatting(gray)
|
||||
|
||||
val darkGray = Formatting.DARK_GRAY
|
||||
fun Style.darkGray(): Style = withFormatting(darkGray)
|
||||
|
||||
val blue = Formatting.BLUE
|
||||
fun Style.blue(): Style = withFormatting(blue)
|
||||
|
||||
val green = Formatting.GREEN
|
||||
fun Style.green(): Style = withFormatting(green)
|
||||
|
||||
val aqua = Formatting.RED
|
||||
fun Style.aqua(): Style = withFormatting(aqua)
|
||||
|
||||
val red = Formatting.RED
|
||||
fun Style.red(): Style = withFormatting(red)
|
||||
|
||||
val lightPurple = Formatting.LIGHT_PURPLE
|
||||
fun Style.lightPurple(): Style = withFormatting(lightPurple)
|
||||
|
||||
val yellow = Formatting.YELLOW
|
||||
fun Style.yellow(): Style = withFormatting(yellow)
|
||||
|
||||
val white = Formatting.WHITE
|
||||
fun Style.white(): Style = withFormatting(white)
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"variants": {
|
||||
"facing=down": {
|
||||
"model": "phycon:block/inserter"
|
||||
},
|
||||
"facing=up": {
|
||||
"model": "phycon:block/inserter",
|
||||
"x": 180
|
||||
},
|
||||
"facing=north": {
|
||||
"model": "phycon:block/inserter",
|
||||
"x": 270
|
||||
},
|
||||
"facing=south": {
|
||||
"model": "phycon:block/inserter",
|
||||
"x": 90
|
||||
},
|
||||
"facing=west": {
|
||||
"model": "phycon:block/inserter",
|
||||
"x": 90,
|
||||
"y": 90
|
||||
},
|
||||
"facing=east": {
|
||||
"model": "phycon:block/inserter",
|
||||
"x": 90,
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,51 +4,51 @@
|
|||
"apply": { "model": "phycon:block/cable_center" }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "down", "powered": "false" },
|
||||
"when": { "facing": "down", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off" }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "up", "powered": "false" },
|
||||
"when": { "facing": "up", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 180 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "north", "powered": "false" },
|
||||
"when": { "facing": "north", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 270 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "south", "powered": "false" },
|
||||
"when": { "facing": "south", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "west", "powered": "false" },
|
||||
"when": { "facing": "west", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90, "y": 90 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "east", "powered": "false" },
|
||||
"when": { "facing": "east", "lit": "false" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_off", "x": 90, "y": 270 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "down", "powered": "true" },
|
||||
"when": { "facing": "down", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on" }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "up", "powered": "true" },
|
||||
"when": { "facing": "up", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 180 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "north", "powered": "true" },
|
||||
"when": { "facing": "north", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 270 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "south", "powered": "true" },
|
||||
"when": { "facing": "south", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "west", "powered": "true" },
|
||||
"when": { "facing": "west", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90, "y": 90 }
|
||||
},
|
||||
{
|
||||
"when": { "facing": "east", "powered": "true" },
|
||||
"when": { "facing": "east", "lit": "true" },
|
||||
"apply": { "model": "phycon:block/redstone_controller_side_on", "x": 90, "y": 270 }
|
||||
},
|
||||
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
{
|
||||
"multipart": [
|
||||
{
|
||||
"apply": { "model": "phycon:block/cable_center" }
|
||||
},
|
||||
{
|
||||
"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 }
|
||||
}
|
||||
]
|
||||
}
|
|
@ -4,10 +4,8 @@
|
|||
"block.phycon.terminal": "Terminal",
|
||||
"block.phycon.cable": "Cable",
|
||||
"block.phycon.extractor": "Inventory Extractor",
|
||||
"block.phycon.inserter": "Inventory Inserter",
|
||||
"block.phycon.miner": "Block Miner",
|
||||
"block.phycon.redstone_controller": "Redstone Controller",
|
||||
"block.phycon.redstone_emitter": "Redstone Emitter",
|
||||
|
||||
"item.phycon.screwdriver": "Screwdriver",
|
||||
"item.phycon.console": "Console",
|
||||
|
@ -20,24 +18,11 @@
|
|||
"gui.phycon.console.redstone.devices": "Managed Devices",
|
||||
"gui.phycon.console.remote": "Remote Management",
|
||||
"gui.phycon.console.remote.mode": "Activation Mode",
|
||||
"gui.phycon.console.miner.mode": "Miner Mode",
|
||||
"gui.phycon.console.provider": "Item Provider",
|
||||
"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.receiver": "Item Receiver",
|
||||
"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.redstone_mode.high": "High",
|
||||
"gui.phycon.redstone_mode.low": "Low",
|
||||
"gui.phycon.redstone_mode.toggle": "Toggle",
|
||||
"gui.phycon.redstone_mode.rising_edge": "Rising Edge",
|
||||
"gui.phycon.redstone_mode.falling_edge": "Falling Edge",
|
||||
"gui.phycon.activation_mode.automatic": "Automatic",
|
||||
"gui.phycon.activation_mode.managed": "Managed",
|
||||
"gui.phycon.emitter.count": "%d Item(s)",
|
||||
"gui.phycon.miner_mode.automatic": "Automatic",
|
||||
"gui.phycon.miner_mode.on_demand": "On Demand",
|
||||
|
||||
"tooltip.phycon.device.configured": "Configured",
|
||||
"tooltip.phycon.device.ip": "IP: "
|
||||
"gui.phycon.activation_mode.managed": "Managed"
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"cable_side": "phycon:block/cable_straight",
|
||||
"cable_end": "phycon:block/cable_cap_end"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 2, 16],
|
||||
"faces": {
|
||||
"down": {"texture": "phycon:block/extractor_front", "cullface": "down"},
|
||||
"down": {"texture": "phycon:block/extractor_front"},
|
||||
"up": {"texture": "phycon:block/extractor_back"},
|
||||
"north": {"texture": "phycon:block/extractor_side"},
|
||||
"south": {"texture": "phycon:block/extractor_side"},
|
||||
|
@ -43,11 +39,11 @@
|
|||
"from": [6, 6, 6],
|
||||
"to": [10, 16, 10],
|
||||
"faces": {
|
||||
"up": {"texture": "#cable_end", "cullface": "up"},
|
||||
"north": {"texture": "#cable_side"},
|
||||
"south": {"texture": "#cable_side"},
|
||||
"west": {"texture": "#cable_side"},
|
||||
"east": {"texture": "#cable_side"}
|
||||
"up": {"texture": "phycon:block/cable_side"},
|
||||
"north": {"texture": "phycon:block/cable_side"},
|
||||
"south": {"texture": "phycon:block/cable_side"},
|
||||
"west": {"texture": "phycon:block/cable_side"},
|
||||
"east": {"texture": "phycon:block/cable_side"}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"cable_side": "phycon:block/cable_straight",
|
||||
"cable_end": "phycon:block/cable_cap_end"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [4, 0, 4],
|
||||
"to": [12, 2, 12],
|
||||
"faces": {
|
||||
"down": {"texture": "phycon:block/extractor_front", "cullface": "down"},
|
||||
"north": {"texture": "phycon:block/extractor_side"},
|
||||
"south": {"texture": "phycon:block/extractor_side"},
|
||||
"west": {"texture": "phycon:block/extractor_side"},
|
||||
"east": {"texture": "phycon:block/extractor_side"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 2, 2],
|
||||
"to": [14, 4, 14],
|
||||
"faces": {
|
||||
"down": {"texture": "phycon:block/extractor_front"},
|
||||
"north": {"texture": "phycon:block/extractor_side"},
|
||||
"south": {"texture": "phycon:block/extractor_side"},
|
||||
"west": {"texture": "phycon:block/extractor_side"},
|
||||
"east": {"texture": "phycon:block/extractor_side"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 4, 0],
|
||||
"to": [16, 6, 16],
|
||||
"faces": {
|
||||
"down": {"texture": "phycon:block/extractor_front"},
|
||||
"up": {"texture": "phycon:block/extractor_back"},
|
||||
"north": {"texture": "phycon:block/extractor_side"},
|
||||
"south": {"texture": "phycon:block/extractor_side"},
|
||||
"west": {"texture": "phycon:block/extractor_side"},
|
||||
"east": {"texture": "phycon:block/extractor_side"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 6, 6],
|
||||
"to": [10, 16, 10],
|
||||
"faces": {
|
||||
"up": {"texture": "#cable_end", "cullface": "up"},
|
||||
"north": {"texture": "#cable_side"},
|
||||
"south": {"texture": "#cable_side"},
|
||||
"west": {"texture": "#cable_side"},
|
||||
"east": {"texture": "#cable_side"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"cable": "phycon:block/cable_straight",
|
||||
"front": "phycon:block/redstone_emitter_front",
|
||||
"back": "phycon:block/redstone_emitter_back",
|
||||
"side": "phycon:block/redstone_emitter_back"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 3, 16],
|
||||
"faces": {
|
||||
"down": { "texture": "#front" },
|
||||
"up": { "texture": "#back" },
|
||||
"north": { "texture": "#side" },
|
||||
"south": { "texture": "#side" },
|
||||
"west": { "texture": "#side" },
|
||||
"east": { "texture": "#side" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 3, 6],
|
||||
"to": [10, 6, 10],
|
||||
"faces": {
|
||||
"north": { "texture": "#cable" },
|
||||
"south": { "texture": "#cable" },
|
||||
"west": { "texture": "#cable" },
|
||||
"east": { "texture": "#cable" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "phycon:item/screwdriver"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue