Terminal: Shift-click transferring, draw slot modes
This commit is contained in:
parent
dedfcae79b
commit
1c3e358f2e
|
@ -0,0 +1,26 @@
|
|||
package net.shadowfacts.phycon.mixin.client;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.shadowfacts.phycon.network.block.terminal.TerminalScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
@Mixin(HandledScreen.class)
|
||||
public class MixinHandledScreen {
|
||||
|
||||
@Inject(method = "drawSlot(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/screen/slot/Slot;)V", at = @At(value = "INVOKE", target = "enableDepthTest()V"))
|
||||
private void drawSlot(MatrixStack matrixStack, Slot slot, CallbackInfo ci) {
|
||||
if ((Object)this instanceof TerminalScreen) {
|
||||
TerminalScreen self = (TerminalScreen)(Object)this;
|
||||
self.drawSlotUnderlay(matrixStack, slot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -238,7 +238,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
|||
|
||||
override fun fromTag(state: BlockState, tag: CompoundTag) {
|
||||
super.fromTag(state, tag)
|
||||
internalBuffer.fromTag(tag.getList("InternalBuffer", 10))
|
||||
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
|
@ -254,14 +254,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento
|
|||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
tag.getList("InternalBuffer", 10)?.also { list ->
|
||||
if (list.isNotEmpty()) {
|
||||
internalBuffer.fromTag(list)
|
||||
} else {
|
||||
// todo: should this clear or just do nothing?
|
||||
internalBuffer.clear()
|
||||
}
|
||||
}
|
||||
internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
|
||||
val list = tag.getList("CachedNetItems", 10)
|
||||
cachedNetItems.clear()
|
||||
for (entryTag in list) {
|
||||
|
|
|
@ -3,6 +3,10 @@ package net.shadowfacts.phycon.network.block.terminal
|
|||
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||
import net.minecraft.inventory.SimpleInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.IntArrayTag
|
||||
import net.shadowfacts.phycon.util.fromTag
|
||||
import net.shadowfacts.phycon.util.toTag
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
|
@ -14,8 +18,21 @@ class TerminalBufferInventory(size: Int): SimpleInventory(size) {
|
|||
TO_NETWORK, FROM_NETWORK, UNASSIGNED
|
||||
}
|
||||
|
||||
// todo: modes should be saved to NBT
|
||||
private val modes = Array(size) { Mode.UNASSIGNED }
|
||||
var modes = Array(size) { Mode.UNASSIGNED }
|
||||
private set
|
||||
|
||||
fun toTag(): CompoundTag {
|
||||
val compound = CompoundTag()
|
||||
compound.put("Inventory", (this as SimpleInventory).toTag())
|
||||
compound.put("Modes", IntArrayTag(modes.map(Mode::ordinal)))
|
||||
return compound
|
||||
}
|
||||
|
||||
fun fromTag(tag: CompoundTag) {
|
||||
val inventory = tag.getList("Inventory", 10)
|
||||
(this as SimpleInventory).fromTag(inventory)
|
||||
tag.getIntArray("Modes").forEachIndexed { i, it -> modes[i] = Mode.values()[it] }
|
||||
}
|
||||
|
||||
fun insertFromNetwork(stack: ItemStack): ItemStack {
|
||||
var remaining = stack.copy()
|
||||
|
@ -57,6 +74,11 @@ class TerminalBufferInventory(size: Int): SimpleInventory(size) {
|
|||
super.setStack(slot, stack)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
super.clear()
|
||||
this.modes = Array(size()) { Mode.UNASSIGNED }
|
||||
}
|
||||
|
||||
fun getMode(slot: Int): Mode {
|
||||
return modes[slot]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package net.shadowfacts.phycon.network.block.terminal
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import net.minecraft.client.gui.DrawableHelper
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.text.LiteralText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
@ -38,4 +40,19 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
|||
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
fun drawSlotUnderlay(matrixStack: MatrixStack, slot: Slot) {
|
||||
if (!handler.isBufferSlot(slot.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
val mode = handler.terminal.internalBuffer.getMode(slot.id - handler.bufferSlotsStart)
|
||||
val color: UInt = when (mode) {
|
||||
TerminalBufferInventory.Mode.TO_NETWORK -> 0xFFFF0000u
|
||||
TerminalBufferInventory.Mode.FROM_NETWORK -> 0xFF00FF00u
|
||||
else -> return
|
||||
}
|
||||
DrawableHelper.fill(matrixStack, slot.x, slot.y, slot.x + 16, slot.y + 16, color.toInt())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class TerminalScreenHandler(syncId: Int, playerInv: PlayerInventory, val termina
|
|||
}
|
||||
|
||||
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack {
|
||||
if (slotId in 0 until 54) {
|
||||
if (isNetworkSlot(slotId)) {
|
||||
// the slot clicked was one of the network stacks
|
||||
if (actionType == SlotActionType.QUICK_MOVE) {
|
||||
val stack = slots[slotId].stack
|
||||
|
@ -83,14 +83,79 @@ class TerminalScreenHandler(syncId: Int, playerInv: PlayerInventory, val termina
|
|||
}
|
||||
}
|
||||
return ItemStack.EMPTY
|
||||
} else if (slotId in 54 until 72) {
|
||||
} else if (isBufferSlot(slotId)) {
|
||||
// internal buffer
|
||||
if (actionType == SlotActionType.PICKUP && !player.inventory.cursorStack.isEmpty) {
|
||||
// todo: why does this think it's quick_craft sometimes?
|
||||
if ((actionType == SlotActionType.PICKUP || actionType == SlotActionType.QUICK_CRAFT) && !player.inventory.cursorStack.isEmpty) {
|
||||
// placing cursor stack into buffer
|
||||
val bufferSlot = slotId - 54 // subtract 54 to convert the handler slot ID to a valid buffer index
|
||||
val bufferSlot = slotId - bufferSlotsStart // subtract 54 to convert the handler slot ID to a valid buffer index
|
||||
terminal.internalBuffer.markSlot(bufferSlot, TerminalBufferInventory.Mode.TO_NETWORK)
|
||||
}
|
||||
}
|
||||
return super.onSlotClick(slotId, clickData, actionType, player)
|
||||
}
|
||||
|
||||
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
|
||||
if (isNetworkSlot(slotId)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
val slot = slots[slotId]
|
||||
if (!slot.hasStack()) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
val result = slot.stack.copy()
|
||||
|
||||
if (isBufferSlot(slotId)) {
|
||||
if (!insertItem(slot.stack, playerSlotsStart, playerSlotsEnd, false)) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
if (slot.stack.isEmpty) {
|
||||
terminal.internalBuffer.markSlot(slotId - bufferSlotsStart, TerminalBufferInventory.Mode.UNASSIGNED)
|
||||
}
|
||||
} else if (isPlayerSlot(slotId)) {
|
||||
val slotsInsertedInto = tryInsertItem(slot.stack, bufferSlotsStart until playerSlotsStart) { terminal.internalBuffer.getMode(it - bufferSlotsStart) != TerminalBufferInventory.Mode.FROM_NETWORK }
|
||||
slotsInsertedInto.forEach { terminal.internalBuffer.markSlot(it - bufferSlotsStart, TerminalBufferInventory.Mode.TO_NETWORK) }
|
||||
if (slot.stack.isEmpty) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun tryInsertItem(stack: ItemStack, slots: IntRange, slotPredicate: (Int) -> Boolean): Collection<Int> {
|
||||
val slotsInsertedInto = mutableListOf<Int>()
|
||||
for (index in slots) {
|
||||
if (stack.isEmpty) break
|
||||
if (!slotPredicate(index)) continue
|
||||
|
||||
val slot = this.slots[index]
|
||||
val slotStack = slot.stack
|
||||
if (slotStack.isEmpty) {
|
||||
slot.stack = stack.copy()
|
||||
stack.count = 0
|
||||
|
||||
slot.markDirty()
|
||||
slotsInsertedInto.add(index)
|
||||
} else if (canStacksCombine(slotStack, stack) && slotStack.count < slotStack.maxCount) {
|
||||
val maxToMove = slotStack.maxCount - slotStack.count
|
||||
val toMove = min(maxToMove, stack.count)
|
||||
slotStack.increment(toMove)
|
||||
stack.decrement(toMove)
|
||||
|
||||
slot.markDirty()
|
||||
slotsInsertedInto.add(index)
|
||||
}
|
||||
}
|
||||
return slotsInsertedInto
|
||||
}
|
||||
|
||||
val bufferSlotsStart = 54
|
||||
val playerSlotsStart = 72
|
||||
val playerSlotsEnd = 72 + 36
|
||||
fun isNetworkSlot(id: Int) = id in 0 until bufferSlotsStart
|
||||
fun isBufferSlot(id: Int) = id in bufferSlotsStart until playerSlotsStart
|
||||
fun isPlayerSlot(id: Int) = id >= playerSlotsStart
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ fun SimpleInventory.toTag(): ListTag {
|
|||
}
|
||||
|
||||
fun SimpleInventory.fromTag(list: ListTag) {
|
||||
if (list.isEmpty()) {
|
||||
this.clear()
|
||||
return
|
||||
}
|
||||
if (list.elementType != 10.toByte()) throw RuntimeException("Can't decode BasicInventory from list tag that does not contain compound tags")
|
||||
this.clear()
|
||||
for (tag in list) {
|
||||
|
|
|
@ -28,7 +28,11 @@
|
|||
]
|
||||
},
|
||||
"mixins": [
|
||||
"phycon.mixins.json"
|
||||
"phycon.mixins.json",
|
||||
{
|
||||
"config": "phycon-client.mixins.json",
|
||||
"environment": "client"
|
||||
}
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.shadowfacts.phycon.mixin.client",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinHandledScreen"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue