aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-08-06 10:37:38 +0800
committershedaniel <daniel@shedaniel.me>2022-08-26 10:54:44 +0900
commitd3bfd79800aacfde6617d5430ead5fdda0a506fe (patch)
treeb8420034448bd3193c7f541f47a6387a9772d99f /runtime
parent8c13c015031a0de865d2e767cd8e879754f803e2 (diff)
downloadRoughlyEnoughItems-d3bfd79800aacfde6617d5430ead5fdda0a506fe.tar.gz
RoughlyEnoughItems-d3bfd79800aacfde6617d5430ead5fdda0a506fe.tar.bz2
RoughlyEnoughItems-d3bfd79800aacfde6617d5430ead5fdda0a506fe.zip
More work okay
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java54
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java194
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/ClientModNameHelperImpl.java69
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/ClientNetworkHelperImpl.java170
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java13
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java46
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/TooltipQueue.java51
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/menu/MenuAccessImpl.java3
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java34
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayedEntryWidget.java6
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DraggableWidget.java13
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java16
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListEntries.java48
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java10
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/DelegateTextField.java13
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/search/OverlaySearchField.java9
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java21
17 files changed, 434 insertions, 336 deletions
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<Object, NetworkModule> 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<Display> category = CategoryIdentifier.of(packetByteBuf.readResourceLocation());
- AbstractContainerMenu container = player.containerMenu;
- InventoryMenu playerContainer = player.inventoryMenu;
- try {
- boolean shift = packetByteBuf.readBoolean();
- try {
- InputSlotCrafter<AbstractContainerMenu, Container, Display> 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<ItemStack> 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<Boolean> isAprilFools = Suppliers.memoize(() -> {
try {
LocalDateTime now = LocalDateTime.now();
@@ -77,11 +59,6 @@ public class ClientHelperImpl implements ClientHelper {
}
return false;
});
- private final Map<String, String> 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<Tooltip.Entry> 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<ItemStack> entry = (EntryStack<ItemStack>) 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<ItemStack> 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<ItemStack> 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<ItemStack> entry = (EntryStack<ItemStack>) 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<ItemStack> 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<ItemStack> 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<String, String> 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<Tooltip.Entry> 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<ItemStack> entry = (EntryStack<ItemStack>) 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<ItemStack> 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<ItemStack> 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<ItemStack> entry = (EntryStack<ItemStack>) 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<ItemStack> 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<ItemStack> 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.