From 282a29394bf8064e44861ecbe22ddfe9e66120d6 Mon Sep 17 00:00:00 2001 From: isXander Date: Mon, 24 Jul 2023 22:26:38 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Resolve=20incompatibility=20with?= =?UTF-8?q?=20FAPI=20item=20group=20API=20where=20custom=20creative=20tabs?= =?UTF-8?q?=20would=20be=20randomly=20ordered=20when=20tabbed=20through?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + .../CreativeModeInventoryScreenProcessor.java | 77 +++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2e40bbc..9792377 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -74,6 +74,7 @@ dependencies { "fabric-screen-api-v1", "fabric-command-api-v2", "fabric-networking-api-v1", + "fabric-item-group-api-v1", ).forEach { modImplementation(fabricApi.module(it, libs.versions.fabric.api.get())) } diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java index e958768..2de80bf 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java @@ -3,12 +3,19 @@ package dev.isxander.controlify.screenop.compat.vanilla; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.mixins.feature.screenop.vanilla.CreativeModeInventoryScreenAccessor; import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; +import net.fabricmc.fabric.impl.client.itemgroup.CreativeGuiExtensions; +import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents; +import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; +import java.util.Comparator; +import java.util.List; import java.util.function.Supplier; +@SuppressWarnings("UnstableApiUsage") // TODO: requires FAPI impl stuff to get pages working. will be changed in future FAPI update (hopefully) public class CreativeModeInventoryScreenProcessor extends AbstractContainerScreenProcessor { public CreativeModeInventoryScreenProcessor(CreativeModeInventoryScreen screen, Supplier hoveredSlot, ClickSlotFunction clickSlotFunction) { super(screen, hoveredSlot, clickSlotFunction); @@ -17,20 +24,78 @@ public class CreativeModeInventoryScreenProcessor extends AbstractContainerScree @Override protected void handleScreenVMouse(Controller controller, VirtualMouseHandler vmouse) { var accessor = (CreativeModeInventoryScreenAccessor) screen; + var ext = (CreativeGuiExtensions) screen; + var tabs = getTabsOnCurrentPage(ext); if (controller.bindings().GUI_NEXT_TAB.justPressed()) { - var tabs = CreativeModeTabs.tabs(); int newIndex = tabs.indexOf(CreativeModeInventoryScreenAccessor.getSelectedTab()) + 1; - if (newIndex >= tabs.size()) newIndex = 0; - accessor.invokeSelectTab(tabs.get(newIndex)); + if (newIndex >= tabs.size()) { + newIndex = 0; + + int currentPage = ext.fabric_currentPage(); + ext.fabric_nextPage(); + if (ext.fabric_currentPage() == currentPage) { + for (int i = 0; i < currentPage; i++) { + ext.fabric_previousPage(); + } + } + } + accessor.invokeSelectTab(getTabsOnCurrentPage(ext).get(newIndex)); } if (controller.bindings().GUI_PREV_TAB.justPressed()) { - var tabs = CreativeModeTabs.tabs(); int newIndex = tabs.indexOf(CreativeModeInventoryScreenAccessor.getSelectedTab()) - 1; - if (newIndex < 0) newIndex = tabs.size() - 1; - accessor.invokeSelectTab(tabs.get(newIndex)); + if (newIndex < 0) { + if (ext.fabric_currentPage() == 0) { + for (int i = 0; i < getLastPage(ext); i++) { + ext.fabric_nextPage(); + } + } else { + ext.fabric_previousPage(); + } + + newIndex = getTabsOnCurrentPage(ext).size() - 1; + } + accessor.invokeSelectTab(getTabsOnCurrentPage(ext).get(newIndex)); } + super.handleScreenVMouse(controller, vmouse); } + + private static List getTabsOnCurrentPage(CreativeGuiExtensions ext) { + return CreativeModeTabs.tabs().stream() // just gets visible tabs from registry (excludes operator tab if disabled) + .filter(tab -> ext.fabric_currentPage() == getFabricPage(ext, tab)) // only want current page of tabs, not all of them + .sorted(Comparator.comparing(CreativeModeTab::row).thenComparingInt(CreativeModeTab::column)) // in hash order from the registry. + .sorted((a, b) -> { + // make stuff aligned to the right go last + if (a.isAlignedRight() && !b.isAlignedRight()) return 1; + if (!a.isAlignedRight() && b.isAlignedRight()) return -1; + return 0; + }) + .toList(); + } + + // straight up ripped from fapi impl + private static int getFabricPage(CreativeGuiExtensions ext, CreativeModeTab tab) { + if (FabricCreativeGuiComponents.COMMON_GROUPS.contains(tab)) { + return ext.fabric_currentPage(); + } + + final FabricItemGroup fabricItemGroup = (FabricItemGroup) tab; + return fabricItemGroup.getPage(); + } + + // this is the only way to get the last page of tabs, since fapi doesn't expose it + private static int getLastPage(CreativeGuiExtensions ext) { + int lastPage = 0; + while (hasGroupForPage(ext, lastPage)) { + lastPage++; + } + return lastPage - 1; + } + + private static boolean hasGroupForPage(CreativeGuiExtensions ext, int page) { + return CreativeModeTabs.tabs().stream() + .anyMatch(itemGroup -> getFabricPage(ext, itemGroup) == page); + } }