145 lines
4.4 KiB
Kotlin
145 lines
4.4 KiB
Kotlin
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.frame.NetworkSplitFrame
|
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
|
import net.shadowfacts.phycon.packet.*
|
|
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
|
import java.lang.ref.WeakReference
|
|
|
|
/**
|
|
* @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 {
|
|
const val REQUEST_INVENTORY_TIMEOUT: Long = 100 // ticks
|
|
|
|
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
|
|
private var requestTimestamp: Long = 0
|
|
|
|
var clientObserver: (() -> Unit)? = null
|
|
|
|
private var isFirstTick = true
|
|
private var targetInventory: WeakReference<Storage<ItemVariant>>? = null
|
|
|
|
override fun handle(packet: Packet) {
|
|
when (packet) {
|
|
is PongPacket -> if (packet.source == target) status = Status.OK
|
|
is ReadItemStoragePacket -> targetInventory = WeakReference(packet.inventory)
|
|
is DeviceRemovedPacket -> if (packet.source == target) targetInventory = null
|
|
}
|
|
}
|
|
|
|
override fun handleNetworkSplit() {
|
|
super.handleNetworkSplit()
|
|
targetInventory = null
|
|
}
|
|
|
|
override fun tick() {
|
|
super.tick()
|
|
|
|
if (isFirstTick) {
|
|
isFirstTick = false
|
|
updateStatus()
|
|
}
|
|
}
|
|
|
|
fun getTargetInventory(): Storage<ItemVariant>? {
|
|
if (target == null) {
|
|
return null
|
|
}
|
|
if (targetInventory?.get() == null && (counter - requestTimestamp) >= REQUEST_INVENTORY_TIMEOUT) {
|
|
status = Status.WAITING_FOR_RESPONSE
|
|
requestTimestamp = counter
|
|
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.SIDED, ipAddress, target!!))
|
|
}
|
|
return targetInventory?.get()
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
}
|