PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt

331 lines
11 KiB
Kotlin
Raw Normal View History

2019-10-27 01:36:31 +00:00
package net.shadowfacts.phycon.network.block.terminal
2021-02-13 23:24:36 +00:00
//
//import alexiil.mc.lib.attributes.item.GroupedItemInv
//import alexiil.mc.lib.attributes.item.ItemStackCollections
//import alexiil.mc.lib.attributes.item.ItemStackUtil
//import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
//import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
//import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
//import net.minecraft.block.BlockState
//import net.minecraft.entity.player.PlayerEntity
//import net.minecraft.entity.player.PlayerInventory
//import net.minecraft.inventory.Inventory
//import net.minecraft.inventory.InventoryChangedListener
//import net.minecraft.item.ItemStack
//import net.minecraft.nbt.CompoundTag
//import net.minecraft.nbt.ListTag
//import net.minecraft.network.PacketByteBuf
//import net.minecraft.screen.ScreenHandler
//import net.minecraft.server.network.ServerPlayerEntity
//import net.minecraft.text.LiteralText
//import net.minecraft.util.Tickable
//import net.shadowfacts.phycon.api.packet.Packet
//import net.shadowfacts.phycon.api.util.MACAddress
//import net.shadowfacts.phycon.init.PhyBlockEntities
//import net.shadowfacts.phycon.network.DeviceBlockEntity
//import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
//import net.shadowfacts.phycon.network.component.ItemStackPacketHandler
//import net.shadowfacts.phycon.network.component.handleItemStack
//import net.shadowfacts.phycon.network.packet.*
//import java.util.*
//import kotlin.math.min
//
///**
// * @author shadowfacts
// */
//class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryChangedListener, BlockEntityClientSerializable, Tickable, ItemStackPacketHandler {
//
// companion object {
// val LOCATE_REQUEST_TIMEOUT = 40 // ticks
// val INSERTION_TIMEOUT = 40
// }
//
// private val inventoryCache = mutableMapOf<MACAddress, GroupedItemInv>()
// val internalBuffer = TerminalBufferInventory(18)
//
// private val locateRequestQueue = LinkedList<StackLocateRequest>()
// private val pendingRequests = LinkedList<StackLocateRequest>()
// private val pendingInsertions = Int2ObjectArrayMap<PendingStackInsertion>()
//
// private var observers = 0
// val cachedNetItems = ItemStackCollections.intMap()
// var cachedSortedNetItems = listOf<ItemStack>()
// var counter = 0
//
// init {
// internalBuffer.addListener(this)
// }
//
// override fun handlePacket(packet: Packet) {
// when (packet) {
// is ReadInventoryPacket -> handleReadInventory(packet)
// is DeviceRemovedPacket -> handleDeviceRemoved(packet)
// is StackLocationPacket -> handleStackLocation(packet)
// is ItemStackPacket -> handleItemStack(packet)
// is CapacityPacket -> handleCapacity(packet)
// }
// }
//
// private fun handleReadInventory(packet: ReadInventoryPacket) {
// inventoryCache[packet.source] = packet.inventory
// updateNetItems()
// sync()
// }
//
// private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
// inventoryCache.remove(packet.source)
// updateNetItems()
// sync()
// }
//
// private fun handleStackLocation(packet: StackLocationPacket) {
// val request = pendingRequests.firstOrNull {
// ItemStackUtil.areEqualIgnoreAmounts(it.stack, packet.stack)
// }
// if (request != null) {
// request.results.add(packet.amount to packet.sourceInterface)
// if (request.totalResultAmount >= request.amount || counter - request.timestamp >= LOCATE_REQUEST_TIMEOUT || request.results.size >= inventoryCache.size) {
// stackLocateRequestCompleted(request)
// }
// }
// }
//
// override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
// val remaining = internalBuffer.insertFromNetwork(packet.stack)
//
// // this happens outside the normal update loop because by receiving the item stack packet
// // we "know" how much the count in the source inventory has changed
// updateNetItems()
// sync()
//
// return remaining
// }
//
// private fun handleCapacity(packet: CapacityPacket) {
// val insertion = pendingInsertions.values.firstOrNull {
// ItemStackUtil.areEqualIgnoreAmounts(packet.stack, it.stack)
// }
// if (insertion != null) {
// insertion.results.add(packet.capacity to packet.receivingInterface)
// if (insertion.isFinishable(counter)) {
// finishInsertion(insertion)
// }
// }
// }
//
// private fun updateNetItems() {
// cachedNetItems.clear()
// for (inventory in inventoryCache.values) {
// for (stack in inventory.storedStacks) {
// val amount = inventory.getAmount(stack)
// cachedNetItems.mergeInt(stack, amount) { a, b -> a + b }
// }
// }
// // todo: is the map necessary or is just the sorted list enough?
// cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
// val stack = it.key.copy()
// stack.count = it.intValue
// stack
// }
// }
//
// private fun beginInsertions() {
// if (world!!.isClient) return
//
// for (slot in 0 until internalBuffer.size()) {
// if (internalBuffer.getMode(slot) != TerminalBufferInventory.Mode.TO_NETWORK) continue
// if (slot in pendingInsertions) continue
// val stack = internalBuffer.getStack(slot)
// pendingInsertions[slot] = PendingStackInsertion(slot, stack, counter)
// sendToSingle(CheckCapacityPacket(stack, macAddress, MACAddress.BROADCAST))
// }
// }
//
// private fun finishPendingInsertions() {
// if (world!!.isClient) return
//
// for (insertion in pendingInsertions.values) {
// if (!insertion.isFinishable(counter)) continue
// finishInsertion(insertion)
// }
// }
//
// private fun sendEnqueuedLocateRequests() {
// if (world!!.isClient) return
//
// for (request in locateRequestQueue) {
// pendingRequests.add(request)
// sendToSingle(LocateStackPacket(request.stack, macAddress))
// }
// locateRequestQueue.clear()
// }
//
// private fun finishPendingRequests() {
// if (world!!.isClient) return
//
// for (request in pendingRequests) {
// if (request.isFinishable(counter)) {
// stackLocateRequestCompleted(request)
// }
// }
// }
//
// fun addObserver() {
// observers++
// }
//
// fun removeObserver() {
// observers--
// }
//
// override fun tick() {
// if (observers > 0 && (++counter % 10) == 0) {
// if (world!!.isClient) {
// println(cachedNetItems)
// } else {
// updateNetItems()
// sendEnqueuedLocateRequests()
// finishPendingRequests()
// beginInsertions()
// finishPendingInsertions()
// sync()
// }
// }
// }
//
// fun onActivate(player: PlayerEntity) {
// if (!world!!.isClient) {
// updateNetItems()
// sync()
//
// inventoryCache.clear()
// sendToSingle(RequestInventoryPacket(macAddress))
// val factory = object: ExtendedScreenHandlerFactory {
// override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler? {
// return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
// }
//
// override fun getDisplayName() = LiteralText("Terminal")
//
// override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
// buf.writeBlockPos(this@TerminalBlockEntity.pos)
// }
// }
// player.openHandledScreen(factory)
// }
// addObserver()
// }
//
// fun requestItem(stack: ItemStack, amount: Int = stack.count) {
// locateRequestQueue.add(StackLocateRequest(stack, amount, counter))
// }
//
// private fun stackLocateRequestCompleted(request: StackLocateRequest) {
// pendingRequests.remove(request)
//
// // todo: also sort results by interface priority
// val sortedResults = request.results.sortedByDescending { it.first }.toMutableList()
// var amountRequested = 0
// while (amountRequested < request.amount && sortedResults.isNotEmpty()) {
// val (sourceAmount, sourceInterface) = sortedResults.removeAt(0)
// val amountToRequest = min(sourceAmount, request.amount - amountRequested)
// amountRequested += amountToRequest
// sendToSingle(ExtractStackPacket(request.stack, amountToRequest, macAddress, sourceInterface.macAddress))
// }
// }
//
// private fun finishInsertion(insertion: PendingStackInsertion) {
// pendingInsertions.remove(insertion.bufferSlot)
//
// // todo: also sort results by interface priority
// val sortedResults = insertion.results.sortedBy { it.first }.toMutableList()
// val remaining = insertion.stack
// while (!remaining.isEmpty && sortedResults.isNotEmpty()) {
// val (capacity, receivingInterface) = sortedResults.removeAt(0)
// if (capacity <= 0) continue
// sendToSingle(ItemStackPacket(remaining.copy(), macAddress, receivingInterface.macAddress))
// // todo: the interface should confirm how much was actually inserted, in case of race condition
// remaining.count -= capacity
// }
// internalBuffer.setStack(insertion.bufferSlot, remaining)
//
// // as with extracting, we "know" the new amounts and so can update instantly without actually sending out packets
// updateNetItems()
// sync()
// }
//
// override fun onInventoryChanged(inv: Inventory) {
// if (inv == internalBuffer && world != null && !world!!.isClient) {
// markDirty()
// sync()
// }
// }
//
// override fun toTag(tag: CompoundTag): CompoundTag {
// tag.put("InternalBuffer", internalBuffer.toTag())
// return super.toTag(tag)
// }
//
// override fun fromTag(state: BlockState, tag: CompoundTag) {
// super.fromTag(state, tag)
// internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
// }
//
// override fun toClientTag(tag: CompoundTag): CompoundTag {
// tag.put("InternalBuffer", internalBuffer.toTag())
// val list = ListTag()
// tag.put("CachedNetItems", list)
// for ((stack, amount) in cachedNetItems) {
// val entryTag = stack.toTag(CompoundTag())
// entryTag.putInt("NetAmount", amount)
// list.add(entryTag)
// }
// return tag
// }
//
// override fun fromClientTag(tag: CompoundTag) {
// internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
// val list = tag.getList("CachedNetItems", 10)
// cachedNetItems.clear()
// for (entryTag in list) {
// val stack = ItemStack.fromTag(entryTag as CompoundTag)
// val netAmount = entryTag.getInt("NetAmount")
// cachedNetItems[stack] = netAmount
// }
// cachedSortedNetItems = cachedNetItems.object2IntEntrySet().sortedByDescending { it.intValue }.map {
// val stack = it.key.copy()
// stack.count = it.intValue
// stack
// }
// }
//
//}
//
//data class StackLocateRequest(
// val stack: ItemStack,
// val amount: Int,
// val timestamp: Int,
// var results: MutableSet<Pair<Int, InterfaceBlockEntity>> = mutableSetOf()
//) {
// val totalResultAmount: Int
// get() = results.fold(0) { acc, (amount, _) -> acc + amount }
//
// fun isFinishable(currentTimestamp: Int): Boolean {
// return totalResultAmount > amount || currentTimestamp - timestamp >= TerminalBlockEntity.LOCATE_REQUEST_TIMEOUT
// }
//}
//
//data class PendingStackInsertion(
// val bufferSlot: Int,
// val stack: ItemStack,
// val timestamp: Int,
// val results: MutableSet<Pair<Int, InterfaceBlockEntity>> = mutableSetOf(),
//) {
// val totalCapacity: Int
// get() = results.fold(0) { acc, (amount, _) -> acc + amount }
//
// fun isFinishable(currentTimestamp: Int): Boolean {
// return totalCapacity > stack.count || currentTimestamp - timestamp >= TerminalBlockEntity.INSERTION_TIMEOUT
// }
//}