mirror of
https://github.com/FabricMC/fabric.git
synced 2025-09-06 11:24:23 +00:00
Add API to control creative inventory screen (#3814)
* Add API to control creative inventory screen
* Rename methods
* Apply suggestions from code review
Co-authored-by: haykam821 <24855774+haykam821@users.noreply.github.com>
* Update fabric-item-group-api-v1/src/client/java/net/fabricmc/fabric/api/client/itemgroup/v1/FabricCreativeInventoryScreen.java
Co-authored-by: haykam821 <24855774+haykam821@users.noreply.github.com>
---------
Co-authored-by: haykam821 <24855774+haykam821@users.noreply.github.com>
(cherry picked from commit 00ab0a636c
)
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.fabricmc.fabric.api.client.itemgroup.v1;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fabric provided extensions to {@link CreativeInventoryScreen}.
|
||||||
|
* This interface is automatically implemented on all creative inventory screens via Mixin and interface injection.
|
||||||
|
*/
|
||||||
|
public interface FabricCreativeInventoryScreen {
|
||||||
|
/**
|
||||||
|
* Switches to the page with the given index if it exists.
|
||||||
|
*
|
||||||
|
* @param page the index of the page to switch to
|
||||||
|
* @return Returns true when the page was changed
|
||||||
|
*/
|
||||||
|
default boolean switchToPage(int page) {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches to the next page if it exists.
|
||||||
|
*
|
||||||
|
* @return Returns true when the page was changed
|
||||||
|
*/
|
||||||
|
default boolean switchToNextPage() {
|
||||||
|
return switchToPage(getCurrentPage() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches to the previous page if it exists.
|
||||||
|
*
|
||||||
|
* @return Returns true when the page was changed
|
||||||
|
*/
|
||||||
|
default boolean switchToPreviousPage() {
|
||||||
|
return switchToPage(getCurrentPage() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the current page.
|
||||||
|
*/
|
||||||
|
default int getCurrentPage() {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of pages.
|
||||||
|
*/
|
||||||
|
default int getPageCount() {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an ordered list containing the item groups on the requested page.
|
||||||
|
*/
|
||||||
|
default List<ItemGroup> getItemGroupsOnPage(int page) {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the page index of the given item group.
|
||||||
|
*
|
||||||
|
* <p>Item groups appearing on every page always return the current page index.
|
||||||
|
*
|
||||||
|
* @param itemGroup the item group to get the page index for
|
||||||
|
* @return the page index of the item group
|
||||||
|
*/
|
||||||
|
default int getPage(ItemGroup itemGroup) {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether there are additional pages to show on top of the default vanilla pages.
|
||||||
|
*
|
||||||
|
* @return true if there are additional pages
|
||||||
|
*/
|
||||||
|
default boolean hasAdditionalPages() {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ItemGroup} that is associated with the currently selected tab.
|
||||||
|
*
|
||||||
|
* @return the currently selected {@link ItemGroup}
|
||||||
|
*/
|
||||||
|
default ItemGroup getSelectedItemGroup() {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the currently selected tab to the given {@link ItemGroup}.
|
||||||
|
*
|
||||||
|
* @param itemGroup the {@link ItemGroup} to select
|
||||||
|
* @return true if the tab was successfully selected
|
||||||
|
*/
|
||||||
|
default boolean setSelectedItemGroup(ItemGroup itemGroup) {
|
||||||
|
throw new AssertionError("Implemented by mixin");
|
||||||
|
}
|
||||||
|
}
|
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.client.itemgroup;
|
|
||||||
|
|
||||||
public interface CreativeGuiExtensions {
|
|
||||||
void fabric_nextPage();
|
|
||||||
|
|
||||||
void fabric_previousPage();
|
|
||||||
|
|
||||||
int fabric_currentPage();
|
|
||||||
|
|
||||||
boolean fabric_isButtonVisible(FabricCreativeGuiComponents.Type type);
|
|
||||||
|
|
||||||
boolean fabric_isButtonEnabled(FabricCreativeGuiComponents.Type type);
|
|
||||||
}
|
|
@@ -18,6 +18,7 @@ package net.fabricmc.fabric.impl.client.itemgroup;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
@@ -30,31 +31,33 @@ import net.minecraft.registry.Registries;
|
|||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
|
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroupImpl;
|
||||||
|
|
||||||
public class FabricCreativeGuiComponents {
|
public class FabricCreativeGuiComponents {
|
||||||
private static final Identifier BUTTON_TEX = new Identifier("fabric", "textures/gui/creative_buttons.png");
|
private static final Identifier BUTTON_TEX = new Identifier("fabric", "textures/gui/creative_buttons.png");
|
||||||
private static final double TABS_PER_PAGE = FabricItemGroup.TABS_PER_PAGE;
|
private static final double TABS_PER_PAGE = FabricItemGroupImpl.TABS_PER_PAGE;
|
||||||
public static final Set<ItemGroup> COMMON_GROUPS = Set.of(ItemGroups.SEARCH, ItemGroups.INVENTORY, ItemGroups.HOTBAR).stream()
|
public static final Set<ItemGroup> COMMON_GROUPS = Set.of(ItemGroups.SEARCH, ItemGroups.INVENTORY, ItemGroups.HOTBAR).stream()
|
||||||
.map(Registries.ITEM_GROUP::getOrThrow)
|
.map(Registries.ITEM_GROUP::getOrThrow)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
public static int getPageCount() {
|
||||||
|
return (int) Math.ceil((ItemGroups.getGroupsToDisplay().size() - COMMON_GROUPS.size()) / TABS_PER_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
public static class ItemGroupButtonWidget extends ButtonWidget {
|
public static class ItemGroupButtonWidget extends ButtonWidget {
|
||||||
final CreativeGuiExtensions extensions;
|
final CreativeInventoryScreen screen;
|
||||||
final CreativeInventoryScreen gui;
|
|
||||||
final Type type;
|
final Type type;
|
||||||
|
|
||||||
public ItemGroupButtonWidget(int x, int y, Type type, CreativeGuiExtensions extensions) {
|
public ItemGroupButtonWidget(int x, int y, Type type, CreativeInventoryScreen screen) {
|
||||||
super(x, y, 11, 12, type.text, (bw) -> type.clickConsumer.accept(extensions), ButtonWidget.DEFAULT_NARRATION_SUPPLIER);
|
super(x, y, 11, 12, type.text, (bw) -> type.clickConsumer.accept(screen), ButtonWidget.DEFAULT_NARRATION_SUPPLIER);
|
||||||
this.extensions = extensions;
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.gui = (CreativeInventoryScreen) extensions;
|
this.screen = screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderWidget(DrawContext drawContext, int mouseX, int mouseY, float delta) {
|
protected void renderWidget(DrawContext drawContext, int mouseX, int mouseY, float delta) {
|
||||||
this.active = extensions.fabric_isButtonEnabled(type);
|
this.active = type.isEnabled.test(screen);
|
||||||
this.visible = extensions.fabric_isButtonVisible(type);
|
this.visible = screen.hasAdditionalPages();
|
||||||
|
|
||||||
if (!this.visible) {
|
if (!this.visible) {
|
||||||
return;
|
return;
|
||||||
@@ -65,22 +68,23 @@ public class FabricCreativeGuiComponents {
|
|||||||
drawContext.drawTexture(BUTTON_TEX, this.getX(), this.getY(), u + (type == Type.NEXT ? 11 : 0), v, 11, 12);
|
drawContext.drawTexture(BUTTON_TEX, this.getX(), this.getY(), u + (type == Type.NEXT ? 11 : 0), v, 11, 12);
|
||||||
|
|
||||||
if (this.isHovered()) {
|
if (this.isHovered()) {
|
||||||
int pageCount = (int) Math.ceil((ItemGroups.getGroupsToDisplay().size() - COMMON_GROUPS.size()) / TABS_PER_PAGE);
|
drawContext.drawTooltip(MinecraftClient.getInstance().textRenderer, Text.translatable("fabric.gui.creativeTabPage", screen.getCurrentPage() + 1, getPageCount()), mouseX, mouseY);
|
||||||
drawContext.drawTooltip(MinecraftClient.getInstance().textRenderer, Text.translatable("fabric.gui.creativeTabPage", extensions.fabric_currentPage() + 1, pageCount), mouseX, mouseY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
NEXT(Text.literal(">"), CreativeGuiExtensions::fabric_nextPage),
|
NEXT(Text.literal(">"), CreativeInventoryScreen::switchToNextPage, screen -> screen.getCurrentPage() + 1 < screen.getPageCount()),
|
||||||
PREVIOUS(Text.literal("<"), CreativeGuiExtensions::fabric_previousPage);
|
PREVIOUS(Text.literal("<"), CreativeInventoryScreen::switchToPreviousPage, screen -> screen.getCurrentPage() != 0);
|
||||||
|
|
||||||
final Text text;
|
final Text text;
|
||||||
final Consumer<CreativeGuiExtensions> clickConsumer;
|
final Consumer<CreativeInventoryScreen> clickConsumer;
|
||||||
|
final Predicate<CreativeInventoryScreen> isEnabled;
|
||||||
|
|
||||||
Type(Text text, Consumer<CreativeGuiExtensions> clickConsumer) {
|
Type(Text text, Consumer<CreativeInventoryScreen> clickConsumer, Predicate<CreativeInventoryScreen> isEnabled) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.clickConsumer = clickConsumer;
|
this.clickConsumer = clickConsumer;
|
||||||
|
this.isEnabled = isEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package net.fabricmc.fabric.mixin.itemgroup.client;
|
package net.fabricmc.fabric.mixin.itemgroup.client;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
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;
|
||||||
@@ -34,12 +37,12 @@ import net.minecraft.item.ItemGroups;
|
|||||||
import net.minecraft.screen.ScreenHandler;
|
import net.minecraft.screen.ScreenHandler;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
import net.fabricmc.fabric.impl.client.itemgroup.CreativeGuiExtensions;
|
import net.fabricmc.fabric.api.client.itemgroup.v1.FabricCreativeInventoryScreen;
|
||||||
import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents;
|
import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents;
|
||||||
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
|
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroupImpl;
|
||||||
|
|
||||||
@Mixin(CreativeInventoryScreen.class)
|
@Mixin(CreativeInventoryScreen.class)
|
||||||
public abstract class CreativeInventoryScreenMixin<T extends ScreenHandler> extends AbstractInventoryScreen<T> implements CreativeGuiExtensions {
|
public abstract class CreativeInventoryScreenMixin<T extends ScreenHandler> extends AbstractInventoryScreen<T> implements FabricCreativeInventoryScreen {
|
||||||
public CreativeInventoryScreenMixin(T screenHandler, PlayerInventory playerInventory, Text text) {
|
public CreativeInventoryScreenMixin(T screenHandler, PlayerInventory playerInventory, Text text) {
|
||||||
super(screenHandler, playerInventory, text);
|
super(screenHandler, playerInventory, text);
|
||||||
}
|
}
|
||||||
@@ -51,51 +54,15 @@ public abstract class CreativeInventoryScreenMixin<T extends ScreenHandler> exte
|
|||||||
private static ItemGroup selectedTab;
|
private static ItemGroup selectedTab;
|
||||||
|
|
||||||
// "static" matches selectedTab
|
// "static" matches selectedTab
|
||||||
private static int fabric_currentPage = 0;
|
@Unique
|
||||||
|
private static int currentPage = 0;
|
||||||
|
|
||||||
@Override
|
@Unique
|
||||||
public void fabric_nextPage() {
|
private void updateSelection() {
|
||||||
if (!fabric_hasGroupForPage(fabric_currentPage + 1)) {
|
if (!isGroupVisible(selectedTab)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fabric_currentPage++;
|
|
||||||
fabric_updateSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fabric_previousPage() {
|
|
||||||
if (fabric_currentPage == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fabric_currentPage--;
|
|
||||||
fabric_updateSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fabric_isButtonVisible(FabricCreativeGuiComponents.Type type) {
|
|
||||||
return ItemGroups.getGroupsToDisplay().size() > (Objects.requireNonNull(ItemGroups.displayContext).hasPermissions() ? 14 : 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fabric_isButtonEnabled(FabricCreativeGuiComponents.Type type) {
|
|
||||||
if (type == FabricCreativeGuiComponents.Type.NEXT) {
|
|
||||||
return fabric_hasGroupForPage(fabric_currentPage + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == FabricCreativeGuiComponents.Type.PREVIOUS) {
|
|
||||||
return fabric_currentPage != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fabric_updateSelection() {
|
|
||||||
if (!fabric_isGroupVisible(selectedTab)) {
|
|
||||||
ItemGroups.getGroups()
|
ItemGroups.getGroups()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(this::fabric_isGroupVisible)
|
.filter(this::isGroupVisible)
|
||||||
.min((a, b) -> Boolean.compare(a.isSpecial(), b.isSpecial()))
|
.min((a, b) -> Boolean.compare(a.isSpecial(), b.isSpecial()))
|
||||||
.ifPresent(this::setSelectedTab);
|
.ifPresent(this::setSelectedTab);
|
||||||
}
|
}
|
||||||
@@ -103,63 +70,131 @@ public abstract class CreativeInventoryScreenMixin<T extends ScreenHandler> exte
|
|||||||
|
|
||||||
@Inject(method = "init", at = @At("RETURN"))
|
@Inject(method = "init", at = @At("RETURN"))
|
||||||
private void init(CallbackInfo info) {
|
private void init(CallbackInfo info) {
|
||||||
fabric_currentPage = fabric_getPage(selectedTab);
|
currentPage = getPage(selectedTab);
|
||||||
|
|
||||||
int xpos = x + 170;
|
int xpos = x + 170;
|
||||||
int ypos = y + 4;
|
int ypos = y + 4;
|
||||||
|
|
||||||
addDrawableChild(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos + 11, ypos, FabricCreativeGuiComponents.Type.NEXT, this));
|
CreativeInventoryScreen self = (CreativeInventoryScreen) (Object) this;
|
||||||
addDrawableChild(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos, ypos, FabricCreativeGuiComponents.Type.PREVIOUS, this));
|
addDrawableChild(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos + 11, ypos, FabricCreativeGuiComponents.Type.NEXT, self));
|
||||||
|
addDrawableChild(new FabricCreativeGuiComponents.ItemGroupButtonWidget(xpos, ypos, FabricCreativeGuiComponents.Type.PREVIOUS, self));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "setSelectedTab", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "setSelectedTab", at = @At("HEAD"), cancellable = true)
|
||||||
private void setSelectedTab(ItemGroup itemGroup, CallbackInfo info) {
|
private void setSelectedTab(ItemGroup itemGroup, CallbackInfo info) {
|
||||||
if (!fabric_isGroupVisible(itemGroup)) {
|
if (!isGroupVisible(itemGroup)) {
|
||||||
info.cancel();
|
info.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "renderTabTooltipIfHovered", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "renderTabTooltipIfHovered", at = @At("HEAD"), cancellable = true)
|
||||||
private void renderTabTooltipIfHovered(DrawContext drawContext, ItemGroup itemGroup, int mx, int my, CallbackInfoReturnable<Boolean> info) {
|
private void renderTabTooltipIfHovered(DrawContext drawContext, ItemGroup itemGroup, int mx, int my, CallbackInfoReturnable<Boolean> info) {
|
||||||
if (!fabric_isGroupVisible(itemGroup)) {
|
if (!isGroupVisible(itemGroup)) {
|
||||||
info.setReturnValue(false);
|
info.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "isClickInTab", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "isClickInTab", at = @At("HEAD"), cancellable = true)
|
||||||
private void isClickInTab(ItemGroup itemGroup, double mx, double my, CallbackInfoReturnable<Boolean> info) {
|
private void isClickInTab(ItemGroup itemGroup, double mx, double my, CallbackInfoReturnable<Boolean> info) {
|
||||||
if (!fabric_isGroupVisible(itemGroup)) {
|
if (!isGroupVisible(itemGroup)) {
|
||||||
info.setReturnValue(false);
|
info.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "renderTabIcon", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "renderTabIcon", at = @At("HEAD"), cancellable = true)
|
||||||
private void renderTabIcon(DrawContext drawContext, ItemGroup itemGroup, CallbackInfo info) {
|
private void renderTabIcon(DrawContext drawContext, ItemGroup itemGroup, CallbackInfo info) {
|
||||||
if (!fabric_isGroupVisible(itemGroup)) {
|
if (!isGroupVisible(itemGroup)) {
|
||||||
info.cancel();
|
info.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fabric_isGroupVisible(ItemGroup itemGroup) {
|
@Unique
|
||||||
return itemGroup.shouldDisplay() && fabric_currentPage == fabric_getPage(itemGroup);
|
private boolean isGroupVisible(ItemGroup itemGroup) {
|
||||||
}
|
return itemGroup.shouldDisplay() && currentPage == getPage(itemGroup);
|
||||||
|
|
||||||
private static int fabric_getPage(ItemGroup itemGroup) {
|
|
||||||
if (FabricCreativeGuiComponents.COMMON_GROUPS.contains(itemGroup)) {
|
|
||||||
return fabric_currentPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
final FabricItemGroup fabricItemGroup = (FabricItemGroup) itemGroup;
|
|
||||||
return fabricItemGroup.getPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean fabric_hasGroupForPage(int page) {
|
|
||||||
return ItemGroups.getGroupsToDisplay().stream()
|
|
||||||
.anyMatch(itemGroup -> fabric_getPage(itemGroup) == page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int fabric_currentPage() {
|
public int getPage(ItemGroup itemGroup) {
|
||||||
return fabric_currentPage;
|
if (FabricCreativeGuiComponents.COMMON_GROUPS.contains(itemGroup)) {
|
||||||
|
return currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FabricItemGroupImpl fabricItemGroup = (FabricItemGroupImpl) itemGroup;
|
||||||
|
return fabricItemGroup.fabric_getPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private boolean hasGroupForPage(int page) {
|
||||||
|
return ItemGroups.getGroupsToDisplay()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(itemGroup -> getPage(itemGroup) == page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean switchToPage(int page) {
|
||||||
|
if (!hasGroupForPage(page)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPage == page) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPage = page;
|
||||||
|
updateSelection();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCurrentPage() {
|
||||||
|
return currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPageCount() {
|
||||||
|
return FabricCreativeGuiComponents.getPageCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ItemGroup> getItemGroupsOnPage(int page) {
|
||||||
|
return ItemGroups.getGroupsToDisplay()
|
||||||
|
.stream()
|
||||||
|
.filter(itemGroup -> getPage(itemGroup) == page)
|
||||||
|
// Thanks to isXander for the sorting
|
||||||
|
.sorted(Comparator.comparing(ItemGroup::getRow).thenComparingInt(ItemGroup::getColumn))
|
||||||
|
.sorted((a, b) -> {
|
||||||
|
if (a.isSpecial() && !b.isSpecial()) return 1;
|
||||||
|
if (!a.isSpecial() && b.isSpecial()) return -1;
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAdditionalPages() {
|
||||||
|
return ItemGroups.getGroupsToDisplay().size() > (Objects.requireNonNull(ItemGroups.displayContext).hasPermissions() ? 14 : 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemGroup getSelectedItemGroup() {
|
||||||
|
return selectedTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setSelectedItemGroup(ItemGroup itemGroup) {
|
||||||
|
Objects.requireNonNull(itemGroup, "itemGroup");
|
||||||
|
|
||||||
|
if (selectedTab == itemGroup) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPage != getPage(itemGroup)) {
|
||||||
|
if (!switchToPage(getPage(itemGroup))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedTab(itemGroup);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package net.fabricmc.fabric.impl.itemgroup;
|
package net.fabricmc.fabric.impl.itemgroup;
|
||||||
|
|
||||||
public interface FabricItemGroup {
|
public interface FabricItemGroupImpl {
|
||||||
int TABS_PER_PAGE = 10;
|
int TABS_PER_PAGE = 10;
|
||||||
|
|
||||||
int getPage();
|
int fabric_getPage();
|
||||||
|
|
||||||
void setPage(int page);
|
void fabric_setPage(int page);
|
||||||
}
|
}
|
@@ -37,11 +37,11 @@ import net.minecraft.registry.RegistryKey;
|
|||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroupEntries;
|
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroupEntries;
|
||||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||||
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
|
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroupImpl;
|
||||||
import net.fabricmc.fabric.impl.itemgroup.ItemGroupEventsImpl;
|
import net.fabricmc.fabric.impl.itemgroup.ItemGroupEventsImpl;
|
||||||
|
|
||||||
@Mixin(ItemGroup.class)
|
@Mixin(ItemGroup.class)
|
||||||
abstract class ItemGroupMixin implements FabricItemGroup {
|
abstract class ItemGroupMixin implements FabricItemGroupImpl {
|
||||||
@Shadow
|
@Shadow
|
||||||
private Collection<ItemStack> displayStacks;
|
private Collection<ItemStack> displayStacks;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ abstract class ItemGroupMixin implements FabricItemGroup {
|
|||||||
private Set<ItemStack> searchTabStacks;
|
private Set<ItemStack> searchTabStacks;
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private int fabric_page = -1;
|
private int page = -1;
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
@Inject(method = "updateEntries", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemGroup;reloadSearchProvider()V"))
|
@Inject(method = "updateEntries", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemGroup;reloadSearchProvider()V"))
|
||||||
@@ -91,16 +91,16 @@ abstract class ItemGroupMixin implements FabricItemGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPage() {
|
public int fabric_getPage() {
|
||||||
if (fabric_page < 0) {
|
if (page < 0) {
|
||||||
throw new IllegalStateException("Item group has no page");
|
throw new IllegalStateException("Item group has no page");
|
||||||
}
|
}
|
||||||
|
|
||||||
return fabric_page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPage(int page) {
|
public void fabric_setPage(int page) {
|
||||||
this.fabric_page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,12 +47,12 @@ import net.minecraft.registry.Registries;
|
|||||||
import net.minecraft.registry.RegistryKey;
|
import net.minecraft.registry.RegistryKey;
|
||||||
import net.minecraft.registry.entry.RegistryEntry;
|
import net.minecraft.registry.entry.RegistryEntry;
|
||||||
|
|
||||||
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
|
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroupImpl;
|
||||||
|
|
||||||
@Mixin(ItemGroups.class)
|
@Mixin(ItemGroups.class)
|
||||||
public class ItemGroupsMixin {
|
public class ItemGroupsMixin {
|
||||||
@Unique
|
@Unique
|
||||||
private static final int TABS_PER_PAGE = FabricItemGroup.TABS_PER_PAGE;
|
private static final int TABS_PER_PAGE = FabricItemGroupImpl.TABS_PER_PAGE;
|
||||||
|
|
||||||
@Inject(method = "collect", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "collect", at = @At("HEAD"), cancellable = true)
|
||||||
private static void deferDuplicateCheck(CallbackInfo ci) {
|
private static void deferDuplicateCheck(CallbackInfo ci) {
|
||||||
@@ -86,16 +86,16 @@ public class ItemGroupsMixin {
|
|||||||
|
|
||||||
for (RegistryEntry.Reference<ItemGroup> reference : sortedItemGroups) {
|
for (RegistryEntry.Reference<ItemGroup> reference : sortedItemGroups) {
|
||||||
final ItemGroup itemGroup = reference.value();
|
final ItemGroup itemGroup = reference.value();
|
||||||
final FabricItemGroup fabricItemGroup = (FabricItemGroup) itemGroup;
|
final FabricItemGroupImpl fabricItemGroup = (FabricItemGroupImpl) itemGroup;
|
||||||
|
|
||||||
if (vanillaGroups.contains(reference.registryKey())) {
|
if (vanillaGroups.contains(reference.registryKey())) {
|
||||||
// Vanilla group goes on the first page.
|
// Vanilla group goes on the first page.
|
||||||
fabricItemGroup.setPage(0);
|
fabricItemGroup.fabric_setPage(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ItemGroupAccessor itemGroupAccessor = (ItemGroupAccessor) itemGroup;
|
final ItemGroupAccessor itemGroupAccessor = (ItemGroupAccessor) itemGroup;
|
||||||
fabricItemGroup.setPage((count / TABS_PER_PAGE) + 1);
|
fabricItemGroup.fabric_setPage((count / TABS_PER_PAGE) + 1);
|
||||||
int pageIndex = count % TABS_PER_PAGE;
|
int pageIndex = count % TABS_PER_PAGE;
|
||||||
ItemGroup.Row row = pageIndex < (TABS_PER_PAGE / 2) ? ItemGroup.Row.TOP : ItemGroup.Row.BOTTOM;
|
ItemGroup.Row row = pageIndex < (TABS_PER_PAGE / 2) ? ItemGroup.Row.TOP : ItemGroup.Row.BOTTOM;
|
||||||
itemGroupAccessor.setRow(row);
|
itemGroupAccessor.setRow(row);
|
||||||
@@ -110,9 +110,9 @@ public class ItemGroupsMixin {
|
|||||||
|
|
||||||
for (RegistryKey<ItemGroup> registryKey : Registries.ITEM_GROUP.getKeys()) {
|
for (RegistryKey<ItemGroup> registryKey : Registries.ITEM_GROUP.getKeys()) {
|
||||||
final ItemGroup itemGroup = Registries.ITEM_GROUP.getOrThrow(registryKey);
|
final ItemGroup itemGroup = Registries.ITEM_GROUP.getOrThrow(registryKey);
|
||||||
final FabricItemGroup fabricItemGroup = (FabricItemGroup) itemGroup;
|
final FabricItemGroupImpl fabricItemGroup = (FabricItemGroupImpl) itemGroup;
|
||||||
final String displayName = itemGroup.getDisplayName().getString();
|
final String displayName = itemGroup.getDisplayName().getString();
|
||||||
final var position = new ItemGroupPosition(itemGroup.getRow(), itemGroup.getColumn(), fabricItemGroup.getPage());
|
final var position = new ItemGroupPosition(itemGroup.getRow(), itemGroup.getColumn(), fabricItemGroup.fabric_getPage());
|
||||||
final String existingName = map.put(position, displayName);
|
final String existingName = map.put(position, displayName);
|
||||||
|
|
||||||
if (existingName != null) {
|
if (existingName != null) {
|
||||||
|
@@ -30,6 +30,9 @@
|
|||||||
],
|
],
|
||||||
"accessWidener": "fabric-item-group-api-v1.accesswidener",
|
"accessWidener": "fabric-item-group-api-v1.accesswidener",
|
||||||
"custom": {
|
"custom": {
|
||||||
"fabric-api:module-lifecycle": "stable"
|
"fabric-api:module-lifecycle": "stable",
|
||||||
|
"loom:injected_interfaces": {
|
||||||
|
"net/minecraft/class_481": ["net/fabricmc/fabric/api/client/itemgroup/v1/FabricCreativeInventoryScreen"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user