PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/block/extractor/ExtractorBlockEntity.kt

134 lines
4.7 KiB
Kotlin
Raw Normal View History

2021-02-28 18:48:39 +00:00
package net.shadowfacts.phycon.block.extractor
2021-02-15 01:01:33 +00:00
import alexiil.mc.lib.attributes.SearchOptions
import alexiil.mc.lib.attributes.Simulation
import alexiil.mc.lib.attributes.item.FixedItemInv
2021-02-15 01:01:33 +00:00
import alexiil.mc.lib.attributes.item.ItemAttributes
import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter
2021-12-22 23:59:51 +00:00
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack
2021-12-22 23:59:51 +00:00
import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
2021-02-15 01:01:33 +00:00
import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.init.PhyBlockEntities
2021-02-28 18:48:39 +00:00
import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock
2021-02-28 18:48:39 +00:00
import net.shadowfacts.phycon.component.ActivationController
import net.shadowfacts.phycon.component.NetworkStackDispatcher
2021-03-05 03:24:40 +00:00
import net.shadowfacts.phycon.component.finishTimedOutPendingInsertions
2021-02-28 18:48:39 +00:00
import net.shadowfacts.phycon.component.handleItemStack
import net.shadowfacts.phycon.packet.CapacityPacket
import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.packet.RemoteActivationPacket
2021-02-24 03:05:05 +00:00
import net.shadowfacts.phycon.util.ActivationMode
2021-03-03 03:32:30 +00:00
import net.shadowfacts.phycon.util.ClientConfigurableDevice
import kotlin.properties.Delegates
2021-02-15 01:01:33 +00:00
/**
* @author shadowfacts
*/
2021-12-22 23:59:51 +00:00
class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.EXTRACTOR, pos, state),
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
2021-03-03 03:32:30 +00:00
ActivationController.ActivatableDevice,
ClientConfigurableDevice {
2021-02-24 03:05:05 +00:00
companion object {
val SLEEP_TIME = 40L
}
2021-02-15 01:01:33 +00:00
private val facing: Direction
get() = cachedState[FaceDeviceBlock.FACING]
2021-02-15 01:01:33 +00:00
private var inventory: FixedItemInv? = null
override val pendingInsertions = mutableListOf<PendingInsertion>()
2021-03-04 04:13:09 +00:00
override val dispatchStackTimeout = 1L
2021-02-24 03:05:05 +00:00
override val controller = ActivationController(SLEEP_TIME, this)
2021-02-15 01:01:33 +00:00
fun updateInventory() {
val offsetPos = pos.offset(facing)
val option = SearchOptions.inDirection(facing)
inventory = ItemAttributes.FIXED_INV.getFirstOrNull(world, offsetPos, option)
2021-02-15 01:01:33 +00:00
}
private fun getInventory(): FixedItemInv? {
2021-02-15 01:01:33 +00:00
if (inventory == null) updateInventory()
return inventory
}
override fun handle(packet: Packet) {
2021-02-24 03:05:05 +00:00
when (packet) {
is CapacityPacket -> handleCapacity(packet)
is ItemStackPacket -> handleItemStack(packet)
2021-02-24 03:05:05 +00:00
is RemoteActivationPacket -> controller.handleRemoteActivation(packet)
}
}
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
// we can't insert things back into the inventory, so just let them spawn
return packet.stack
}
override fun createPendingInsertion(stack: ItemStack) = PendingInsertion(stack, counter)
override fun finishInsertion(insertion: PendingInsertion): ItemStack {
val inventory = getInventory() ?: return insertion.stack
// if the inventory has changed, the old slot index is meaningless
if (inventory !== insertion.inventory) return insertion.stack
val extracted = inventory.extractStack(insertion.inventorySlot, ExactItemStackFilter(insertion.stack), ItemStack.EMPTY, insertion.totalCapacity, Simulation.ACTION)
if (extracted.isEmpty) return insertion.stack
// if we extracted less than expected, make sure super.finishInsertion doesn't send more than we actually have
insertion.stack = extracted
return super.finishInsertion(insertion)
2021-02-15 01:01:33 +00:00
}
override fun tick() {
super.tick()
2021-02-24 03:05:05 +00:00
if (!world!!.isClient) {
controller.tick()
2021-03-05 03:24:40 +00:00
finishTimedOutPendingInsertions()
2021-02-15 01:01:33 +00:00
}
}
2021-02-24 03:05:05 +00:00
override fun activate(): Boolean {
val inventory = getInventory() ?: return false
for (slot in 0 until inventory.slotCount) {
val slotStack = inventory.getInvStack(slot)
if (slotStack.isEmpty) continue
val extractable = inventory.extractStack(slot, ExactItemStackFilter(slotStack), ItemStack.EMPTY, slotStack.count, Simulation.SIMULATE)
if (extractable.isEmpty) continue
dispatchItemStack(extractable) { insertion ->
insertion.inventory = inventory
insertion.inventorySlot = slot
}
return true
}
return false
2021-02-24 03:05:05 +00:00
}
2021-12-22 23:59:51 +00:00
override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag)
2021-03-03 03:32:30 +00:00
writeDeviceConfiguration(tag)
2021-02-24 03:05:05 +00:00
}
2021-12-22 23:59:51 +00:00
override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag)
2021-03-03 03:32:30 +00:00
loadDeviceConfiguration(tag)
}
2021-12-22 23:59:51 +00:00
override fun writeDeviceConfiguration(tag: NbtCompound) {
2021-03-03 03:32:30 +00:00
tag.putString("ActivationMode", controller.activationMode.name)
}
2021-12-22 23:59:51 +00:00
override fun loadDeviceConfiguration(tag: NbtCompound) {
2021-02-24 03:05:05 +00:00
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
}
class PendingInsertion(stack: ItemStack, timestamp: Long): NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
lateinit var inventory: FixedItemInv
var inventorySlot by Delegates.notNull<Int>()
}
2021-02-24 03:05:05 +00:00
}