diff --git a/build.gradle b/build.gradle index 4659861..d9ab7a4 100644 --- a/build.gradle +++ b/build.gradle @@ -58,6 +58,13 @@ allprojects { } } + maven { + url "https://maven.terraformersmc.com/" + content { + includeGroup "dev.emi" + } + } + maven { url "https://www.cursemaven.com" content { diff --git a/common/build.gradle b/common/build.gradle index 9b9d4e8..59a56ff 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -20,6 +20,7 @@ dependencies { modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${rootProject.rei_version}") modCompileOnly("mezz.jei:jei-${rootProject.minecraft_version}-common-api:${rootProject.jei_version}") + modCompileOnly("dev.emi:emi-xplat-intermediary:${rootProject.emi_version}+${rootProject.minecraft_version}:api") compileOnly("net.luckperms:api:${rootProject.luckperms_api_version}") diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/FTBXModCompat.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/FTBXModCompat.java index 2e6a36d..a18f80e 100644 --- a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/FTBXModCompat.java +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/FTBXModCompat.java @@ -21,6 +21,7 @@ public class FTBXModCompat { public static boolean isGameStagesLoaded; public static boolean isREILoaded; public static boolean isJEILoaded; + public static boolean isEMILoaded; public static boolean isLuckPermsLoaded; public static boolean isWaystonesLoaded; public static boolean isCommonProtLoaded; @@ -47,6 +48,7 @@ private static void detectLoadedMods() { isGameStagesLoaded = Platform.isModLoaded("gamestages"); isREILoaded = Platform.isModLoaded("roughlyenoughitems"); isJEILoaded = Platform.isModLoaded("jei"); + isEMILoaded = Platform.isModLoaded("emi"); isLuckPermsLoaded = Platform.isModLoaded("luckperms"); isWaystonesLoaded = Platform.isModLoaded("waystones"); isCommonProtLoaded = Platform.isModLoaded("common-protection-api"); diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/FTBQuestsSetup.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/FTBQuestsSetup.java index 3785de9..c758eba 100644 --- a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/FTBQuestsSetup.java +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/FTBQuestsSetup.java @@ -2,16 +2,22 @@ import dev.ftb.mods.ftbquests.FTBQuests; import dev.ftb.mods.ftbxmodcompat.FTBXModCompat; +import dev.ftb.mods.ftbxmodcompat.ftbquests.emi.helper.EMIRecipeHelper; import dev.ftb.mods.ftbxmodcompat.ftbquests.jei.helper.JEIRecipeHelper; import dev.ftb.mods.ftbxmodcompat.ftbquests.rei.helper.REIRecipeHelper; public class FTBQuestsSetup { public static void init() { - if (FTBXModCompat.isJEILoaded) { - FTBQuests.setRecipeModHelper(new JEIRecipeHelper()); + // EMI will load JEI plugins if JEI is also installed, + // and REI will do the same if "REI Plugin Compatibilities" is installed, + // so we make sure to check for JEI *last* + if (FTBXModCompat.isEMILoaded) { + FTBQuests.setRecipeModHelper(new EMIRecipeHelper()); } else if (FTBXModCompat.isREILoaded) { FTBQuests.setRecipeModHelper(new REIRecipeHelper()); + } else if (FTBXModCompat.isJEILoaded) { + FTBQuests.setRecipeModHelper(new JEIRecipeHelper()); } FTBXModCompat.LOGGER.info("[FTB Quests] recipe helper provider is [{}]", FTBQuests.getRecipeModHelper().getHelperName()); } -} +} \ No newline at end of file diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/EMICategories.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/EMICategories.java new file mode 100644 index 0000000..72b47f1 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/EMICategories.java @@ -0,0 +1,12 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi; + +import dev.emi.emi.api.recipe.EmiRecipeCategory; +import dev.emi.emi.api.stack.EmiStack; +import dev.ftb.mods.ftbquests.FTBQuests; +import dev.ftb.mods.ftbquests.item.FTBQuestsItems; +import net.minecraft.resources.ResourceLocation; + +public class EMICategories { + public static final EmiRecipeCategory QUEST = new EmiRecipeCategory(ResourceLocation.tryBuild(FTBQuests.MOD_ID, "quest"), EmiStack.of(FTBQuestsItems.BOOK.get())); + public static final EmiRecipeCategory LOOT_CRATE = new EmiRecipeCategory(ResourceLocation.tryBuild(FTBQuests.MOD_ID, "loot_crate"), EmiStack.of(FTBQuestsItems.BOOK.get())); +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/FTBQuestsEMIIntegration.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/FTBQuestsEMIIntegration.java new file mode 100644 index 0000000..475e46d --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/FTBQuestsEMIIntegration.java @@ -0,0 +1,31 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi; + +import dev.emi.emi.api.EmiApi; +import dev.emi.emi.api.EmiEntrypoint; +import dev.emi.emi.api.EmiPlugin; +import dev.emi.emi.api.EmiRegistry; +import dev.emi.emi.api.stack.EmiStack; +import dev.ftb.mods.ftbquests.item.FTBQuestsItems; +import dev.ftb.mods.ftbxmodcompat.FTBXModCompat; +import net.minecraft.world.item.ItemStack; + +@EmiEntrypoint +public class FTBQuestsEMIIntegration implements EmiPlugin { + public static final EmiStack WORKSTATION = EmiStack.of(FTBQuestsItems.BOOK.get()); + + @Override + public void register(EmiRegistry registry) { + if (FTBXModCompat.isFTBQuestsLoaded) { + registry.addCategory(EMICategories.QUEST); + registry.addWorkstation(EMICategories.QUEST, WORKSTATION); + + QuestRecipeManager.INSTANCE.getQuests().forEach(quest -> { + registry.addRecipe(new QuestRecipe(quest)); + }); + } + } + + public static void showRecipes(ItemStack stack) { + EmiApi.displayRecipes(EmiStack.of(stack)); + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/LootCrateRecipe.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/LootCrateRecipe.java new file mode 100644 index 0000000..c43df19 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/LootCrateRecipe.java @@ -0,0 +1,4 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi; + +public class LootCrateRecipe { +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipe.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipe.java new file mode 100644 index 0000000..c9938a0 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipe.java @@ -0,0 +1,64 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi; + +import dev.emi.emi.api.recipe.BasicEmiRecipe; +import dev.emi.emi.api.render.EmiTexture; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.EmiStack; +import dev.emi.emi.api.widget.WidgetHolder; +import dev.ftb.mods.ftbquests.FTBQuests; +import dev.ftb.mods.ftbxmodcompat.ftbquests.emi.widget.ClickableTextWidget; +import dev.ftb.mods.ftbxmodcompat.ftbquests.recipemod_common.WrappedQuest; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; + +public class QuestRecipe extends BasicEmiRecipe { + private final WrappedQuest wrappedQuest; + + public QuestRecipe(WrappedQuest wrappedQuest) { + super(EMICategories.QUEST, ResourceLocation.tryBuild(FTBQuests.MOD_ID, String.valueOf(wrappedQuest.quest.id)), 152, 70); + + for (Ingredient ingredient : wrappedQuest.inputIngredients()) { + this.inputs.add(EmiIngredient.of(ingredient)); + } + + for (Ingredient ingredient : wrappedQuest.outputIngredients()) { + for (ItemStack item : ingredient.getItems()) { + this.outputs.add(EmiStack.of(item)); + } + } + + this.wrappedQuest = wrappedQuest; + } + + @Override + public void addWidgets(WidgetHolder widgets) { + int inputSize = Math.min(9, inputs.size()); + for (int i = 0; i < 9; i++) { + EmiIngredient ingredient = i < inputSize ? inputs.get(i) : EmiStack.EMPTY; + widgets.addSlot(ingredient, (i % 3) * 18 + 4, (i / 3) * 18 + 13); + } + + int outputSize = Math.min(9, outputs.size()); + for (int i = 0; i < 9; i++) { + EmiIngredient ingredient = i < outputSize ? outputs.get(i) : EmiStack.EMPTY; + widgets.addSlot(ingredient, (i % 3) * 18 + 94, (i / 3) * 18 + 13).recipeContext(this); + } + + widgets.addTexture(EmiTexture.EMPTY_ARROW, 64, 32); + + Component text = wrappedQuest.quest.getTitle().copy().withStyle(ChatFormatting.UNDERLINE); + widgets.add(new ClickableTextWidget(text.getVisualOrderText(), 1, 1, 0, false, c -> { + Minecraft.getInstance().setScreen(null); + wrappedQuest.openQuestGui(); + })); + } + + @Override + public boolean supportsRecipeTree() { + return false; + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipeManager.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipeManager.java new file mode 100644 index 0000000..6fe5810 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/QuestRecipeManager.java @@ -0,0 +1,20 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi; + +import dev.ftb.mods.ftbxmodcompat.ftbquests.recipemod_common.WrappedQuest; +import dev.ftb.mods.ftbxmodcompat.ftbquests.recipemod_common.WrappedQuestCache; + +import java.util.List; + +public enum QuestRecipeManager { + INSTANCE; + + private final WrappedQuestCache cache = new WrappedQuestCache(); + + public void refresh() { + cache.clear(); + } + + public List getQuests() { + return cache.getCachedItems(); + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/helper/EMIRecipeHelper.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/helper/EMIRecipeHelper.java new file mode 100644 index 0000000..b7cf10b --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/helper/EMIRecipeHelper.java @@ -0,0 +1,26 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi.helper; + +import dev.ftb.mods.ftbxmodcompat.ftbquests.emi.FTBQuestsEMIIntegration; +import dev.ftb.mods.ftbxmodcompat.ftbquests.emi.QuestRecipeManager; +import dev.ftb.mods.ftbxmodcompat.ftbquests.recipemod_common.BaseRecipeHelper; +import net.minecraft.world.item.ItemStack; + +public class EMIRecipeHelper extends BaseRecipeHelper { + @Override + public void showRecipes(ItemStack itemStack) { + FTBQuestsEMIIntegration.showRecipes(itemStack); + } + + @Override + public String getHelperName() { + return "EMI"; + } + + protected void refreshQuests() { + QuestRecipeManager.INSTANCE.refresh(); + } + + protected void refreshLootcrates() { + // TODO + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/widget/ClickableTextWidget.java b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/widget/ClickableTextWidget.java new file mode 100644 index 0000000..ff93745 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbxmodcompat/ftbquests/emi/widget/ClickableTextWidget.java @@ -0,0 +1,24 @@ +package dev.ftb.mods.ftbxmodcompat.ftbquests.emi.widget; + +import dev.emi.emi.api.widget.TextWidget; +import net.minecraft.util.FormattedCharSequence; + +import java.util.function.Consumer; + +public class ClickableTextWidget extends TextWidget { + private final Consumer onClick; + + public ClickableTextWidget(FormattedCharSequence text, int x, int y, int color, boolean shadow, Consumer onClick) { + super(text, x, y, color, shadow); + this.onClick = onClick; + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (getBounds().contains(mouseX, mouseY)) { + onClick.accept(this); + return true; + } + return false; + } +} diff --git a/common/src/main/resources/assets/ftbxmodcompat/lang/en_us.json b/common/src/main/resources/assets/ftbxmodcompat/lang/en_us.json index 7a73a41..b795b90 100644 --- a/common/src/main/resources/assets/ftbxmodcompat/lang/en_us.json +++ b/common/src/main/resources/assets/ftbxmodcompat/lang/en_us.json @@ -1,2 +1,4 @@ { -} \ No newline at end of file + "emi.category.ftbquests.quest": "Quests", + "emi.category.ftbquests.loot_crate": "Loot Crates" +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 8c11eb3..4fe16c6 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -148,6 +148,7 @@ if (ENV.CURSEFORGE_KEY) { optionalDependency 'kubejs' optionalDependency 'jei' optionalDependency 'roughly-enough-items' + optionalDependency 'emi' optionalDependency 'waystones-fabric' } changelog = ENV.CHANGELOG // expected to exist if ENV.CURSEFORGE_KEY does diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 12e74ad..d20162a 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -19,6 +19,9 @@ ], "rei_client": [ "dev.ftb.mods.ftbxmodcompat.ftbquests.rei.FTBQuestsREIIntegration" + ], + "emi": [ + "dev.ftb.mods.ftbxmodcompat.ftbquests.emi.FTBQuestsEMIIntegration" ] }, "depends": { diff --git a/forge/build.gradle b/forge/build.gradle index e18bd81..021ec15 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -142,6 +142,7 @@ if (ENV.CURSEFORGE_KEY) { optionalDependency 'kubejs' optionalDependency 'jei' optionalDependency 'roughly-enough-items' + optionalDependency 'emi' optionalDependency 'game-stages' optionalDependency 'waystones' } diff --git a/gradle.properties b/gradle.properties index c58a42c..beff9ac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,6 +24,7 @@ kubejs_version=1902.6.1-build.300 gamestages_version=11.0.2 rei_version=9.1.619 jei_version=11.6.0.1016 +emi_version=1.0.19 common_prot_api_version=1.0.0 waystones_forge_version=3901921 waystones_fabric_version=3901920