aboutsummaryrefslogtreecommitdiff
path: root/neoforge/src/main/java
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2023-11-19 03:04:21 +0800
committershedaniel <daniel@shedaniel.me>2023-11-19 03:04:21 +0800
commitb10f1308f5359ce73a9f4b899cf9516c4ad5388f (patch)
tree5b5700934ae88681918a620edc39754dbf82d496 /neoforge/src/main/java
parent11b87fdd96f5542d646aa8f5136095917f207564 (diff)
downloadRoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.tar.gz
RoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.tar.bz2
RoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.zip
Support NeoForge
Diffstat (limited to 'neoforge/src/main/java')
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java119
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java237
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/PrimitivePlatformAdapterImpl.java69
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java38
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginClient.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginCommon.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginDedicatedServer.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoader.java38
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderClient.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderCommon.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderDedicatedServer.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java45
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/CodepointMapWrapper.java92
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/forge/CreativeModeTabCollectorImpl.java67
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/forge/ErrorDisplayerImpl.java55
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/gui/credits/forge/CreditsScreenImpl.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/gui/forge/ScreenOverlayImplForge.java76
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java51
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinEffectRenderingInventoryScreen.java66
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinFontSet.java62
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinInputConstants.java52
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinInputConstantsKey.java57
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinPacketEncoder.java57
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java47
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinTagLoader.java134
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinTagManager.java47
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/client/forge/DefaultClientPluginImpl.java88
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/common/displays/crafting/forge/DefaultCraftingDisplayImpl.java40
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/common/forge/DefaultPluginImpl.java61
29 files changed, 1836 insertions, 0 deletions
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java b/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java
new file mode 100644
index 000000000..9a13e0cdc
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java
@@ -0,0 +1,119 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.forge;
+
+import com.google.common.collect.Lists;
+import me.shedaniel.rei.impl.init.PrimitivePlatformAdapter;
+import net.neoforged.api.distmarker.Dist;
+import net.neoforged.fml.ModList;
+import net.neoforged.fml.loading.FMLEnvironment;
+import net.neoforged.fml.loading.moddiscovery.ModAnnotation;
+import net.neoforged.neoforgespi.language.IModInfo;
+import net.neoforged.neoforgespi.language.ModFileScanData;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.util.TriConsumer;
+import org.objectweb.asm.Type;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+public class AnnotationUtils {
+ public static final Logger LOGGER = LogManager.getFormatterLogger("REI");
+
+ public static <A, T> void scanAnnotation(Class<A> clazz, Predicate<Class<T>> predicate, TriConsumer<List<String>, Supplier<T>, Class<T>> consumer) {
+ scanAnnotation(Type.getType(clazz), predicate, consumer);
+ }
+
+ public static <T> void scanAnnotation(Type annotationType, Predicate<Class<T>> predicate, TriConsumer<List<String>, Supplier<T>, Class<T>> consumer) {
+ List<Triple<List<String>, Supplier<T>, Class<T>>> instances = Lists.newArrayList();
+ for (ModFileScanData data : ModList.get().getAllScanData()) {
+ List<String> modIds = data.getIModInfoData().stream()
+ .flatMap(info -> info.getMods().stream())
+ .map(IModInfo::getModId)
+ .collect(Collectors.toList());
+ out:
+ for (ModFileScanData.AnnotationData annotation : data.getAnnotations()) {
+ if (annotationType.equals(annotation.annotationType())) {
+ Object value = annotation.annotationData().get("value");
+ boolean enabled;
+
+ if (value instanceof Dist[]) {
+ enabled = Arrays.asList((Dist[]) value).contains(FMLEnvironment.dist);
+ } else if (value instanceof ModAnnotation.EnumHolder) {
+ enabled = Objects.equals(((ModAnnotation.EnumHolder) value).getValue(), FMLEnvironment.dist.name());
+ } else if (value instanceof List) {
+ List<ModAnnotation.EnumHolder> holders = ((List<?>) value).stream().filter(o -> o instanceof ModAnnotation.EnumHolder)
+ .map(o -> (ModAnnotation.EnumHolder) o).toList();
+ if (!holders.isEmpty()) {
+ enabled = holders.stream()
+ .anyMatch(o -> Objects.equals(o.getValue(), FMLEnvironment.dist.name()));
+ } else {
+ enabled = true;
+ }
+ } else {
+ enabled = true;
+ }
+
+ if (!enabled) continue;
+
+ try {
+ Class<T> clazz = (Class<T>) Class.forName(annotation.memberName());
+ if (predicate.test(clazz)) {
+ instances.add(new ImmutableTriple<>(modIds, () -> {
+ try {
+ return clazz.getDeclaredConstructor().newInstance();
+ } catch (Throwable throwable) {
+ LOGGER.error("Failed to load plugin: " + annotation.memberName(), throwable);
+ return null;
+ }
+ }, clazz));
+ }
+ } catch (Throwable throwable) {
+ Throwable t = throwable;
+ while (t != null) {
+ if (t.getMessage() != null && t.getMessage().contains("invalid dist DEDICATED_SERVER") && !PrimitivePlatformAdapter.get().isClient()) {
+ LOGGER.warn("Plugin " + annotation.memberName() + " is attempting to load on the server, but is not compatible with the server. " +
+ "The mod should declare the environments it is compatible with in the @" + annotationType.getClassName() + " annotation.");
+ continue out;
+ }
+ t = t.getCause();
+ }
+ LOGGER.error("Failed to load plugin: " + annotation.memberName(), throwable);
+ }
+ }
+ }
+ }
+
+ for (Triple<List<String>, Supplier<T>, Class<T>> pair : instances) {
+ consumer.accept(pair.getLeft(), pair.getMiddle(), pair.getRight());
+ }
+ }
+}
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java b/neoforge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java
new file mode 100644
index 000000000..f96f0b409
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java
@@ -0,0 +1,237 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.forge;
+
+import com.google.common.base.Suppliers;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
+import me.shedaniel.rei.api.common.plugins.PluginManager;
+import me.shedaniel.rei.api.common.plugins.PluginView;
+import me.shedaniel.rei.api.common.plugins.REIPluginProvider;
+import me.shedaniel.rei.api.common.plugins.REIServerPlugin;
+import me.shedaniel.rei.impl.init.PluginDetector;
+import me.shedaniel.rei.plugin.client.forge.DefaultClientPluginImpl;
+import me.shedaniel.rei.plugin.client.runtime.DefaultClientRuntimePlugin;
+import me.shedaniel.rei.plugin.client.runtime.HideIngredientsFromTagsPlugin;
+import me.shedaniel.rei.plugin.common.forge.DefaultPluginImpl;
+import me.shedaniel.rei.plugin.common.runtime.DefaultRuntimePlugin;
+import net.neoforged.api.distmarker.Dist;
+import net.neoforged.api.distmarker.OnlyIn;
+import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
+import net.neoforged.fml.loading.FMLEnvironment;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.Supplier;
+
+public class PluginDetectorImpl implements PluginDetector {
+ private static <P extends me.shedaniel.rei.api.common.plugins.REIPlugin<?>> REIPluginProvider<P> wrapPlugin(List<String> modId, REIPluginProvider<P> plugin) {
+ return new REIPluginProvider<P>() {
+ final String nameSuffix = " [" + String.join(", ", modId) + "]";
+
+ @Override
+ public Collection<P> provide() {
+ return plugin.provide();
+ }
+
+ @Override
+ public Class<P> getPluginProviderClass() {
+ return plugin.getPluginProviderClass();
+ }
+
+ @Override
+ public String getPluginProviderName() {
+ return plugin.getPluginProviderName() + nameSuffix;
+ }
+ };
+ }
+
+ private static final Supplier<List<Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>>>> loaderProvided =
+ Suppliers.memoize(() -> getPluginsLoader(REIPluginLoader.class));
+ private static final Supplier<List<Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>>>> loaderProvidedCommon =
+ Suppliers.memoize(() -> getPluginsLoader(REIPluginLoaderCommon.class));
+ private static final Supplier<List<Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>>>> loaderProvidedDist;
+
+ static {
+ Supplier<List<Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>>>> dist;
+ if (FMLEnvironment.dist == Dist.CLIENT) {
+ dist = Suppliers.memoize(() -> getPluginsLoader(REIPluginLoaderClient.class));
+ } else if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) {
+ dist = Suppliers.memoize(() -> getPluginsLoader(REIPluginLoaderDedicatedServer.class));
+ } else throw new IllegalStateException("Unknown environment: " + FMLEnvironment.dist);
+ loaderProvidedDist = dist;
+ }
+
+ @NotNull
+ private static <T, P extends me.shedaniel.rei.api.common.plugins.REIPlugin<?>> List<Map.Entry<REIPluginProvider<P>, List<String>>> getPluginsLoader(Class<T> annotation) {
+ List<Map.Entry<REIPluginProvider<P>, List<String>>> list = new ArrayList<>();
+ AnnotationUtils.<T, REIPluginProvider<P>>scanAnnotation(annotation, REIPluginProvider.class::isAssignableFrom, (modId, provider, clazz) -> {
+ try {
+ list.add(new AbstractMap.SimpleEntry<>(provider.get(), modId));
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ }
+ });
+ return list;
+ }
+
+ @Override
+ public void detectServerPlugins() {
+ PluginView.getServerInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultPluginImpl()));
+ PluginView.getServerInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultRuntimePlugin()));
+
+ // Legacy Annotation
+ AnnotationUtils.<REIPlugin, REIServerPlugin>scanAnnotation(REIPlugin.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Common plugins
+ AnnotationUtils.<REIPluginCommon, REIServerPlugin>scanAnnotation(REIPluginCommon.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Dist plugins
+ if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) {
+ AnnotationUtils.<REIPluginDedicatedServer, REIServerPlugin>scanAnnotation(REIPluginDedicatedServer.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+ } else {
+ AnnotationUtils.<REIPluginClient, REIServerPlugin>scanAnnotation(REIPluginClient.class, REIServerPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+ }
+
+ // Loaders
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvided.get()) {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIServerPlugin.class)));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedCommon.get()) {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIServerPlugin.class)));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedDist.get()) {
+ ((PluginView<REIServerPlugin>) PluginManager.getServerInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIServerPlugin.class)));
+ }
+ }
+
+ @Override
+ public void detectCommonPlugins() {
+ // Legacy Annotation
+ AnnotationUtils.<REIPlugin, me.shedaniel.rei.api.common.plugins.REIPlugin<?>>scanAnnotation(REIPlugin.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Common plugins
+ AnnotationUtils.<REIPluginCommon, me.shedaniel.rei.api.common.plugins.REIPlugin<?>>scanAnnotation(REIPluginCommon.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Dist plugins
+ if (FMLEnvironment.dist == Dist.CLIENT) {
+ AnnotationUtils.<REIPluginClient, me.shedaniel.rei.api.common.plugins.REIPlugin>scanAnnotation(REIPluginClient.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+ } else if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) {
+ AnnotationUtils.<REIPluginDedicatedServer, me.shedaniel.rei.api.common.plugins.REIPlugin>scanAnnotation(REIPluginDedicatedServer.class, me.shedaniel.rei.api.common.plugins.REIPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+ }
+
+ // Loaders
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvided.get()) {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(entry.getValue(), entry.getKey()));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedCommon.get()) {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(entry.getValue(), entry.getKey()));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedDist.get()) {
+ ((PluginView) PluginManager.getInstance()).registerPlugin(wrapPlugin(entry.getValue(), entry.getKey()));
+ }
+ }
+
+ @OnlyIn(Dist.CLIENT)
+ @Override
+ public Supplier<Runnable> detectClientPlugins() {
+ return () -> () -> {
+ PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientPluginImpl()));
+ PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new DefaultClientRuntimePlugin()));
+ PluginView.getClientInstance().registerPlugin(wrapPlugin(Collections.singletonList("roughlyenoughitems"), new HideIngredientsFromTagsPlugin()));
+
+ // Legacy Annotation
+ AnnotationUtils.<REIPlugin, REIClientPlugin>scanAnnotation(REIPlugin.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Common plugins
+ AnnotationUtils.<REIPluginCommon, REIClientPlugin>scanAnnotation(REIPluginCommon.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Dist plugins
+ AnnotationUtils.<REIPluginClient, REIClientPlugin>scanAnnotation(REIPluginClient.class, REIClientPlugin.class::isAssignableFrom, (modId, plugin, clazz) -> {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(modId, plugin.get()));
+ });
+
+ // Loaders
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvided.get()) {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIClientPlugin.class)));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedCommon.get()) {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIClientPlugin.class)));
+ }
+ for (Map.Entry<REIPluginProvider<me.shedaniel.rei.api.common.plugins.REIPlugin<?>>, List<String>> entry : loaderProvidedDist.get()) {
+ ((PluginView<REIClientPlugin>) PluginManager.getClientInstance()).registerPlugin(wrapPlugin(entry.getValue(), wrapAndFilter(entry.getKey(), REIClientPlugin.class)));
+ }
+ };
+ }
+
+ private static <P extends me.shedaniel.rei.api.common.plugins.REIPlugin<P>> REIPluginProvider<P> wrapAndFilter(REIPluginProvider<?> provider, Class<P> clazz) {
+ return new REIPluginProvider<>() {
+ @Override
+ public Collection<P> provide() {
+ return new AbstractCollection<>() {
+ @Override
+ public Iterator<P> iterator() {
+ return Iterables.filter(provider.provide(), clazz).iterator();
+ }
+
+ @Override
+ public int size() {
+ return Iterators.size(iterator());
+ }
+ };
+ }
+
+ @Override
+ public Class<P> getPluginProviderClass() {
+ return clazz;
+ }
+
+ @Override
+ public String getPluginProviderName() {
+ return provider.getPluginProviderName();
+ }
+ };
+ }
+}
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/PrimitivePlatformAdapterImpl.java b/neoforge/src/main/java/me/shedaniel/rei/forge/PrimitivePlatformAdapterImpl.java
new file mode 100644
index 000000000..01491ecb5
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/PrimitivePlatformAdapterImpl.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, 2023 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.forge;
+
+import me.shedaniel.rei.RoughlyEnoughItemsState;
+import me.shedaniel.rei.impl.init.PrimitivePlatformAdapter;
+import net.neoforged.api.distmarker.Dist;
+import net.neoforged.fml.ModList;
+import net.neoforged.fml.loading.FMLEnvironment;
+import net.neoforged.fml.loading.FMLLoader;
+import org.apache.maven.artifact.versioning.ComparableVersion;
+
+public class PrimitivePlatformAdapterImpl implements PrimitivePlatformAdapter {
+ @Override
+ public boolean isClient() {
+ return FMLEnvironment.dist == Dist.CLIENT;
+ }
+
+ @Override
+ public void checkMods() {
+ if (ModList.get().isLoaded("moreoverlays")) {
+ RoughlyEnoughItemsState.error("REI is not compatible with MoreOverlays, and actually contains Builtin Inventory Highlighting, other features can be installed via different mods!");
+ }
+ }
+
+ @Override
+ public boolean isDev() {
+ return !FMLLoader.isProduction();
+ }
+
+ @Override
+ public String getMinecraftVersion() {
+ return ModList.get().getModContainerById("minecraft").get().getModInfo().getVersion().toString();
+ }
+
+ @Override
+ public int compareVersions(String version1, String version2) {
+ ComparableVersion v1 = new ComparableVersion(version1);
+ ComparableVersion v2 = new ComparableVersion(version2);
+
+ try {
+ return v1.compareTo(v2);
+ } catch (IllegalStateException e) {
+ new IllegalStateException("Failed to compare versions: " + version1 + " and " + version2, e).printStackTrace();
+ return 0;
+ }
+ }
+}
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java b/neoforge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java
new file mode 100644
index 000000000..c89748640
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java
@@ -0,0 +1,38 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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.forge;
+
+import net.neoforged.api.distmarker.Dist;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Deprecated(forRemoval = true)
+public @interface REIPlugin {
+ Dist[] value() default {Dist.CLIENT, Dist.DEDICATED_SERVER};
+}
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginClient.java b/neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginClient.java
new file mode 100644
index 000000000..0ae0ad4a4
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginClient.java
@@ -0,0 +1,34 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 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