aboutsummaryrefslogtreecommitdiff
path: root/runtime-engine
diff options
context:
space:
mode:
Diffstat (limited to 'runtime-engine')
-rw-r--r--runtime-engine/initialization/src/main/java/me/shedaniel/rei/impl/common/init/CoreInitialization.java2
-rw-r--r--runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/TransferNetworkModule.java (renamed from runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/REITransferNetwork.java)27
-rw-r--r--runtime-engine/menu-info/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java19
-rw-r--r--runtime-engine/menu-info/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkModule1
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/CheatItemStatusNetworkModule.java78
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/NotEnoughItemsNetworkModule.java111
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/NetworkingHelperImpl.java89
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGiveNetworkModule.java78
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGrabNetworkModule.java86
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemHotbarNetworkModule.java85
-rw-r--r--runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/DeleteItemNetworkModule.java76
-rw-r--r--runtime-engine/networking/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkModule6
-rw-r--r--runtime-engine/networking/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkingHelper1
13 files changed, 640 insertions, 19 deletions
diff --git a/runtime-engine/initialization/src/main/java/me/shedaniel/rei/impl/common/init/CoreInitialization.java b/runtime-engine/initialization/src/main/java/me/shedaniel/rei/impl/common/init/CoreInitialization.java
index 13a392e59..fc6304272 100644
--- a/runtime-engine/initialization/src/main/java/me/shedaniel/rei/impl/common/init/CoreInitialization.java
+++ b/runtime-engine/initialization/src/main/java/me/shedaniel/rei/impl/common/init/CoreInitialization.java
@@ -32,6 +32,7 @@ import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry;
import me.shedaniel.rei.api.common.entry.settings.EntrySettingsAdapterRegistry;
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry;
import me.shedaniel.rei.api.common.fluid.FluidSupportProvider;
+import me.shedaniel.rei.api.common.networking.NetworkingHelper;
import me.shedaniel.rei.api.common.plugins.PluginManager;
import me.shedaniel.rei.api.common.plugins.REIPlugin;
import me.shedaniel.rei.api.common.plugins.REIServerPlugin;
@@ -70,6 +71,7 @@ public class CoreInitialization {
manager.registerReloadable(DisplaySerializerRegistry.class);
manager.registerReloadable(FluidSupportProvider.class);
PluginManager<REIServerPlugin> serverManager = PluginManager.getServerInstance();
+ serverManager.registerReloadable(NetworkingHelper.class);
serverManager.registerReloadable(MenuInfoRegistry.class);
Internals.attachInstance((Runnable) () -> reloadPlugins(null, null), "reloadREI");
}
diff --git a/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/REITransferNetwork.java b/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/TransferNetworkModule.java
index 357bddfa9..fe7cde2f7 100644
--- a/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/REITransferNetwork.java
+++ b/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/impl/common/transfer/TransferNetworkModule.java
@@ -25,11 +25,14 @@ package me.shedaniel.rei.impl.common.transfer;
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.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
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;
@@ -39,22 +42,22 @@ import net.minecraft.world.inventory.RecipeBookMenu;
import java.util.Collections;
-public class REITransferNetwork implements NetworkModule {
- public static final ResourceLocation MOVE_ITEMS_PACKET = new ResourceLocation("roughlyenoughitems", "move_items");
+public class TransferNetworkModule implements NetworkModule<NetworkModule.TransferData> {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "move_items");
@Override
- public Object getKey() {
+ public NetworkModuleKey<NetworkModule.TransferData> getKey() {
return NetworkModule.TRANSFER;
}
@Override
- public boolean canUse() {
- return NetworkManager.canServerReceive(REITransferNetwork.MOVE_ITEMS_PACKET);
+ public boolean canUse(Object target) {
+ return NetworkManager.canServerReceive(TransferNetworkModule.ID);
}
@Override
public void onInitialize() {
- NetworkManager.registerReceiver(NetworkManager.c2s(), MOVE_ITEMS_PACKET, Collections.singletonList(new SplitPacketTransformer()), (packetByteBuf, context) -> {
+ NetworkManager.registerReceiver(NetworkManager.c2s(), ID, Collections.singletonList(new SplitPacketTransformer()), (packetByteBuf, context) -> {
ServerPlayer player = (ServerPlayer) context.getPlayer();
CategoryIdentifier<Display> category = CategoryIdentifier.of(packetByteBuf.readResourceLocation());
AbstractContainerMenu container = player.containerMenu;
@@ -88,4 +91,14 @@ public class REITransferNetwork implements NetworkModule {
}
});
}
+
+ @Override
+ public void send(Object target, TransferData data) {
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeResourceLocation(data.categoryIdentifier().getIdentifier());
+ buf.writeBoolean(data.stacked());
+
+ buf.writeNbt(data.displayTag());
+ NetworkManager.sendToServer(TransferNetworkModule.ID, buf);
+ }
}
diff --git a/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java b/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
index 096b36879..14f685906 100644
--- a/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
+++ b/runtime-engine/menu-info/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
@@ -23,17 +23,16 @@
package me.shedaniel.rei.plugin.autocrafting;
-import dev.architectury.networking.NetworkManager;
-import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntSet;
-import me.shedaniel.rei.api.client.ClientHelper;
import me.shedaniel.rei.api.client.registry.transfer.TransferHandler;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
import me.shedaniel.rei.api.common.entry.InputIngredient;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkingHelper;
import me.shedaniel.rei.api.common.transfer.RecipeFinder;
import me.shedaniel.rei.api.common.transfer.info.MenuInfo;
import me.shedaniel.rei.api.common.transfer.info.MenuInfoContext;
@@ -41,13 +40,11 @@ import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry;
import me.shedaniel.rei.api.common.transfer.info.MenuTransferException;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.api.common.util.EntryIngredients;
-import me.shedaniel.rei.impl.common.transfer.REITransferNetwork;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener;
-import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
@@ -96,7 +93,7 @@ public class DefaultCategoryHandler implements TransferHandler {
})
.tooltipMissing(CollectionUtils.map(missing, ingredient -> EntryIngredients.ofItemStacks(ingredient.get())));
}
- if (!ClientHelper.getInstance().canUseMovePackets()) {
+ if (!NetworkingHelper.getInstance().canUse(NetworkModule.TRANSFER)) {
return Result.createFailed(new TranslatableComponent("error.rei.not.on.server"));
}
if (!context.isActuallyCrafting()) {
@@ -107,12 +104,10 @@ public class DefaultCategoryHandler implements TransferHandler {
if (containerScreen instanceof RecipeUpdateListener listener) {
listener.getRecipeBookComponent().ghostRecipe.clear();
}
- FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
- buf.writeResourceLocation(display.getCategoryIdentifier().getIdentifier());
- buf.writeBoolean(context.isStackedCrafting());
-
- buf.writeNbt(menuInfo.save(menuInfoContext, display));
- NetworkManager.sendToServer(REITransferNetwork.MOVE_ITEMS_PACKET, buf);
+ NetworkingHelper.getInstance().sendToServer(NetworkModule.TRANSFER,
+ new NetworkModule.TransferData(display.getCategoryIdentifier(),
+ context.isStackedCrafting(),
+ menuInfo.save(menuInfoContext, display)));
return Result.createSuccessful();
}
diff --git a/runtime-engine/menu-info/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkModule b/runtime-engine/menu-info/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkModule
new file mode 100644
index 000000000..86049f550
--- /dev/null
+++ b/runtime-engine/menu-info/src/main/resources/META-INF/services/me.shedaniel.rei.api.common.networking.NetworkModule
@@ -0,0 +1 @@
+me.shedaniel.rei.impl.common.transfer.TransferNetworkModule \ No newline at end of file
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/CheatItemStatusNetworkModule.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/CheatItemStatusNetworkModule.java
new file mode 100644
index 000000000..45c687cdf
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/CheatItemStatusNetworkModule.java
@@ -0,0 +1,78 @@
+/*
+ * 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.networking.modules;
+
+import dev.architectury.networking.NetworkManager;
+import dev.architectury.networking.transformers.SplitPacketTransformer;
+import dev.architectury.utils.Env;
+import dev.architectury.utils.EnvExecutor;
+import io.netty.buffer.Unpooled;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
+import me.shedaniel.rei.api.common.util.EntryStacks;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.resources.language.I18n;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.item.ItemStack;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class CheatItemStatusNetworkModule implements NetworkModule<Map.Entry<ItemStack, String>> {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "ci_msg");
+
+ @Override
+ public NetworkModuleKey<Map.Entry<ItemStack, String>> getKey() {
+ return NetworkModule.CHEAT_STATUS_REPLY;
+ }
+
+ @Override
+ public boolean canUse(Object target) {
+ return NetworkManager.canPlayerReceive((ServerPlayer) target, CheatItemStatusNetworkModule.ID);
+ }
+
+ @Override
+ public void onInitialize() {
+ EnvExecutor.runInEnv(Env.CLIENT, () -> () -> {
+ NetworkManager.registerReceiver(NetworkManager.c2s(), ID, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {
+ ItemStack stack = buf.readItem();
+ String player = buf.readUtf(32767);
+ if (Minecraft.getInstance().player != null) {
+ Minecraft.getInstance().player.displayClientMessage(new TextComponent(I18n.get("text.rei.cheat_items").replaceAll("\\{item_name}", EntryStacks.of(stack.copy()).asFormattedText().getString()).replaceAll("\\{item_count}", stack.copy().getCount() + "").replaceAll("\\{player_name}", player)), false);
+ }
+ });
+ });
+ }
+
+ @Override
+ public void send(Object target, Map.Entry<ItemStack, String> data) {
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeItem(data.getKey().copy());
+ buf.writeUtf(data.getValue(), 32767);
+ NetworkManager.sendToServer(CheatItemStatusNetworkModule.ID, buf);
+ }
+}
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/NotEnoughItemsNetworkModule.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/NotEnoughItemsNetworkModule.java
new file mode 100644
index 000000000..c135eb921
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/client/networking/modules/NotEnoughItemsNetworkModule.java
@@ -0,0 +1,111 @@
+/*
+ * 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.networking.modules;
+
+import com.google.common.collect.Lists;
+import dev.architectury.networking.NetworkManager;
+import dev.architectury.networking.transformers.SplitPacketTransformer;
+import dev.architectury.utils.Env;
+import dev.architectury.utils.EnvExecutor;
+import io.netty.buffer.Unpooled;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.CraftingScreen;
+import net.minecraft.client.gui.screens.recipebook.GhostRecipe;
+import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.inventory.CraftingMenu;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.item.crafting.Ingredient;
+
+import java.util.Collections;
+import java.util.List;
+
+public class NotEnoughItemsNetworkModule implements NetworkModule<List<List<ItemStack>>> {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "og_not_enough");
+
+ @Override
+ public NetworkModuleKey<List<List<ItemStack>>> getKey() {
+ return NetworkModule.NOT_ENOUGH_ITEMS;
+ }
+
+ @Override
+ public boolean canUse(Object target) {
+ return NetworkManager.canPlayerReceive((ServerPlayer) target, NotEnoughItemsNetworkModule.ID);
+ }
+
+ @Override
+ public void onInitialize() {
+ EnvExecutor.runInEnv(Env.CLIENT, () -> () -> {
+ NetworkManager.registerReceiver(NetworkManager.c2s(), ID, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {
+ Screen currentScreen = Minecraft.getInstance().screen;
+ if (currentScreen instanceof CraftingScreen craftingScreen) {
+ RecipeBookComponent recipeBookGui = craftingScreen.getRecipeBookComponent();
+ GhostRecipe ghostSlots = recipeBookGui.ghostRecipe;
+ ghostSlots.clear();
+
+ List<List<ItemStack>> input = Lists.newArrayList();
+ int mapSize = buf.readInt();
+ for (int i = 0; i < mapSize; i++) {
+ List<ItemStack> list = Lists.newArrayList();
+ int count = buf.readInt();
+ for (int j = 0; j < count; j++) {
+ list.add(buf.readItem());
+ }
+ input.add(list);
+ }
+
+ ghostSlots.addIngredient(Ingredient.of(Items.STONE), 381203812, 12738291);
+ CraftingMenu container = craftingScreen.getMenu();
+ for (int i = 0; i < input.size(); i++) {
+ List<ItemStack> stacks = input.get(i);
+ if (!stacks.isEmpty()) {
+ Slot slot = container.getSlot(i + container.getResultSlotIndex() + 1);
+ ghostSlots.addIngredient(Ingredient.of(stacks.toArray(new ItemStack[0])), slot.x, slot.y);
+ }
+ }
+ }
+ });
+ });
+ }
+
+ @Override
+ public void send(Object target, List<List<ItemStack>> data) {
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeInt(data.size());
+ for (List<ItemStack> stacks : data) {
+ buf.writeInt(stacks.size());
+ for (ItemStack stack : stacks) {
+ buf.writeItem(stack);
+ }
+ }
+ NetworkManager.sendToServer(NotEnoughItemsNetworkModule.ID, buf);
+ }
+}
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/NetworkingHelperImpl.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/NetworkingHelperImpl.java
new file mode 100644
index 000000000..bb3e7a6fa
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/NetworkingHelperImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.common.networking;
+
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
+import me.shedaniel.rei.api.common.networking.NetworkingHelper;
+import me.shedaniel.rei.impl.common.Internals;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.Minecraft;
+import net.minecraft.server.level.ServerPlayer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class NetworkingHelperImpl implements NetworkingHelper {
+ private static final Map<NetworkModuleKey<?>, NetworkModule<?>> MODULES = new HashMap<>();
+
+ static {
+ for (NetworkModule<?> module : Internals.resolveServices(NetworkModule.class)) {
+ MODULES.put(module.getKey(), module);
+ }
+ }
+
+ @Override
+ public <T> boolean has(NetworkModuleKey<T> moduleKey) {
+ return MODULES.containsKey(moduleKey);
+ }
+
+ @Override
+ public <T> boolean canUse(NetworkModuleKey<T> moduleKey) {
+ return has(moduleKey) && MODULES.get(moduleKey).canUse(null);
+ }
+
+ @Override
+ public <T> boolean canPlayerUse(ServerPlayer player, NetworkModuleKey<T> moduleKey) {
+ return has(moduleKey) && MODULES.get(moduleKey).canUse(player);
+ }
+
+ @Override
+ public <T> void send(Object target, NetworkModuleKey<T> moduleKey, T data) {
+ if (canUse(moduleKey)) {
+ ((NetworkModule<T>) MODULES.get(moduleKey)).send(target, data);
+ }
+ }
+
+ @SuppressWarnings("Convert2Lambda")
+ @Override
+ @Environment(EnvType.CLIENT)
+ public Client client() {
+ return new Client() {
+ @Environment(EnvType.CLIENT)
+ @Override
+ public boolean hasOperatorPermission() {
+ try {
+ return Minecraft.getInstance().getConnection().getSuggestionsProvider().hasPermission(1);
+ } catch (NullPointerException e) {
+ return true;
+ }
+ }
+ };
+ }
+
+ @Override
+ public void startReload() {
+ }
+}
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGiveNetworkModule.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGiveNetworkModule.java
new file mode 100644
index 000000000..b503e7811
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGiveNetworkModule.java
@@ -0,0 +1,78 @@
+/*
+ * 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.common.networking.modules;
+
+import dev.architectury.networking.NetworkManager;
+import dev.architectury.networking.transformers.SplitPacketTransformer;
+import io.netty.buffer.Unpooled;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
+import me.shedaniel.rei.api.common.networking.NetworkingHelper;
+import net.minecraft.ChatFormatting;
+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.world.item.ItemStack;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+
+public class CheatItemGiveNetworkModule implements NetworkModule<ItemStack> {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "create_item");
+
+ @Override
+ public NetworkModuleKey<ItemStack> getKey() {
+ return NetworkModule.CHEAT_GIVE;
+ }
+
+ @Override
+ public boolean canUse(Object target) {
+ return NetworkManager.canServerReceive(CheatItemGiveNetworkModule.ID);
+ }
+
+ @Override
+ public void onInitialize() {
+ NetworkManager.registerReceiver(NetworkManager.c2s(), ID, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {
+ ServerPlayer player = (ServerPlayer) context.getPlayer();
+ if (player.getServer().getProfilePermissions(player.getGameProfile()) < player.getServer().getOperatorUserPermissionLevel()) {
+ player.displayClientMessage(new TranslatableComponent("text.rei.no_permission_cheat").withStyle(ChatFormatting.RED), false);
+ return;
+ }
+ ItemStack stack = buf.readItem();
+ if (player.getInventory().add(stack.copy())) {
+ NetworkingHelper.getInstance().sendToPlayer(player, NetworkModule.CHEAT_STATUS_REPLY, new AbstractMap.SimpleEntry<>(stack.copy(), player.getScoreboardName()));
+ } else {
+ player.displayClientMessage(new TranslatableComponent("text.rei.failed_cheat_items"), false);
+ }
+ });
+ }
+
+ @Override
+ public void send(Object target, ItemStack data) {
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeItem(data.copy());
+ NetworkManager.sendToServer(CheatItemGiveNetworkModule.ID, buf);
+ }
+}
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGrabNetworkModule.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGrabNetworkModule.java
new file mode 100644
index 000000000..0c76f1e14
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemGrabNetworkModule.java
@@ -0,0 +1,86 @@
+/*
+ * 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.common.networking.modules;
+
+import dev.architectury.networking.NetworkManager;
+import dev.architectury.networking.transformers.SplitPacketTransformer;
+import io.netty.buffer.Unpooled;
+import me.shedaniel.rei.api.common.networking.NetworkModule;
+import me.shedaniel.rei.api.common.networking.NetworkModuleKey;
+import me.shedaniel.rei.api.common.networking.NetworkingHelper;
+import net.minecraft.ChatFormatting;
+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.inventory.AbstractContainerMenu;
+import net.minecraft.world.item.ItemStack;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+
+public class CheatItemGrabNetworkModule implements NetworkModule<ItemStack> {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "create_item_grab");
+
+ @Override
+ public NetworkModuleKey<ItemStack> getKey() {
+ return NetworkModule.CHEAT_GRAB;
+ }
+
+ @Override
+ public boolean canUse(Object target) {
+ return NetworkManager.canServerReceive(CheatItemGrabNetworkModule.ID);
+ }
+
+ @Override
+ public void onInitialize() {
+ NetworkManager.registerReceiver(NetworkManager.c2s(), ID, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {
+ ServerPlayer player = (ServerPlayer) context.getPlayer();
+ if (player.getServer().getProfilePermissions(player.getGameProfile()) < player.getServer().getOperatorUserPermissionLevel()) {
+ player.displayClientMessage(new TranslatableComponent("text.rei.no_permission_cheat").withStyle(ChatFormatting.RED), false);
+ return;
+ }
+
+ AbstractContainerMenu menu = player.containerMenu;
+ ItemStack itemStack = buf.readItem();
+ ItemStack stack = itemStack.copy();
+ if (!menu.getCarried().isEmpty() && ItemStack.isSameIgnoreDurability(menu.getCarried(), stack) && ItemStack.tagMatches(menu.getCarried(), stack)) {
+ stack.setCount(Mth.clamp(stack.getCount() + menu.getCarried().getCount(), 1, stack.getMaxStackSize()));
+ } else if (!menu.getCarried().isEmpty()) {
+ return;
+ }
+ menu.setCarried(stack.copy());
+ menu.broadcastChanges();
+ NetworkingHelper.getInstance().sendToPlayer(player, NetworkModule.CHEAT_STATUS_REPLY, new AbstractMap.SimpleEntry<>(stack.copy(), player.getScoreboardName()));
+ });
+ }
+
+ @Override
+ public void send(Object target, ItemStack data) {
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeItem(data.copy());
+ NetworkManager.sendToServer(CheatItemGrabNetworkModule.ID, buf);
+ }
+}
diff --git a/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemHotbarNetworkModule.java b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemHotbarNetworkModule.java
new file mode 100644
index 000000000..01c406901
--- /dev/null
+++ b/runtime-engine/networking/src/main/java/me/shedaniel/rei/impl/common/networking/modules/CheatItemHotbarNetworkModule.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */