PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/block/netinterface/InterfaceBlockEntity.kt

136 lines
4.3 KiB
Kotlin

package net.shadowfacts.phycon.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.NbtCompound
import net.minecraft.util.math.BlockPos
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 kotlin.math.min
/**
* @author shadowfacts
*/
class InterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.INTERFACE, pos, state),
ItemStackPacketHandler,
NetworkStackProvider,
NetworkStackReceiver,
ClientConfigurableDevice {
private val facing: Direction
get() = cachedState[FaceDeviceBlock.FACING]
override var providerPriority = 0
override var receiverPriority = 0
var syncPriorities = true
// todo: should this be a weak ref?
private var inventory: GroupedItemInv? = null
fun updateInventory() {
val offsetPos = pos.offset(facing)
val option = SearchOptions.inDirection(facing)
inventory = ItemAttributes.GROUPED_INV.getFirstOrNull(world, offsetPos, option)
}
private fun getInventory(): GroupedItemInv? {
// if we don't have an inventory, try to get one
// this happens when readAll is called before a neighbor state changes, such as immediately after world load
if (inventory == null) updateInventory()
return inventory
}
override fun handle(packet: Packet) {
when (packet) {
is RequestInventoryPacket -> handleRequestInventory(packet)
is LocateStackPacket -> handleLocateStack(packet)
is ExtractStackPacket -> handleExtractStack(packet)
is CheckCapacityPacket -> handleCheckCapacity(packet)
is ItemStackPacket -> handleItemStack(packet)
}
}
private fun handleRequestInventory(packet: RequestInventoryPacket) {
getInventory()?.also { inv ->
sendPacket(ReadInventoryPacket(inv, ipAddress, packet.source))
}
}
private fun handleLocateStack(packet: LocateStackPacket) {
getInventory()?.also { inv ->
val amount = inv.getAmount(packet.stack)
sendPacket(StackLocationPacket(packet.stack, amount, this, ipAddress, packet.source))
}
}
private fun handleExtractStack(packet: ExtractStackPacket) {
getInventory()?.also { inv ->
var amount = packet.amount
while (amount > 0) {
val extracted = inv.extract(packet.stack, min(amount, packet.stack.maxCount))
if (extracted.isEmpty) {
break
} else {
amount -= extracted.count
sendPacket(ItemStackPacket(extracted, ipAddress, packet.source))
}
}
}
}
private fun handleCheckCapacity(packet: CheckCapacityPacket) {
getInventory()?.also { inv ->
val remaining = inv.attemptInsertion(packet.stack, Simulation.SIMULATE)
val couldAccept = packet.stack.count - remaining.count
sendPacket(CapacityPacket(packet.stack, couldAccept, this, ipAddress, packet.source))
}
}
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
val inventory = getInventory()
if (inventory != null) {
val remaining = inventory.insert(packet.stack)
// whatever could not be inserted will be sent back to the packet's source
return remaining
} else {
return packet.stack
}
}
override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag)
writeDeviceConfiguration(tag)
}
override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag)
loadDeviceConfiguration(tag)
}
override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putInt("ProviderPriority", providerPriority)
tag.putInt("ReceiverPriority", receiverPriority)
tag.putBoolean("SyncPriorities", syncPriorities)
}
override fun loadDeviceConfiguration(tag: NbtCompound) {
providerPriority = tag.getInt("ProviderPriority")
receiverPriority = tag.getInt("ReceiverPriority")
syncPriorities = tag.getBoolean("SyncPriorities")
}
}