Add P2P inventory system
This commit is contained in:
parent
9cbad193e2
commit
e88ecd3215
|
@ -2,8 +2,10 @@ package net.shadowfacts.phycon
|
|||
|
||||
import net.fabricmc.api.ModInitializer
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage
|
||||
import net.fabricmc.loader.api.FabricLoader
|
||||
import net.shadowfacts.phycon.api.PhyConPlugin
|
||||
import net.shadowfacts.phycon.block.p2p.P2PReceiverBlockEntity
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.init.PhyBlocks
|
||||
import net.shadowfacts.phycon.init.PhyItems
|
||||
|
@ -31,6 +33,8 @@ object PhysicalConnectivity: ModInitializer {
|
|||
registerGlobalReceiver(C2STerminalRequestItem)
|
||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||
|
||||
ItemStorage.SIDED.registerForBlockEntity(P2PReceiverBlockEntity::provideItemStorage, PhyBlockEntities.P2P_RECEIVER)
|
||||
|
||||
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
||||
it.initializePhyCon(PhyConAPIImpl)
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
|||
is DeviceRemovedPacket -> {
|
||||
arpTable.remove(packet.source)
|
||||
}
|
||||
is PingPacket -> {
|
||||
sendPacket(PongPacket(ipAddress, packet.source))
|
||||
}
|
||||
}
|
||||
handle(packet)
|
||||
}
|
||||
|
|
|
@ -57,10 +57,10 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyB
|
|||
}
|
||||
|
||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
||||
if (minerMode != MinerMode.ON_DEMAND) {
|
||||
if (minerMode != MinerMode.ON_DEMAND || packet.kind != RequestInventoryPacket.Kind.GROUPED) {
|
||||
return
|
||||
}
|
||||
sendPacket(ReadInventoryPacket(invProxy, ipAddress, packet.source))
|
||||
sendPacket(ReadGroupedInventoryPacket(invProxy, ipAddress, packet.source))
|
||||
}
|
||||
|
||||
private fun handleLocateStack(packet: LocateStackPacket) {
|
||||
|
|
|
@ -64,8 +64,11 @@ class InterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(
|
|||
}
|
||||
|
||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
||||
if (packet.kind != RequestInventoryPacket.Kind.GROUPED) {
|
||||
return
|
||||
}
|
||||
getInventory()?.also { inv ->
|
||||
sendPacket(ReadInventoryPacket(inv, ipAddress, packet.source))
|
||||
sendPacket(ReadGroupedInventoryPacket(inv, ipAddress, packet.source))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package net.shadowfacts.phycon.block.p2p
|
||||
|
||||
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
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class P2PInterfaceBlock: FaceDeviceBlock<P2PInterfaceBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "p2p_interface")
|
||||
}
|
||||
|
||||
override val faceThickness = 4.0
|
||||
override val faceShapes = mapOf(
|
||||
Direction.DOWN to createCuboidShape(0.0, 0.0, 0.0, 16.0, 4.0, 16.0),
|
||||
Direction.UP to createCuboidShape(0.0, 12.0, 0.0, 16.0, 16.0, 16.0),
|
||||
Direction.NORTH to createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 4.0),
|
||||
Direction.SOUTH to createCuboidShape(0.0, 0.0, 12.0, 16.0, 16.0, 16.0),
|
||||
Direction.WEST to createCuboidShape(0.0, 0.0, 0.0, 4.0, 16.0, 16.0),
|
||||
Direction.EAST to createCuboidShape(12.0, 0.0, 0.0, 16.0, 16.0, 16.0)
|
||||
)
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState) = P2PInterfaceBlockEntity(pos, state)
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package net.shadowfacts.phycon.block.p2p
|
||||
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.shadowfacts.phycon.api.packet.Packet
|
||||
import net.shadowfacts.phycon.block.DeviceBlockEntity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||
import net.shadowfacts.phycon.packet.ReadItemStoragePacket
|
||||
import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class P2PInterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.P2P_INTERFACE, pos, state) {
|
||||
|
||||
private var inventory: Storage<ItemVariant>? = null
|
||||
|
||||
private fun updateInventory() {
|
||||
val facing = cachedState[FaceDeviceBlock.FACING]
|
||||
inventory = ItemStorage.SIDED.find(world!!, pos.offset(facing), facing.opposite)
|
||||
}
|
||||
|
||||
private fun getInventory(): Storage<ItemVariant>? {
|
||||
if (inventory == null) updateInventory()
|
||||
return inventory
|
||||
}
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is RequestInventoryPacket -> handleRequestInventory(packet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
||||
if (packet.kind != RequestInventoryPacket.Kind.SIDED) {
|
||||
return
|
||||
}
|
||||
getInventory()?.also {
|
||||
sendPacket(ReadItemStoragePacket(it, ipAddress, packet.source))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.shadowfacts.phycon.block.p2p
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.InventoryProvider
|
||||
import net.minecraft.block.Material
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||
import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class P2PReceiverBlock: FaceDeviceBlock<P2PReceiverBlockEntity>(
|
||||
Settings.of(Material.METAL)
|
||||
.strength(1.5f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier(PhysicalConnectivity.MODID, "p2p_receiver")
|
||||
}
|
||||
|
||||
override val faceThickness = 4.0
|
||||
override val faceShapes = mapOf(
|
||||
Direction.DOWN to createCuboidShape(0.0, 0.0, 0.0, 16.0, 4.0, 16.0),
|
||||
Direction.UP to createCuboidShape(0.0, 12.0, 0.0, 16.0, 16.0, 16.0),
|
||||
Direction.NORTH to createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 4.0),
|
||||
Direction.SOUTH to createCuboidShape(0.0, 0.0, 12.0, 16.0, 16.0, 16.0),
|
||||
Direction.WEST to createCuboidShape(0.0, 0.0, 0.0, 4.0, 16.0, 16.0),
|
||||
Direction.EAST to createCuboidShape(12.0, 0.0, 0.0, 16.0, 16.0, 16.0)
|
||||
)
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState) = P2PReceiverBlockEntity(pos, state)
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package net.shadowfacts.phycon.block.p2p
|
||||
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.text.TranslatableText
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
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.*
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.P2P_RECEIVER, pos, state),
|
||||
ClientConfigurableDevice {
|
||||
|
||||
enum class Status {
|
||||
OK,
|
||||
NO_TARGET,
|
||||
WAITING_FOR_RESPONSE;
|
||||
|
||||
val displayName: Text
|
||||
get() = when (this) {
|
||||
OK -> TranslatableText("gui.phycon.p2p_receiver.status.ok")
|
||||
NO_TARGET -> TranslatableText("gui.phycon.p2p_receiver.status.no_target")
|
||||
WAITING_FOR_RESPONSE -> TranslatableText("gui.phycon.p2p_receiver.status.waiting_for_response")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun provideItemStorage(be: P2PReceiverBlockEntity, side: Direction): Storage<ItemVariant>? {
|
||||
if (side == be.cachedState[FaceDeviceBlock.FACING]) {
|
||||
return be.getTargetInventory()
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
var target: IPAddress? = null
|
||||
var status = Status.NO_TARGET
|
||||
|
||||
var clientObserver: (() -> Unit)? = null
|
||||
|
||||
private var isFirstTick = true
|
||||
// todo: need some way of removing this when there's no network path to the p2p interface
|
||||
private var targetInventory: Storage<ItemVariant>? = null
|
||||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is PongPacket -> if (packet.source == target) status = Status.OK
|
||||
is ReadItemStoragePacket -> targetInventory = packet.inventory
|
||||
is DeviceRemovedPacket -> if (packet.source == target) targetInventory = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
if (isFirstTick) {
|
||||
isFirstTick = false
|
||||
updateStatus()
|
||||
}
|
||||
}
|
||||
|
||||
fun getTargetInventory(): Storage<ItemVariant>? {
|
||||
if (target == null) {
|
||||
return null
|
||||
}
|
||||
if (targetInventory == null) {
|
||||
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.SIDED, ipAddress, target!!))
|
||||
}
|
||||
return targetInventory
|
||||
}
|
||||
|
||||
private fun updateStatus() {
|
||||
if (world?.isClient != false) {
|
||||
return
|
||||
}
|
||||
assert(!world!!.isClient)
|
||||
if (target == null) {
|
||||
status = Status.NO_TARGET
|
||||
} else {
|
||||
status = Status.WAITING_FOR_RESPONSE
|
||||
sendPacket(PingPacket(ipAddress, target!!))
|
||||
}
|
||||
|
||||
markUpdate()
|
||||
}
|
||||
|
||||
override fun toCommonTag(tag: NbtCompound) {
|
||||
super.toCommonTag(tag)
|
||||
writeDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun fromCommonTag(tag: NbtCompound) {
|
||||
super.fromCommonTag(tag)
|
||||
loadDeviceConfiguration(tag)
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: NbtCompound): NbtCompound {
|
||||
tag.putInt("Status", status.ordinal)
|
||||
return super.toClientTag(tag)
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: NbtCompound) {
|
||||
super.fromClientTag(tag)
|
||||
status = Status.values()[tag.getInt("Status")]
|
||||
clientObserver?.invoke()
|
||||
}
|
||||
|
||||
override fun writeDeviceConfiguration(tag: NbtCompound) {
|
||||
target?.address?.let { tag.putInt("Target", it) }
|
||||
}
|
||||
|
||||
override fun loadDeviceConfiguration(tag: NbtCompound) {
|
||||
target = if (tag.contains("Target")) {
|
||||
IPAddress(tag.getInt("Target"))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
updateStatus()
|
||||
}
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ 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.ReadGroupedInventoryPacket
|
||||
import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
||||
import net.shadowfacts.phycon.util.GhostInv
|
||||
|
@ -42,12 +42,12 @@ class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockE
|
|||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is ReadInventoryPacket -> handleReadInventory(packet)
|
||||
is ReadGroupedInventoryPacket -> handleReadInventory(packet)
|
||||
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
||||
private fun handleReadInventory(packet: ReadGroupedInventoryPacket) {
|
||||
inventoryCache[packet.source] = packet.inventory
|
||||
recalculateRedstone()
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockE
|
|||
}
|
||||
|
||||
private fun updateInventories() {
|
||||
sendPacket(RequestInventoryPacket(ipAddress))
|
||||
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.GROUPED, ipAddress))
|
||||
}
|
||||
|
||||
private fun recalculateRedstone() {
|
||||
|
|
|
@ -70,7 +70,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
|
|||
|
||||
override fun handle(packet: Packet) {
|
||||
when (packet) {
|
||||
is ReadInventoryPacket -> handleReadInventory(packet)
|
||||
is ReadGroupedInventoryPacket -> handleReadInventory(packet)
|
||||
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
|
||||
is StackLocationPacket -> handleStackLocation(packet)
|
||||
is ItemStackPacket -> handleItemStack(packet)
|
||||
|
@ -78,7 +78,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleReadInventory(packet: ReadInventoryPacket) {
|
||||
private fun handleReadInventory(packet: ReadGroupedInventoryPacket) {
|
||||
inventoryCache[packet.source] = packet.inventory
|
||||
updateAndSync()
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTer
|
|||
updateAndSync()
|
||||
|
||||
inventoryCache.clear()
|
||||
sendPacket(RequestInventoryPacket(ipAddress))
|
||||
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.GROUPED, ipAddress))
|
||||
val factory = object: ExtendedScreenHandlerFactory {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler? {
|
||||
return CraftingTerminalScreenHandler(syncId, playerInv, this@CraftingTerminalBlockEntity)
|
||||
|
|
|
@ -22,7 +22,7 @@ class TerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTerminalBlo
|
|||
updateAndSync()
|
||||
|
||||
inventoryCache.clear()
|
||||
sendPacket(RequestInventoryPacket(ipAddress))
|
||||
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.GROUPED, ipAddress))
|
||||
val factory = object: ExtendedScreenHandlerFactory {
|
||||
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
|
||||
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
||||
|
|
|
@ -25,6 +25,10 @@ class PhyModelProvider(resourceManager: ResourceManager) : ModelResourceProvider
|
|||
val EXTRACTOR_SIDE = Identifier(PhysicalConnectivity.MODID, "block/extractor_side")
|
||||
val INSERTER = Identifier(PhysicalConnectivity.MODID, "block/inserter")
|
||||
val INSERTER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/inserter_side")
|
||||
val P2P_INTERFACE = Identifier(PhysicalConnectivity.MODID, "block/p2p_interface")
|
||||
val P2P_INTERFACE_SIDE = Identifier(PhysicalConnectivity.MODID, "block/p2p_interface_side")
|
||||
val P2P_RECEIVER = Identifier(PhysicalConnectivity.MODID, "block/p2p_receiver")
|
||||
val P2P_RECEIVER_SIDE = Identifier(PhysicalConnectivity.MODID, "block/p2p_receiver_side")
|
||||
|
||||
val CABLES = DyeColor.values().map {
|
||||
Identifier(PhysicalConnectivity.MODID, "block/cable/${it.getName()}") to it
|
||||
|
@ -38,6 +42,8 @@ class PhyModelProvider(resourceManager: ResourceManager) : ModelResourceProvider
|
|||
REDSTONE_EMITTER -> SimpleFaceDeviceModel(REDSTONE_EMITTER_SIDE)
|
||||
EXTRACTOR -> SimpleFaceDeviceModel(EXTRACTOR_SIDE)
|
||||
INSERTER -> SimpleFaceDeviceModel(INSERTER_SIDE)
|
||||
P2P_INTERFACE -> SimpleFaceDeviceModel(P2P_INTERFACE_SIDE)
|
||||
P2P_RECEIVER -> SimpleFaceDeviceModel(P2P_RECEIVER_SIDE)
|
||||
in CABLES -> ColoredCableModel(CABLES[resourceId]!!)
|
||||
else -> null
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ 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.p2p.P2PReceiverBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlockEntity
|
||||
import net.shadowfacts.phycon.component.ActivationController
|
||||
|
@ -90,6 +91,15 @@ class DeviceConsoleScreen(
|
|||
RedstoneEmitterViewController(device)
|
||||
))
|
||||
}
|
||||
if (device is P2PReceiverBlockEntity) {
|
||||
tabs.add(TabViewController.SimpleTab(
|
||||
TextureView(Texture(Identifier("textures/item/ender_pearl.png"), 0, 0, 16, 16)).apply {
|
||||
intrinsicContentSize = Size(16.0, 16.0)
|
||||
},
|
||||
TranslatableText("block.phycon.p2p_receiver"),
|
||||
P2PReceiverViewController(device)
|
||||
))
|
||||
}
|
||||
|
||||
tabController = TabViewController(tabs)
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package net.shadowfacts.phycon.client.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.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.p2p.P2PReceiverBlockEntity
|
||||
import net.shadowfacts.phycon.networking.C2SConfigureDevice
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class P2PReceiverViewController(
|
||||
val device: P2PReceiverBlockEntity,
|
||||
): ViewController() {
|
||||
|
||||
override fun viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
val label = Label(TranslatableText("gui.phycon.console.p2p_receiver.target")).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(label)
|
||||
|
||||
val textField =
|
||||
TextField(device.target?.toString() ?: "") {
|
||||
device.target = IPAddress.parse(it.text)
|
||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2SConfigureDevice(device))
|
||||
}
|
||||
view.addSubview(textField)
|
||||
|
||||
val status = Label(device.status.displayName).apply {
|
||||
textColor = Color.TEXT
|
||||
}
|
||||
view.addSubview(status)
|
||||
device.clientObserver = {
|
||||
status.text = device.status.displayName
|
||||
}
|
||||
|
||||
view.solver.dsl {
|
||||
textField.widthAnchor equalTo 100
|
||||
textField.heightAnchor equalTo 20
|
||||
textField.topAnchor equalTo view.topAnchor
|
||||
textField.rightAnchor equalTo view.rightAnchor
|
||||
|
||||
label.centerYAnchor equalTo textField.centerYAnchor
|
||||
label.rightAnchor equalTo (textField.leftAnchor - 4)
|
||||
|
||||
status.centerXAnchor equalTo view.centerXAnchor
|
||||
status.centerYAnchor equalTo (view.centerYAnchor - 10)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,10 @@ 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.p2p.P2PInterfaceBlock
|
||||
import net.shadowfacts.phycon.block.p2p.P2PInterfaceBlockEntity
|
||||
import net.shadowfacts.phycon.block.p2p.P2PReceiverBlock
|
||||
import net.shadowfacts.phycon.block.p2p.P2PReceiverBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlockEntity
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
|
@ -40,6 +44,8 @@ object PhyBlockEntities {
|
|||
val MINER = create(::MinerBlockEntity, PhyBlocks.MINER)
|
||||
val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER)
|
||||
val REDSTONE_EMITTER = create(::RedstoneEmitterBlockEntity, PhyBlocks.REDSTONE_EMITTER)
|
||||
val P2P_INTERFACE = create(::P2PInterfaceBlockEntity, PhyBlocks.P2P_INTERFACE)
|
||||
val P2P_RECEIVER = create(::P2PReceiverBlockEntity, PhyBlocks.P2P_RECEIVER)
|
||||
|
||||
private fun <T: BlockEntity> create(builder: (BlockPos, BlockState) -> T, block: Block): BlockEntityType<T> {
|
||||
return BlockEntityType.Builder.create(builder, block).build(null)
|
||||
|
@ -55,6 +61,8 @@ object PhyBlockEntities {
|
|||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
register(P2PInterfaceBlock.ID, P2P_INTERFACE)
|
||||
register(P2PReceiverBlock.ID, P2P_RECEIVER)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, type: BlockEntityType<*>) {
|
||||
|
|
|
@ -11,6 +11,8 @@ 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.p2p.P2PInterfaceBlock
|
||||
import net.shadowfacts.phycon.block.p2p.P2PReceiverBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
import net.shadowfacts.phycon.block.terminal.CraftingTerminalBlock
|
||||
|
@ -32,6 +34,8 @@ object PhyBlocks {
|
|||
val MINER = MinerBlock()
|
||||
val REDSTONE_CONTROLLER = RedstoneControllerBlock()
|
||||
val REDSTONE_EMITTER = RedstoneEmitterBlock()
|
||||
val P2P_INTERFACE = P2PInterfaceBlock()
|
||||
val P2P_RECEIVER = P2PReceiverBlock()
|
||||
|
||||
fun init() {
|
||||
for ((color, block) in CABLES) {
|
||||
|
@ -47,6 +51,8 @@ object PhyBlocks {
|
|||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
register(P2PInterfaceBlock.ID, P2P_INTERFACE)
|
||||
register(P2PReceiverBlock.ID, P2P_RECEIVER)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, block: Block) {
|
||||
|
|
|
@ -12,12 +12,15 @@ 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.p2p.P2PInterfaceBlock
|
||||
import net.shadowfacts.phycon.block.p2p.P2PReceiverBlock
|
||||
import net.shadowfacts.phycon.block.redstone_controller.RedstoneControllerBlock
|
||||
import net.shadowfacts.phycon.block.redstone_emitter.RedstoneEmitterBlock
|
||||
import net.shadowfacts.phycon.block.terminal.CraftingTerminalBlock
|
||||
import net.shadowfacts.phycon.block.terminal.TerminalBlock
|
||||
import net.shadowfacts.phycon.item.DeviceBlockItem
|
||||
import net.shadowfacts.phycon.item.FaceDeviceBlockItem
|
||||
import net.shadowfacts.phycon.util.text
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
|
@ -37,6 +40,8 @@ object PhyItems {
|
|||
val MINER = DeviceBlockItem(PhyBlocks.MINER, Item.Settings())
|
||||
val REDSTONE_CONTROLLER = FaceDeviceBlockItem(PhyBlocks.REDSTONE_CONTROLLER, Item.Settings())
|
||||
val REDSTONE_EMITTER = FaceDeviceBlockItem(PhyBlocks.REDSTONE_EMITTER, Item.Settings())
|
||||
val P2P_INTERFACE = FaceDeviceBlockItem(PhyBlocks.P2P_INTERFACE, Item.Settings())
|
||||
val P2P_RECEIVER = FaceDeviceBlockItem(PhyBlocks.P2P_RECEIVER, Item.Settings())
|
||||
|
||||
val SCREWDRIVER = ScrewdriverItem()
|
||||
val CONSOLE = ConsoleItem()
|
||||
|
@ -61,6 +66,18 @@ object PhyItems {
|
|||
register(MinerBlock.ID, MINER)
|
||||
register(RedstoneControllerBlock.ID, REDSTONE_CONTROLLER)
|
||||
register(RedstoneEmitterBlock.ID, REDSTONE_EMITTER)
|
||||
register(P2PInterfaceBlock.ID, P2P_INTERFACE)
|
||||
P2P_INTERFACE.addTooltip(text {
|
||||
withStyle(darkGray) {
|
||||
+translate("tooltip.phycon.p2p_interface")
|
||||
}
|
||||
})
|
||||
register(P2PReceiverBlock.ID, P2P_RECEIVER)
|
||||
P2P_RECEIVER.addTooltip(text {
|
||||
withStyle(darkGray) {
|
||||
+translate("tooltip.phycon.p2p_receiver")
|
||||
}
|
||||
})
|
||||
|
||||
register(ScrewdriverItem.ID, SCREWDRIVER)
|
||||
register(ConsoleItem.ID, CONSOLE)
|
||||
|
|
|
@ -14,7 +14,15 @@ import net.shadowfacts.phycon.util.text
|
|||
*/
|
||||
open class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) {
|
||||
|
||||
private var tooltip = mutableListOf<Text>()
|
||||
|
||||
fun addTooltip(tooltip: Text) {
|
||||
this.tooltip.add(tooltip)
|
||||
}
|
||||
|
||||
override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) {
|
||||
list.addAll(tooltip)
|
||||
|
||||
val beTag = stack.getSubNbt("BlockEntityTag")
|
||||
if (beTag != null) {
|
||||
val ip = IPAddress(beTag.getInt("IPAddress"))
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class PingPacket(source: IPAddress, destination: IPAddress): BasePacket(source, destination)
|
||||
|
||||
class PongPacket(source: IPAddress, destination: IPAddress): BasePacket(source, destination)
|
|
@ -6,7 +6,7 @@ import net.shadowfacts.phycon.api.util.IPAddress
|
|||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class ReadInventoryPacket(
|
||||
class ReadGroupedInventoryPacket(
|
||||
val inventory: GroupedItemInvView,
|
||||
source: IPAddress,
|
||||
destination: IPAddress
|
|
@ -0,0 +1,14 @@
|
|||
package net.shadowfacts.phycon.packet
|
||||
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage
|
||||
import net.shadowfacts.phycon.api.util.IPAddress
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class ReadItemStoragePacket(
|
||||
val inventory: Storage<ItemVariant>,
|
||||
source: IPAddress,
|
||||
destination: IPAddress
|
||||
): BasePacket(source, destination)
|
|
@ -5,4 +5,12 @@ import net.shadowfacts.phycon.api.util.IPAddress
|
|||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class RequestInventoryPacket(source: IPAddress, destination: IPAddress = IPAddress.BROADCAST): BasePacket(source, destination)
|
||||
class RequestInventoryPacket(
|
||||
val kind: Kind,
|
||||
source: IPAddress,
|
||||
destination: IPAddress = IPAddress.BROADCAST
|
||||
): BasePacket(source, destination) {
|
||||
enum class Kind {
|
||||
GROUPED, SIDED
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"multipart": [
|
||||
{
|
||||
"apply": { "model": "phycon:block/p2p_interface" }
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"multipart": [
|
||||
{
|
||||
"apply": { "model": "phycon:block/p2p_receiver" }
|
||||
}
|
||||
]
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
"block.phycon.miner": "Block Miner",
|
||||
"block.phycon.redstone_controller": "Redstone Controller",
|
||||
"block.phycon.redstone_emitter": "Redstone Emitter",
|
||||
"block.phycon.p2p_interface": "P2P Interface",
|
||||
"block.phycon.p2p_receiver": "P2P Receiver",
|
||||
|
||||
"item.phycon.screwdriver": "Screwdriver",
|
||||
"item.phycon.console": "Console",
|
||||
|
@ -56,6 +58,7 @@
|
|||
"gui.phycon.console.receiver.priority_desc": "When a device puts items into the network, it starts with receiver (e.g., interfaces) with higher priorities. Priorities can be negative.",
|
||||
"gui.phycon.console.receiver.sync": "Sync with Provider Priority",
|
||||
"gui.phycon.console.emitter.mode": "Measurement Mode",
|
||||
"gui.phycon.console.p2p_receiver.target": "P2P Target",
|
||||
"gui.phycon.redstone_mode.high": "High",
|
||||
"gui.phycon.redstone_mode.low": "Low",
|
||||
"gui.phycon.redstone_mode.toggle": "Toggle",
|
||||
|
@ -68,9 +71,14 @@
|
|||
"gui.phycon.miner_mode.on_demand": "On Demand",
|
||||
"gui.phycon.redstone_emitter_mode.analog": "Analog",
|
||||
"gui.phycon.redstone_emitter_mode.digital": "Digital",
|
||||
"gui.phycon.p2p_receiver.status.ok": "OK",
|
||||
"gui.phycon.p2p_receiver.status.no_target": "No target",
|
||||
"gui.phycon.p2p_receiver.status.waiting_for_response": "Waiting for response",
|
||||
|
||||
"tooltip.phycon.device.configured": "Configured",
|
||||
"tooltip.phycon.device.ip": "IP: ",
|
||||
"tooltip.phycon.p2p_interface": "Attach to the point-to-point target inventory",
|
||||
"tooltip.phycon.p2p_receiver": "Point-to-point inventory destination",
|
||||
|
||||
"advancements.phycon.root.title": "Physical Connectivity",
|
||||
"advancements.phycon.root.description": "Mass item storage and local networking",
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"cable": "phycon:block/cable_straight",
|
||||
"front": "phycon:block/p2p_interface_front",
|
||||
"back": "phycon:block/p2p_interface_back",
|
||||
"side": "phycon:block/p2p_interface_back"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 4, 16],
|
||||
"faces": {
|
||||
"down": { "texture": "#front" },
|
||||
"up": { "texture": "#back" },
|
||||
"north": { "texture": "#side" },
|
||||
"south": { "texture": "#side" },
|
||||
"west": { "texture": "#side" },
|
||||
"east": { "texture": "#side" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 4, 6],
|
||||
"to": [10, 6, 10],
|
||||
"faces": {
|
||||
"north": { "texture": "#cable" },
|
||||
"south": { "texture": "#cable" },
|
||||
"west": { "texture": "#cable" },
|
||||
"east": { "texture": "#cable" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"cable": "phycon:block/cable_straight",
|
||||
"front": "phycon:block/p2p_receiver_front",
|
||||
"back": "phycon:block/p2p_receiver_back",
|
||||
"side": "phycon:block/p2p_receiver_back"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 4, 16],
|
||||
"faces": {
|
||||
"down": { "texture": "#front" },
|
||||
"up": { "texture": "#back" },
|
||||
"north": { "texture": "#side" },
|
||||
"south": { "texture": "#side" },
|
||||
"west": { "texture": "#side" },
|
||||
"east": { "texture": "#side" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 4, 6],
|
||||
"to": [10, 6, 10],
|
||||
"faces": {
|
||||
"north": { "texture": "#cable" },
|
||||
"south": { "texture": "#cable" },
|
||||
"west": { "texture": "#cable" },
|
||||
"east": { "texture": "#cable" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue