diff --git a/src/main/java/de/dafuqs/spectrum/api/recipe/GatedRecipe.java b/src/main/java/de/dafuqs/spectrum/api/recipe/GatedRecipe.java index 885b48c26a..b9ed21dce4 100644 --- a/src/main/java/de/dafuqs/spectrum/api/recipe/GatedRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/api/recipe/GatedRecipe.java @@ -16,22 +16,22 @@ public interface GatedRecipe extends Recipe { boolean isSecret(); Identifier getRequiredAdvancementIdentifier(); Identifier getRecipeTypeUnlockIdentifier(); - + String getRecipeTypeShortID(); - + default boolean canPlayerCraft(PlayerEntity playerEntity) { return AdvancementHelper.hasAdvancement(playerEntity, getRecipeTypeUnlockIdentifier()) && AdvancementHelper.hasAdvancement(playerEntity, getRequiredAdvancementIdentifier()); } - + default Text getSingleUnlockToastString() { return Text.translatable("spectrum.toast." + getRecipeTypeShortID() + "_recipe_unlocked.title"); } - + default Text getMultipleUnlockToastString() { return Text.translatable("spectrum.toast." + getRecipeTypeShortID() + "_recipes_unlocked.title"); } - + default void registerInToastManager(RecipeType recipeType, GatedRecipe gatedRecipe) { if (FabricLoader.getInstance().getEnvironmentType() != EnvType.SERVER) { registerInToastManagerClient(recipeType, gatedRecipe); diff --git a/src/main/java/de/dafuqs/spectrum/blocks/enchanter/EnchanterBlockEntity.java b/src/main/java/de/dafuqs/spectrum/blocks/enchanter/EnchanterBlockEntity.java index 3aad25565e..cdea142c2d 100644 --- a/src/main/java/de/dafuqs/spectrum/blocks/enchanter/EnchanterBlockEntity.java +++ b/src/main/java/de/dafuqs/spectrum/blocks/enchanter/EnchanterBlockEntity.java @@ -338,10 +338,12 @@ public static void enchantCenterItem(@NotNull EnchanterBlockEntity enchanterBloc public static Map getHighestEnchantmentsInItemBowls(@NotNull EnchanterBlockEntity enchanterBlockEntity) { List bowlStacks = new ArrayList<>(); for (int i = 0; i < 8; i++) { - bowlStacks.add(enchanterBlockEntity.virtualInventoryIncludingBowlStacks.getStack(2 + i)); + if (!SpectrumItemTags.isIn(SpectrumItemTags.ENCHANTER_ITEM_BLACKLIST, enchanterBlockEntity.virtualInventoryIncludingBowlStacks.getStack(2 + i).getItem())) { + bowlStacks.add(enchanterBlockEntity.virtualInventoryIncludingBowlStacks.getStack(2 + i)); + } } - return SpectrumEnchantmentHelper.collectHighestEnchantments(bowlStacks); + return SpectrumEnchantmentHelper.collectHighestEnchantments(bowlStacks, SpectrumEnchantmentTags.ENCHANTER_BLACKLIST); } public static int getRequiredExperienceToEnchantCenterItem(@NotNull EnchanterBlockEntity enchanterBlockEntity) { diff --git a/src/main/java/de/dafuqs/spectrum/commands/SanityCommand.java b/src/main/java/de/dafuqs/spectrum/commands/SanityCommand.java index b83a7e8112..d339fb136c 100644 --- a/src/main/java/de/dafuqs/spectrum/commands/SanityCommand.java +++ b/src/main/java/de/dafuqs/spectrum/commands/SanityCommand.java @@ -1,11 +1,5 @@ package de.dafuqs.spectrum.commands; -import com.klikli_dev.modonomicon.book.*; -import com.klikli_dev.modonomicon.book.conditions.*; -import com.klikli_dev.modonomicon.book.conditions.context.*; -import com.klikli_dev.modonomicon.book.entries.*; -import com.klikli_dev.modonomicon.book.page.*; -import com.klikli_dev.modonomicon.data.*; import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.tree.*; import de.dafuqs.revelationary.*; @@ -15,9 +9,7 @@ import de.dafuqs.spectrum.api.item.*; import de.dafuqs.spectrum.api.recipe.*; import de.dafuqs.spectrum.blocks.*; -import de.dafuqs.spectrum.blocks.deeper_down.flora.*; import de.dafuqs.spectrum.blocks.gemstone.*; -import de.dafuqs.spectrum.compat.modonomicon.pages.*; import de.dafuqs.spectrum.enchantments.*; import de.dafuqs.spectrum.items.*; import de.dafuqs.spectrum.items.trinkets.*; @@ -32,9 +24,6 @@ import net.minecraft.advancement.criterion.*; import net.minecraft.block.*; import net.minecraft.enchantment.*; -import net.minecraft.entity.*; -import net.minecraft.entity.attribute.*; -import net.minecraft.entity.effect.*; import net.minecraft.inventory.*; import net.minecraft.item.*; import net.minecraft.loot.*; @@ -52,9 +41,7 @@ import java.util.*; public class SanityCommand { - - private static final Identifier WIP_ADVANCEMENT_ID = SpectrumCommon.locate("__wip"); - + private static final List ADVANCEMENT_GATING_WARNING_WHITELIST = List.of( SpectrumCommon.locate("find_preservation_ruins"), // does not have a prerequisite SpectrumCommon.locate("fail_to_glitch_into_preservation_ruin"), // does not have a prerequisite @@ -63,10 +50,6 @@ public class SanityCommand { SpectrumCommon.locate("lategame/strike_up_hummingstone_hymn") // its parent is 2 parents in ); - private static final List GUIDEBOOK_WARNING_WHITELIST = List.of( - SpectrumCommon.locate("cuisine/cookbooks/brewers_handbook") // "*_fluid" mod compat recipe page - ); - public static void register(LiteralCommandNode root) { LiteralCommandNode sanity = CommandManager.literal("sanity") .requires((source) -> source.hasPermissionLevel(2)) @@ -98,7 +81,6 @@ private static int execute(ServerCommandSource source, String modId) { && !blockState.isIn(BlockTags.HOE_MINEABLE) && !blockState.isIn(FabricMineableTags.SHEARS_MINEABLE) && !blockState.isIn(FabricMineableTags.SWORD_MINEABLE) - && !blockState.isIn(BlockTags.SWORD_EFFICIENT) && !blockState.isIn(SpectrumBlockTags.EXEMPT_FROM_MINEABLE_DEBUG_CHECK)) { SpectrumCommon.logWarning("[SANITY: Mineable Tags] Block " + registryKey.getValue() + " is not contained in a any vanilla mineable tag."); } @@ -117,9 +99,6 @@ private static int execute(ServerCommandSource source, String modId) { if (block instanceof SpectrumBuddingBlock) { continue; // does not have any drop by default } - if (block instanceof WeepingGalaFrondsBlock) { - continue; // Fronds do not drop anything by default - } BlockState blockState = entry.getValue().getDefaultState(); Identifier lootTableID = block.getLootTableId(); @@ -142,12 +121,12 @@ private static int execute(ServerCommandSource source, String modId) { } } } - - // Statistic: Build an empty map of maps for counting used gem colors for each tier + + // Statistic: Build an empty hashmap of hashmaps for counting used gem colors for each tier // This info can be used to balance usage a bit - Map> usedColorsForEachTier = new HashMap<>(); + HashMap> usedColorsForEachTier = new HashMap<>(); for (PedestalRecipeTier pedestalRecipeTier : PedestalRecipeTier.values()) { - Map colorMap = new HashMap<>(); + HashMap colorMap = new HashMap<>(); for (GemstoneColor gemstoneColor : BuiltinGemstoneColor.values()) { colorMap.put(gemstoneColor, 0); } @@ -160,6 +139,10 @@ private static int execute(ServerCommandSource source, String modId) { // Pedestal recipes that use gemstone powder not available at that tier yet for (PedestalRecipe pedestalRecipe : recipeManager.listAllOfType(SpectrumRecipeTypes.PEDESTAL)) { + /* There are some recipes that use advanced ingredients by design + despite being of a low tier, like black colored lights. + While the player does not have access to that yet it is no problem at all + */ if (pedestalRecipe.getTier() == PedestalRecipeTier.BASIC || pedestalRecipe.getTier() == PedestalRecipeTier.SIMPLE) { if (pedestalRecipe.getPowderInputs().getOrDefault(BuiltinGemstoneColor.BLACK, 0) > 0) { SpectrumCommon.logWarning("[SANITY: Pedestal Recipe Ingredients] Pedestal recipe '" + pedestalRecipe.getId() + "' of tier '" + pedestalRecipe.getTier() + "' is using onyx powder as input! Players will not have access to Onyx at that tier"); @@ -175,73 +158,19 @@ private static int execute(ServerCommandSource source, String modId) { } } - // Checking for missing translation strings + // Items / Blocks without a translation for (Map.Entry, Item> item : Registries.ITEM.getEntrySet()) { - if (!item.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(item.getValue().getTranslationKey())) { SpectrumCommon.logWarning("[SANITY: Item Lang] Missing translation string " + item.getValue().getTranslationKey()); } } for (Map.Entry, Block> block : Registries.BLOCK.getEntrySet()) { - if (!block.getKey().getValue().getNamespace().equals(modId)) { - continue; - } if (!Language.getInstance().hasTranslation(block.getValue().getTranslationKey())) { SpectrumCommon.logWarning("[SANITY: Block Lang] Missing translation string " + block.getValue().getTranslationKey()); } } - for (Map.Entry>, EntityType> entityType : Registries.ENTITY_TYPE.getEntrySet()) { - if (!entityType.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey())) { - SpectrumCommon.logWarning("[SANITY: EntityType Lang] Missing translation string " + entityType.getValue().getTranslationKey()); - } - } - for (Map.Entry, Enchantment> entityType : Registries.ENCHANTMENT.getEntrySet()) { - if (!entityType.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey())) { - SpectrumCommon.logWarning("[SANITY: Enchantment Lang] Missing translation string " + entityType.getValue().getTranslationKey()); - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey() + ".desc")) { - SpectrumCommon.logWarning("[SANITY: Enchantment Lang] Missing description string " + entityType.getValue().getTranslationKey() + ".desc"); - } - } - for (Map.Entry, StatusEffect> entityType : Registries.STATUS_EFFECT.getEntrySet()) { - if (!entityType.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey())) { - SpectrumCommon.logWarning("[SANITY: Status Effect Lang] Missing translation string " + entityType.getValue().getTranslationKey()); - } - } - for (Map.Entry, EntityAttribute> entityType : Registries.ATTRIBUTE.getEntrySet()) { - if (!entityType.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey())) { - SpectrumCommon.logWarning("[SANITY: Attribute Lang] Missing translation string " + entityType.getValue().getTranslationKey()); - } - } - for (Map.Entry, EntityAttribute> entityType : Registries.ATTRIBUTE.getEntrySet()) { - if (!entityType.getKey().getValue().getNamespace().equals(modId)) { - continue; - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey())) { - SpectrumCommon.logWarning("[SANITY: Attribute Lang] Missing translation string " + entityType.getValue().getTranslationKey()); - } - if (!Language.getInstance().hasTranslation(entityType.getValue().getTranslationKey() + ".desc")) { - SpectrumCommon.logWarning("[SANITY: Attribute Lang] Missing description string " + entityType.getValue().getTranslationKey() + ".desc"); - } - } - - // recipe groups without localization + // recipe groups without localisation Set recipeGroups = new HashSet<>(); recipeManager.keys().forEach(identifier -> { Optional> recipe = recipeManager.get(identifier); @@ -263,17 +192,21 @@ private static int execute(ServerCommandSource source, String modId) { } // Impossible to unlock recipes - for (Recipe recipe : recipeManager.values()) { - if (recipe instanceof GatedRecipe gatedRecipe) { - Identifier advancementIdentifier = gatedRecipe.getRequiredAdvancementIdentifier(); - if (advancementIdentifier != null && advancementLoader.get(advancementIdentifier) == null) { - SpectrumCommon.logWarning("[SANITY: " + gatedRecipe.getRecipeTypeShortID() + " Recipe Unlocks] Advancement '" + gatedRecipe.getRequiredAdvancementIdentifier() + "' in recipe '" + recipe.getId() + "' does not exist"); - } - } - } + testRecipeUnlocks(SpectrumRecipeTypes.PEDESTAL, "Pedestal", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.ANVIL_CRUSHING, "Anvil Crushing", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.FUSION_SHRINE, "Fusion Shrine", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.ENCHANTER, "Enchanting", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.ENCHANTMENT_UPGRADE, "Enchantment Upgrade", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.POTION_WORKSHOP_BREWING, "Potion Workshop Brewing", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.POTION_WORKSHOP_CRAFTING, "Potion Workshop Reagent", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.POTION_WORKSHOP_REACTING, "Potion Workshop Crafting", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.MIDNIGHT_SOLUTION_CONVERTING, "Midnight Solution Converting", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.SPIRIT_INSTILLING, "Spirit Instilling", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.INK_CONVERTING, "Ink Converting", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.CRYSTALLARIEUM, "Crystallarieum", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.CINDERHEARTH, "Cinderhearth", recipeManager, advancementLoader); + testRecipeUnlocks(SpectrumRecipeTypes.TITRATION_BARREL, "Titration Barrel", recipeManager, advancementLoader); - // Recipes that spawn effects based on item color, - // but input / output items do not have a color registered DynamicRegistryManager registryManager = source.getRegistryManager(); testIngredientsAndOutputInColorRegistry(SpectrumRecipeTypes.FUSION_SHRINE, "Fusion Shrine", recipeManager, registryManager); testIngredientsAndOutputInColorRegistry(SpectrumRecipeTypes.ENCHANTER, "Enchanting", recipeManager, registryManager); @@ -284,12 +217,7 @@ private static int execute(ServerCommandSource source, String modId) { // Impossible to unlock block cloaks for (Map.Entry> cloaks : RevelationRegistry.getBlockStateEntries().entrySet()) { if (advancementLoader.get(cloaks.getKey()) == null) { - SpectrumCommon.logWarning("[SANITY: Block Cloaks] Advancement '" + cloaks.getKey().toString() + "' for block cloaking does not exist. Registered cloaks: " + cloaks.getValue().size()); - } - } - for (Map.Entry> cloaks : RevelationRegistry.getItemEntries().entrySet()) { - if (advancementLoader.get(cloaks.getKey()) == null) { - SpectrumCommon.logWarning("[SANITY: Item Cloaks] Advancement '" + cloaks.getKey().toString() + "' for item cloaking does not exist. Registered cloaks: " + cloaks.getValue().size()); + SpectrumCommon.logWarning("[SANITY: Block Cloaks] Advancement '" + cloaks.getKey().toString() + "' for block / item cloaking does not exist. Registered cloaks: " + cloaks.getValue().size()); } } @@ -300,9 +228,6 @@ private static int execute(ServerCommandSource source, String modId) { // "has advancement" criteria with nonexistent advancements if (conditions instanceof AdvancementGottenCriterion.Conditions hasAdvancementConditions) { Identifier advancementIdentifier = hasAdvancementConditions.getAdvancementIdentifier(); - if (advancementIdentifier.equals(WIP_ADVANCEMENT_ID)) { - continue; - } Advancement advancementCriterionAdvancement = advancementLoader.get(advancementIdentifier); if (advancementCriterionAdvancement == null) { SpectrumCommon.logWarning("[SANITY: Has_Advancement Criteria] Advancement '" + advancement.getId() + "' references advancement '" + advancementIdentifier + "' that does not exist"); @@ -310,9 +235,6 @@ private static int execute(ServerCommandSource source, String modId) { // "advancement count" criteria with nonexistent advancements } else if (conditions instanceof AdvancementCountCriterion.Conditions hasAdvancementConditions) { for (Identifier advancementIdentifier : hasAdvancementConditions.getAdvancementIdentifiers()) { - if (advancementIdentifier.equals(WIP_ADVANCEMENT_ID)) { - continue; - } Advancement advancementCriterionAdvancement = advancementLoader.get(advancementIdentifier); if (advancementCriterionAdvancement == null) { SpectrumCommon.logWarning("[SANITY: Advancement_Count Criteria] Advancement '" + advancement.getId() + "' references advancement '" + advancementIdentifier + "' that does not exist"); @@ -321,8 +243,8 @@ private static int execute(ServerCommandSource source, String modId) { } } } - - // advancements that don't require their parent (or parents of their parents, for 'collecting' type advancements) + + // advancements that dont require parent for (Advancement advancement : advancementLoader.getAdvancements()) { String path = advancement.getId().getPath(); if (advancement.getId().getNamespace().equals(modId) && !path.startsWith("hidden") && !path.startsWith("progression") && !path.startsWith("milestones") && advancement.getParent() != null) { @@ -358,9 +280,8 @@ private static int execute(ServerCommandSource source, String modId) { // Pedestal Recipes in wrong data folder for (PedestalRecipe recipe : recipeManager.listAllOfType(SpectrumRecipeTypes.PEDESTAL)) { Identifier id = recipe.getId(); - if (id.getPath().startsWith("mod_integration/") || id.getPath().contains("/glass/") || id.getPath().contains("/saplings/") || id.getPath().contains("/detectors/") || id.getPath().contains("/gemstone_lights/") || id.getPath().contains("/decostones/") - || id.getPath().contains("/runes/") || id.getPath().contains("/pastel_network/") || id.getPath().contains("/gemstone_chimes/") || id.getPath().contains("/pastel_network/") || id.getPath().contains("/semi_permeable_glass/") - || id.getPath().contains("/colored_lamps/") || id.getPath().contains("/colored_spore_blossoms/") || id.getPath().contains("/glowblocks/")) { + if (id.getPath().startsWith("mod_integration/") || id.getPath().contains("/glass/") || id.getPath().contains("/saplings/") || id.getPath().contains("/detectors/") || id.getPath().contains("/gem_lamps/") || id.getPath().contains("/decostones/") + || id.getPath().contains("/runes/") || id.getPath().contains("/pastel_network/") || id.getPath().contains("/gemstone_chimes/") || id.getPath().contains("/pastel_network/") || id.getPath().contains("/player_only_glass/")) { continue; } @@ -406,8 +327,8 @@ private static int execute(ServerCommandSource source, String modId) { } } } - - // Enchantments without a recipe + + // Enchantments without recipe Map craftingColors = new HashMap<>(); Map upgradeColors = new HashMap<>(); for (EnchanterRecipe recipe : recipeManager.listAllOfType(SpectrumRecipeTypes.ENCHANTER)) { @@ -452,8 +373,8 @@ private static int execute(ServerCommandSource source, String modId) { SpectrumCommon.logWarning("[SANITY: Enchantment Tags] Enchantment '" + entry.getKey().getValue() + "' is missing in the spectrum:enchantments tag"); } } - - // Trinkets that have invalid equip advancement and thus can't be equipped + + // Trinkets that have an invalid equip advancement and thus can't be equipped for (Map.Entry, Item> item : Registries.ITEM.getEntrySet()) { if (item.getValue() instanceof SpectrumTrinketItem trinketItem) { Identifier advancementIdentifier = trinketItem.getUnlockIdentifier(); @@ -464,9 +385,10 @@ private static int execute(ServerCommandSource source, String modId) { } } - // items / blocks missing in the creative tab (this will also omit them from most recipe viewers) + // items / blocks missing in the creative tab (will also omit them from most recipe viewers) Collection itemGroupStacks = SpectrumItemGroups.MAIN.getSearchTabStacks(); for (Map.Entry, Item> item : Registries.ITEM.getEntrySet()) { + if (item.getKey().getValue().getNamespace().equals(modId) && !item.getValue().getRegistryEntry().isIn(SpectrumItemTags.COMING_SOON_TOOLTIP)) { boolean found = false; for(ItemStack stack : itemGroupStacks) { @@ -482,43 +404,18 @@ private static int execute(ServerCommandSource source, String modId) { } } - // Guidebook entries/pages that may be un-unlockable - Book book = BookDataManager.get().getBook(GuidebookItem.GUIDEBOOK_ID); - for (Map.Entry entry : book.getEntries().entrySet()) { - if (GUIDEBOOK_WARNING_WHITELIST.contains(entry.getKey())) { - continue; - } - - BookCondition condition = entry.getValue().getCondition(); - BookConditionContext context = new BookConditionCategoryContext(book, entry.getValue().getCategory()); - if (!condition.test(context, source.getPlayer())) { - SpectrumCommon.logWarning("[SANITY: Guidebook] Entry '" + entry.getKey() + "' is still locked for the executing player. Does the player have the required advancements? Can it be unlocked?"); - } - for (BookPage page : entry.getValue().getPages()) { - if (!page.getCondition().test(context, source.getPlayer())) { - SpectrumCommon.logWarning("[SANITY: Guidebook] Entry '" + entry.getKey() + "' page " + page.getPageNumber() + " of type '" + page.getType() + "' is still locked for the executing player. Does the player have the required advancements? Can it be unlocked? Or is it only a missing mod compat recipe page?"); - } - if (page instanceof BookHintPage bookHintPage) { - Identifier completionAdvancement = bookHintPage.getCompletionAdvancement(); - Advancement advancement = advancementLoader.get(completionAdvancement); - if (advancement == null) { - SpectrumCommon.logWarning("[SANITY: Guidebook] Hint Page '" + entry.getKey() + "' page " + page.getPageNumber() + " is missing it's completion advancement '" + completionAdvancement + "'"); - } - } - } - } - + SpectrumCommon.logInfo("##### SANITY CHECK FINISHED ######"); SpectrumCommon.logInfo("##### SANITY CHECK PEDESTAL RECIPE STATISTICS ######"); for (PedestalRecipeTier pedestalRecipeTier : PedestalRecipeTier.values()) { - Map entry = usedColorsForEachTier.get(pedestalRecipeTier); + HashMap entry = usedColorsForEachTier.get(pedestalRecipeTier); SpectrumCommon.logInfo("[SANITY: Pedestal Recipe Gemstone Usages] Gemstone Powder for tier " + StringUtils.leftPad(pedestalRecipeTier.toString(), 8) + - ": C:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.CYAN).toString(), 4) + - " M:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.MAGENTA).toString(), 4) + - " Y:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.YELLOW).toString(), 4) + - " K:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.BLACK).toString(), 4) + - " W:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.WHITE).toString(), 4)); + ": C:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.CYAN).toString(), 3) + + " M:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.MAGENTA).toString(), 3) + + " Y:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.YELLOW).toString(), 3) + + " K:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.BLACK).toString(), 3) + + " W:" + StringUtils.leftPad(entry.get(BuiltinGemstoneColor.WHITE).toString(), 3)); } if (source.getEntity() instanceof ServerPlayerEntity serverPlayerEntity) { @@ -527,7 +424,16 @@ private static int execute(ServerCommandSource source, String modId) { return 0; } - + + private static , C extends Inventory> void testRecipeUnlocks(RecipeType recipeType, String name, RecipeManager recipeManager, ServerAdvancementLoader advancementLoader) { + for (GatedRecipe recipe : recipeManager.listAllOfType(recipeType)) { + Identifier advancementIdentifier = recipe.getRequiredAdvancementIdentifier(); + if (advancementIdentifier != null && advancementLoader.get(advancementIdentifier) == null) { + SpectrumCommon.logWarning("[SANITY: " + name + " Recipe Unlocks] Advancement '" + recipe.getRequiredAdvancementIdentifier() + "' in recipe '" + recipe.getId() + "' does not exist"); + } + } + } + private static , C extends Inventory> void testIngredientsAndOutputInColorRegistry(RecipeType recipeType, String name, RecipeManager recipeManager, DynamicRegistryManager registryManager) { for (GatedRecipe recipe : recipeManager.listAllOfType(recipeType)) { for (Ingredient inputIngredient : recipe.getIngredients()) { diff --git a/src/main/java/de/dafuqs/spectrum/compat/REI/REIClientIntegration.java b/src/main/java/de/dafuqs/spectrum/compat/REI/REIClientIntegration.java index 00cfa4137c..6e3e551776 100644 --- a/src/main/java/de/dafuqs/spectrum/compat/REI/REIClientIntegration.java +++ b/src/main/java/de/dafuqs/spectrum/compat/REI/REIClientIntegration.java @@ -126,7 +126,7 @@ public void registerDisplays(DisplayRegistry registry) { registry.registerRecipeFiller(CinderhearthRecipe.class, SpectrumRecipeTypes.CINDERHEARTH, CinderhearthDisplay::new); registry.registerRecipeFiller(ITitrationBarrelRecipe.class, SpectrumRecipeTypes.TITRATION_BARREL, TitrationBarrelDisplay::new); registry.registerRecipeFiller(PrimordialFireBurningRecipe.class, SpectrumRecipeTypes.PRIMORDIAL_FIRE_BURNING, PrimordialFireBurningDisplay::new); - + NaturesStaffConversionDataLoader.CONVERSIONS.forEach((key, value) -> registry.add(new NaturesStaffConversionsDisplay(EntryStacks.of(key), EntryStacks.of(value.getBlock()), NaturesStaffConversionDataLoader.UNLOCK_IDENTIFIERS.getOrDefault(key, null)))); FreezingIdolBlock.FREEZING_STATE_MAP.forEach((key, value) -> registry.add(new FreezingDisplay(BlockToBlockWithChanceDisplay.blockToEntryStack(key.getBlock()), BlockToBlockWithChanceDisplay.blockToEntryStack(value.getLeft().getBlock()), value.getRight()))); FreezingIdolBlock.FREEZING_MAP.forEach((key, value) -> registry.add(new FreezingDisplay(BlockToBlockWithChanceDisplay.blockToEntryStack(key), BlockToBlockWithChanceDisplay.blockToEntryStack(value.getLeft().getBlock()), value.getRight()))); diff --git a/src/main/java/de/dafuqs/spectrum/compat/SpectrumIntegrationPacks.java b/src/main/java/de/dafuqs/spectrum/compat/SpectrumIntegrationPacks.java index ba86f6e61d..8c31193d27 100644 --- a/src/main/java/de/dafuqs/spectrum/compat/SpectrumIntegrationPacks.java +++ b/src/main/java/de/dafuqs/spectrum/compat/SpectrumIntegrationPacks.java @@ -63,14 +63,18 @@ public static void register() { registerIntegrationPack(CREATE_ID, () -> new CreateCompat()); registerIntegrationPack(FARMERSDELIGHT_ID, () -> new FDCompat()); registerIntegrationPack(GOBBER_ID, () -> new GobberCompat()); - registerIntegrationPack(MALUM_ID, () -> new MalumCompat()); registerIntegrationPack(NEEPMEAT_ID, () -> new NEEPMeatCompat()); if (!CONNECTOR_LOADED) { // Traveler's Backpack for Forge crashes due to Fabric lacking Fluid#getFluidType (a Forge method) // This cannot be reasonably worked around AFAIK // ~unilock, 2025 + + //Malum for Fabric uses Create Porter Lib, Atemps to register enchantments though it create NoSuchField errors + // Needs replacement or hacky workaround + // ~Shibva, 2026 registerIntegrationPack(TRAVELERS_BACKPACK_ID, () -> new TravelersBackpackCompat()); + registerIntegrationPack(MALUM_ID, () -> new MalumCompat()); } for (ModIntegrationPack container : INTEGRATION_PACKS.values()) { diff --git a/src/main/java/de/dafuqs/spectrum/compat/emi/SpectrumEmiPlugin.java b/src/main/java/de/dafuqs/spectrum/compat/emi/SpectrumEmiPlugin.java index 3f2e050082..f04518a086 100644 --- a/src/main/java/de/dafuqs/spectrum/compat/emi/SpectrumEmiPlugin.java +++ b/src/main/java/de/dafuqs/spectrum/compat/emi/SpectrumEmiPlugin.java @@ -2,23 +2,18 @@ import de.dafuqs.spectrum.*; import de.dafuqs.spectrum.api.block.*; -import de.dafuqs.spectrum.blocks.fluid.*; import de.dafuqs.spectrum.blocks.idols.*; -import de.dafuqs.spectrum.compat.*; import de.dafuqs.spectrum.compat.emi.handlers.*; import de.dafuqs.spectrum.compat.emi.recipes.*; import de.dafuqs.spectrum.data_loaders.*; import de.dafuqs.spectrum.inventories.*; import de.dafuqs.spectrum.inventories.slots.*; -import de.dafuqs.spectrum.recipe.fluid_converting.*; import de.dafuqs.spectrum.registries.*; import dev.emi.emi.api.*; import dev.emi.emi.api.recipe.*; import dev.emi.emi.api.stack.*; -import net.fabricmc.loader.api.*; import net.minecraft.block.*; import net.minecraft.client.gui.screen.ingame.*; -import net.minecraft.fluid.*; import net.minecraft.inventory.*; import net.minecraft.recipe.*; import net.minecraft.registry.*; @@ -154,7 +149,7 @@ public void registerRecipes(EmiRegistry registry) { return; } Identifier id = syntheticId("freezing", key.getBlock()); // The synthetic IDs generated here assume there will never be multiple conversions of the same block with different states - registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.FREEZING, id, in, out, SpectrumAdvancements.UNLOCK_IDOLS)); + registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.FREEZING, id, in, out, SpectrumCommon.locate("unlocks/blocks/idols"))); }); FreezingIdolBlock.FREEZING_MAP.forEach((key, value) -> { EmiStack in = EmiStack.of(key); @@ -163,7 +158,7 @@ public void registerRecipes(EmiRegistry registry) { return; } Identifier id = syntheticId("freezing", key); - registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.FREEZING, id, in, out, SpectrumAdvancements.UNLOCK_IDOLS)); + registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.FREEZING, id, in, out, SpectrumCommon.locate("unlocks/blocks/idols"))); }); FirestarterIdolBlock.BURNING_MAP.forEach((key, value) -> { EmiStack in = EmiStack.of(key); @@ -172,7 +167,7 @@ public void registerRecipes(EmiRegistry registry) { return; } Identifier id = syntheticId("heating", key); - registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.HEATING, id, in, out, SpectrumAdvancements.UNLOCK_IDOLS)); + registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.HEATING, id, in, out, SpectrumCommon.locate("unlocks/blocks/idols"))); }); NaturesStaffConversionDataLoader.CONVERSIONS.forEach((key, value) -> { EmiStack in = EmiStack.of(key); @@ -181,118 +176,8 @@ public void registerRecipes(EmiRegistry registry) { return; } Identifier id = syntheticId("natures_staff", key); - registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.NATURES_STAFF, id, in, out, SpectrumAdvancements.UNLOCK_NATURES_STAFF)); + registry.addRecipe(new BlockToBlockWithChanceEmiRecipe(SpectrumEmiRecipeCategories.NATURES_STAFF, id, in, out, SpectrumCommon.locate("unlocks/items/natures_staff"))); }); - - //WorldInteractionRecipe - long amount = SpectrumIntegrationPacks.CONNECTOR_LOADED ? 1_000 : 81_000; - EmiStack water = EmiStack.of(Fluids.WATER, amount); - EmiStack lava = EmiStack.of(Fluids.LAVA, amount); - EmiStack dragonrot = EmiStack.of(SpectrumFluids.DRAGONROT, amount); - EmiStack liquidCrystal = EmiStack.of(SpectrumFluids.LIQUID_CRYSTAL, amount); - EmiStack midnightSolution = EmiStack.of(SpectrumFluids.MIDNIGHT_SOLUTION, amount); - EmiStack mud = EmiStack.of(SpectrumFluids.MUD, amount); - EmiStack waterCatalyst = water.copy().setRemainder(water); - EmiStack lavaCatalyst = lava.copy().setRemainder(lava); - EmiStack dragonrotCatalyst = dragonrot.copy().setRemainder(dragonrot); - EmiStack liquidCrystalCatalyst = liquidCrystal.copy().setRemainder(liquidCrystal); - EmiStack midnightSolutionCatalyst = midnightSolution.copy().setRemainder(midnightSolution); - EmiStack mudCatalyst = mud.copy().setRemainder(mud); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", SpectrumBlocks.SLUSH)) - .leftInput(dragonrotCatalyst) - .rightInput(waterCatalyst, false) - .output(EmiStack.of(SpectrumBlocks.SLUSH)) - .requiredAdvancement(DragonrotConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.BLACKSTONE)) - .leftInput(dragonrotCatalyst) - .rightInput(lavaCatalyst, false) - .output(EmiStack.of(Blocks.BLACKSTONE)) - .requiredAdvancement(DragonrotConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.COARSE_DIRT)) - .leftInput(dragonrotCatalyst) - .rightInput(mudCatalyst, false) - .output(EmiStack.of(Blocks.COARSE_DIRT)) - .requiredAdvancement(DragonrotConvertingRecipe.UNLOCK_IDENTIFIER) - .requiredAdvancement(MudConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", SpectrumBlocks.ROTTEN_GROUND)) - .leftInput(dragonrotCatalyst) - .rightInput(liquidCrystalCatalyst, false) - .output(EmiStack.of(SpectrumBlocks.ROTTEN_GROUND)) - .requiredAdvancement(DragonrotConvertingRecipe.UNLOCK_IDENTIFIER) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", SpectrumBlocks.BLACK_SLUDGE)) - .leftInput(dragonrotCatalyst) - .rightInput(midnightSolutionCatalyst, false) - .output(EmiStack.of(SpectrumBlocks.BLACK_SLUDGE)) - .requiredAdvancement(DragonrotConvertingRecipe.UNLOCK_IDENTIFIER) - .requiredAdvancement(MidnightSolutionConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", SpectrumBlocks.FROSTBITE_CRYSTAL)) - .leftInput(liquidCrystal) - .rightInput(waterCatalyst, false) - .output(EmiStack.of(SpectrumBlocks.FROSTBITE_CRYSTAL)) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.CALCITE)) - .leftInput(liquidCrystalCatalyst) - .rightInput(waterCatalyst, false) - .output(EmiStack.of(Blocks.CALCITE)) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", SpectrumBlocks.BLAZING_CRYSTAL)) - .leftInput(liquidCrystal) - .rightInput(lavaCatalyst, false) - .output(EmiStack.of(SpectrumBlocks.BLAZING_CRYSTAL)) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.COBBLED_DEEPSLATE)) - .leftInput(liquidCrystalCatalyst) - .rightInput(lavaCatalyst, false) - .output(EmiStack.of(Blocks.COBBLED_DEEPSLATE)) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.CLAY)) - .leftInput(liquidCrystalCatalyst) - .rightInput(mudCatalyst, false) - .output(EmiStack.of(Blocks.CLAY)) - .requiredAdvancement(LiquidCrystalConvertingRecipe.UNLOCK_IDENTIFIER) - .requiredAdvancement(MudConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.TERRACOTTA)) - .leftInput(midnightSolutionCatalyst) - .rightInput(lavaCatalyst, false) - .output(EmiStack.of(Blocks.TERRACOTTA)) - .requiredAdvancement(MidnightSolutionConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.DIRT)) - .leftInput(mudCatalyst) - .rightInput(waterCatalyst, false) - .output(EmiStack.of(Blocks.DIRT)) - .requiredAdvancement(MudConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); - addRecipeSafe(registry, () -> SpectrumWorldInteractionRecipe.customBuilder() - .id(syntheticId("world/fluid_interaction", Blocks.MUD)) - .leftInput(mudCatalyst) - .rightInput(lavaCatalyst, false) - .output(EmiStack.of(Blocks.MUD)) - .requiredAdvancement(MudConvertingRecipe.UNLOCK_IDENTIFIER) - .build()); } public void registerRecipeHandlers(EmiRegistry registry) { @@ -313,14 +198,5 @@ public > void addAll(EmiRegistry regist registry.addRecipe(constructor.apply(recipe)); } } - - private static void addRecipeSafe(EmiRegistry registry, Supplier supplier) { - try { - registry.addRecipe(supplier.get()); - } catch (Throwable e) { - SpectrumCommon.logWarning("Exception thrown when parsing EMI recipe (no ID available)"); - SpectrumCommon.logError(e.toString()); - } - } - + } diff --git a/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/EnchanterEmiRecipeGated.java b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/EnchanterEmiRecipeGated.java index 4054b19f93..a3f6dacb63 100644 --- a/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/EnchanterEmiRecipeGated.java +++ b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/EnchanterEmiRecipeGated.java @@ -40,7 +40,7 @@ public EnchanterEmiRecipeGated(EmiRecipeCategory category, EnchantmentUpgradeRec } inputs.add(EmiStack.of(KnowledgeGemItem.getKnowledgeDropStackWithXP(recipe.getRequiredExperience(), true))); } - + private EnchanterEmiRecipeGated(EmiRecipeCategory category, GatedSpectrumRecipe recipe, Text description, int craftingTime) { super(category, recipe, 132, 80); this.craftingTime = craftingTime; diff --git a/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapedGatedCraftingEMIRecipe.java b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapedGatedCraftingEMIRecipe.java new file mode 100644 index 0000000000..789faa9e53 --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapedGatedCraftingEMIRecipe.java @@ -0,0 +1,54 @@ +package de.dafuqs.spectrum.compat.emi.recipes; + +import de.dafuqs.spectrum.compat.emi.*; +import de.dafuqs.spectrum.recipe.crafting.*; +import dev.emi.emi.api.recipe.*; +import dev.emi.emi.api.render.*; +import dev.emi.emi.api.stack.*; +import dev.emi.emi.api.widget.*; +import net.minecraft.item.*; + +public class ShapedGatedCraftingEMIRecipe extends GatedSpectrumEmiRecipe { + + public ShapedGatedCraftingEMIRecipe(ShapedGatedCraftingRecipe recipe) { + super(VanillaEmiRecipeCategories.CRAFTING, recipe, 118, 54); + } + + public boolean canFit(int width, int height) { + if (inputs.size() > 9) { + return false; + } + for (int i = 0; i < inputs.size(); i++) { + int x = i % 3; + int y = i / 3; + if (!inputs.get(i).isEmpty() && (x >= width || y >= height)) { + return false; + } + } + return true; + } + + @Override + public void addUnlockedWidgets(WidgetHolder widgets) { + widgets.addTexture(EmiTexture.EMPTY_ARROW, 60, 18); + + int sOff = 0; + if (canFit(1, 3)) { + sOff -= 1; + } + if (canFit(3, 1)) { + sOff -= 3; + } + for (int i = 0; i < 9; i++) { + int s = i + sOff; + if (s >= 0 && s < inputs.size()) { + widgets.addSlot(inputs.get(s), i % 3 * 18, i / 3 * 18); + } else { + widgets.addSlot(EmiStack.of(ItemStack.EMPTY), i % 3 * 18, i / 3 * 18); + } + } + + widgets.addSlot(outputs.get(0), 92, 14).large(true).recipeContext(this); + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapelessGatedCraftingEMIRecipe.java b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapelessGatedCraftingEMIRecipe.java new file mode 100644 index 0000000000..daa4960fb1 --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/compat/emi/recipes/ShapelessGatedCraftingEMIRecipe.java @@ -0,0 +1,33 @@ +package de.dafuqs.spectrum.compat.emi.recipes; + +import de.dafuqs.spectrum.compat.emi.*; +import de.dafuqs.spectrum.recipe.crafting.*; +import dev.emi.emi.api.recipe.*; +import dev.emi.emi.api.render.*; +import dev.emi.emi.api.stack.*; +import dev.emi.emi.api.widget.*; +import net.minecraft.item.*; + +public class ShapelessGatedCraftingEMIRecipe extends GatedSpectrumEmiRecipe { + + public ShapelessGatedCraftingEMIRecipe(ShapelessGatedCraftingRecipe recipe) { + super(VanillaEmiRecipeCategories.CRAFTING, recipe, 118, 54); + } + + @Override + public void addUnlockedWidgets(WidgetHolder widgets) { + widgets.addTexture(EmiTexture.EMPTY_ARROW, 60, 18); + widgets.addTexture(EmiTexture.SHAPELESS, 97, 0); + + for (int i = 0; i < 9; i++) { + if (i < inputs.size()) { + widgets.addSlot(inputs.get(i), i % 3 * 18, i / 3 * 18); + } else { + widgets.addSlot(EmiStack.of(ItemStack.EMPTY), i % 3 * 18, i / 3 * 18); + } + } + + widgets.addSlot(outputs.get(0), 92, 14).large(true).recipeContext(this); + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/compat/modonomicon/pages/BookGatedRecipePage.java b/src/main/java/de/dafuqs/spectrum/compat/modonomicon/pages/BookGatedRecipePage.java index 44060fda7f..8945843d08 100644 --- a/src/main/java/de/dafuqs/spectrum/compat/modonomicon/pages/BookGatedRecipePage.java +++ b/src/main/java/de/dafuqs/spectrum/compat/modonomicon/pages/BookGatedRecipePage.java @@ -4,7 +4,6 @@ import com.klikli_dev.modonomicon.book.*; import com.klikli_dev.modonomicon.book.conditions.*; import com.klikli_dev.modonomicon.book.page.*; -import com.klikli_dev.modonomicon.util.*; import de.dafuqs.spectrum.api.recipe.*; import de.dafuqs.spectrum.compat.modonomicon.unlock_conditions.*; import net.minecraft.item.*; @@ -20,7 +19,7 @@ public class BookGatedRecipePage> extends BookRecipePag private final Identifier pageType; public BookGatedRecipePage(RecipeType recipeType, Identifier pageType, BookTextHolder title1, Identifier recipeId1, BookTextHolder title2, Identifier recipeId2, BookTextHolder text, String anchor, BookCondition condition) { - super(recipeType, title1, recipeId1, title2, recipeId2, text, anchor, condition); + super(recipeType, title1, recipeId1, title2, recipeId2, text, anchor, getConditionWithRecipes(condition, recipeId1, recipeId2)); this.pageType = pageType; } @@ -35,30 +34,16 @@ public static BookCondition getConditionWithRecipes(BookCondition condition, Ide BookCondition[] conditions = {condition, new RecipesLoadedAndUnlockedCondition(null, list)}; return new BookAndCondition(null, conditions); } - - public static > BookGatedRecipePage fromJson(Identifier pageType, RecipeType recipeType, JsonObject json, boolean supportsTwoRecipesOnOnePage) { + + public static > BookGatedRecipePage fromJson(Identifier pageType, RecipeType recipeType, JsonObject json) { + var common = BookRecipePage.commonFromJson(json); var anchor = JsonHelper.getString(json, "anchor", ""); var condition = json.has("condition") ? BookCondition.fromJson(json.getAsJsonObject("condition")) : new BookNoneCondition(); - var text = BookGsonHelper.getAsBookTextHolder(json, "text", BookTextHolder.EMPTY); - var skipRecipeUnlockCheck = JsonHelper.getBoolean(json, "skip_recipe_unlock_check", false); - - if (supportsTwoRecipesOnOnePage) { - var title1 = BookGsonHelper.getAsBookTextHolder(json, "title", BookTextHolder.EMPTY); - var title2 = BookGsonHelper.getAsBookTextHolder(json, "title2", BookTextHolder.EMPTY); - Identifier recipeId1 = json.has("recipe_id") ? Identifier.tryParse(JsonHelper.getString(json, "recipe_id")) : null; - Identifier recipeId2 = json.has("recipe_id2") ? Identifier.tryParse(JsonHelper.getString(json, "recipe_id2")) : null; - condition = skipRecipeUnlockCheck ? condition : getConditionWithRecipes(condition, recipeId1, recipeId2); - return new BookGatedRecipePage<>(recipeType, pageType, title1, recipeId1, title2, recipeId2, text, anchor, condition); - } else { - var title = BookGsonHelper.getAsBookTextHolder(json, "title", BookTextHolder.EMPTY); - Identifier recipeId = json.has("recipe_id") ? Identifier.tryParse(JsonHelper.getString(json, "recipe_id")) : null; - condition = skipRecipeUnlockCheck ? condition : getConditionWithRecipes(condition, recipeId, null); - return new BookGatedRecipePage<>(recipeType, pageType, title, recipeId, BookTextHolder.EMPTY, null, text, anchor, condition); - } + return new BookGatedRecipePage<>(recipeType, pageType, common.title1(), common.recipeId1(), common.title2(), common.recipeId2(), common.text(), anchor, condition); } - + public static > BookGatedRecipePage fromNetwork(Identifier pageType, RecipeType recipeType, PacketByteBuf buffer) { var common = BookRecipePage.commonFromNetwork(buffer); var anchor = buffer.readString(); diff --git a/src/main/java/de/dafuqs/spectrum/helpers/SpectrumEnchantmentHelper.java b/src/main/java/de/dafuqs/spectrum/helpers/SpectrumEnchantmentHelper.java index b6c5b1b2be..53ce1c0548 100644 --- a/src/main/java/de/dafuqs/spectrum/helpers/SpectrumEnchantmentHelper.java +++ b/src/main/java/de/dafuqs/spectrum/helpers/SpectrumEnchantmentHelper.java @@ -8,6 +8,7 @@ import net.minecraft.item.*; import net.minecraft.nbt.*; import net.minecraft.registry.*; +import net.minecraft.registry.tag.*; import net.minecraft.util.*; import org.jetbrains.annotations.*; @@ -141,13 +142,40 @@ public static boolean hasEnchantmentThatConflictsWith(ItemStack itemStack, Encha return false; } - public static Map collectHighestEnchantments(List itemStacks) { + //This instance of collectHighestEnchantments is to enable the use of an optional filter + public static Map collectHighestEnchantments(List itemStacks, TagKey blacklist) { Map enchantmentLevelMap = new LinkedHashMap<>(); + for (ItemStack itemStack : itemStacks) { + Map itemStackEnchantments = EnchantmentHelper.get(itemStack); + for (Enchantment enchantment : itemStackEnchantments.keySet()) { + int level = itemStackEnchantments.get(enchantment); + + if (SpectrumEnchantmentTags.isIn(blacklist, enchantment)) { + continue; + } + + if (enchantmentLevelMap.containsKey(enchantment)) { + int storedLevel = enchantmentLevelMap.get(enchantment); + if (level > storedLevel) { + enchantmentLevelMap.put(enchantment, level); + } + } else { + enchantmentLevelMap.put(enchantment, level); + } + } + } + return enchantmentLevelMap; + } + + //The filterless version of the method above + public static Map collectHighestEnchantments(List itemStacks) { + Map enchantmentLevelMap = new LinkedHashMap<>(); for (ItemStack itemStack : itemStacks) { Map itemStackEnchantments = EnchantmentHelper.get(itemStack); for (Enchantment enchantment : itemStackEnchantments.keySet()) { int level = itemStackEnchantments.get(enchantment); + if (enchantmentLevelMap.containsKey(enchantment)) { int storedLevel = enchantmentLevelMap.get(enchantment); if (level > storedLevel) { diff --git a/src/main/java/de/dafuqs/spectrum/mixin/accessors/ShapelessRecipeSerializerAccessor.java b/src/main/java/de/dafuqs/spectrum/mixin/accessors/ShapelessRecipeSerializerAccessor.java new file mode 100644 index 0000000000..c0e1797fba --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/mixin/accessors/ShapelessRecipeSerializerAccessor.java @@ -0,0 +1,17 @@ +package de.dafuqs.spectrum.mixin.accessors; + +import com.google.gson.*; +import net.minecraft.recipe.*; +import net.minecraft.util.collection.*; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.gen.*; + +@Mixin(ShapelessRecipe.Serializer.class) +public interface ShapelessRecipeSerializerAccessor { + + @Invoker(value = "getIngredients") + static DefaultedList invokeGetIngredients(JsonArray json) { + throw new AssertionError(); + } + +} \ No newline at end of file diff --git a/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipe.java new file mode 100644 index 0000000000..55f8184746 --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipe.java @@ -0,0 +1,44 @@ +package de.dafuqs.spectrum.recipe.crafting; + +import de.dafuqs.spectrum.api.recipe.*; +import de.dafuqs.spectrum.registries.*; +import net.minecraft.inventory.*; +import net.minecraft.item.*; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.*; +import net.minecraft.util.*; +import net.minecraft.util.collection.*; +import org.jetbrains.annotations.*; + +public class ShapedGatedCraftingRecipe extends ShapedRecipe implements GatedRecipe { + + public final boolean secret; + public final @Nullable Identifier requiredAdvancementIdentifier; + + public ShapedGatedCraftingRecipe(Identifier id, String group, CraftingRecipeCategory category, int width, int height, DefaultedList input, ItemStack output, boolean showNotification, boolean secret, @Nullable Identifier requiredAdvancementIdentifier) { + super(id, group, category, width, height, input, output, showNotification); + this.secret = secret; + this.requiredAdvancementIdentifier = requiredAdvancementIdentifier; + } + + @Override + public boolean isSecret() { + return this.secret; + } + + @Override + public @Nullable Identifier getRequiredAdvancementIdentifier() { + return this.requiredAdvancementIdentifier; + } + + @Override + public Identifier getRecipeTypeUnlockIdentifier() { + return null; + } + + @Override + public String getRecipeTypeShortID() { + return SpectrumRecipeTypes.SHAPED_GATED_CRAFTING_RECIPE_ID; + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipeSerializer.java b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipeSerializer.java new file mode 100644 index 0000000000..451b6182cc --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapedGatedCraftingRecipeSerializer.java @@ -0,0 +1,77 @@ +package de.dafuqs.spectrum.recipe.crafting; + +import com.google.gson.*; +import de.dafuqs.spectrum.api.recipe.*; +import de.dafuqs.spectrum.mixin.accessors.*; +import net.minecraft.item.*; +import net.minecraft.network.*; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.*; +import net.minecraft.registry.*; +import net.minecraft.util.*; +import net.minecraft.util.collection.*; +import org.jetbrains.annotations.*; + +import java.util.*; + +public class ShapedGatedCraftingRecipeSerializer implements GatedRecipeSerializer { + + public final ShapedGatedCraftingRecipeSerializer.RecipeFactory recipeFactory; + + public ShapedGatedCraftingRecipeSerializer(ShapedGatedCraftingRecipeSerializer.RecipeFactory recipeFactory) { + this.recipeFactory = recipeFactory; + } + + public interface RecipeFactory { + ShapedGatedCraftingRecipe create(Identifier id, String group, CraftingRecipeCategory category, int width, int height, DefaultedList input, ItemStack output, boolean notification, boolean secret, @Nullable Identifier requiredAdvancementIdentifier); + } + + @Override + public ShapedGatedCraftingRecipe read(Identifier id, JsonObject jsonObject) { + String group = JsonHelper.getString(jsonObject, "group", ""); + CraftingRecipeCategory category = CraftingRecipeCategory.CODEC.byId(JsonHelper.getString(jsonObject, "category", null), CraftingRecipeCategory.MISC); + Map map = ShapedRecipeAccessor.invokeReadSymbols(JsonHelper.getObject(jsonObject, "key")); + String[] strings = ShapedRecipeAccessor.invokeRemovePadding(ShapedRecipeAccessor.invokeGetPattern(JsonHelper.getArray(jsonObject, "pattern"))); + int width = strings[0].length(); + int height = strings.length; + DefaultedList input = ShapedRecipeAccessor.invokeCreatePatternMatrix(strings, map, width, height); + ItemStack output = ShapedRecipe.outputFromJson(JsonHelper.getObject(jsonObject, "result")); + boolean bl = JsonHelper.getBoolean(jsonObject, "show_notification", true); + boolean secret = readSecret(jsonObject); + @Nullable Identifier requiredAdvancementIdentifier = readRequiredAdvancementIdentifier(jsonObject); + return new ShapedGatedCraftingRecipe(id, group, category, width, height, input, output, bl, secret, requiredAdvancementIdentifier); + } + + + @Override + public void write(PacketByteBuf packetByteBuf, ShapedGatedCraftingRecipe recipe) { + packetByteBuf.writeVarInt(recipe.getWidth()); + packetByteBuf.writeVarInt(recipe.getHeight()); + packetByteBuf.writeString(recipe.getGroup()); + packetByteBuf.writeEnumConstant(recipe.getCategory()); + for (Ingredient ingredient : recipe.getIngredients()) { + ingredient.write(packetByteBuf); + } + packetByteBuf.writeItemStack(recipe.getOutput(DynamicRegistryManager.EMPTY)); + packetByteBuf.writeBoolean(recipe.showNotification()); + packetByteBuf.writeBoolean(recipe.isSecret()); + writeNullableIdentifier(packetByteBuf, recipe.getRecipeTypeUnlockIdentifier()); + } + + + @Override + public ShapedGatedCraftingRecipe read(Identifier identifier, PacketByteBuf packetByteBuf) { + int i = packetByteBuf.readVarInt(); + int j = packetByteBuf.readVarInt(); + String string = packetByteBuf.readString(); + CraftingRecipeCategory craftingRecipeCategory = packetByteBuf.readEnumConstant(CraftingRecipeCategory.class); + DefaultedList defaultedList = DefaultedList.ofSize(i * j, Ingredient.EMPTY); + defaultedList.replaceAll(ignored -> Ingredient.fromPacket(packetByteBuf)); + ItemStack itemStack = packetByteBuf.readItemStack(); + boolean bl = packetByteBuf.readBoolean(); + boolean secret = packetByteBuf.readBoolean(); + @Nullable Identifier requiredAdvancementIdentifier = readNullableIdentifier(packetByteBuf); + return new ShapedGatedCraftingRecipe(identifier, string, craftingRecipeCategory, i, j, defaultedList, itemStack, bl, secret, requiredAdvancementIdentifier); + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipe.java new file mode 100644 index 0000000000..eb9320e05f --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipe.java @@ -0,0 +1,44 @@ +package de.dafuqs.spectrum.recipe.crafting; + +import de.dafuqs.spectrum.api.recipe.*; +import de.dafuqs.spectrum.registries.*; +import net.minecraft.inventory.*; +import net.minecraft.item.*; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.*; +import net.minecraft.util.*; +import net.minecraft.util.collection.*; +import org.jetbrains.annotations.*; + +public class ShapelessGatedCraftingRecipe extends ShapelessRecipe implements GatedRecipe { + + public final boolean secret; + public final @Nullable Identifier requiredAdvancementIdentifier; + + public ShapelessGatedCraftingRecipe(Identifier id, String group, CraftingRecipeCategory category, ItemStack output, DefaultedList input, boolean secret, @Nullable Identifier requiredAdvancementIdentifier) { + super(id, group, category, output, input); + this.secret = secret; + this.requiredAdvancementIdentifier = requiredAdvancementIdentifier; + } + + @Override + public boolean isSecret() { + return this.secret; + } + + @Override + public @Nullable Identifier getRequiredAdvancementIdentifier() { + return this.requiredAdvancementIdentifier; + } + + @Override + public Identifier getRecipeTypeUnlockIdentifier() { + return null; + } + + @Override + public String getRecipeTypeShortID() { + return SpectrumRecipeTypes.SHAPED_GATED_CRAFTING_RECIPE_ID; + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipeSerializer.java b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipeSerializer.java new file mode 100644 index 0000000000..f14f8959d6 --- /dev/null +++ b/src/main/java/de/dafuqs/spectrum/recipe/crafting/ShapelessGatedCraftingRecipeSerializer.java @@ -0,0 +1,73 @@ +package de.dafuqs.spectrum.recipe.crafting; + +import com.google.gson.*; +import de.dafuqs.spectrum.api.recipe.*; +import de.dafuqs.spectrum.mixin.accessors.*; +import net.minecraft.item.*; +import net.minecraft.network.*; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.*; +import net.minecraft.registry.*; +import net.minecraft.util.*; +import net.minecraft.util.collection.*; +import org.jetbrains.annotations.*; + +public class ShapelessGatedCraftingRecipeSerializer implements GatedRecipeSerializer { + + public final ShapelessGatedCraftingRecipeSerializer.RecipeFactory recipeFactory; + + public ShapelessGatedCraftingRecipeSerializer(ShapelessGatedCraftingRecipeSerializer.RecipeFactory recipeFactory) { + this.recipeFactory = recipeFactory; + } + + public interface RecipeFactory { + ShapelessGatedCraftingRecipe create(Identifier id, String group, CraftingRecipeCategory category, ItemStack output, DefaultedList input, boolean secret, @Nullable Identifier requiredAdvancementIdentifier); + } + + @Override + public ShapelessGatedCraftingRecipe read(Identifier identifier, JsonObject jsonObject) { + String string = JsonHelper.getString(jsonObject, "group", ""); + CraftingRecipeCategory craftingRecipeCategory = CraftingRecipeCategory.CODEC.byId(JsonHelper.getString(jsonObject, "category", (String) null), CraftingRecipeCategory.MISC); + DefaultedList defaultedList = ShapelessRecipeSerializerAccessor.invokeGetIngredients(JsonHelper.getArray(jsonObject, "ingredients")); + if (defaultedList.isEmpty()) { + throw new JsonParseException("No ingredients for shapeless recipe"); + } else if (defaultedList.size() > 9) { + throw new JsonParseException("Too many ingredients for shapeless recipe"); + } else { + ItemStack itemStack = ShapedRecipe.outputFromJson(JsonHelper.getObject(jsonObject, "result")); + boolean secret = readSecret(jsonObject); + @Nullable Identifier requiredAdvancementIdentifier = readRequiredAdvancementIdentifier(jsonObject); + return new ShapelessGatedCraftingRecipe(identifier, string, craftingRecipeCategory, itemStack, defaultedList, secret, requiredAdvancementIdentifier); + } + } + + + @Override + public void write(PacketByteBuf packetByteBuf, ShapelessGatedCraftingRecipe recipe) { + packetByteBuf.writeString(recipe.getGroup()); + packetByteBuf.writeEnumConstant(recipe.getCategory()); + packetByteBuf.writeVarInt(recipe.getIngredients().size()); + for (Ingredient ingredient : recipe.getIngredients()) { + ingredient.write(packetByteBuf); + } + packetByteBuf.writeItemStack(recipe.getOutput(DynamicRegistryManager.EMPTY)); + packetByteBuf.writeBoolean(recipe.isSecret()); + writeNullableIdentifier(packetByteBuf, recipe.getRecipeTypeUnlockIdentifier()); + } + + + @Override + public ShapelessGatedCraftingRecipe read(Identifier identifier, PacketByteBuf packetByteBuf) { + String string = packetByteBuf.readString(); + CraftingRecipeCategory craftingRecipeCategory = packetByteBuf.readEnumConstant(CraftingRecipeCategory.class); + int i = packetByteBuf.readVarInt(); + DefaultedList defaultedList = DefaultedList.ofSize(i, Ingredient.EMPTY); + defaultedList.replaceAll(ignored -> Ingredient.fromPacket(packetByteBuf)); + boolean secret = packetByteBuf.readBoolean(); + @Nullable Identifier requiredAdvancementIdentifier = readNullableIdentifier(packetByteBuf); + + ItemStack itemStack = packetByteBuf.readItemStack(); + return new ShapelessGatedCraftingRecipe(identifier, string, craftingRecipeCategory, itemStack, defaultedList, secret, requiredAdvancementIdentifier); + } + +} diff --git a/src/main/java/de/dafuqs/spectrum/recipe/crafting/dynamic/ClearCraftingTabletRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/crafting/dynamic/ClearCraftingTabletRecipe.java index d37541e43e..bf08ddf055 100644 --- a/src/main/java/de/dafuqs/spectrum/recipe/crafting/dynamic/ClearCraftingTabletRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/recipe/crafting/dynamic/ClearCraftingTabletRecipe.java @@ -1,6 +1,6 @@ package de.dafuqs.spectrum.recipe.crafting.dynamic; -import de.dafuqs.spectrum.items.magic_items.*; +import de.dafuqs.spectrum.items.*; import de.dafuqs.spectrum.recipe.*; import net.minecraft.item.*; import net.minecraft.recipe.*; diff --git a/src/main/java/de/dafuqs/spectrum/recipe/fusion_shrine/FusionShrineRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/fusion_shrine/FusionShrineRecipe.java index 2b77810c18..57939a2fed 100644 --- a/src/main/java/de/dafuqs/spectrum/recipe/fusion_shrine/FusionShrineRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/recipe/fusion_shrine/FusionShrineRecipe.java @@ -10,8 +10,8 @@ import de.dafuqs.spectrum.helpers.*; import de.dafuqs.spectrum.recipe.*; import de.dafuqs.spectrum.registries.*; -import net.fabricmc.fabric.api.transfer.v1.fluid.*; -import net.fabricmc.fabric.api.transfer.v1.storage.base.*; +import net.minecraft.fluid.*; +import net.minecraft.inventory.*; import net.minecraft.item.*; import net.minecraft.recipe.*; import net.minecraft.registry.*; @@ -24,12 +24,12 @@ import java.util.*; -public class FusionShrineRecipe extends GatedStackSpectrumRecipe { +public class FusionShrineRecipe extends GatedStackSpectrumRecipe { public static final Identifier UNLOCK_IDENTIFIER = SpectrumCommon.locate("build_fusion_shrine"); protected final List craftingInputs; - protected final FluidIngredient fluid; + protected final Fluid fluidInput; protected final ItemStack output; protected final float experience; protected final int craftingTime; @@ -54,12 +54,12 @@ public class FusionShrineRecipe extends GatedStackSpectrumRecipe craftingInputs, FluidIngredient fluid, ItemStack output, float experience, int craftingTime, boolean yieldUpgradesDisabled, boolean playCraftingFinishedEffects, boolean copyNbt, + List craftingInputs, Fluid fluidInput, ItemStack output, float experience, int craftingTime, boolean yieldUpgradesDisabled, boolean playCraftingFinishedEffects, boolean copyNbt, List worldConditions, @NotNull FusionShrineRecipeWorldEffect startWorldEffect, @NotNull List duringWorldEffects, @NotNull FusionShrineRecipeWorldEffect finishWorldEffect, @Nullable Text description) { super(id, group, secret, requiredAdvancementIdentifier); this.craftingInputs = craftingInputs; - this.fluid = fluid; + this.fluidInput = fluidInput; this.output = output; this.experience = experience; this.craftingTime = craftingTime; @@ -81,21 +81,12 @@ public FusionShrineRecipe(Identifier id, String group, boolean secret, Identifie * The required fluid has to be tested manually by the crafting block. */ @Override - public boolean matches(FusionShrineBlockEntity inv, World world) { - SingleVariantStorage fluidStorage = inv.getFluidStorage(); - if (!this.fluid.test(fluidStorage.variant)) { - return false; - } - if (this.fluid != FluidIngredient.EMPTY) { - if (fluidStorage.getAmount() != fluidStorage.getCapacity()) { - return false; - } - } + public boolean matches(Inventory inv, World world) { return matchIngredientStacksExclusively(inv, getIngredientStacks()); } @Override - public ItemStack craft(FusionShrineBlockEntity inv, DynamicRegistryManager drm) { + public ItemStack craft(Inventory inv, DynamicRegistryManager drm) { return output.copy(); } @@ -146,8 +137,8 @@ public boolean areConditionMetCurrently(ServerWorld world, BlockPos pos) { return true; } - public FluidIngredient getFluid() { - return this.fluid; + public Fluid getFluidInput() { + return this.fluidInput; } public int getCraftingTime() { diff --git a/src/main/java/de/dafuqs/spectrum/recipe/spirit_instiller/SpiritInstillerRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/spirit_instiller/SpiritInstillerRecipe.java index 74afcd60a3..b0cbc4de70 100644 --- a/src/main/java/de/dafuqs/spectrum/recipe/spirit_instiller/SpiritInstillerRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/recipe/spirit_instiller/SpiritInstillerRecipe.java @@ -26,11 +26,11 @@ public class SpiritInstillerRecipe extends GatedStackSpectrumRecipe { + public static final Identifier UNLOCK_IDENTIFIER = SpectrumCommon.locate("midgame/build_spirit_instiller_structure"); + public static final int CENTER_INGREDIENT = 0; public static final int FIRST_INGREDIENT = 1; public static final int SECOND_INGREDIENT = 2; - public static final Identifier UNLOCK_IDENTIFIER = SpectrumCommon.locate("midgame/build_spirit_instiller_structure"); - ; protected final IngredientStack centerIngredient; protected final IngredientStack bowlIngredient1; diff --git a/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/ITitrationBarrelRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/ITitrationBarrelRecipe.java index d618587056..c7308a6902 100644 --- a/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/ITitrationBarrelRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/ITitrationBarrelRecipe.java @@ -3,7 +3,6 @@ import de.dafuqs.matchbooks.recipe.*; import de.dafuqs.spectrum.*; import de.dafuqs.spectrum.api.recipe.*; -import de.dafuqs.spectrum.blocks.titration_barrel.*; import de.dafuqs.spectrum.helpers.TimeHelper; import de.dafuqs.spectrum.helpers.*; import de.dafuqs.spectrum.items.food.beverages.properties.*; @@ -24,7 +23,7 @@ * Making it a non-ticking block entity and also "fermenting" when the game is not running * This also means TitrationBarrelRecipes have to calculate their time using real life seconds, instead of game ticks */ -public interface ITitrationBarrelRecipe extends GatedRecipe { +public interface ITitrationBarrelRecipe extends GatedRecipe { Identifier UNLOCK_ADVANCEMENT_IDENTIFIER = SpectrumCommon.locate("unlocks/blocks/titration_barrel"); @@ -59,19 +58,19 @@ default int getOutputCountAfterAngelsShare(World world, float temperature, long return originalOutputCount; } - // Linearly adjust the output count based on angel's share - float angelsShareResultCountMod = getAngelsShareResultCountMod(secondsFermented, temperature); - if (angelsShareResultCountMod > 0) { - return Math.max(1, (int) Math.ceil((originalOutputCount - angelsShareResultCountMod))); + // Linearly adjust the output count based on angelsShareResultCount + float angelsShareResultCount = getAngelsShareResultCount(secondsFermented, temperature); + if (angelsShareResultCount > 0) { + return Math.max(1, (int) Math.ceil((originalOutputCount - angelsShareResultCount))); } else { - return Math.max(1, (int) Math.floor((originalOutputCount - angelsShareResultCountMod))); + return Math.max(1, (int) Math.floor((originalOutputCount - angelsShareResultCount))); } } // the amount of fluid that evaporated while fermenting // the higher the temperature in the biome is, the more evaporates // making colder biomes more desirable - default float getAngelsShareResultCountMod(long secondsFermented, float temperature) { + default float getAngelsShareResultCount(long secondsFermented, float temperature) { return Math.max(0.1F, temperature / 10F) * TimeHelper.minecraftDaysFromSeconds(secondsFermented) * getAngelsSharePerMcDay(); } diff --git a/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/TitrationBarrelRecipe.java b/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/TitrationBarrelRecipe.java index f7d76423f3..da84febdc6 100644 --- a/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/TitrationBarrelRecipe.java +++ b/src/main/java/de/dafuqs/spectrum/recipe/titration_barrel/TitrationBarrelRecipe.java @@ -3,14 +3,11 @@ import de.dafuqs.matchbooks.recipe.*; import de.dafuqs.spectrum.api.item.*; import de.dafuqs.spectrum.api.recipe.*; -import de.dafuqs.spectrum.blocks.titration_barrel.*; import de.dafuqs.spectrum.helpers.TimeHelper; import de.dafuqs.spectrum.helpers.*; import de.dafuqs.spectrum.items.food.beverages.properties.*; import de.dafuqs.spectrum.recipe.*; import de.dafuqs.spectrum.registries.*; -import net.fabricmc.fabric.api.transfer.v1.fluid.*; -import net.fabricmc.fabric.api.transfer.v1.storage.base.*; import net.minecraft.entity.effect.*; import net.minecraft.inventory.*; import net.minecraft.item.*; @@ -23,7 +20,7 @@ import java.util.*; -public class TitrationBarrelRecipe extends GatedStackSpectrumRecipe implements ITitrationBarrelRecipe { +public class TitrationBarrelRecipe extends GatedStackSpectrumRecipe implements ITitrationBarrelRecipe { public static final List FERMENTATION_DURATION_DISPLAY_TIME_MULTIPLIERS = new ArrayList<>() {{ add(1); @@ -53,16 +50,7 @@ public TitrationBarrelRecipe(Identifier id, String group, boolean secret, Identi } @Override - public boolean matches(TitrationBarrelBlockEntity inventory, World world) { - SingleVariantStorage fluidStorage = inventory.getFluidStorage(); - if (!this.fluid.test(fluidStorage.variant)) { - return false; - } - if (this.fluid != FluidIngredient.EMPTY) { - if (fluidStorage.getAmount() != fluidStorage.getCapacity()) { - return false; - } - } + public boolean matches(Inventory inventory, World world) { return matchIngredientStacksExclusively(inventory, getIngredientStacks()); } @@ -88,7 +76,7 @@ public FermentationData getFermentationData() { @Override @Deprecated - public ItemStack craft(TitrationBarrelBlockEntity inventory, DynamicRegistryManager drm) { + public ItemStack craft(Inventory inventory, DynamicRegistryManager drm) { return getDefaultTap(1).copy(); } diff --git a/src/main/java/de/dafuqs/spectrum/registries/SpectrumEnchantmentTags.java b/src/main/java/de/dafuqs/spectrum/registries/SpectrumEnchantmentTags.java index 7c519830ba..2d3abf9216 100644 --- a/src/main/java/de/dafuqs/spectrum/registries/SpectrumEnchantmentTags.java +++ b/src/main/java/de/dafuqs/spectrum/registries/SpectrumEnchantmentTags.java @@ -12,6 +12,8 @@ public class SpectrumEnchantmentTags { public static final TagKey SPECTRUM_ENCHANTMENT = of("enchantments"); + public static final TagKey ENCHANTER_BLACKLIST = of("enchanter_copying_and_applying_blacklisted"); + private static TagKey of(String id) { return TagKey.of(RegistryKeys.ENCHANTMENT, SpectrumCommon.locate(id)); } @@ -22,10 +24,7 @@ public static boolean isIn(TagKey tag, Enchantment enchantment) { return false; } Optional> registryEntry = Registries.ENCHANTMENT.getEntry(optionalKey.get()); - if (registryEntry.isEmpty()) { - return false; - } - return Registries.ENCHANTMENT.getOrCreateEntryList(tag).contains(registryEntry.get()); + return registryEntry.filter(enchantmentReference -> Registries.ENCHANTMENT.getOrCreateEntryList(tag).contains(enchantmentReference)).isPresent(); } } diff --git a/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java b/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java index 6454fdea33..b330101627 100644 --- a/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java +++ b/src/main/java/de/dafuqs/spectrum/registries/SpectrumItemTags.java @@ -1,11 +1,15 @@ package de.dafuqs.spectrum.registries; import de.dafuqs.spectrum.*; +import net.minecraft.enchantment.*; import net.minecraft.item.*; import net.minecraft.registry.*; +import net.minecraft.registry.entry.*; import net.minecraft.registry.tag.*; import net.minecraft.util.*; +import java.util.*; + public class SpectrumItemTags { // "c" namespace @@ -32,7 +36,9 @@ public class SpectrumItemTags { public static final TagKey TAG_FILTERING_ITEMS = of("tag_filtering_items"); public static final TagKey WEEPING_GALA_LOGS = of("weeping_gala_logs"); public static final TagKey PLAYER_ATTRIBUTED_PLACEMENT = of("player_attributed_placement"); - + + public static final TagKey ENCHANTER_ITEM_BLACKLIST = of("enchanter_copying_and_applying_item_blacklisted"); + private static TagKey of(String id) { return TagKey.of(RegistryKeys.ITEM, SpectrumCommon.locate(id)); } @@ -41,4 +47,13 @@ private static TagKey common(String id) { return TagKey.of(RegistryKeys.ITEM, new Identifier("c", id)); } + public static boolean isIn(TagKey tag, Item item) { + Optional> optionalKey = Registries.ITEM.getKey(item); + if (optionalKey.isEmpty()) { + return false; + } + Optional> registryEntry = Registries.ITEM.getEntry(optionalKey.get()); + return registryEntry.filter(itemReference -> Registries.ITEM.getOrCreateEntryList(tag).contains(itemReference)).isPresent(); + } + } diff --git a/src/main/java/de/dafuqs/spectrum/registries/SpectrumRecipeTypes.java b/src/main/java/de/dafuqs/spectrum/registries/SpectrumRecipeTypes.java index 2ea2f96742..8ac9244548 100644 --- a/src/main/java/de/dafuqs/spectrum/registries/SpectrumRecipeTypes.java +++ b/src/main/java/de/dafuqs/spectrum/registries/SpectrumRecipeTypes.java @@ -3,6 +3,7 @@ import de.dafuqs.spectrum.*; import de.dafuqs.spectrum.recipe.anvil_crushing.*; import de.dafuqs.spectrum.recipe.cinderhearth.*; +import de.dafuqs.spectrum.recipe.crafting.*; import de.dafuqs.spectrum.recipe.crystallarieum.*; import de.dafuqs.spectrum.recipe.enchanter.*; import de.dafuqs.spectrum.recipe.enchantment_upgrade.*; @@ -18,6 +19,11 @@ import net.minecraft.registry.*; public class SpectrumRecipeTypes { + + public static final String SHAPED_GATED_CRAFTING_RECIPE_ID = "gated_crafting_shaped"; + public static final String SHAPELESS_GATED_CRAFTING_RECIPE_ID = "gated_crafting_shapeless"; + public static RecipeSerializer SHAPED_GATED_CRAFTING_RECIPE_SERIALIZER; + public static RecipeSerializer SHAPELESS_GATED_CRAFTING_RECIPE_SERIALIZER; public static final String SHAPED_PEDESTAL_RECIPE_ID = "pedestal"; public static final String SHAPELESS_PEDESTAL_RECIPE_ID = "pedestal_shapeless"; @@ -107,10 +113,13 @@ public String toString() { } public static void registerSerializer() { + SHAPED_GATED_CRAFTING_RECIPE_SERIALIZER = registerSerializer(SHAPED_GATED_CRAFTING_RECIPE_ID, new ShapedGatedCraftingRecipeSerializer(ShapedGatedCraftingRecipe::new)); + SHAPELESS_GATED_CRAFTING_RECIPE_SERIALIZER = registerSerializer(SHAPELESS_GATED_CRAFTING_RECIPE_ID, new ShapelessGatedCraftingRecipeSerializer(ShapelessGatedCraftingRecipe::new)); + SHAPED_PEDESTAL_RECIPE_SERIALIZER = registerSerializer(SHAPED_PEDESTAL_RECIPE_ID, new ShapedPedestalRecipeSerializer(ShapedPedestalRecipe::new)); SHAPELESS_PEDESTAL_RECIPE_SERIALIZER = registerSerializer(SHAPELESS_PEDESTAL_RECIPE_ID, new ShapelessPedestalRecipeSerializer(ShapelessPedestalRecipe::new)); PEDESTAL = registerRecipeType(SHAPED_PEDESTAL_RECIPE_ID); - + ANVIL_CRUSHING_RECIPE_SERIALIZER = registerSerializer(ANVIL_CRUSHING_ID, new AnvilCrushingRecipeSerializer(AnvilCrushingRecipe::new)); ANVIL_CRUSHING = registerRecipeType(ANVIL_CRUSHING_ID); diff --git a/src/main/resources/data/spectrum/recipes/crafting_table/glistering_melon.json b/src/main/resources/data/spectrum/recipes/crafting_table/glistering_melon.json index 7de41799e8..3f37df07a2 100644 --- a/src/main/resources/data/spectrum/recipes/crafting_table/glistering_melon.json +++ b/src/main/resources/data/spectrum/recipes/crafting_table/glistering_melon.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shaped", + "type": "spectrum:gated_crafting_shaped", "pattern": [ "MMM", "MMM", diff --git a/src/main/resources/data/spectrum/recipes/crafting_table/mushroom_stew.json b/src/main/resources/data/spectrum/recipes/crafting_table/mushroom_stew.json index 8ba0d81715..67df285a0d 100644 --- a/src/main/resources/data/spectrum/recipes/crafting_table/mushroom_stew.json +++ b/src/main/resources/data/spectrum/recipes/crafting_table/mushroom_stew.json @@ -1,5 +1,5 @@ { - "type": "minecraft:crafting_shapeless", + "type": "spectrum:gated_crafting_shapeless", "ingredients": [ { "tag": "spectrum:noxshrooms" diff --git a/src/main/resources/data/spectrum/tags/enchantment/enchanter_copying_and_applying_blacklisted.json b/src/main/resources/data/spectrum/tags/enchantment/enchanter_copying_and_applying_blacklisted.json new file mode 100644 index 0000000000..f72d209df7 --- /dev/null +++ b/src/main/resources/data/spectrum/tags/enchantment/enchanter_copying_and_applying_blacklisted.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/main/resources/data/spectrum/tags/items/enchanter_copying_and_applying_item_blacklisted.json b/src/main/resources/data/spectrum/tags/items/enchanter_copying_and_applying_item_blacklisted.json new file mode 100644 index 0000000000..f72d209df7 --- /dev/null +++ b/src/main/resources/data/spectrum/tags/items/enchanter_copying_and_applying_item_blacklisted.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/main/resources/spectrum.mixins.json b/src/main/resources/spectrum.mixins.json index 82896268ec..61f4e197c7 100644 --- a/src/main/resources/spectrum.mixins.json +++ b/src/main/resources/spectrum.mixins.json @@ -97,6 +97,7 @@ "accessors.PersistentProjectileEntityAccessor", "accessors.ProjectileAttackGoalAccessor", "accessors.ShapedRecipeAccessor", + "accessors.ShapelessRecipeSerializerAccessor", "accessors.SlimeEntityAccessor", "accessors.StatusEffectInstanceAccessor", "accessors.TridentEntityAccessor",