Compare commits
7 Commits
f4f4c7ff03
...
8a20837f11
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 8a20837f11 | |
Shadowfacts | 14125143dc | |
Shadowfacts | 37692aac7d | |
Shadowfacts | 2ec294d427 | |
Shadowfacts | 654baa81a1 | |
Shadowfacts | 98134825a6 | |
Shadowfacts | 2a9fc29cdd |
|
@ -14,13 +14,11 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), Tickable, PacketSink {
|
abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), PacketSink {
|
||||||
|
|
||||||
var macAddress = MACAddress.random()
|
var macAddress = MACAddress.random()
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
private val sendQueue = LinkedList<Pair<Packet, WeakReference<PacketSink>>>()
|
|
||||||
|
|
||||||
override fun getMACAddress(): MACAddress {
|
override fun getMACAddress(): MACAddress {
|
||||||
return macAddress
|
return macAddress
|
||||||
}
|
}
|
||||||
|
@ -33,7 +31,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
|
||||||
|
|
||||||
protected abstract fun handlePacket(packet: Packet)
|
protected abstract fun handlePacket(packet: Packet)
|
||||||
|
|
||||||
fun acceptsPacket(packet: Packet): Boolean {
|
protected open fun acceptsPacket(packet: Packet): Boolean {
|
||||||
return when (packet.destination.type) {
|
return when (packet.destination.type) {
|
||||||
MACAddress.Type.BROADCAST -> true
|
MACAddress.Type.BROADCAST -> true
|
||||||
MACAddress.Type.UNICAST -> macAddress == packet.destination
|
MACAddress.Type.UNICAST -> macAddress == packet.destination
|
||||||
|
@ -45,33 +43,28 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueue(packet: Packet, destination: PacketSink) {
|
fun send(packet: Packet, destination: PacketSink) {
|
||||||
sendQueue.add(packet to WeakReference(destination))
|
destination.handle(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: better name for this
|
// todo: better name for this
|
||||||
fun enqueueToSingle(packet: Packet) {
|
fun sendToSingle(packet: Packet) {
|
||||||
val destinations = NetworkUtil.findDestinations(world!!, pos)
|
val destinations = NetworkUtil.findDestinations(world!!, pos)
|
||||||
if (destinations.size != 1) {
|
if (destinations.size != 1) {
|
||||||
// todo: handle this better
|
// todo: handle this better
|
||||||
println("Can't send packet, multiple destinations available: $destinations")
|
println("Can't send packet, multiple destinations available: $destinations")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
enqueue(packet, destinations.first())
|
send(packet, destinations.first())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueueToAll(packet: Packet) {
|
fun sendToAll(packet: Packet) {
|
||||||
enqueueToAll(packet, NetworkUtil.findDestinations(world!!, pos))
|
sendToAll(packet, NetworkUtil.findDestinations(world!!, pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueueToAll(packet: Packet, destinations: Iterable<PacketSink>) {
|
fun sendToAll(packet: Packet, destinations: Iterable<PacketSink>) {
|
||||||
sendQueue.addAll(destinations.map { packet to WeakReference(it) })
|
destinations.forEach {
|
||||||
}
|
it.handle(packet)
|
||||||
|
|
||||||
override fun tick() {
|
|
||||||
if (sendQueue.isNotEmpty()) {
|
|
||||||
val (packet, destination) = sendQueue.pop()
|
|
||||||
destination.get()?.handle(packet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +79,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBreak() {
|
fun onBreak() {
|
||||||
enqueueToAll(DeviceRemovedPacket(this))
|
sendToAll(DeviceRemovedPacket(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,21 +43,21 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE) {
|
||||||
|
|
||||||
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
private fun handleRequestInventory(packet: RequestInventoryPacket) {
|
||||||
getInventory()?.also { inv ->
|
getInventory()?.also { inv ->
|
||||||
enqueueToSingle(ReadInventoryPacket(inv, macAddress, packet.source))
|
sendToSingle(ReadInventoryPacket(inv, macAddress, packet.source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLocateStack(packet: LocateStackPacket) {
|
private fun handleLocateStack(packet: LocateStackPacket) {
|
||||||
getInventory()?.also { inv ->
|
getInventory()?.also { inv ->
|
||||||
val amount = inv.getAmount(packet.stack)
|
val amount = inv.getAmount(packet.stack)
|
||||||
enqueueToSingle(StackLocationPacket(packet.stack, amount, this, macAddress, packet.source))
|
sendToSingle(StackLocationPacket(packet.stack, amount, this, macAddress, packet.source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleExtractStack(packet: ExtractStackPacket) {
|
private fun handleExtractStack(packet: ExtractStackPacket) {
|
||||||
getInventory()?.also { inv ->
|
getInventory()?.also { inv ->
|
||||||
val extracted = inv.extract(packet.stack, packet.amount)
|
val extracted = inv.extract(packet.stack, packet.amount)
|
||||||
enqueueToSingle(ItemStackPacket(extracted, macAddress, packet.source))
|
sendToSingle(ItemStackPacket(extracted, macAddress, packet.source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package net.shadowfacts.phycon.network.block.netswitch
|
package net.shadowfacts.phycon.network.block.netswitch
|
||||||
|
|
||||||
|
import net.minecraft.entity.ItemEntity
|
||||||
|
import net.minecraft.util.Tickable
|
||||||
import net.minecraft.util.math.Direction
|
import net.minecraft.util.math.Direction
|
||||||
import net.shadowfacts.phycon.api.PacketSink
|
import net.shadowfacts.phycon.api.PacketSink
|
||||||
import net.shadowfacts.phycon.api.packet.Packet
|
import net.shadowfacts.phycon.api.packet.Packet
|
||||||
|
@ -7,30 +9,44 @@ import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.NetworkUtil
|
import net.shadowfacts.phycon.network.NetworkUtil
|
||||||
|
import net.shadowfacts.phycon.network.packet.ItemStackPacket
|
||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
import javax.print.attribute.standard.Destination
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class SwitchBlockEntity: DeviceBlockEntity(PhyBlockEntities.SWITCH) {
|
class SwitchBlockEntity: DeviceBlockEntity(PhyBlockEntities.SWITCH), Tickable {
|
||||||
|
|
||||||
private val macTable = mutableMapOf<MACAddress, Direction>()
|
companion object {
|
||||||
|
var SWITCHING_CAPACITY = 256
|
||||||
override fun handlePacket(packet: Packet) {
|
|
||||||
throw RuntimeException("Unreachable")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handle(packet: Packet) {
|
private val macTable = mutableMapOf<MACAddress, Direction>()
|
||||||
|
private var packetsHandledThisTick = 0
|
||||||
|
|
||||||
|
override fun acceptsPacket(packet: Packet) = true
|
||||||
|
|
||||||
|
override fun handlePacket(packet: Packet) {
|
||||||
|
if (packetsHandledThisTick >= SWITCHING_CAPACITY) {
|
||||||
|
if (packet is ItemStackPacket) {
|
||||||
|
// todo: calculate entity spawn point by finding non-obstructed location
|
||||||
|
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
|
||||||
|
world!!.spawnEntity(entity)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
packetsHandledThisTick++
|
||||||
|
|
||||||
if (packet.destination == MACAddress.BROADCAST) {
|
if (packet.destination == MACAddress.BROADCAST) {
|
||||||
val allDestinations = NetworkUtil.findDestinations(world!!, pos).filter { it.macAddress != packet.source }
|
val allDestinations = NetworkUtil.findDestinations(world!!, pos).filter { it.macAddress != packet.source }
|
||||||
enqueueToAll(packet, allDestinations)
|
sendToAll(packet, allDestinations)
|
||||||
} else {
|
} else {
|
||||||
val direction = macTable[packet.destination]
|
val direction = macTable[packet.destination]
|
||||||
if (direction != null) {
|
if (direction != null) {
|
||||||
val dest = findDestination(direction)
|
val dest = findDestination(direction)
|
||||||
if (dest != null && packet.destination == dest.macAddress) {
|
if (dest != null && packet.destination == dest.macAddress) {
|
||||||
enqueue(packet, dest)
|
send(packet, dest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,10 +69,14 @@ class SwitchBlockEntity: DeviceBlockEntity(PhyBlockEntities.SWITCH) {
|
||||||
val dest = findDestination(dir)
|
val dest = findDestination(dir)
|
||||||
if (dest != null && packet.destination == dest.macAddress) {
|
if (dest != null && packet.destination == dest.macAddress) {
|
||||||
macTable[packet.destination] = dir
|
macTable[packet.destination] = dir
|
||||||
enqueue(packet, dest)
|
send(packet, dest)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
packetsHandledThisTick = 0
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import net.minecraft.inventory.InventoryListener
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
|
import net.minecraft.util.Tickable
|
||||||
import net.shadowfacts.phycon.api.packet.Packet
|
import net.shadowfacts.phycon.api.packet.Packet
|
||||||
import net.shadowfacts.phycon.api.util.MACAddress
|
import net.shadowfacts.phycon.api.util.MACAddress
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
|
@ -20,6 +21,7 @@ import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
|
||||||
import net.shadowfacts.phycon.network.packet.*
|
import net.shadowfacts.phycon.network.packet.*
|
||||||
import net.shadowfacts.phycon.util.fromTag
|
import net.shadowfacts.phycon.util.fromTag
|
||||||
|
import net.shadowfacts.phycon.util.insert
|
||||||
import net.shadowfacts.phycon.util.toTag
|
import net.shadowfacts.phycon.util.toTag
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -27,14 +29,14 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryListener, BlockEntityClientSerializable {
|
class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryListener, BlockEntityClientSerializable, Tickable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val LOCATE_REQUEST_TIMEOUT = 40 // ticks
|
val LOCATE_REQUEST_TIMEOUT = 40 // ticks
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inventoryCache = mutableMapOf<MACAddress, GroupedItemInv>()
|
private val inventoryCache = mutableMapOf<MACAddress, GroupedItemInv>()
|
||||||
val internalBuffer = BasicInventory(18)
|
val internalBuffer = TerminalBufferInventory(18)
|
||||||
|
|
||||||
private val pendingRequests = LinkedList<StackLocateRequest>()
|
private val pendingRequests = LinkedList<StackLocateRequest>()
|
||||||
|
|
||||||
|
@ -82,16 +84,12 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleItemStack(packet: ItemStackPacket) {
|
private fun handleItemStack(packet: ItemStackPacket) {
|
||||||
// todo: handle merging stacks into the buffer better?
|
val remaining = internalBuffer.insertFromNetwork(packet.stack)
|
||||||
for (i in 0 until internalBuffer.invSize) {
|
if (!remaining.isEmpty) {
|
||||||
if (internalBuffer.getInvStack(i).isEmpty) {
|
// todo: calculate entity spawn point by finding non-obstructed location
|
||||||
internalBuffer.setInvStack(i, packet.stack)
|
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), remaining)
|
||||||
return
|
world!!.spawnEntity(entity)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// todo: calculate entity spawn point by finding non-obstructed location
|
|
||||||
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
|
|
||||||
world!!.spawnEntity(entity)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateNetItems() {
|
private fun updateNetItems() {
|
||||||
|
@ -119,8 +117,6 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
|
||||||
|
|
||||||
if (observers > 0 && (++counter % 20) == 0) {
|
if (observers > 0 && (++counter % 20) == 0) {
|
||||||
if (world!!.isClient) {
|
if (world!!.isClient) {
|
||||||
println(cachedNetItems)
|
println(cachedNetItems)
|
||||||
|
@ -137,7 +133,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
||||||
sync()
|
sync()
|
||||||
|
|
||||||
inventoryCache.clear()
|
inventoryCache.clear()
|
||||||
enqueueToSingle(RequestInventoryPacket(macAddress))
|
sendToSingle(RequestInventoryPacket(macAddress))
|
||||||
ContainerProviderRegistry.INSTANCE.openContainer(TerminalContainer.ID, player) { buf ->
|
ContainerProviderRegistry.INSTANCE.openContainer(TerminalContainer.ID, player) { buf ->
|
||||||
buf.writeBlockPos(pos)
|
buf.writeBlockPos(pos)
|
||||||
}
|
}
|
||||||
|
@ -147,7 +143,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
||||||
|
|
||||||
fun requestItem(stack: ItemStack, amount: Int = stack.count) {
|
fun requestItem(stack: ItemStack, amount: Int = stack.count) {
|
||||||
pendingRequests.add(StackLocateRequest(stack, amount, counter))
|
pendingRequests.add(StackLocateRequest(stack, amount, counter))
|
||||||
enqueueToSingle(LocateStackPacket(stack, macAddress))
|
sendToSingle(LocateStackPacket(stack, macAddress))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
private fun stackLocateRequestCompleted(request: StackLocateRequest) {
|
||||||
|
@ -158,12 +154,12 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
||||||
val (sourceAmount, sourceInterface) = sortedResults.removeAt(0)
|
val (sourceAmount, sourceInterface) = sortedResults.removeAt(0)
|
||||||
val amountToRequest = min(sourceAmount, request.amount - amountRequested)
|
val amountToRequest = min(sourceAmount, request.amount - amountRequested)
|
||||||
amountRequested += amountToRequest
|
amountRequested += amountToRequest
|
||||||
enqueueToSingle(ExtractStackPacket(request.stack, amountToRequest, macAddress, sourceInterface.macAddress))
|
sendToSingle(ExtractStackPacket(request.stack, amountToRequest, macAddress, sourceInterface.macAddress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInvChange(inv: Inventory) {
|
override fun onInvChange(inv: Inventory) {
|
||||||
if (inv == internalBuffer && !world!!.isClient) {
|
if (inv == internalBuffer && world != null && !world!!.isClient) {
|
||||||
markDirty()
|
markDirty()
|
||||||
sync()
|
sync()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package net.shadowfacts.phycon.network.block.terminal
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||||
|
import net.minecraft.inventory.BasicInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class TerminalBufferInventory(size: Int): BasicInventory(size) {
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
TO_NETWORK, FROM_NETWORK, UNASSIGNED
|
||||||
|
}
|
||||||
|
|
||||||
|
private val modes = Array(size) { Mode.UNASSIGNED }
|
||||||
|
|
||||||
|
fun insertFromNetwork(stack: ItemStack): ItemStack {
|
||||||
|
var remaining = stack.copy()
|
||||||
|
for (slot in 0 until invSize) {
|
||||||
|
if (modes[slot] == Mode.TO_NETWORK) continue
|
||||||
|
|
||||||
|
remaining = insertFromNetwork(stack, slot)
|
||||||
|
|
||||||
|
if (remaining.isEmpty) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaining
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertFromNetwork(stack: ItemStack, slot: Int): ItemStack {
|
||||||
|
val mode = modes[slot]
|
||||||
|
if (mode == Mode.TO_NETWORK) return stack
|
||||||
|
val current = getInvStack(slot)
|
||||||
|
if (current.isEmpty) {
|
||||||
|
setInvStack(slot, stack)
|
||||||
|
modes[slot] = Mode.FROM_NETWORK
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
} else if (ItemStackUtil.areEqualIgnoreAmounts(stack, current)) {
|
||||||
|
val toTransfer = min(current.maxCount - current.count, stack.count)
|
||||||
|
current.count += toTransfer
|
||||||
|
stack.count -= toTransfer
|
||||||
|
modes[slot] = Mode.FROM_NETWORK
|
||||||
|
return stack
|
||||||
|
} else {
|
||||||
|
return stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setInvStack(slot: Int, stack: ItemStack) {
|
||||||
|
if (stack.isEmpty) {
|
||||||
|
modes[slot] = Mode.UNASSIGNED
|
||||||
|
}
|
||||||
|
super.setInvStack(slot, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,7 +8,8 @@ import net.minecraft.entity.player.PlayerInventory
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import kotlin.math.max
|
import kotlin.math.ceil
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -57,16 +58,25 @@ class TerminalContainer(syncId: Int, playerInv: PlayerInventory, val terminal: T
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||||
if (actionType == SlotActionType.QUICK_MOVE) {
|
if (slotId in 0 until 54) {
|
||||||
if (slotId < 54) {
|
// the slot clicked was one of the network stacks
|
||||||
// the slot clicked was one of the network stacks
|
if (actionType == SlotActionType.QUICK_MOVE) {
|
||||||
val slot = slotList[slotId]
|
|
||||||
val stack = slotList[slotId].stack
|
val stack = slotList[slotId].stack
|
||||||
if (!stack.isEmpty && !player.world.isClient) {
|
if (!stack.isEmpty && !player.world.isClient) {
|
||||||
terminal.requestItem(stack, max(stack.count, stack.maxCount))
|
terminal.requestItem(stack, min(stack.count, stack.maxCount))
|
||||||
|
}
|
||||||
|
} else if (actionType == SlotActionType.PICKUP && clickData == 1) {
|
||||||
|
if (clickData == 1) {
|
||||||
|
// right click, request half stack
|
||||||
|
val stack = slotList[slotId].stack
|
||||||
|
if (!stack.isEmpty && !player.world.isClient) {
|
||||||
|
terminal.requestItem(stack, ceil(min(stack.count, stack.maxCount) / 2f).toInt())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// todo: left click, show amount dialog
|
||||||
}
|
}
|
||||||
return ItemStack.EMPTY
|
|
||||||
}
|
}
|
||||||
|
return ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package net.shadowfacts.phycon.util
|
package net.shadowfacts.phycon.util
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||||
import net.minecraft.inventory.BasicInventory
|
import net.minecraft.inventory.BasicInventory
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -32,3 +34,30 @@ fun BasicInventory.fromTag(list: ListTag) {
|
||||||
setInvStack(slot, stack)
|
setInvStack(slot, stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun BasicInventory.insert(stack: ItemStack, slot: Int): ItemStack {
|
||||||
|
@Suppress("NAME_SHADOWING") val stack = stack.copy()
|
||||||
|
val current = getInvStack(slot)
|
||||||
|
if (current.isEmpty) {
|
||||||
|
setInvStack(slot, stack)
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
} else if (ItemStackUtil.areEqualIgnoreAmounts(stack, current)) {
|
||||||
|
val toTransfer = min(current.maxCount - current.count, stack.count)
|
||||||
|
current.count += toTransfer
|
||||||
|
stack.count -= toTransfer
|
||||||
|
return stack
|
||||||
|
} else {
|
||||||
|
return stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BasicInventory.insert(stack: ItemStack): ItemStack {
|
||||||
|
var remaining = stack
|
||||||
|
for (slot in 0 until invSize) {
|
||||||
|
remaining = insert(stack, slot)
|
||||||
|
if (remaining.isEmpty) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaining
|
||||||
|
}
|
Loading…
Reference in New Issue