127 lines
4.3 KiB
Kotlin
127 lines
4.3 KiB
Kotlin
package net.shadowfacts.phycon.block.extractor
|
|
|
|
import alexiil.mc.lib.attributes.SearchOptions
|
|
import alexiil.mc.lib.attributes.Simulation
|
|
import alexiil.mc.lib.attributes.item.FixedItemInv
|
|
import alexiil.mc.lib.attributes.item.ItemAttributes
|
|
import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter
|
|
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.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.util.ActivationMode
|
|
import net.shadowfacts.phycon.util.ClientConfigurableDevice
|
|
import kotlin.properties.Delegates
|
|
|
|
/**
|
|
* @author shadowfacts
|
|
*/
|
|
class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
|
|
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
|
|
ActivationController.ActivatableDevice,
|
|
ClientConfigurableDevice {
|
|
|
|
companion object {
|
|
val SLEEP_TIME = 40L
|
|
}
|
|
|
|
private val facing: Direction
|
|
get() = cachedState[ExtractorBlock.FACING]
|
|
|
|
private var inventory: FixedItemInv? = null
|
|
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
|
override val dispatchStackTimeout = 40L
|
|
override val controller = ActivationController(SLEEP_TIME, this)
|
|
|
|
fun updateInventory() {
|
|
val offsetPos = pos.offset(facing)
|
|
val option = SearchOptions.inDirection(facing)
|
|
inventory = ItemAttributes.FIXED_INV.getFirstOrNull(world, offsetPos, option)
|
|
}
|
|
|
|
private fun getInventory(): FixedItemInv? {
|
|
if (inventory == null) updateInventory()
|
|
return inventory
|
|
}
|
|
|
|
override fun handle(packet: Packet) {
|
|
when (packet) {
|
|
is CapacityPacket -> handleCapacity(packet)
|
|
is ItemStackPacket -> handleItemStack(packet)
|
|
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)
|
|
}
|
|
|
|
override fun tick() {
|
|
super.tick()
|
|
|
|
if (!world!!.isClient) {
|
|
controller.tick()
|
|
}
|
|
}
|
|
|
|
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
|
|
dispatchItemStack(slotStack) { insertion ->
|
|
insertion.inventory = inventory
|
|
insertion.inventorySlot = slot
|
|
}
|
|
return true
|
|
}
|
|
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) {
|
|
tag.putString("ActivationMode", controller.activationMode.name)
|
|
}
|
|
|
|
override fun loadDeviceConfiguration(tag: CompoundTag) {
|
|
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>()
|
|
}
|
|
}
|