From d3bfd79800aacfde6617d5430ead5fdda0a506fe Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 6 Aug 2022 10:37:38 +0800 Subject: More work okay --- .../shedaniel/rei/RoughlyEnoughItemsNetwork.java | 54 ++---- .../rei/impl/client/ClientHelperImpl.java | 194 +-------------------- .../rei/impl/client/ClientModNameHelperImpl.java | 69 ++++++++ .../rei/impl/client/ClientNetworkHelperImpl.java | 170 ++++++++++++++++++ .../shedaniel/rei/impl/client/REIRuntimeImpl.java | 13 +- .../rei/impl/client/gui/ScreenOverlayImpl.java | 46 ++--- .../rei/impl/client/gui/TooltipQueue.java | 51 ++++++ .../rei/impl/client/gui/menu/MenuAccessImpl.java | 3 +- .../gui/widget/DefaultDisplayChoosePageWidget.java | 34 ++-- .../client/gui/widget/DisplayedEntryWidget.java | 6 +- .../impl/client/gui/widget/DraggableWidget.java | 13 +- .../entrylist/CollapsingEntryListWidget.java | 16 +- .../gui/widget/entrylist/EntryListEntries.java | 48 +++++ .../gui/widget/entrylist/EntryListWidget.java | 10 +- .../gui/widget/search/DelegateTextField.java | 13 ++ .../gui/widget/search/OverlaySearchField.java | 9 +- .../client/runtime/DefaultClientRuntimePlugin.java | 21 --- 17 files changed, 434 insertions(+), 336 deletions(-) create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/ClientModNameHelperImpl.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/ClientNetworkHelperImpl.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/TooltipQueue.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListEntries.java (limited to 'runtime/src/main') diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java index 80d868c28..037fa0fc9 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java @@ -26,34 +26,39 @@ package me.shedaniel.rei; import dev.architectury.networking.NetworkManager; import dev.architectury.networking.transformers.SplitPacketTransformer; import io.netty.buffer.Unpooled; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.display.Display; -import me.shedaniel.rei.impl.common.transfer.InputSlotCrafter; +import me.shedaniel.rei.impl.common.Internals; +import me.shedaniel.rei.impl.common.networking.NetworkModule; import net.minecraft.ChatFormatting; -import net.minecraft.Util; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; -import net.minecraft.world.Container; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.ItemStack; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class RoughlyEnoughItemsNetwork { + private static final Map MODULES = new HashMap<>(); public static final ResourceLocation DELETE_ITEMS_PACKET = new ResourceLocation("roughlyenoughitems", "delete_item"); public static final ResourceLocation CREATE_ITEMS_PACKET = new ResourceLocation("roughlyenoughitems", "create_item"); public static final ResourceLocation CREATE_ITEMS_HOTBAR_PACKET = new ResourceLocation("roughlyenoughitems", "create_item_hotbar"); public static final ResourceLocation CREATE_ITEMS_GRAB_PACKET = new ResourceLocation("roughlyenoughitems", "create_item_grab"); public static final ResourceLocation CREATE_ITEMS_MESSAGE_PACKET = new ResourceLocation("roughlyenoughitems", "ci_msg"); - public static final ResourceLocation MOVE_ITEMS_PACKET = new ResourceLocation("roughlyenoughitems", "move_items"); public static final ResourceLocation NOT_ENOUGH_ITEMS_PACKET = new ResourceLocation("roughlyenoughitems", "og_not_enough"); + public static boolean canUse(Object key) { + return MODULES.containsKey(key) && MODULES.get(key).canUse(); + } + public static void onInitialize() { + for (NetworkModule module : Internals.resolveServices(NetworkModule.class)) { + MODULES.put(module.getKey(), module); + } + NetworkManager.registerReceiver(NetworkManager.c2s(), DELETE_ITEMS_PACKET, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> { ServerPlayer player = (ServerPlayer) context.getPlayer(); if (player.getServer().getProfilePermissions(player.getGameProfile()) < player.getServer().getOperatorUserPermissionLevel()) { @@ -115,38 +120,5 @@ public class RoughlyEnoughItemsNetwork { player.displayClientMessage(new TranslatableComponent("text.rei.failed_cheat_items"), false); } }); - NetworkManager.registerReceiver(NetworkManager.c2s(), MOVE_ITEMS_PACKET, Collections.singletonList(new SplitPacketTransformer()), (packetByteBuf, context) -> { - ServerPlayer player = (ServerPlayer) context.getPlayer(); - CategoryIdentifier category = CategoryIdentifier.of(packetByteBuf.readResourceLocation()); - AbstractContainerMenu container = player.containerMenu; - InventoryMenu playerContainer = player.inventoryMenu; - try { - boolean shift = packetByteBuf.readBoolean(); - try { - InputSlotCrafter crafter = InputSlotCrafter.start(category, container, player, packetByteBuf.readAnySizeNbt(), shift); - } catch (InputSlotCrafter.NotEnoughMaterialsException e) { - if (!(container instanceof RecipeBookMenu)) { - return; - } - // TODO Implement Ghost Recipes - /*FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); - buf.writeInt(input.size()); - for (List stacks : input) { - buf.writeInt(stacks.size()); - for (ItemStack stack : stacks) { - buf.writeItem(stack); - } - } - NetworkManager.sendToPlayer(player, NOT_ENOUGH_ITEMS_PACKET, buf);*/ - } catch (IllegalStateException e) { - player.sendMessage(new TranslatableComponent(e.getMessage()).withStyle(ChatFormatting.RED), Util.NIL_UUID); - } catch (Exception e) { - player.sendMessage(new TranslatableComponent("error.rei.internal.error", e.getMessage()).withStyle(ChatFormatting.RED), Util.NIL_UUID); - e.printStackTrace(); - } - } catch (Exception e) { - e.printStackTrace(); - } - }); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java index 78128ca0a..7a537fcec 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java @@ -24,23 +24,15 @@ package me.shedaniel.rei.impl.client; import com.google.common.base.Suppliers; -import dev.architectury.networking.NetworkManager; -import dev.architectury.platform.Platform; -import io.netty.buffer.Unpooled; -import me.shedaniel.rei.RoughlyEnoughItemsNetwork; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.gui.config.DisplayScreenType; import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.client.view.ViewSearchBuilder; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; -import me.shedaniel.rei.api.common.util.EntryStacks; -import me.shedaniel.rei.api.common.util.FormattingUtils; import me.shedaniel.rei.impl.client.gui.screen.CompositeDisplayViewingScreen; import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; import me.shedaniel.rei.impl.display.DisplaySpec; @@ -48,27 +40,17 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Supplier; @ApiStatus.Internal @Environment(EnvType.CLIENT) -public class ClientHelperImpl implements ClientHelper { +public class ClientHelperImpl extends ClientNetworkHelperImpl implements ClientModNameHelperImpl { public final Supplier isAprilFools = Suppliers.memoize(() -> { try { LocalDateTime now = LocalDateTime.now(); @@ -77,11 +59,6 @@ public class ClientHelperImpl implements ClientHelper { } return false; }); - private final Map modNameCache = new HashMap<>() {{ - put("minecraft", "Minecraft"); - put("c", "Global"); - put("global", "Global"); - }}; /** * @return the instance of {@link ClientHelperImpl} @@ -92,165 +69,6 @@ public class ClientHelperImpl implements ClientHelper { return (ClientHelperImpl) ClientHelper.getInstance(); } - public boolean hasPermissionToUsePackets() { - try { - Minecraft.getInstance().getConnection().getSuggestionsProvider().hasPermission(0); - return hasOperatorPermission() && canUsePackets(); - } catch (NullPointerException e) { - return true; - } - } - - public boolean hasOperatorPermission() { - try { - return Minecraft.getInstance().getConnection().getSuggestionsProvider().hasPermission(1); - } catch (NullPointerException e) { - return true; - } - } - - public boolean canUsePackets() { - return NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET) && NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_GRAB_PACKET) && NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET); - } - - public boolean canUseHotbarPackets() { - return NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_HOTBAR_PACKET); - } - - public boolean canDeleteItems() { - return hasPermissionToUsePackets() || Minecraft.getInstance().gameMode.hasInfiniteItems(); - } - - @Override - public void appendModIdToTooltips(Tooltip components, String modId) { - final String modName = ClientHelper.getInstance().getModFromModId(modId); - Iterator iterator = components.entries().iterator(); - while (iterator.hasNext()) { - Tooltip.Entry entry = iterator.next(); - if (entry.isText() && FormattingUtils.stripFormatting(entry.getAsText().getString()).equalsIgnoreCase(modName)) { - iterator.remove(); - } - } - components.add(ClientHelper.getInstance().getFormattedModFromModId(modId)); - } - - @Override - public String getModFromModId(String modId) { - if (modId == null) - return ""; - String any = modNameCache.getOrDefault(modId, null); - if (any != null) - return any; - if (Platform.isModLoaded(modId)) { - String modName = Platform.getMod(modId).getName(); - modNameCache.put(modId, modName); - return modName; - } - return modId; - } - - @Override - public boolean isCheating() { - return ConfigObject.getInstance().isCheating(); - } - - @Override - public void setCheating(boolean cheating) { - ConfigObject.getInstance().setCheating(cheating); - ConfigManager.getInstance().saveConfig(); - } - - @Override - public void sendDeletePacket() { - if (Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen inventoryScreen) { - Minecraft.getInstance().player.containerMenu.setCarried(ItemStack.EMPTY); - inventoryScreen.isQuickCrafting = false; - return; - } - NetworkManager.sendToServer(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET, new FriendlyByteBuf(Unpooled.buffer())); - if (Minecraft.getInstance().screen instanceof AbstractContainerScreen containerScreen) { - containerScreen.isQuickCrafting = false; - } - } - - @Override - public boolean tryCheatingEntry(EntryStack e) { - if (e.getType() != VanillaEntryTypes.ITEM) - return false; - EntryStack entry = (EntryStack) e; - if (Minecraft.getInstance().player == null) return false; - if (Minecraft.getInstance().player.getInventory() == null) return false; - ItemStack cheatedStack = entry.getValue().copy(); - if (ConfigObject.getInstance().isGrabbingItems() && Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen) { - AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; - EntryStack stack = entry.copy(); - if (!menu.getCarried().isEmpty() && EntryStacks.equalsExact(EntryStacks.of(menu.getCarried()), stack)) { - stack.getValue().setCount(Mth.clamp(stack.getValue().getCount() + menu.getCarried().getCount(), 1, stack.getValue().getMaxStackSize())); - } else if (!menu.getCarried().isEmpty()) { - return false; - } - menu.setCarried(stack.getValue().copy()); - return true; - } else if (ClientHelperImpl.getInstance().canUsePackets()) { - AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; - EntryStack stack = entry.copy(); - if (!menu.getCarried().isEmpty() && !EntryStacks.equalsExact(EntryStacks.of(menu.getCarried()), stack)) { - return false; - } - try { - NetworkManager.sendToServer(ConfigObject.getInstance().isGrabbingItems() ? RoughlyEnoughItemsNetwork.CREATE_ITEMS_GRAB_PACKET : RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET, new FriendlyByteBuf(Unpooled.buffer()).writeItem(cheatedStack)); - return true; - } catch (Exception exception) { - return false; - } - } else { - ResourceLocation identifier = entry.getIdentifier(); - if (identifier == null) { - return false; - } - String tagMessage = cheatedStack.copy().getTag() != null && !cheatedStack.copy().getTag().isEmpty() ? cheatedStack.copy().getTag().getAsString() : ""; - String og = cheatedStack.getCount() == 1 ? ConfigObject.getInstance().getGiveCommand().replaceAll(" \\{count}", "") : ConfigObject.getInstance().getGiveCommand(); - String madeUpCommand = og.replaceAll("\\{player_name}", Minecraft.getInstance().player.getScoreboardName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", tagMessage).replaceAll("\\{count}", String.valueOf(cheatedStack.getCount())); - if (madeUpCommand.length() > 256) { - madeUpCommand = og.replaceAll("\\{player_name}", Minecraft.getInstance().player.getScoreboardName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", "").replaceAll("\\{count}", String.valueOf(cheatedStack.getCount())); - Minecraft.getInstance().player.displayClientMessage(new TranslatableComponent("text.rei.too_long_nbt"), false); - } - Minecraft.getInstance().player.chat(madeUpCommand); - return true; - } - } - - @Override - public boolean tryCheatingEntryTo(EntryStack e, int hotbarSlotId) { - if (e.getType() != VanillaEntryTypes.ITEM) - return false; - EntryStack entry = (EntryStack) e; - if (Minecraft.getInstance().player == null) return false; - if (Minecraft.getInstance().player.getInventory() == null) return false; - if (Minecraft.getInstance().gameMode != null && Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen) { - AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; - EntryStack stack = entry.copy(); - if (menu.getCarried().isEmpty()) { - Minecraft.getInstance().player.getInventory().setItem(hotbarSlotId, stack.getValue().copy()); - Minecraft.getInstance().player.inventoryMenu.broadcastChanges(); - return true; - } - } - if (ClientHelperImpl.getInstance().canUseHotbarPackets()) { - AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; - EntryStack stack = entry.copy(); - if (!menu.getCarried().isEmpty()) { - return false; - } - try { - NetworkManager.sendToServer(RoughlyEnoughItemsNetwork.CREATE_ITEMS_HOTBAR_PACKET, new FriendlyByteBuf(Unpooled.buffer()).writeItem(stack.getValue().copy()).writeVarInt(hotbarSlotId)); - return true; - } catch (Exception exception) { - return false; - } - } else return false; - } - @Override public boolean openView(ViewSearchBuilder builder) { return openView(builder.buildMapInternal(), builder.getPreferredOpenedCategory(), builder.getUsagesFor(), builder.getRecipesFor()); @@ -266,11 +84,6 @@ public class ClientHelperImpl implements ClientHelper { ConfigObject.getInstance().setRecipeScreenType(DisplayScreenType.ORIGINAL); ConfigManager.getInstance().saveConfig(); return openView(map, category, usagesFor, recipesFor); -// screen = new UncertainDisplayViewingScreen(REIRuntime.getInstance().getPreviousScreen(), DisplayScreenType.UNSET, true, original -> { -// ConfigObject.getInstance().setRecipeScreenType(original ? DisplayScreenType.ORIGINAL : DisplayScreenType.COMPOSITE); -// ConfigManager.getInstance().saveConfig(); -// openView(builder); -// }); } else { screen = new DefaultDisplayViewingScreen(map, category); } @@ -288,9 +101,4 @@ public class ClientHelperImpl implements ClientHelper { Minecraft.getInstance().setScreen(screen); return true; } - - @Override - public boolean canUseMovePackets() { - return NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.MOVE_ITEMS_PACKET); - } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientModNameHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientModNameHelperImpl.java new file mode 100644 index 000000000..8fd9a9417 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientModNameHelperImpl.java @@ -0,0 +1,69 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client; + +import dev.architectury.platform.Platform; +import me.shedaniel.rei.api.client.ClientHelper; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.common.util.FormattingUtils; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public interface ClientModNameHelperImpl extends ClientHelper { + Map MOD_NAME_CACHE = new HashMap<>() {{ + put("minecraft", "Minecraft"); + put("c", "Common"); + put("global", "Global"); + }}; + + @Override + default void appendModIdToTooltips(Tooltip components, String modId) { + final String modName = ClientHelper.getInstance().getModFromModId(modId); + Iterator iterator = components.entries().iterator(); + while (iterator.hasNext()) { + Tooltip.Entry entry = iterator.next(); + if (entry.isText() && FormattingUtils.stripFormatting(entry.getAsText().getString()).equalsIgnoreCase(modName)) { + iterator.remove(); + } + } + components.add(ClientHelper.getInstance().getFormattedModFromModId(modId)); + } + + @Override + default String getModFromModId(String modId) { + if (modId == null) + return ""; + String any = MOD_NAME_CACHE.getOrDefault(modId, null); + if (any != null) + return any; + if (Platform.isModLoaded(modId)) { + String modName = Platform.getMod(modId).getName(); + MOD_NAME_CACHE.put(modId, modName); + return modName; + } + return modId; + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientNetworkHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientNetworkHelperImpl.java new file mode 100644 index 000000000..18efbbf22 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientNetworkHelperImpl.java @@ -0,0 +1,170 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client; + +import dev.architectury.networking.NetworkManager; +import io.netty.buffer.Unpooled; +import me.shedaniel.rei.RoughlyEnoughItemsNetwork; +import me.shedaniel.rei.api.client.ClientHelper; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.util.EntryStacks; +import me.shedaniel.rei.impl.common.networking.NetworkModule; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; + +public abstract class ClientNetworkHelperImpl implements ClientHelper { + public boolean hasPermissionToUsePackets() { + try { + Minecraft.getInstance().getConnection().getSuggestionsProvider().hasPermission(0); + return hasOperatorPermission() && canUsePackets(); + } catch (NullPointerException e) { + return true; + } + } + + public boolean hasOperatorPermission() { + try { + return Minecraft.getInstance().getConnection().getSuggestionsProvider().hasPermission(1); + } catch (NullPointerException e) { + return true; + } + } + + public boolean canUsePackets() { + return NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET) && NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_GRAB_PACKET) && NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET); + } + + public boolean canUseHotbarPackets() { + return NetworkManager.canServerReceive(RoughlyEnoughItemsNetwork.CREATE_ITEMS_HOTBAR_PACKET); + } + + public boolean canDeleteItems() { + return hasPermissionToUsePackets() || Minecraft.getInstance().gameMode.hasInfiniteItems(); + } + + @Override + public void sendDeletePacket() { + if (Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen inventoryScreen) { + Minecraft.getInstance().player.containerMenu.setCarried(ItemStack.EMPTY); + inventoryScreen.isQuickCrafting = false; + return; + } + NetworkManager.sendToServer(RoughlyEnoughItemsNetwork.DELETE_ITEMS_PACKET, new FriendlyByteBuf(Unpooled.buffer())); + if (Minecraft.getInstance().screen instanceof AbstractContainerScreen containerScreen) { + containerScreen.isQuickCrafting = false; + } + } + + @Override + public boolean tryCheatingEntry(EntryStack e) { + if (e.getType() != VanillaEntryTypes.ITEM) + return false; + EntryStack entry = (EntryStack) e; + if (Minecraft.getInstance().player == null) return false; + if (Minecraft.getInstance().player.getInventory() == null) return false; + ItemStack cheatedStack = entry.getValue().copy(); + if (ConfigObject.getInstance().isGrabbingItems() && Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen) { + AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; + EntryStack stack = entry.copy(); + if (!menu.getCarried().isEmpty() && EntryStacks.equalsExact(EntryStacks.of(menu.getCarried()), stack)) { + stack.getValue().setCount(Mth.clamp(stack.getValue().getCount() + menu.getCarried().getCount(), 1, stack.getValue().getMaxStackSize())); + } else if (!menu.getCarried().isEmpty()) { + return false; + } + menu.setCarried(stack.getValue().copy()); + return true; + } else if (ClientHelperImpl.getInstance().canUsePackets()) { + AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; + EntryStack stack = entry.copy(); + if (!menu.getCarried().isEmpty() && !EntryStacks.equalsExact(EntryStacks.of(menu.getCarried()), stack)) { + return false; + } + try { + NetworkManager.sendToServer(ConfigObject.getInstance().isGrabbingItems() ? RoughlyEnoughItemsNetwork.CREATE_ITEMS_GRAB_PACKET : RoughlyEnoughItemsNetwork.CREATE_ITEMS_PACKET, new FriendlyByteBuf(Unpooled.buffer()).writeItem(cheatedStack)); + return true; + } catch (Exception exception) { + return false; + } + } else { + ResourceLocation identifier = entry.getIdentifier(); + if (identifier == null) { + return false; + } + String tagMessage = cheatedStack.copy().getTag() != null && !cheatedStack.copy().getTag().isEmpty() ? cheatedStack.copy().getTag().getAsString() : ""; + String og = cheatedStack.getCount() == 1 ? ConfigObject.getInstance().getGiveCommand().replaceAll(" \\{count}", "") : ConfigObject.getInstance().getGiveCommand(); + String madeUpCommand = og.replaceAll("\\{player_name}", Minecraft.getInstance().player.getScoreboardName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", tagMessage).replaceAll("\\{count}", String.valueOf(cheatedStack.getCount())); + if (madeUpCommand.length() > 256) { + madeUpCommand = og.replaceAll("\\{player_name}", Minecraft.getInstance().player.getScoreboardName()).replaceAll("\\{item_name}", identifier.getPath()).replaceAll("\\{item_identifier}", identifier.toString()).replaceAll("\\{nbt}", "").replaceAll("\\{count}", String.valueOf(cheatedStack.getCount())); + Minecraft.getInstance().player.displayClientMessage(new TranslatableComponent("text.rei.too_long_nbt"), false); + } + Minecraft.getInstance().player.chat(madeUpCommand); + return true; + } + } + + @Override + public boolean tryCheatingEntryTo(EntryStack e, int hotbarSlotId) { + if (e.getType() != VanillaEntryTypes.ITEM) + return false; + EntryStack entry = (EntryStack) e; + if (Minecraft.getInstance().player == null) return false; + if (Minecraft.getInstance().player.getInventory() == null) return false; + if (Minecraft.getInstance().gameMode != null && Minecraft.getInstance().screen instanceof CreativeModeInventoryScreen) { + AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; + EntryStack stack = entry.copy(); + if (menu.getCarried().isEmpty()) { + Minecraft.getInstance().player.getInventory().setItem(hotbarSlotId, stack.getValue().copy()); + Minecraft.getInstance().player.inventoryMenu.broadcastChanges(); + return true; + } + } + if (ClientHelperImpl.getInstance().canUseHotbarPackets()) { + AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; + EntryStack stack = entry.copy(); + if (!menu.getCarried().isEmpty()) { + return false; + } + try { + NetworkManager.sendToServer(RoughlyEnoughItemsNetwork.CREATE_ITEMS_HOTBAR_PACKET, new FriendlyByteBuf(Unpooled.buffer()).writeItem(stack.getValue().copy()).writeVarInt(hotbarSlotId)); + return true; + } catch (Exception exception) { + return false; + } + } else return false; + } + + @Override + public boolean canUseMovePackets() { + return RoughlyEnoughItemsNetwork.canUse(NetworkModule.TRANSFER); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java index b890bc98a..5cff0c22d 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java @@ -43,11 +43,12 @@ import me.shedaniel.rei.api.client.overlay.ScreenOverlay; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.search.SearchProvider; import me.shedaniel.rei.api.common.registry.ReloadStage; -import me.shedaniel.rei.impl.common.Internals; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; +import me.shedaniel.rei.impl.client.gui.TooltipQueue; import me.shedaniel.rei.impl.client.gui.hints.HintProvider; import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField; +import me.shedaniel.rei.impl.common.Internals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -58,7 +59,10 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.lang.reflect.InvocationTargetException; -import java.util.*; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Optional; import static me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget.entrySize; @@ -91,14 +95,14 @@ public class REIRuntimeImpl implements REIRuntime { @Override public void queueTooltip(@Nullable Tooltip tooltip) { if (overlay != null && tooltip != null) { - overlay.addTooltip(tooltip); + TooltipQueue.addTooltip(tooltip); } } @Override public void clearTooltips() { if (overlay != null) { - overlay.clearTooltips(); + TooltipQueue.clearTooltips(); } } @@ -269,6 +273,7 @@ public class REIRuntimeImpl implements REIRuntime { }); ClientTickEvent.CLIENT_POST.register(minecraft -> { if (isOverlayVisible() && REIRuntime.getInstance().getOverlay().isPresent()) { + REIRuntime.getInstance().getSearchTextField().tick(); ScreenOverlayImpl.getInstance().tick(); } }); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index 2b3b59a9b..3f8fb9be9 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java @@ -31,7 +31,6 @@ import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.client.REIRuntime; -import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.config.DisplayPanelLocation; @@ -76,7 +75,6 @@ import static me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget. @ApiStatus.Internal public abstract class ScreenOverlayImpl extends ScreenOverlay { - private static final List TOOLTIPS = Lists.newArrayList(); private static EntryListWidget entryListWidget = null; private static FavoritesListWidget favoritesListWidget = null; private static OverlaySearchField searchField = null; @@ -84,7 +82,6 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { public boolean shouldReload = false; public boolean shouldReloadSearch = false; private Rectangle bounds; - private Window window; private Widget configButton; private CurrentDraggingStack draggingStack = new CurrentDraggingStack(); @Nullable @@ -123,7 +120,6 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { public void tick() { if (searchField != null) { - getSearchField().tick(); if (Minecraft.getInstance().player != null && !PluginManager.areAnyReloading() && Minecraft.getInstance().player.tickCount % 5 == 0) { CraftableFilter.INSTANCE.tick(); } @@ -140,6 +136,16 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { shouldReloadSearch = true; } + @Override + public boolean isOverlayReloadQueued() { + return shouldReload; + } + + @Override + public boolean isSearchReloadQueued() { + return shouldReloadSearch || shouldReload; + } + @Override public DraggingContext getDraggingContext() { return draggingStack; @@ -156,9 +162,12 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { this.shouldReload = false; this.shouldReloadSearch = false; this.children().clear(); - this.window = Minecraft.getInstance().getWindow(); this.bounds = calculateOverlayBounds(); + if (choosePageWidget != null) { + this.widgets.add(choosePageWidget); + } + if (ConfigObject.getInstance().isFavoritesEnabled()) { if (favoritesListWidget == null) { favoritesListWidget = new FavoritesListWidget(); @@ -202,10 +211,12 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { } private Rectangle getBottomSideSearchFieldArea(int widthRemoved) { + Window window = Minecraft.getInstance().getWindow(); return new Rectangle(bounds.x + 2, window.getGuiScaledHeight() - 22, bounds.width - 6 - widthRemoved, 18); } private Rectangle getCenterSearchFieldArea(int widthRemoved) { + Window window = Minecraft.getInstance().getWindow(); Rectangle screenBounds = ScreenRegistry.getInstance().getScreenBounds(minecraft.screen); return new Rectangle(screenBounds.x, window.getGuiScaledHeight() - 22, screenBounds.width - widthRemoved, 18); } @@ -228,7 +239,7 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { } } } - if (shouldReloadSearch || (ConfigManager.getInstance().isCraftableOnlyEnabled() && CraftableFilter.INSTANCE.wasDirty())) { + if (shouldReloadSearch) { shouldReloadSearch = false; getEntryListWidget().updateSearch(getSearchField().getText(), true); } @@ -292,17 +303,21 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { matrices.popPose(); if (choosePageWidget != null) { setBlitOffset(500); + Window window = Minecraft.getInstance().getWindow(); this.fillGradient(matrices, 0, 0, window.getGuiScaledWidth(), window.getGuiScaledHeight(), -1072689136, -804253680); setBlitOffset(0); choosePageWidget.render(matrices, mouseX, mouseY, delta); } } if (choosePageWidget == null) { - TOOLTIPS.stream().filter(Objects::nonNull) - .reduce((tooltip, tooltip2) -> tooltip2) - .ifPresent(tooltip -> renderTooltip(matrices, tooltip)); + Tooltip tooltip = TooltipQueue.get(); + + if (tooltip != null) { + renderTooltip(matrices, tooltip); + } } - TOOLTIPS.clear(); + + REIRuntime.getInstance().clearTooltips(); if (REIRuntime.getInstance().isOverlayVisible()) { menuAccess.afterRender(); } @@ -315,15 +330,6 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { protected abstract void renderTooltipInner(Screen screen, PoseStack matrices, Tooltip tooltip, int mouseX, int mouseY); - public void addTooltip(@Nullable Tooltip tooltip) { - if (tooltip != null) - TOOLTIPS.add(tooltip); - } - - public void clearTooltips() { - TOOLTIPS.clear(); - } - public void renderWidgets(PoseStack matrices, int mouseX, int mouseY, float delta) { if (!REIRuntime.getInstance().isOverlayVisible()) return; @@ -566,7 +572,7 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { if (searchField == null) { searchField = new OverlaySearchField(0, 0, 0, 0); } - + return searchField; } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/TooltipQueue.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/TooltipQueue.java new file mode 100644 index 000000000..204798203 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/TooltipQueue.java @@ -0,0 +1,51 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui; + +import com.google.common.collect.Lists; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Objects; + +public class TooltipQueue { + private static final List TOOLTIPS = Lists.newArrayList(); + + public static void addTooltip(@Nullable Tooltip tooltip) { + if (tooltip != null) + TOOLTIPS.add(tooltip); + } + + public static void clearTooltips() { + TOOLTIPS.clear(); + } + + @Nullable + public static Tooltip get() { + return TOOLTIPS.stream().filter(Objects::nonNull) + .reduce((tooltip, tooltip2) -> tooltip2) + .orElse(null); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/menu/MenuAccessImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/menu/MenuAccessImpl.java index aae20757f..c51330f94 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/menu/MenuAccessImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/menu/MenuAccessImpl.java @@ -27,6 +27,7 @@ import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.math.Point; import me.shedaniel.math.impl.PointHelper; +import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.Widgets; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; @@ -108,7 +109,7 @@ public class MenuAccessImpl implements MenuAccess { close(); } else { if (menu.wrappedMenu.containsMouse(mouseX, mouseY)) { - ScreenOverlayImpl.getInstance().clearTooltips(); + REIRuntime.getInstance().clearTooltips(); } menu.wrappedMenu.render(matrices, mouseX, mouseY, delta); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java index 894c8825f..1815822b4 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java @@ -54,18 +54,12 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { private Button btnDone; public DefaultDisplayChoosePageWidget(IntConsumer callback, int currentPage, int maxPage) { - super(getPointFromConfig()); this.callback = callback; this.currentPage = currentPage; this.maxPage = maxPage; initWidgets(getMidPoint()); } - private static Point getPointFromConfig() { - Window window = Minecraft.getInstance().getWindow(); - return new Point(window.getGuiScaledWidth() * .5, window.getGuiScaledHeight() * .5); - } - @Override public Rectangle getBounds() { return bounds; @@ -127,16 +121,13 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { this.widgets.add((textFieldWidget = Widgets.createTextField(new Rectangle(bounds.x + 7, bounds.y + 16, bounds.width - width - 12, 18))).asWidget()); textFieldWidget.setMaxLength(10000); textFieldWidget.setTextTransformer(s -> { - StringBuilder stringBuilder_1 = new StringBuilder(); - char[] var2 = s.toCharArray(); - int var3 = var2.length; - - for (char char_1 : var2) { - if (Character.isDigit(char_1)) - stringBuilder_1.append(char_1); + StringBuilder builder = new StringBuilder(); + for (char ch : s.toCharArray()) { + if (Character.isDigit(ch)) + builder.append(ch); } - return stringBuilder_1.toString(); + return builder.toString(); }); textFieldWidget.setText(String.valueOf(currentPage + 1)); widgets.add(btnDone = Widgets.createButton(new Rectangle(bounds.x + bounds.width - 45, bounds.y + bounds.height + 3, 40, 20), new TranslatableComponent("gui.done")) @@ -158,32 +149,32 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { } @Override - public void render(PoseStack matrices, int i, int i1, float v) { + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { matrices.pushPose(); matrices.translate(0, 0, 800); for (Widget widget : widgets) { - widget.render(matrices, i, i1, v); + widget.render(matrices, mouseX, mouseY, delta); } matrices.popPose(); } @Override - public boolean charTyped(char char_1, int int_1) { + public boolean charTyped(char character, int modifiers) { for (Widget widget : widgets) - if (widget.charTyped(char_1, int_1)) + if (widget.charTyped(character, modifiers)) return true; return false; } @Override - public boolean keyPressed(int int_1, int int_2, int int_3) { - if (int_1 == 335 || int_1 == 257) { + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == 335 || keyCode == 257) { callback.accept(Mth.clamp(getIntFromString(textFieldWidget.getText()).orElse(0) - 1, 0, maxPage - 1)); ScreenOverlayImpl.getInstance().choosePageWidget = null; return true; } for (Widget widget : widgets) - if (widget.keyPressed(int_1, int_2, int_3)) + if (widget.keyPressed(keyCode, scanCode, modifiers)) return true; return false; } @@ -199,5 +190,4 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { @Override public void onMouseReleaseMidPoint(Point midPoint) { } - } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayedEntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayedEntryWidget.java index 3e62d7f02..de04449c7 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayedEntryWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayedEntryWidget.java @@ -36,12 +36,12 @@ import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; import me.shedaniel.rei.api.client.overlay.ScreenOverlay; import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; +import me.shedaniel.rei.api.client.view.Views; import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.util.EntryStacks; -import me.shedaniel.rei.impl.client.view.ViewsImpl; import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.client.KeyMapping; @@ -217,7 +217,7 @@ public abstract class DisplayedEntryWidget extends EntryWidget { try { for (List displays : DisplayRegistry.getInstance().getAll().values()) { for (Display display : displays) { - if (ViewsImpl.isRecipesFor(getEntries(), display)) { + if (Views.getInstance().isRecipesFor(getEntries(), display)) { AutoCraftingEvaluator.AutoCraftingResult result = AutoCraftingEvaluator.evaluateAutoCrafting(false, false, display, null); if (result.successful) { this.display = display; @@ -242,7 +242,7 @@ public abstract class DisplayedEntryWidget extends EntryWidget { } if (display != null) { - if (ViewsImpl.isRecipesFor(getEntries(), display)) { + if (Views.getInstance().isRecipesFor(getEntries(), display)) { AutoCraftingEvaluator.AutoCraftingResult result = AutoCraftingEvaluator.evaluateAutoCrafting(false, false, display, null); if (result.successful) { return result.successfulHandler; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DraggableWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DraggableWidget.java index 4d41efd35..0eafebd75 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DraggableWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DraggableWidget.java @@ -34,7 +34,6 @@ import org.jetbrains.annotations.ApiStatus; @ApiStatus.Internal public abstract class DraggableWidget extends WidgetWithBounds { - public boolean dragged = false; private Point midPoint, startPoint; private int relateX, relateY; @@ -60,9 +59,9 @@ public abstract class DraggableWidget extends WidgetWithBounds { } @Override - public boolean mouseDragged(double double_1, double double_2, int int_1, double double_3, double double_4) { + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { Point mouse = PointHelper.ofMouse(); - if (int_1 == 0) { + if (button == 0) { if (!dragged) { if (getGrabBounds().contains(mouse)) { startPoint = new Point(midPoint.x, midPoint.y); @@ -78,7 +77,7 @@ public abstract class DraggableWidget extends WidgetWithBounds { return true; } for (GuiEventListener listener : children()) - if (listener.mouseDragged(double_1, double_2, int_1, double_3, double_4)) + if (listener.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) return true; return false; } @@ -86,15 +85,15 @@ public abstract class DraggableWidget extends WidgetWithBounds { public abstract Point processMidPoint(Point midPoint, Point mouse, Point startPoint, Window window, int relateX, int relateY); @Override - public boolean mouseReleased(double double_1, double double_2, int int_1) { - if (int_1 == 0) + public boolean mouseReleased(double mouseX, double mouseY, int button) { + if (button == 0) if (dragged) { dragged = false; onMouseReleaseMidPoint(getMidPoint()); return true; } for (GuiEventListener listener : children()) - if (listener.mouseReleased(double_1, double_2, int_1)) + if (listener.mouseReleased(mouseX, mouseY, button)) return true; return false; } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java index d38372e4a..1869936d0 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java @@ -33,10 +33,7 @@ import java.util.List; import java.util.Map; public abstract class CollapsingEntryListWidget extends EntryListWidget { - private List | CollapsedStack*/ Object> collapsedStacks = new ArrayList<>(); private Int2ObjectMap collapsedStackIndexed = new Int2ObjectOpenHashMap<>(); - protected int updatedCount; - protected int lastUpdatedCount; public abstract List | List>*/ Object> getStacks(); @@ -46,17 +43,6 @@ public abstract class CollapsingEntryListWidget extends EntryListWidget { return collapsedStackIndexed; } - @Override - public boolean isEmpty() { - return collapsedStacks.isEmpty(); - } - - @Override - protected void setCollapsedStacks(List | CollapsedStack*/ Object> stacks) { - this.collapsedStacks = stacks; - updateStacks(); - } - @Override public void updateEntriesPosition() { if (updatedCount != lastUpdatedCount) { @@ -69,6 +55,8 @@ public abstract class CollapsingEntryListWidget extends EntryListWidget { private void updateStacks() { lastUpdatedCount = updatedCount; + List | CollapsedStack*/ Object> collapsedStacks = EntryListEntries.INSTANCE.getCollapsedStacks(); + List | List>*/ Object> stacks = new ArrayList<>((int) (collapsedStacks.size() * 1.5)); Map | List>*/ Object, CollapsedStack> collapsedStackMap = new Reference2ObjectOpenHashMap<>(); Int2ObjectMap collapsedStackIndexed = new Int2ObjectOpenHashMap<>(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListEntries.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListEntries.java new file mode 100644 index 000000000..095c0fbb9 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListEntries.java @@ -0,0 +1,48 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget.entrylist; + +import java.util.ArrayList; +import java.util.List; + +public class EntryListEntries { + public static final EntryListEntries INSTANCE = new EntryListEntries(); + private List | CollapsedStack*/ Object> collapsedStacks = new ArrayList<>(); + + public void updateSearch(String searchTerm, boolean ignoreLastSearch, EntriesCallback callback) { + EntryListSearchManager.INSTANCE.update(searchTerm, ignoreLastSearch, stacks -> { + collapsedStacks = stacks; + callback.updateStacks(); + }); + } + + public List | CollapsedStack*/ Object> getCollapsedStacks() { + return collapsedStacks; + } + + @FunctionalInterface + public interface EntriesCallback { + void updateStacks(); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java index 71f837952..075dd910f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java @@ -71,6 +71,8 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla private static final int SIZE = 18; protected final RegionRenderingDebugger debugger = new RegionRenderingDebugger(); protected Rectangle bounds, innerBounds; + protected int updatedCount; + protected int lastUpdatedCount; public final NumberAnimator scaleIndicator = ValueAnimator.ofDouble(0.0D) .withConvention(() -> 0.0D, 8000); @@ -266,13 +268,9 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla protected abstract void updateEntries(int entrySize, boolean zoomed); - public abstract boolean isEmpty(); - - protected abstract void setCollapsedStacks(List | CollapsedStack*/ Object> stacks); - public void updateSearch(String searchTerm, boolean ignoreLastSearch) { - EntryListSearchManager.INSTANCE.update(searchTerm, ignoreLastSearch, stacks -> { - setCollapsedStacks(stacks); + EntryListEntries.INSTANCE.updateSearch(searchTerm, ignoreLastSearch, () -> { + updatedCount++; updateEntriesPosition(); }); debugger.debugTime = ConfigObject.getInstance().doDebugRenderTimeRequired(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/DelegateTextField.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/DelegateTextField.java index 0697fe71f..d8b77d6f6 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/DelegateTextField.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/DelegateTextField.java @@ -27,6 +27,9 @@ import it.unimi.dsi.fastutil.booleans.BooleanConsumer; import me.shedaniel.rei.api.client.gui.widgets.TextField; import org.jetbrains.annotations.Nullable; +import java.util.function.Consumer; +import java.util.function.Function; + public interface DelegateTextField extends TextField { TextField delegateTextField(); @@ -61,6 +64,16 @@ public interface DelegateTextField extends TextField { delegateTextField().setSuggestionRenderer(renderer); } + @Override + default void setTextTransformer(Function textTransformer) { + delegateTextField().setTextTransformer(textTransformer); + } + + @Override + default void setResponder(Consumer responder) { + delegateTextField().setResponder(responder); + } + @Override default String getText() { return delegateTextField().getText(); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java index c0a128987..919108b6f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java @@ -43,6 +43,7 @@ import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.hints.HintProvider; +import me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListEntries; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchFieldSyntaxHighlighter.HighlightInfo; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchFieldSyntaxHighlighter.PartHighlightInfo; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchFieldSyntaxHighlighter.QuoteHighlightInfo; @@ -113,7 +114,7 @@ public class OverlaySearchField extends DelegateWidget implements DelegateTextFi return TextTransformations.forwardWithTransformation(text, (s, charIndex, c) -> { HighlightInfo arg = highlighter.highlighted[charIndex + index]; Style style = Style.EMPTY; - if (isMain && ScreenOverlayImpl.getEntryListWidget().isEmpty() && !textField.getText().isEmpty()) { + if (isMain && EntryListEntries.INSTANCE.isEmpty() && !textField.getText().isEmpty()) { style = ERROR_STYLE; } if (arg instanceof PartHighlightInfo part) { @@ -235,7 +236,7 @@ public class OverlaySearchField extends DelegateWidget implements DelegateTextFi if (new Rectangle(x + 3, y + 3 + font.lineHeight * i, lineWidth, font.lineHeight).contains(mouseX, mouseY)) { Tooltip tooltip = pair.getFirst().provideTooltip(new Point(mouseX, mouseY)); if (tooltip != null) { - ScreenOverlayImpl.getInstance().clearTooltips(); + REIRuntime.getInstance().clearTooltips(); ScreenOverlayImpl.getInstance().renderTooltip(poses, tooltip); } } @@ -279,7 +280,7 @@ public class OverlaySearchField extends DelegateWidget implements DelegateTextFi isHighlighting = isHighlighting && ConfigObject.getInstance().isInventoryHighlightingAllowed(); if (isMain && isHighlighting) { return 0xfff2ff0c; - } else if (isMain && ScreenOverlayImpl.getEntryListWidget().isEmpty() && !textField.getText().isEmpty()) { + } else if (isMain && EntryListEntries.INSTANCE.isEmpty() && !textField.getText().isEmpty()) { return 0xffff5555; } else { return TextField.BorderColorProvider.DEFAULT.getBorderColor(textField); @@ -375,7 +376,7 @@ public class OverlaySearchField extends DelegateWidget i