Allow using arrows to navigate in storage overview

This commit is contained in:
Linnea Gräf
2024-07-10 04:50:31 +02:00
parent 5a91c407d6
commit ca17fe502d
6 changed files with 90 additions and 15 deletions

View File

@@ -7,12 +7,17 @@
package moe.nea.firmament.mixins; package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import moe.nea.firmament.events.SlotClickEvent; import moe.nea.firmament.events.SlotClickEvent;
import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.SlotActionType; import net.minecraft.screen.slot.SlotActionType;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -20,12 +25,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayerInteractionManager.class) @Mixin(ClientPlayerInteractionManager.class)
public class SlotClickEventPatch { public class SlotClickEventPatch {
@Inject(method = "clickSlot", at = @At(value = "FIELD", target = "Lnet/minecraft/screen/ScreenHandler;slots:Lnet/minecraft/util/collection/DefaultedList;", opcode = Opcodes.GETFIELD))
private void onSlotClickSaveSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
if (0 <= slotId && slotId < handler.slots.size()) {
slotContent.set(handler.getSlot(slotId).getStack().copy());
}
}
@Inject(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) @Inject(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V"))
private void onSlotClick(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler) { private void onSlotClick(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
if (0 <= slotId && slotId < handler.slots.size()) { if (0 <= slotId && slotId < handler.slots.size()) {
SlotClickEvent.Companion.publish(new SlotClickEvent( SlotClickEvent.Companion.publish(new SlotClickEvent(
handler.getSlot(slotId), handler.getSlot(slotId),
handler.getSlot(slotId).getStack(), slotContent.get(),
button, button,
actionType actionType
)); ));

View File

@@ -15,6 +15,7 @@ import net.minecraft.text.Text
import moe.nea.firmament.apis.UrsaManager import moe.nea.firmament.apis.UrsaManager
import moe.nea.firmament.events.CommandEvent import moe.nea.firmament.events.CommandEvent
import moe.nea.firmament.features.inventory.buttons.InventoryButtons import moe.nea.firmament.features.inventory.buttons.InventoryButtons
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverviewScreen import moe.nea.firmament.features.inventory.storageoverlay.StorageOverviewScreen
import moe.nea.firmament.features.world.FairySouls import moe.nea.firmament.features.world.FairySouls
import moe.nea.firmament.gui.config.AllConfigsGui import moe.nea.firmament.gui.config.AllConfigsGui
@@ -105,12 +106,18 @@ fun firmamentCommand() = literal("firmament") {
} }
} }
} }
thenLiteral("storage") { thenLiteral("storageoverview") {
thenExecute { thenExecute {
ScreenUtil.setScreenLater(StorageOverviewScreen()) ScreenUtil.setScreenLater(StorageOverviewScreen())
MC.player?.networkHandler?.sendChatCommand("storage") MC.player?.networkHandler?.sendChatCommand("storage")
} }
} }
thenLiteral("storage") {
thenExecute {
ScreenUtil.setScreenLater(StorageOverlayScreen())
MC.player?.networkHandler?.sendChatCommand("storage")
}
}
thenLiteral("repo") { thenLiteral("repo") {
thenLiteral("reload") { thenLiteral("reload") {
thenLiteral("fetch") { thenLiteral("fetch") {

View File

@@ -9,14 +9,19 @@ package moe.nea.firmament.features.inventory.storageoverlay
import java.util.SortedMap import java.util.SortedMap
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.item.Items
import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket
import net.minecraft.text.Text
import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ScreenChangeEvent import moe.nea.firmament.events.ScreenChangeEvent
import moe.nea.firmament.events.SlotClickEvent
import moe.nea.firmament.events.TickEvent import moe.nea.firmament.events.TickEvent
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.customgui.customGui import moe.nea.firmament.util.customgui.customGui
import moe.nea.firmament.util.data.ProfileSpecificDataHolder import moe.nea.firmament.util.data.ProfileSpecificDataHolder
@@ -43,7 +48,8 @@ object StorageOverlay : FirmamentFeature {
override val config: TConfig override val config: TConfig
get() = TConfig get() = TConfig
var lastStorageOverlay: Screen? = null var lastStorageOverlay: StorageOverviewScreen? = null
var skipNextStorageOverlayBackflip = false
var currentHandler: StorageBackingHandle? = null var currentHandler: StorageBackingHandle? = null
@Subscribe @Subscribe
@@ -51,23 +57,59 @@ object StorageOverlay : FirmamentFeature {
rememberContent(currentHandler ?: return) rememberContent(currentHandler ?: return)
} }
@Subscribe
fun onClick(event: SlotClickEvent) {
if (lastStorageOverlay != null && event.slot.inventory !is PlayerInventory && event.slot.index < 9
&& event.stack.item != Items.BLACK_STAINED_GLASS_PANE
) {
skipNextStorageOverlayBackflip = true
}
}
@Subscribe @Subscribe
fun onScreenChange(it: ScreenChangeEvent) { fun onScreenChange(it: ScreenChangeEvent) {
if (it.old == null && it.new == null) return
val storageOverlayScreen = it.old as? StorageOverlayScreen val storageOverlayScreen = it.old as? StorageOverlayScreen
?: ((it.old as? HandledScreen<*>)?.customGui as? StorageOverlayCustom)?.overview ?: ((it.old as? HandledScreen<*>)?.customGui as? StorageOverlayCustom)?.overview
var storageOverviewScreen = it.old as? StorageOverviewScreen
val screen = it.new as? GenericContainerScreen
val oldHandler = currentHandler
currentHandler = StorageBackingHandle.fromScreen(screen)
rememberContent(currentHandler)
if (storageOverviewScreen != null && oldHandler is StorageBackingHandle.HasBackingScreen) {
val player = MC.player
assert(player != null)
player?.networkHandler?.sendPacket(CloseHandledScreenC2SPacket(oldHandler.handler.syncId))
if (player?.currentScreenHandler === oldHandler.handler) {
player.currentScreenHandler = player.playerScreenHandler
}
}
storageOverviewScreen = storageOverviewScreen ?: lastStorageOverlay
if (it.new == null && storageOverlayScreen != null && !storageOverlayScreen.isExiting) { if (it.new == null && storageOverlayScreen != null && !storageOverlayScreen.isExiting) {
it.overrideScreen = storageOverlayScreen it.overrideScreen = storageOverlayScreen
return return
} }
val screen = it.new as? GenericContainerScreen ?: return if (storageOverviewScreen != null
currentHandler = StorageBackingHandle.fromScreen(screen) && !storageOverviewScreen.isClosing
&& (currentHandler is StorageBackingHandle.Overview || currentHandler == null)
) {
if (skipNextStorageOverlayBackflip) {
skipNextStorageOverlayBackflip = false
} else {
it.overrideScreen = storageOverviewScreen
lastStorageOverlay = null
}
return
}
screen ?: return
screen.customGui = StorageOverlayCustom( screen.customGui = StorageOverlayCustom(
currentHandler as? StorageBackingHandle.Page ?: return, currentHandler ?: return,
screen, screen,
storageOverlayScreen ?: return) storageOverlayScreen ?: return)
} }
fun rememberContent(handler: StorageBackingHandle) { fun rememberContent(handler: StorageBackingHandle?) {
handler ?: return
// TODO: Make all of these functions work on deltas / updates instead of the entire contents // TODO: Make all of these functions work on deltas / updates instead of the entire contents
val data = Data.data?.storageInventories ?: return val data = Data.data?.storageInventories ?: return
when (handler) { when (handler) {

View File

@@ -17,7 +17,7 @@ import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
import moe.nea.firmament.util.customgui.CustomGui import moe.nea.firmament.util.customgui.CustomGui
class StorageOverlayCustom( class StorageOverlayCustom(
val handler: StorageBackingHandle.Page, val handler: StorageBackingHandle,
val screen: GenericContainerScreen, val screen: GenericContainerScreen,
val overview: StorageOverlayScreen, val overview: StorageOverlayScreen,
) : CustomGui() { ) : CustomGui() {
@@ -59,7 +59,7 @@ class StorageOverlayCustom(
} }
override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean {
return overview.mouseClicked(mouseX, mouseY, button, handler.storagePageSlot) return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot)
} }
override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) { override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
@@ -68,7 +68,7 @@ class StorageOverlayCustom(
mouseX, mouseX,
mouseY, mouseY,
delta, delta,
handler.storagePageSlot, (handler as? StorageBackingHandle.Page)?.storagePageSlot,
screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9), screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9),
Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament)) Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament))
overview.drawScrollBar(drawContext) overview.drawScrollBar(drawContext)

View File

@@ -7,6 +7,7 @@
package moe.nea.firmament.features.inventory.storageoverlay package moe.nea.firmament.features.inventory.storageoverlay
import org.lwjgl.glfw.GLFW
import kotlin.math.max import kotlin.math.max
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.client.gui.DrawContext import net.minecraft.client.gui.DrawContext
@@ -119,8 +120,9 @@ class StorageOverviewScreen() : Screen(Text.empty()) {
} }
} }
override fun close() { override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
isClosing = true if (keyCode == GLFW.GLFW_KEY_ESCAPE)
super.close() isClosing = true
return super.keyPressed(keyCode, scanCode, modifiers)
} }
} }

View File

@@ -13,16 +13,19 @@ import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
import me.shedaniel.rei.api.client.registry.screen.ExclusionZones import me.shedaniel.rei.api.client.registry.screen.ExclusionZones
import me.shedaniel.rei.api.client.registry.screen.OverlayDecider
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
import me.shedaniel.rei.api.client.registry.transfer.TransferHandler import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
import me.shedaniel.rei.api.common.entry.EntryStack import me.shedaniel.rei.api.common.entry.EntryStack
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.ActionResult
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.events.HandledScreenPushREIEvent import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay import moe.nea.firmament.features.inventory.CraftingOverlay
@@ -99,6 +102,15 @@ class FirmamentReiPlugin : REIClientPlugin {
} }
override fun registerScreens(registry: ScreenRegistry) { override fun registerScreens(registry: ScreenRegistry) {
registry.registerDecider(object : OverlayDecider {
override fun <R : Screen?> isHandingScreen(screen: Class<R>?): Boolean {
return screen == StorageOverlayScreen::class.java
}
override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): ActionResult {
return ActionResult.SUCCESS
}
})
registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider) registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider)
} }