From 4ed86bae9113703ce11b2dcd096e91b64ca3bd1a Mon Sep 17 00:00:00 2001
From: raoulvdberge <raoulvdberge@gmail.com>
Date: Sat, 30 Nov 2024 21:25:58 +0100
Subject: [PATCH] feat: recipe mod integration for jei and emi

Ghost dragging support.
---
 CHANGELOG.md                                  |  1 +
 build.gradle.kts                              | 10 +++++
 gradle.properties                             |  2 +
 .../mekanism/ModInitializer.java              |  8 ++++
 ...latformExternalStorageProviderFactory.java |  2 +-
 ...hemicalResourceModIngredientConverter.java | 45 +++++++++++++++++++
 ...iChemicalRecipeModIngredientConverter.java | 40 +++++++++++++++++
 .../mekanism/recipemod/package-info.java      |  7 +++
 8 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/EmiChemicalResourceModIngredientConverter.java
 create mode 100644 src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/JeiChemicalRecipeModIngredientConverter.java
 create mode 100644 src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/package-info.java

diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc48607..2b6ee17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,3 +15,4 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 - Chemical support in the Importer.
 - Chemical support in the Exporter.
 - Chemical support in the External Storage.
+- Ghost dragging support for chemicals in JEI and EMI.
diff --git a/build.gradle.kts b/build.gradle.kts
index 06a3c73..425b67c 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -22,6 +22,10 @@ repositories {
         name = "JEI"
         url = uri("https://maven.blamejared.com/")
     }
+    maven {
+        name = "EMI"
+        url = uri("https://maven.terraformersmc.com/")
+    }
 }
 
 refinedarchitect {
@@ -40,12 +44,16 @@ base {
 }
 
 val refinedstorageVersion: String by project
+val refinedstorageJeiIntegrationVersion: String by project
 val minecraftVersion: String by project
 val mekanismVersion: String by project
 val jeiVersion: String by project
+val emiVersion: String by project
 
 dependencies {
     api("com.refinedmods.refinedstorage:refinedstorage-neoforge:${refinedstorageVersion}")
+    runtimeOnly("com.refinedmods.refinedstorage:refinedstorage-jei-integration-neoforge:${refinedstorageJeiIntegrationVersion}")
+    // runtimeOnly("com.refinedmods.refinedstorage:refinedstorage-emi-integration-neoforge:0.5.0")
     compileOnlyApi("mekanism:Mekanism:${minecraftVersion}-${mekanismVersion}:api")
     runtimeOnly("mekanism:Mekanism:${minecraftVersion}-${mekanismVersion}:all") {
         exclude(group = "com.blamejared.crafttweaker")
@@ -54,5 +62,7 @@ dependencies {
     compileOnlyApi("mezz.jei:jei-${minecraftVersion}-common-api:${jeiVersion}")
     testCompileOnly("mezz.jei:jei-${minecraftVersion}-common:${jeiVersion}")
     compileOnlyApi("mezz.jei:jei-${minecraftVersion}-neoforge-api:${jeiVersion}")
+    // runtimeOnly("dev.emi:emi-neoforge:${emiVersion}")
+    compileOnlyApi("dev.emi:emi-neoforge:${emiVersion}")
 }
 
diff --git a/gradle.properties b/gradle.properties
index 87129a5..2d77d61 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,8 +1,10 @@
 refinedarchitectVersion=0.20.0
 refinedstorageVersion=2.0.0-milestone.4.10
+refinedstorageJeiIntegrationVersion=0.6.0
 # https://www.curseforge.com/minecraft/mc-mods/mekanism/files/all
 mekanismVersion=10.7.7.64
 jeiVersion=19.20.0.241
+emiVersion=1.1.11+1.21
 minecraftVersion=1.21.1
 # Gradle
 org.gradle.jvmargs=-Xmx1G
diff --git a/src/main/java/com/refinedmods/refinedstorage/mekanism/ModInitializer.java b/src/main/java/com/refinedmods/refinedstorage/mekanism/ModInitializer.java
index c2dff29..9b38d85 100644
--- a/src/main/java/com/refinedmods/refinedstorage/mekanism/ModInitializer.java
+++ b/src/main/java/com/refinedmods/refinedstorage/mekanism/ModInitializer.java
@@ -9,6 +9,8 @@
 import com.refinedmods.refinedstorage.mekanism.grid.ChemicalGridExtractionStrategy;
 import com.refinedmods.refinedstorage.mekanism.grid.ChemicalGridInsertionStrategy;
 import com.refinedmods.refinedstorage.mekanism.importer.ChemicalImporterTransferStrategyFactory;
+import com.refinedmods.refinedstorage.mekanism.recipemod.EmiChemicalResourceModIngredientConverter;
+import com.refinedmods.refinedstorage.mekanism.recipemod.JeiChemicalRecipeModIngredientConverter;
 import com.refinedmods.refinedstorage.mekanism.storage.ChemicalStorageDiskItem;
 import com.refinedmods.refinedstorage.mekanism.storage.ChemicalStorageVariant;
 import com.refinedmods.refinedstorage.mekanism.storagemonitor.ChemicalStorageMonitorInsertionStrategy;
@@ -22,6 +24,7 @@
 import net.minecraft.world.item.crafting.RecipeSerializer;
 import net.neoforged.api.distmarker.Dist;
 import net.neoforged.bus.api.IEventBus;
+import net.neoforged.fml.ModList;
 import net.neoforged.fml.common.Mod;
 import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
 import net.neoforged.fml.loading.FMLEnvironment;
@@ -97,6 +100,11 @@ private void setup(final FMLCommonSetupEvent e) {
         RefinedStorageApi.INSTANCE.addExternalStorageProviderFactory(
             new ChemicalPlatformExternalStorageProviderFactory()
         );
+        if (ModList.get().isLoaded("emi")) {
+            RefinedStorageApi.INSTANCE.addIngredientConverter(new EmiChemicalResourceModIngredientConverter());
+        } else if (ModList.get().isLoaded("jei")) {
+            RefinedStorageApi.INSTANCE.addIngredientConverter(new JeiChemicalRecipeModIngredientConverter());
+        }
     }
 
     private void registerCreativeModeTabListener(final BuildCreativeModeTabContentsEvent e) {
diff --git a/src/main/java/com/refinedmods/refinedstorage/mekanism/externalstorage/ChemicalPlatformExternalStorageProviderFactory.java b/src/main/java/com/refinedmods/refinedstorage/mekanism/externalstorage/ChemicalPlatformExternalStorageProviderFactory.java
index b0cb20d..960b750 100644
--- a/src/main/java/com/refinedmods/refinedstorage/mekanism/externalstorage/ChemicalPlatformExternalStorageProviderFactory.java
+++ b/src/main/java/com/refinedmods/refinedstorage/mekanism/externalstorage/ChemicalPlatformExternalStorageProviderFactory.java
@@ -21,6 +21,6 @@ public Optional<ExternalStorageProvider> create(final ServerLevel level,
 
     @Override
     public int getPriority() {
-        return -2;
+        return -1;
     }
 }
diff --git a/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/EmiChemicalResourceModIngredientConverter.java b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/EmiChemicalResourceModIngredientConverter.java
new file mode 100644
index 0000000..d2c7d7e
--- /dev/null
+++ b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/EmiChemicalResourceModIngredientConverter.java
@@ -0,0 +1,45 @@
+package com.refinedmods.refinedstorage.mekanism.recipemod;
+
+import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
+import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey;
+import com.refinedmods.refinedstorage.common.api.support.resource.RecipeModIngredientConverter;
+import com.refinedmods.refinedstorage.mekanism.ChemicalResource;
+
+import java.util.Optional;
+
+import dev.emi.emi.api.stack.EmiStack;
+import mekanism.api.IMekanismAccess;
+import mekanism.api.chemical.Chemical;
+import net.neoforged.neoforge.fluids.FluidType;
+
+import static com.refinedmods.refinedstorage.mekanism.ChemicalResource.ofChemicalStack;
+
+public class EmiChemicalResourceModIngredientConverter implements RecipeModIngredientConverter {
+    @Override
+    public Optional<PlatformResourceKey> convertToResource(final Object ingredient) {
+        if (ingredient instanceof EmiStack emiStack) {
+            return IMekanismAccess.INSTANCE.emiHelper()
+                .asChemicalStack(emiStack)
+                .map(ChemicalResource::ofChemicalStack);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<ResourceAmount> convertToResourceAmount(final Object ingredient) {
+        if (ingredient instanceof EmiStack emiStack) {
+            return IMekanismAccess.INSTANCE.emiHelper()
+                .asChemicalStack(emiStack)
+                .map(chemical -> new ResourceAmount(ofChemicalStack(chemical), emiStack.getAmount()));
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Object> convertToIngredient(final PlatformResourceKey resourceKey) {
+        if (resourceKey instanceof ChemicalResource(Chemical chemical)) {
+            return Optional.of(IMekanismAccess.INSTANCE.emiHelper().createEmiStack(chemical, FluidType.BUCKET_VOLUME));
+        }
+        return Optional.empty();
+    }
+}
diff --git a/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/JeiChemicalRecipeModIngredientConverter.java b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/JeiChemicalRecipeModIngredientConverter.java
new file mode 100644
index 0000000..a08b08d
--- /dev/null
+++ b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/JeiChemicalRecipeModIngredientConverter.java
@@ -0,0 +1,40 @@
+package com.refinedmods.refinedstorage.mekanism.recipemod;
+
+import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
+import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey;
+import com.refinedmods.refinedstorage.common.api.support.resource.RecipeModIngredientConverter;
+import com.refinedmods.refinedstorage.mekanism.ChemicalResource;
+
+import java.util.Optional;
+
+import mekanism.api.chemical.Chemical;
+import mekanism.api.chemical.ChemicalStack;
+import net.neoforged.neoforge.fluids.FluidType;
+
+import static com.refinedmods.refinedstorage.mekanism.ChemicalResource.ofChemicalStack;
+
+public class JeiChemicalRecipeModIngredientConverter implements RecipeModIngredientConverter {
+    @Override
+    public Optional<PlatformResourceKey> convertToResource(final Object ingredient) {
+        if (ingredient instanceof ChemicalStack stack) {
+            return Optional.of(ofChemicalStack(stack));
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<ResourceAmount> convertToResourceAmount(final Object ingredient) {
+        if (ingredient instanceof ChemicalStack stack) {
+            return Optional.of(new ResourceAmount(ofChemicalStack(stack), stack.getAmount()));
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Object> convertToIngredient(final PlatformResourceKey resourceKey) {
+        if (resourceKey instanceof ChemicalResource(Chemical chemical)) {
+            return Optional.of(new ChemicalStack(chemical, FluidType.BUCKET_VOLUME));
+        }
+        return Optional.empty();
+    }
+}
diff --git a/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/package-info.java b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/package-info.java
new file mode 100644
index 0000000..86ae0f8
--- /dev/null
+++ b/src/main/java/com/refinedmods/refinedstorage/mekanism/recipemod/package-info.java
@@ -0,0 +1,7 @@
+@ParametersAreNonnullByDefault
+@FieldsAndMethodsAreNonnullByDefault
+package com.refinedmods.refinedstorage.mekanism.recipemod;
+
+import com.refinedmods.refinedstorage.api.core.FieldsAndMethodsAreNonnullByDefault;
+
+import javax.annotation.ParametersAreNonnullByDefault;