From d0116a37acce52ea2589e029384592be95585cb6 Mon Sep 17 00:00:00 2001 From: AyaYumi Date: Sat, 24 Oct 2026 14:39:02 +0800 Subject: [PATCH 1/3] fix(1.20.1): align optional dependencies and config behavior - bump UselessMod to 20.2.4.7 and align Mekanism/Generators 10.4.16.80, AppMek 1.4.3, Mekanism Extras 1.5.0 and Botany Pots 13.0.0+ - guard the Mekanism Extras 1.5 naquadah API and keep the optional integration boundary - make max_upgrade a single config source and cover getMax/NBT save-load clamps - fix ExtendedAE matrix pattern inventory sizing before exposedInventory is built - skip absent optional recipe adapters at debug level instead of warning with stack traces - clean unused textures, legacy templates and stale verification docs --- .gitignore | 4 + README.md | 17 +- build.gradle | 8 +- gradle.properties | 2 +- .../com/sorrowmist/useless/UselessMod.java | 4 +- .../compat/forge1201/OptionalIntegration.java | 45 +++- .../MekanismGeneratorsCompatLoader.java | 27 ++- .../recipe/AlloyFurnaceRecipeCatalog.java | 2 +- .../adapters/RecipeAdapterCompatRegistry.java | 12 + .../NaquadahReactorRecipeAdapter.java | 14 +- .../useless/core/config/ConfigManager.java | 14 +- .../eae/TileAssemblerMatrixPatternMixin.java | 33 +-- .../useless/mixin/mek/CachedRecipeMixin.java | 6 +- .../useless/mixin/mek/DigitalMinerMixin.java | 9 +- .../useless/mixin/mek/ElectricPumpMixin.java | 6 +- .../mixin/mek/FluidicPlenisherMixin.java | 6 +- .../mek/FormulaicAssemblicatorMixin.java | 6 +- .../useless/mixin/mek/MekanismUtilsMixin.java | 2 +- .../useless/mixin/mek/UpgradeMixin.java | 67 +++++- .../useless/mixin/mek/UpgradeUtilsMixin.java | 2 +- .../com/sorrowmist/useless/utils/MekTemp.java | 24 -- .../sorrowmist/useless/utils/MekUtils.java | 77 ++++-- .../utils/MekanismAccelerationState.java | 50 ++++ src/main/resources/META-INF/mods.toml | 6 +- .../block/advanced_alloy_furnace_bottom.png | Bin 351 -> 0 bytes .../block/advanced_alloy_furnace_flame.png | Bin 1811 -> 0 bytes .../advanced_alloy_furnace_flame.png.mcmeta | 6 - .../block/advanced_alloy_furnace_front.png | Bin 500 -> 0 bytes .../advanced_alloy_furnace_front_active.png | Bin 828 -> 0 bytes ...nced_alloy_furnace_front_active.png.mcmeta | 6 - .../block/advanced_alloy_furnace_granule.png | Bin 611 -> 0 bytes .../block/advanced_alloy_furnace_side.png | Bin 518 -> 0 bytes .../block/advanced_alloy_furnace_top.png | Bin 567 -> 0 bytes ...ture_regulator_panel.dark-original.bak.png | Bin 448 -> 0 bytes .../advanced_alloy_furnace_pattern_solt.png | Bin 616 -> 0 bytes .../gui/advanced_alloy_furnace_tips.png | Bin 159 -> 0 bytes .../gui/advanced_alloy_furnace_zu_jian.png | Bin 2420 -> 0 bytes .../jei_arrow_advanced_alloy_furnace_gui.png | Bin 141 -> 0 bytes .../useless_mod/textures/icon/slave.png | Bin 149 -> 0 bytes .../coils/Coil_ctm.png | Bin 339 -> 0 bytes .../coils/Coli_base.png | Bin 179 -> 0 bytes .../coils/Gallery.cache | 1 - .../useless_mod/textures/block/xbai2024.png | Bin 2981 -> 0 bytes .../gui/advanced_alloy_furnace_tips.png | Bin 159 -> 0 bytes .../jei_arrow_advanced_alloy_furnace_gui.png | Bin 141 -> 0 bytes src/main/resources/xia/updatelog.txt | 56 ----- .../templates/META-INF/enumextensions.json | 22 -- .../templates/META-INF/neoforge.mods.toml | 222 ------------------ .../forge1201/DependencyMetadataTest.java | 6 +- .../forge1201/OptionalIntegrationTest.java | 18 ++ 50 files changed, 347 insertions(+), 433 deletions(-) delete mode 100644 src/main/java/com/sorrowmist/useless/utils/MekTemp.java create mode 100644 src/main/java/com/sorrowmist/useless/utils/MekanismAccelerationState.java delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_bottom.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_flame.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_flame.png.mcmeta delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_front.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_front_active.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_front_active.png.mcmeta delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_granule.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_side.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_top.png delete mode 100644 src/main/resources/assets/useless_mod/textures/block/temperature_regulator_panel.dark-original.bak.png delete mode 100644 src/main/resources/assets/useless_mod/textures/gui/advanced_alloy_furnace_pattern_solt.png delete mode 100644 src/main/resources/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png delete mode 100644 src/main/resources/assets/useless_mod/textures/gui/advanced_alloy_furnace_zu_jian.png delete mode 100644 src/main/resources/assets/useless_mod/textures/gui/jei_arrow_advanced_alloy_furnace_gui.png delete mode 100644 src/main/resources/assets/useless_mod/textures/icon/slave.png delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Coil_ctm.png delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Coli_base.png delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Gallery.cache delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/block/xbai2024.png delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png delete mode 100644 src/main/resources/xia/assets/useless_mod/textures/gui/jei_arrow_advanced_alloy_furnace_gui.png delete mode 100644 src/main/resources/xia/updatelog.txt delete mode 100644 src/main/templates/META-INF/enumextensions.json delete mode 100644 src/main/templates/META-INF/neoforge.mods.toml create mode 100644 src/portBridgeTest/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegrationTest.java diff --git a/.gitignore b/.gitignore index cd3343a9..59b29725 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,10 @@ othermods crashreport .cursor .cache +*.cache +*.bak.png +*.orig +*.rej .codex # external reference code references/ diff --git a/README.md b/README.md index 572b662e..459938e1 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ A Minecraft mod featuring various utilities and enhancements. ## Forge 1.20.1 -Version `20.2.4.6` targets Minecraft 1.20.1, Forge 47.3.10+, Java 17, -AE2 15.4.8 and the Create 2 Mekanism: Sky Edition 2 integration profile. +Version `20.2.4.7` targets Minecraft 1.20.1, Forge 47.3.10+, Java 17, +AE2 15.4.8+, Mekanism 10.4.15+ (compiled against 10.4.16.80), +Mekanism Extras 1.5.0+ and the Create 2 Mekanism: Sky Edition 2 integration profile. Build with `./gradlew build` (Windows: `gradlew.bat build`); Python 3 is used by nine release-bytecode/outline regression checks. Dependencies resolve from public Maven repositories. The `portBridgeTest` suite also runs as part of `check` and is not shipped in the mod jar. @@ -13,15 +14,21 @@ The `portBridgeTest` suite also runs as part of `check` and is not shipped in th Forge, Minecraft and AE2 are required. Every compiled mod integration declares a minimum and compatible version range in `src/main/resources/META-INF/mods.toml`; these integrations remain optional, so an absent integration does not prevent startup. -Minimum versions follow the actual mod metadata (for example, Mekanism `10.4.15`, -not the jar filename's build suffix). Ore Generator samples accept Forge's `ores` -and `raw_materials` item tags, plus the equivalent `c:` datapack tags. +Runtime minima and compile pins are separate: for example, Mekanism accepts +`10.4.15+` while this build compiles against `10.4.16.80`. Botany Pots is accepted +from `13.0.0`; Mekanism Extras starts at `1.5.0` and uses its plural +`registries`/`genregistries` API for the Naquadah reactor adapter. Ore Generator +samples accept Forge's `ores` and `raw_materials` item tags, plus the equivalent +`c:` datapack tags. Optional integrations without a Forge implementation are excluded explicitly in `gradle/forge1201-pack-profile.json`; this is not a universal backport of every NeoForge integration. Extended Crafting compiles against official 6.0.10; the pack's unofficial tier-5/11x11 extension is supported through its native recipe contract and registry lookup without bundling or replacing the pack's jar. +Missing optional adapter classes are skipped quietly at debug level instead of +failing the interaction; actual invocation failures are reported once. The +Occultism spirit-egg handler is one such excluded adapter in this Forge build. ## Features diff --git a/build.gradle b/build.gradle index 4980c2d8..b154ab98 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ dependencies { modCompileOnly 'maven.modrinth:rxYaglEe:d83Wdhdn' // AdvancedAE 1.3.6-1.20.1 modCompileOnly 'maven.modrinth:qDJXZJTz:PQ3IlR98' // Mekanism More Machine 1.2.1 modCompileOnly 'maven.modrinth:rqFWfVlz:tT3CLYvK' // apotheosis-1.20.1-7.4.8 - modCompileOnly 'maven.modrinth:IiATswDj:d9GM663Q' // applied-mekanistics-1.4.2 + modCompileOnly 'maven.modrinth:IiATswDj:9n9p68Qq' // applied-mekanistics-1.4.3 modCompileOnly 'maven.modrinth:XxWD5pD3:jYgSnxye' // appliedenergistics2-forge-15.4.11 modCompileOnly 'maven.modrinth:udZtKfzP:Qm3GW128' // neoecoae-20.4.2-forge modCompileOnly 'maven.modrinth:B1CBVXHX:YSOP0G6O' // ldlib-forge-1.20.1-1.0.52.a @@ -81,8 +81,8 @@ dependencies { modCompileOnly 'maven.modrinth:fRiHVvU7:WtJS5tVw' // emi-1.1.22-1.20.1-forge modCompileOnly 'maven.modrinth:u6dRKJwZ:TrKZlZ0b' // JEI 15.74.0.227 modCompileOnly 'maven.modrinth:umyGl7zF:g5igndAv' // kubejs-forge-2001.6.5-build.16 - modCompileOnly 'maven.modrinth:Ce6I4WUE:9iboPfea' // mekanism-1.20.1-10.4.15.75 - modCompileOnly 'maven.modrinth:OFVYKsAk:x9re7wt4' // mekanismgenerators-1.20.1-10.4.15.75 + modCompileOnly 'maven.modrinth:Ce6I4WUE:uxe1WQp4' // mekanism-1.20.1-10.4.16.80 + modCompileOnly 'maven.modrinth:OFVYKsAk:Th4Czz4N' // mekanismgenerators-1.20.1-10.4.16.80 modCompileOnly 'maven.modrinth:tCkE8p2N:6SkuAGoz' // placebo-1.20.1-8.6.3 modCompileOnly 'maven.modrinth:KZO4S4DO:xDOvxyqP' // powah-5.0.11 modCompileOnly 'com.tterrag.registrate:Registrate:MC1.20-1.3.11' // registrate-mc1.20-1.3.11 @@ -91,7 +91,7 @@ dependencies { modCompileOnly 'maven.modrinth:1Ro7m06l:8krhHkrZ' // titanium-1.20.1-3.8.32 modCompileOnly 'maven.modrinth:Rw1NrDzF:tHDveaxK' // cucumber-1.20.1-7.0.15 modCompileOnly 'maven.modrinth:UhW5uCKw:eoUaDkZf' // glodium-1.20-1.5-forge - modCompileOnly 'maven.modrinth:HUZkxNTQ:zzqHs32A' // mekanism_extras-1.20.1-1.4.1 + modCompileOnly 'maven.modrinth:HUZkxNTQ:9T6CetkG' // mekanism_extras-1.20.1-1.5.0 modCompileOnly 'net.createmod.ponder:Ponder-Forge-1.20.1:1.0.80' // ponder-forge-1.20.1-1.0.80 modCompileOnly 'dev.engine-room.flywheel:flywheel-forge-1.20.1:1.0.4' // flywheel-forge-1.20.1-1.0.4 annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' diff --git a/gradle.properties b/gradle.properties index e57f6398..b4d4ee73 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,6 @@ forge_version=47.4.10 loader_version_range=[47,) mod_id=useless_mod mod_name=Useless Mod -mod_version=20.2.4.6 +mod_version=20.2.4.7 mod_group_id=com.sorrowmist.useless mod_license=MIT diff --git a/src/main/java/com/sorrowmist/useless/UselessMod.java b/src/main/java/com/sorrowmist/useless/UselessMod.java index b8de687b..aeaebc5a 100644 --- a/src/main/java/com/sorrowmist/useless/UselessMod.java +++ b/src/main/java/com/sorrowmist/useless/UselessMod.java @@ -208,7 +208,9 @@ public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { } private static InteractionResult trySpawnMarkedOccultismSpirit(PlayerInteractEvent.RightClickBlock event) { - if (!ModList.get().isLoaded("occultism")) { + if (!ModList.get().isLoaded("occultism") + || !OptionalIntegration.hasClass( + "com.sorrowmist.useless.content.recipe.adapters.occultism.OccultismSpiritEggHandler")) { return InteractionResult.PASS; } return OccultismCompat.trySpawnMarkedSpirit(event); diff --git a/src/main/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegration.java b/src/main/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegration.java index 4715ac66..385aea12 100644 --- a/src/main/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegration.java +++ b/src/main/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegration.java @@ -1,10 +1,17 @@ package com.sorrowmist.useless.compat.forge1201; +import com.mojang.logging.LogUtils; import java.lang.reflect.InvocationTargetException; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import net.minecraftforge.fml.ModList; +import org.slf4j.Logger; /** Optional source boundaries: no class linkage when the corresponding mod is absent. */ public final class OptionalIntegration { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Set REPORTED_FAILURES = ConcurrentHashMap.newKeySet(); + private OptionalIntegration() {} public static boolean hasClass(String className) { @@ -14,14 +21,46 @@ public static boolean hasClass(String className) { public static T call(String modId,String className,String method,Class resultType,T absent, Class[] signature,Object... arguments) { - if (!ModList.get().isLoaded(modId)) return absent; + ModList modList = ModList.get(); + if (modList == null || !modList.isLoaded(modId)) return absent; try { Object result=Class.forName(className).getMethod(method,signature).invoke(null,arguments); return resultType==Void.class ? null : resultType.cast(result); } catch (InvocationTargetException e) { - throw new IllegalStateException("Integration "+modId+" failed in "+className+"#"+method,e.getCause()); + reportFailure(modId, className, method, e.getCause()); + return absent; } catch (ReflectiveOperationException | LinkageError e) { - throw new IllegalStateException("Installed integration "+modId+" is unavailable in this build: "+className,e); + reportFailure(modId, className, method, e); + return absent; + } catch (ClassCastException e) { + reportFailure(modId, className, method, e); + return absent; + } + } + + /** + * Optional integrations must not take the game down. A missing class is common + * when this Forge build intentionally excludes a NeoForge-only adapter; report + * the first occurrence once and let the caller continue with its fallback. + */ + private static void reportFailure(String modId, String className, String method, Throwable cause) { + String key = modId + "#" + className + "#" + method; + if (REPORTED_FAILURES.add(key)) { + boolean missing = cause instanceof ClassNotFoundException + || cause instanceof NoClassDefFoundError; + if (missing) { + // Build-profile exclusions are expected; keep them out of normal logs. + LOGGER.debug("Optional integration {} is not present at {}#{}; skipping it", + modId, className, method); + return; + } + if (cause == null) { + LOGGER.warn("Optional integration {} is unavailable or failed at {}#{}; skipping it", + modId, className, method); + } else { + LOGGER.warn("Optional integration {} is unavailable or failed at {}#{}; skipping it", + modId, className, method, cause); + } } } } diff --git a/src/main/java/com/sorrowmist/useless/compat/mekanismgenerators/MekanismGeneratorsCompatLoader.java b/src/main/java/com/sorrowmist/useless/compat/mekanismgenerators/MekanismGeneratorsCompatLoader.java index e7748967..35e4b01e 100644 --- a/src/main/java/com/sorrowmist/useless/compat/mekanismgenerators/MekanismGeneratorsCompatLoader.java +++ b/src/main/java/com/sorrowmist/useless/compat/mekanismgenerators/MekanismGeneratorsCompatLoader.java @@ -14,9 +14,34 @@ private MekanismGeneratorsCompatLoader() { public static void register() { AlloyFurnaceRecipeManager.getInstance().registerAdapter( new FissionRecipeAdapter(), RecipeSourceIds.MEKANISM_GENERATORS); - if (ModList.get().isLoaded("mekanism_extras")) { + if (ModList.get().isLoaded("mekanism_extras") && hasNaquadahApi()) { AlloyFurnaceRecipeManager.getInstance().registerAdapter( new NaquadahReactorRecipeAdapter(), RecipeSourceIds.MEKANISM_GENERATORS); } } + + /** + * The 1.5 API moved these registries into plural packages. Keep a string-only + * check here so a future package move does not turn an optional integration + * into a hard class-loading failure. + */ + private static boolean hasNaquadahApi() { + try { + ClassLoader loader = MekanismGeneratorsCompatLoader.class.getClassLoader(); + Class gases = Class.forName( + "com.jerry.mekanism_extras.common.registries.ExtraGases", false, loader); + gases.getField("RICH_NAQUADAH_FUEL"); + gases.getField("RICH_URANIUM_FUEL"); + gases.getField("NAQUADAH_URANIUM_FUEL"); + Class blocks = Class.forName( + "com.jerry.generator_extras.common.genregistries.ExtraGenBlocks", false, loader); + blocks.getField("NAQUADAH_REACTOR_CONTROLLER"); + Class genGases = Class.forName( + "com.jerry.generator_extras.common.genregistries.ExtraGenGases", false, loader); + genGases.getField("POLONIUM_CONTAINING_STEAM"); + return true; + } catch (ClassNotFoundException | NoSuchFieldException | LinkageError ignored) { + return false; + } + } } diff --git a/src/main/java/com/sorrowmist/useless/content/recipe/AlloyFurnaceRecipeCatalog.java b/src/main/java/com/sorrowmist/useless/content/recipe/AlloyFurnaceRecipeCatalog.java index de3795b1..cd8e9f08 100644 --- a/src/main/java/com/sorrowmist/useless/content/recipe/AlloyFurnaceRecipeCatalog.java +++ b/src/main/java/com/sorrowmist/useless/content/recipe/AlloyFurnaceRecipeCatalog.java @@ -579,7 +579,7 @@ private static Snapshot build(Level level, long generation) { Map.copyOf(bySource), Map.copyOf(bySourceAndRecipeId), generation, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), ConcurrentHashMap.newKeySet()); - LOGGER.info("Built alloy-furnace recipe catalog: generation={}, recipes={}, sources={}, elapsed={} ms", + LOGGER.debug("Built alloy-furnace recipe catalog: generation={}, recipes={}, sources={}, elapsed={} ms", generation, ordered.size(), bySource.size(), (System.nanoTime() - startedAt) / 1_000_000L); return snapshot; } diff --git a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java index 040e6e51..edb455f0 100644 --- a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java +++ b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java @@ -200,6 +200,10 @@ private static void initCompat(FMLCommonSetupEvent event, @Nullable String modId } private static void registerByName(String className) { + if (!isClassAvailable(className)) { + LOGGER.debug("Optional recipe adapter {} is not present in this build", className); + return; + } try { Class type=Class.forName(className,true,RecipeAdapterCompatRegistry.class.getClassLoader()); register((IRecipeAdapter)type.getConstructor().newInstance()); @@ -209,6 +213,10 @@ private static void registerByName(String className) { } private static void registerFactory(String className) { + if (!isClassAvailable(className)) { + LOGGER.debug("Optional recipe adapter factory {} is not present in this build", className); + return; + } try { Class type=Class.forName(className,true,RecipeAdapterCompatRegistry.class.getClassLoader()); var adapters=(java.util.List)type.getMethod("createAdapters").invoke(null); @@ -329,6 +337,10 @@ private static void registerMekanismGenerators() { } private static void invokeOptionalLoader(String className) { + if (!isClassAvailable(className)) { + LOGGER.debug("Optional recipe adapter loader {} is not present in this build", className); + return; + } try { Class loader = Class.forName(className, true, RecipeAdapterCompatRegistry.class.getClassLoader()); loader.getMethod("register").invoke(null); diff --git a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/mekanism/mekanismextra/NaquadahReactorRecipeAdapter.java b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/mekanism/mekanismextra/NaquadahReactorRecipeAdapter.java index ba0af5d0..593511c2 100644 --- a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/mekanism/mekanismextra/NaquadahReactorRecipeAdapter.java +++ b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/mekanism/mekanismextra/NaquadahReactorRecipeAdapter.java @@ -2,9 +2,9 @@ import appeng.api.stacks.GenericStack; import com.jerry.generator_extras.common.config.GenLoadConfig; -import com.jerry.generator_extras.common.genregistry.ExtraGenBlocks; -import com.jerry.generator_extras.common.genregistry.ExtraGenGases; -import com.jerry.mekanism_extras.common.registry.ExtraGases; +import com.jerry.generator_extras.common.genregistries.ExtraGenBlocks; +import com.jerry.generator_extras.common.genregistries.ExtraGenGases; +import com.jerry.mekanism_extras.common.registries.ExtraGases; import com.sorrowmist.useless.content.recipe.AdapterUtils; import com.sorrowmist.useless.content.recipe.AdvancedAlloyFurnaceRecipe; import com.sorrowmist.useless.content.recipe.adapters.mekanism.MekanismChemicalRecipeSupport; @@ -22,7 +22,7 @@ import java.util.List; -/** Optional Mekanism Extras naquadah reactor recipe-viewer adapter. */ +/** Optional Mekanism Extras 1.5+ naquadah reactor recipe-viewer adapter. */ public final class NaquadahReactorRecipeAdapter extends MekanismSyntheticRecipeAdapter { private static final long PROCESS_TICKS = AdapterUtils.MEKANISM_BASE_TICKS_REQUIRED; private static final ResourceLocation SOURCE_ID = @@ -56,12 +56,12 @@ protected List> createGeneratedRecipes(Lev } addFuelRecipe(result, pairedFuelWaterInputs, - List.of(ExtraGases.RICH_SILICON_LIQUID_FUEL.getStack(1), - ExtraGases.RICH_URANIUM_LIQUID_FUEL.getStack(1)), + List.of(ExtraGases.RICH_NAQUADAH_FUEL.getStack(1), + ExtraGases.RICH_URANIUM_FUEL.getStack(1)), MekanismChemicalRecipeSupport.saturatingMultiply(waterPerFuel, 2L), "rich_fuels_water"); addFuelRecipe(result, singleFuelWaterInputs, - List.of(ExtraGases.SILICON_URANIUM_FUEL.getStack(1)), + List.of(ExtraGases.NAQUADAH_URANIUM_FUEL.getStack(1)), waterPerFuel, "naquadah_uranium_fuel_water"); addWaterOnlyRecipe(result); return result; diff --git a/src/main/java/com/sorrowmist/useless/core/config/ConfigManager.java b/src/main/java/com/sorrowmist/useless/core/config/ConfigManager.java index 7ff29460..302528f5 100644 --- a/src/main/java/com/sorrowmist/useless/core/config/ConfigManager.java +++ b/src/main/java/com/sorrowmist/useless/core/config/ConfigManager.java @@ -218,7 +218,8 @@ public class ConfigManager { .defineInRange("botany_pot_growth_multiplier", 1, 1, Integer.MAX_VALUE); MATRIX_PATTERN_COUNT = SERVER_BUILDER - .comment("矩阵样板槽位倍数 - 减少数量时请保持槽位空!否则可能会造成样板丢失") + .comment("矩阵样板槽位倍数 - 新放置的矩阵样板方块生效;已放置的方块保持原有容量", + "减少数量时请保持槽位空!否则可能会造成样板丢失") .defineInRange("matrix_pattern_count", 1, 1, 100); SERVER_BUILDER.pop(); @@ -803,6 +804,8 @@ public class ConfigManager { "enable_ufo_recipe_conversion", true); COMMON_BUILDER.pop(); + // Options for adapters excluded by gradle/forge1201-pack-profile.json stay in the + // spec for cross-pack config compatibility; the registry skips their absent classes. RECIPE_CONVERSION_OPTIONS = Map.ofEntries( Map.entry("thermal", ENABLE_THERMAL_RECIPE_CONVERSION), Map.entry("bloodmagic", ENABLE_BLOOD_MAGIC_RECIPE_CONVERSION), @@ -1013,6 +1016,15 @@ public static int getMaxUpgrade() { return getConfigValue(MAX_UPGRADE); } + /** Returns the loaded max_upgrade, or null while the server config is not available yet. */ + public static Integer getLoadedMaxUpgrade() { + try { + return MAX_UPGRADE.get(); + } catch (IllegalStateException | NullPointerException ignored) { + return null; + } + } + // 万象炉AE网络抽电配置 public static boolean isFurnaceDrawAppfluxEnergyEnabled() { return getConfigValue(FURNACE_DRAW_APPFLUX_ENERGY); diff --git a/src/main/java/com/sorrowmist/useless/mixin/eae/TileAssemblerMatrixPatternMixin.java b/src/main/java/com/sorrowmist/useless/mixin/eae/TileAssemblerMatrixPatternMixin.java index a9b09e50..7d3ae24c 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/eae/TileAssemblerMatrixPatternMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/eae/TileAssemblerMatrixPatternMixin.java @@ -1,36 +1,23 @@ package com.sorrowmist.useless.mixin.eae; -import appeng.util.inv.AppEngInternalInventory; -import com.glodblock.github.extendedae.common.tileentities.matrix.TileAssemblerMatrixPattern; import com.sorrowmist.useless.core.config.ConfigManager; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; -@Mixin(value = TileAssemblerMatrixPattern.class,remap = false) +@Mixin(targets = "com.glodblock.github.extendedae.common.tileentities.matrix.TileAssemblerMatrixPattern", remap = false) public class TileAssemblerMatrixPatternMixin { - @Mutable @Shadow @Final private AppEngInternalInventory patternInventory; - /** - * 在构造函数完成后替换patternInventory + * 修改构造函数中 patternInventory 的硬编码容量。 + * 必须在 exposedInventory 包装它之前改掉,否则两个库存容量会不一致。 */ - @Inject( + @ModifyConstant( method = "", - at = @At("RETURN") + constant = @Constant(intValue = 36), + remap = false ) - private void onConstructed(BlockPos pos, BlockState blockState, CallbackInfo ci) { - TileAssemblerMatrixPattern self = (TileAssemblerMatrixPattern) (Object) this; - - // 创建新的库存实例 - int newSize = 36 * ConfigManager.getMatrixPatternCount(); - this.patternInventory = new AppEngInternalInventory(self, newSize, 1); - this.patternInventory.setFilter(new TileAssemblerMatrixPattern.Filter(self::getLevel)); + private int useless$modifyPatternInventorySize(int original) { + return 36 * ConfigManager.getMatrixPatternCount(); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/CachedRecipeMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/CachedRecipeMixin.java index db080511..e46cbf0d 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/CachedRecipeMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/CachedRecipeMixin.java @@ -1,6 +1,6 @@ package com.sorrowmist.useless.mixin.mek; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import mekanism.api.recipes.cache.CachedRecipe; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -10,7 +10,7 @@ import java.util.function.IntSupplier; -@Mixin(value = CachedRecipe.class, remap = false) +@Mixin(value = CachedRecipe.class, remap = false, priority = 2000) public abstract class CachedRecipeMixin { @Shadow @@ -29,6 +29,6 @@ public abstract class CachedRecipeMixin { remap = false ) private void injected(CallbackInfo ci) { - MekTemp.inject.accept(this.requiredTicks.getAsInt(), this::process); + MekanismAccelerationState.inject.accept(this.requiredTicks.getAsInt(), this::process); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/DigitalMinerMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/DigitalMinerMixin.java index 2ece5d1e..891358ef 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/DigitalMinerMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/DigitalMinerMixin.java @@ -2,14 +2,14 @@ import mekanism.api.Upgrade; import mekanism.common.tile.machine.TileEntityDigitalMiner; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(value = TileEntityDigitalMiner.class, remap = false) +@Mixin(value = TileEntityDigitalMiner.class, remap = false, priority = 2000) public abstract class DigitalMinerMixin { @Shadow private int delay; @@ -28,9 +28,12 @@ public abstract class DigitalMinerMixin { remap = false ) private void onEnergyExtracted(CallbackInfo cir) { + if (MekanismAccelerationState.rebornOwnsAcceleration()) { + return; + } if (this.delay < 0) { // 补足所有负 delay 的挖掘 - int extraOperations = Math.min(-this.delay, MekTemp.MAX_EXTRA_OPERATIONS_PER_TICK); + int extraOperations = Math.min(-this.delay, MekanismAccelerationState.MAX_EXTRA_OPERATIONS_PER_TICK); for (int i = 0; i < extraOperations; i++) { this.tryMineBlock(); } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/ElectricPumpMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/ElectricPumpMixin.java index 4db2f0b3..c735e8e7 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/ElectricPumpMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/ElectricPumpMixin.java @@ -1,6 +1,6 @@ package com.sorrowmist.useless.mixin.mek; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import mekanism.common.tile.machine.TileEntityElectricPump; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(value = TileEntityElectricPump.class, remap = false) +@Mixin(value = TileEntityElectricPump.class, remap = false, priority = 2000) public abstract class ElectricPumpMixin { @Shadow @@ -24,6 +24,6 @@ public abstract class ElectricPumpMixin { shift = At.Shift.AFTER ) ) private void injected(CallbackInfo cir) { - MekTemp.inject.accept(this.ticksRequired, this::onUpdateServer); + MekanismAccelerationState.inject.accept(this.ticksRequired, this::onUpdateServer); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/FluidicPlenisherMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/FluidicPlenisherMixin.java index 2fbb3bfb..643d0328 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/FluidicPlenisherMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/FluidicPlenisherMixin.java @@ -1,6 +1,6 @@ package com.sorrowmist.useless.mixin.mek; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import mekanism.common.tile.machine.TileEntityFluidicPlenisher; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(value = TileEntityFluidicPlenisher.class, remap = false) +@Mixin(value = TileEntityFluidicPlenisher.class, remap = false, priority = 2000) public abstract class FluidicPlenisherMixin { @Shadow @@ -27,6 +27,6 @@ public abstract class FluidicPlenisherMixin { remap = false ) public void injected(CallbackInfo cir) { - MekTemp.inject.accept(this.ticksRequired, this::onUpdateServer); + MekanismAccelerationState.inject.accept(this.ticksRequired, this::onUpdateServer); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/FormulaicAssemblicatorMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/FormulaicAssemblicatorMixin.java index d0deeeed..cd5c92a3 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/FormulaicAssemblicatorMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/FormulaicAssemblicatorMixin.java @@ -1,6 +1,6 @@ package com.sorrowmist.useless.mixin.mek; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import mekanism.common.tile.machine.TileEntityFormulaicAssemblicator; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(value = TileEntityFormulaicAssemblicator.class, remap = false) +@Mixin(value = TileEntityFormulaicAssemblicator.class, remap = false, priority = 2000) public abstract class FormulaicAssemblicatorMixin { @Shadow @@ -27,6 +27,6 @@ public abstract class FormulaicAssemblicatorMixin { remap = false ) public void injected(CallbackInfo cir) { - MekTemp.inject.accept(this.ticksRequired, this::onUpdateServer); + MekanismAccelerationState.inject.accept(this.ticksRequired, this::onUpdateServer); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/MekanismUtilsMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/MekanismUtilsMixin.java index 29d1965a..6d2bfb72 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/MekanismUtilsMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/MekanismUtilsMixin.java @@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(value=MekanismUtils.class,remap=false) +@Mixin(value = MekanismUtils.class, remap = false, priority = 2000) public class MekanismUtilsMixin { @Inject(method="getTicks",at=@At("HEAD"),cancellable=true) private static void ticks(IUpgradeTile tile,int base,CallbackInfoReturnable cir){ diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java index dfa6a852..aac224ed 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java @@ -1,16 +1,20 @@ package com.sorrowmist.useless.mixin.mek; -import com.sorrowmist.useless.utils.MekTemp; +import com.sorrowmist.useless.utils.MekanismAccelerationState; import com.sorrowmist.useless.utils.MekUtils; import mekanism.api.Upgrade; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** - * Mixin to modify Mekanism upgrade limits + * Mixin to modify Mekanism upgrade limits. */ -@Mixin({Upgrade.class}) +@Mixin(value = Upgrade.class, priority = 2000) public abstract class UpgradeMixin { @ModifyVariable( method = {""}, @@ -18,9 +22,9 @@ public abstract class UpgradeMixin { ordinal = 1, argsOnly = true ) - private static String getName(String s) { - MekTemp.name = s; - return s; + private static String useless$captureName(String name) { + MekanismAccelerationState.name = name; + return name; } @ModifyVariable( @@ -29,7 +33,54 @@ private static String getName(String s) { ordinal = 1, argsOnly = true ) - private static int toFullStack(int i) { - return !MekTemp.name.equals("speed") && !MekTemp.name.equals("energy") ? i : MekUtils.MAX_UPGRADE; + private static int useless$maxUpgrade(int original) { + return !"speed".equals(MekanismAccelerationState.name) + && !"energy".equals(MekanismAccelerationState.name) + ? original : MekUtils.getMaxUpgrade(); + } + + /** + * maxStack is captured when the enum is constructed. Return the live config + * value for runtime reads too, including config reloads. + */ + @Inject(method = "getMax", at = @At("HEAD"), cancellable = true, remap = false) + private void useless$getMax(CallbackInfoReturnable cir) { + Upgrade self = (Upgrade) (Object) this; + if (self == Upgrade.SPEED || self == Upgrade.ENERGY) { + cir.setReturnValue(MekUtils.getMaxUpgrade()); + } + } + + /** + * NBT loading reads the captured maxStack field directly, bypassing getMax(). + */ + @Redirect( + method = "buildMap", + at = @At( + value = "FIELD", + target = "Lmekanism/api/Upgrade;maxStack:I", + opcode = Opcodes.GETFIELD + ), + remap = false + ) + private static int useless$nbtLoadMax(Upgrade upgrade) { + return upgrade.getMax(); + } + + /** + * NBT saving also reads maxStack directly; without this redirect a machine + * with more than 16 upgrades would be clamped back to 16 on save. + */ + @Redirect( + method = "saveMap", + at = @At( + value = "FIELD", + target = "Lmekanism/api/Upgrade;maxStack:I", + opcode = Opcodes.GETFIELD + ), + remap = false + ) + private static int useless$nbtSaveMax(Upgrade upgrade) { + return upgrade.getMax(); } } diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeUtilsMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeUtilsMixin.java index 9956226f..dfaa2b15 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeUtilsMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeUtilsMixin.java @@ -16,7 +16,7 @@ /** * Mixin for UpgradeUtils to modify upgrade information display */ -@Mixin(value = UpgradeUtils.class, remap = false) +@Mixin(value = UpgradeUtils.class, remap = false, priority = 2000) public class UpgradeUtilsMixin { /** diff --git a/src/main/java/com/sorrowmist/useless/utils/MekTemp.java b/src/main/java/com/sorrowmist/useless/utils/MekTemp.java deleted file mode 100644 index 76a13642..00000000 --- a/src/main/java/com/sorrowmist/useless/utils/MekTemp.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sorrowmist.useless.utils; - -import java.util.function.BiConsumer; - -public class MekTemp { - public static String name; - public static final int MAX_EXTRA_OPERATIONS_PER_TICK = 128; - public static final ThreadLocal isInjecting = ThreadLocal.withInitial(() -> false); - public static final BiConsumer - inject = (reqTime, process) -> { - if (!isInjecting.get()) { - isInjecting.set(true); - - try { - int extraOperations = Math.min(-reqTime, MAX_EXTRA_OPERATIONS_PER_TICK); - for(int i = 0; i < extraOperations; ++i) { - process.run(); - } - } finally { - isInjecting.set(false); - } - } - }; -} diff --git a/src/main/java/com/sorrowmist/useless/utils/MekUtils.java b/src/main/java/com/sorrowmist/useless/utils/MekUtils.java index d683945a..ba9019a7 100644 --- a/src/main/java/com/sorrowmist/useless/utils/MekUtils.java +++ b/src/main/java/com/sorrowmist/useless/utils/MekUtils.java @@ -3,36 +3,69 @@ import com.electronwill.nightconfig.core.Config; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.sorrowmist.useless.core.config.ConfigManager; +import com.mojang.logging.LogUtils; import mekanism.api.Upgrade; import mekanism.common.config.MekanismConfig; import mekanism.common.tile.interfaces.IUpgradeTile; import net.minecraftforge.fml.loading.FMLPaths; +import org.slf4j.Logger; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; public class MekUtils { - public static int MAX_UPGRADE = 16; + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int DEFAULT_MAX_UPGRADE = 16; + private static volatile int startupMaxUpgrade = -1; - static { - File file = FMLPaths.CONFIGDIR.get().resolve("useless_mod-server.toml").toFile(); - - CommentedFileConfig config = CommentedFileConfig.builder(file).autosave().sync().build(); - config.load(); + /** + * Reads max_upgrade from the single owning config source. The TOML fallback + * is only used while Mekanism's Upgrade enum is being constructed, which + * happens before Forge finishes loading the server config. + */ + public static int getMaxUpgrade() { + Integer loaded = ConfigManager.getLoadedMaxUpgrade(); + if (loaded != null) { + return loaded; + } - Config mekanism = config.get("mekanism_upgrade"); - if (mekanism != null) { - int max = mekanism.getInt("max_upgrade"); - if (max < 1 || max > 64) { - max = 16; + int cached = startupMaxUpgrade; + if (cached < 0) { + synchronized (MekUtils.class) { + cached = startupMaxUpgrade; + if (cached < 0) { + cached = readStartupMaxUpgrade(); + startupMaxUpgrade = cached; + } } - MAX_UPGRADE = max; - } else { - config.set("mekanism_upgrade.max_upgrade", MAX_UPGRADE); - config.save(); + } + return cached; + } + + private static int readStartupMaxUpgrade() { + Path path = FMLPaths.CONFIGDIR.get().resolve("useless_mod-server.toml"); + if (!Files.isRegularFile(path)) { + return DEFAULT_MAX_UPGRADE; } - config.close(); + try (CommentedFileConfig config = CommentedFileConfig.builder(path).build()) { + config.load(); + Config section = config.get("mekanism_upgrade"); + if (section != null) { + Object raw = section.get("max_upgrade"); + if (raw instanceof Number number) { + int value = number.intValue(); + if (value >= 1 && value <= 64) { + return value; + } + } + } + } catch (RuntimeException exception) { + LOGGER.debug("Unable to read mekanism_upgrade.max_upgrade from {}; using {}", + path, DEFAULT_MAX_UPGRADE, exception); + } + return DEFAULT_MAX_UPGRADE; } public static double time(IUpgradeTile tile) { @@ -43,11 +76,17 @@ public static double time(IUpgradeTile tile) { public static double electricity(IUpgradeTile tile) { // 简化公式:每8个能量升级降低10倍能耗 - return Math.pow((double)(MekanismConfig.general.maxUpgradeMultiplier.get() * ConfigManager.getElectricityMultiplier()), (double)tile.getComponent().getUpgrades(Upgrade.ENERGY) / (double)-8.0F); + double multiplier = Math.pow((double)(MekanismConfig.general.maxUpgradeMultiplier.get() + * ConfigManager.getElectricityMultiplier()), + (double)tile.getComponent().getUpgrades(Upgrade.ENERGY) / (double)-8.0F); + return Double.isFinite(multiplier) ? multiplier : 1.0; } public static double capacity(IUpgradeTile tile) { - return Math.pow((double)(MekanismConfig.general.maxUpgradeMultiplier.get() * ConfigManager.getCapacityMultiplier()), (double)tile.getComponent().getUpgrades(Upgrade.ENERGY) / (double)8.0F); + double multiplier = Math.pow((double)(MekanismConfig.general.maxUpgradeMultiplier.get() + * ConfigManager.getCapacityMultiplier()), + (double)tile.getComponent().getUpgrades(Upgrade.ENERGY) / (double)8.0F); + return Double.isFinite(multiplier) ? multiplier : 1.0; } public static String exponential(double d) { diff --git a/src/main/java/com/sorrowmist/useless/utils/MekanismAccelerationState.java b/src/main/java/com/sorrowmist/useless/utils/MekanismAccelerationState.java new file mode 100644 index 00000000..9df60ff4 --- /dev/null +++ b/src/main/java/com/sorrowmist/useless/utils/MekanismAccelerationState.java @@ -0,0 +1,50 @@ +package com.sorrowmist.useless.utils; + +import net.minecraftforge.fml.ModList; + +import java.util.function.BiConsumer; + +public class MekanismAccelerationState { + /** Set by UpgradeMixin while Mekanism's Upgrade enum is being constructed. */ + public static String name; + public static final int MAX_EXTRA_OPERATIONS_PER_TICK = 128; + public static final ThreadLocal isInjecting = ThreadLocal.withInitial(() -> false); + private static Boolean rebornLoaded; + + /** + * Mekanism Upgrades: Reborn installs equivalent extra-operation callbacks. + * Running both would process the same machine twice per tick, so only one + * implementation may own the acceleration loop. + */ + public static boolean rebornOwnsAcceleration() { + Boolean cached = rebornLoaded; + if (cached == null) { + try { + if (ModList.get() == null) { + return false; + } + cached = ModList.get().isLoaded("mekanismupgradesreborn"); + } catch (Throwable ignored) { + cached = false; + } + rebornLoaded = cached; + } + return cached; + } + + public static final BiConsumer + inject = (reqTime, process) -> { + if (!rebornOwnsAcceleration() && !isInjecting.get()) { + isInjecting.set(true); + + try { + int extraOperations = Math.min(-reqTime, MAX_EXTRA_OPERATIONS_PER_TICK); + for(int i = 0; i < extraOperations; ++i) { + process.run(); + } + } finally { + isInjecting.set(false); + } + } + }; +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 1db259bb..7ef42f4a 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -41,7 +41,7 @@ ordering="AFTER" side="BOTH" # Optional integrations: absence is allowed; installed versions must match the supported API line. -# Minimums are the versions used by this Forge build, taken from each dependency's mods.toml. +# Minimums are the lowest API lines accepted by this Forge build; compile pins live in build.gradle. [[dependencies.useless_mod]] modId="advanced_ae" @@ -88,7 +88,7 @@ side="BOTH" [[dependencies.useless_mod]] modId="botanypots" mandatory=false -versionRange="[13.0.41,14)" +versionRange="[13.0.0,14)" ordering="AFTER" side="BOTH" @@ -291,7 +291,7 @@ side="BOTH" [[dependencies.useless_mod]] modId="mekanism_extras" mandatory=false -versionRange="[1.20.1-1.4.1,1.20.2)" +versionRange="[1.5.0,2)" ordering="AFTER" side="BOTH" diff --git a/src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_bottom.png b/src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_bottom.png deleted file mode 100644 index af5005ae148a1be54481d323d2ea52b8d31d2ba6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 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 diff --git a/src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_side.png b/src/main/resources/assets/useless_mod/textures/block/advanced_alloy_furnace_side.png deleted file mode 100644 index ce0edad4f28b011b79aae8b48b8b323ff4267ece..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 518 zcmV+h0{Q)kP)pF8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0004z zNklAj z`yqRR@XjA(94DQyi_?r}tfYOl+3T!z)>-?6%uJ>S;MgAwma0YYFu9kpkeSK!R&u#M zNmYsKI{&G|g9AdTX|tDKTP3@&0Dx^-Xu3{xGz>ts-e5d2M!V|%but_1Ns60PP-4PQ9+PrgLAL{0>F;vswreL{Qv*}07*qo IM6N<$f^iq+eEpF8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0005P zNklyu2O5c zx3$IY-ku{EkI(sjaY4fvQfu)&4@5wf)LH<1V?dQZxw^Zp7W=(}g@qqiSNOL~0vsWf zU{8e2R*R=ko;iZogMsr~otlGu01?tSE-m_=M>7mv233MI53pejX#uXP@w~DpLBPx2 zfy?0i$y;ucqy!g$LOSptAwWMmq;|jkARC^%<5wKh$N{U~*Hu3{Tvp)cld4K?Q&ZGY z|0vI3IN)ZQV6CM%RyPJ!T{~Swcy)a22;O`cay|LEBwIw*5~RRp7`kh0Z+Eg!pFi?@ zIxVG&2k^@&2oUE?E+x83a6jwCf1IoQuJB|Qg{&&9k#&<4^r}fEa@O#1wOVR6n_4cHs#Gdg?)UpDm&;0}QnpT~)5>HrIvfrTQy}0Jz{L4{)@U@c zMkXSds?lgz{(L^|&*!ISkw~O-yWLbM6f_=>4NM~huh&cLZ8jT|w%u;E-|s)cemFri z8nu)$8Ig&+29c8;k4NE!$D4%f^=kEcy&lM13WUXC(dx6=%<&4hFc=KJU_YHsS}YcC znlUq<&zqT($wVBqUat)sJSde)9hi5!osm2q57V5@W|d4P6_3Z|VB}mbmv;|18N*x# zO?ZI>0x&(){aUF96DgwcZ}T7pNVuuC`2GX}PCz>j|4G9A6HG=um&=7IsfSze2CmU_ qULB8TwOWN2$v$Sc+imdwLHq{$veabb1wPgQ00004nJa0`PlBg3pY5)2GX zQl2i3Ar*7p-Z1n^4rFM%`1}FWluXxUm%I-0_Gs*A+E`E;d^@7Ux`0_MEQ&YJ#WQE0 zQYVY?lgx9PB7*ZCK8}0%H#&X!^!3cawp%RiUR{|gce^;P&}f>aB)@XximxF0EhK^R-r+mc&|C#`YQ(NXCxOa< zlqn|`R{+gDbV=0D4Jdy}be$(Q{{c;!wywYkC=aB3F+Boy+J=(W$v|a5Dq9FMh(M0f z`OH;cSZA~5&?4DH+4GTB$1Z<9y}=V_@PJK?^uGSEe$M56U28XAK7GBkz9UiP9)rk+ Wyj?6+Qs;q5hr!d;&t;ucLK6U&2kL78 diff --git a/src/main/resources/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png b/src/main/resources/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png deleted file mode 100644 index bc23b7dbd3583492d37485c9571439b56ac651b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)L!3HEN&baUbsWeX)#}En0ap8k(4`X_X-d$t}5+Lb*1D zT&9SFGUaYend@O>Zn4>(InVRFown%3HkPvqz09k1=p)OlbzO%zPRp9?m<>lcb?+y z-12=o1r^PvCfb=8huG~7fjQeZw493r4NM0@N)#-ELw)@S1XIhT^x?&|hF^^Qn2)RZ z*Xvi!LOULRViV`D9a zqIB3%5rEJ2Edb0OuzCMhp3<_TzB5Tx{SAKK4IRMNjR|TP&`8l#{^$C?X#W8{Is^b< zwo-uh%mE1DApC|2slPe0yAarSrG1(6YJ5HP=wb2TA_&-d z;J;w}d%6XX_jAqMpoa=+MZ`&BObwXFYDi9bSwKhCN7g686uu|PkX?pG)|w(0HT_tV zj0iSUs>7+8Jn20z$oC&I33EEtQp^dhtSI(+{puOFb3}!#ID>foeG-Uu%^EJd#>;YJ zkV#0SCwXn$fy+IXla%Sv`=%n0b-{w6B^6$x4GVn>u&L}t#AQS>%vf0yA+yVB| zuf-Q>9}q=|87#w1p2z)VdQAjKj{4=5qW?U*4nL3)iX;T+@$Ov-ksBSwp#a0iTBn`%(l*(0_TA*N<$nR8(iyN<|7B=J2C5Xt*SbEA%=ias~)lUUFH z3HV(TKDcC_u{=FA+miWF6;>0kBf6My9+cypUTw45f zJq-(33*pY*a#aw@f2~!L=&UMQwG4%qO+{96OO$ja)Tw#(vVTa~sMQ92T-R(so0QCW zyOxhC+;eaDpnOOZyt`DlcgGYx2-(DhkgI;C!bLOLE0^~IIm}tvEpl`%MOe`lRL-Z2 zUS-CRXeyURtGd{jyufP7##Q4```iWxOSbG)&!Cl;M?W`kD=3Yaby+wQy3y9hV#`QB z<+f1NaqRx2cP-5apiuNkJ)e`1HpuTMI8>h#+F$8FMT!hqKx| zHWsRd$^GTbet_D!6X355k9@f*dK&d;a3*_4$QL!(ax_8%Os`SMM@zeP0ZK&U{T$}mxtj#5p&N)K^wXN$)IS71B-425b z6WKc08I?Waw-$#dojDj+`PVf~K+AVeH25e>l!f=Sxz%B=3=#On8aVY^N2Zlv;=48; zw^0L;SYZF*QbI_rlr-~qn*;+(kc3Ulk-0H?f<`#c3TN4|!ew1Tqu)DP8{C-~0vF)( zv$61vrLIGP${y6lPRs!K;6(p)zDJY-M1RgZ_>)Pjg=r2m2KX@(Y(xwTbQ4uCYIf#D zJ$oukVS4st#I3miWg!J(RS;`Wnmn-cIf!y+Q!6&52n@u!3%dT;WbXwp{D26%=@Mtf z^d*6{WcpHB$U`ltSNJz(tfoJIg#LXj9T*)e{vjz?Hh$IxXPb@ z7is(u8cWlQr42@xlgR;nh&~RMKOROz(r4XetKUfDL{X$X%M~kC)(&jwel-lKPPSkt<=ey=ag=*YHh2JPSa@bm z+)s>Fg~rmu%9K_GxuDMqKnktCL{b(f<5RGvrugsL*}J$pDP$SwX>4W;K)ECLzroF^ zcRI8tpE57iaD95<&f~*d?8#~f5=*&i`nb4fSHEN1(m5}qDUSGC^M7wur-cf)^BZi9 SVlfGu&Q2b8M3x-$x&056!B<59 diff --git a/src/main/resources/assets/useless_mod/textures/gui/jei_arrow_advanced_alloy_furnace_gui.png b/src/main/resources/assets/useless_mod/textures/gui/jei_arrow_advanced_alloy_furnace_gui.png deleted file mode 100644 index c5c16997aba3481c6fd3525d92362daf8c574cc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^ia^Z4!3HGD-KR|iQX!r$jv*F;$q5n+ALKbEtW9-# zc42bw8v(ZzK3iGF&E0}5Y_|jzj`Kv69B_Jcu$i4lN1^GSgQFv3j_Qd#S65fJs@weA p_@}VEyT8AGlJkpq0wwGW47D4TufLSz+W|D6!PC{xWt~$(698x)EA{{Y diff --git a/src/main/resources/assets/useless_mod/textures/icon/slave.png b/src/main/resources/assets/useless_mod/textures/icon/slave.png deleted file mode 100644 index feefa4499c470106cf7eab9dc2c16773426ccfd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`F`h1tAr^vf11$L%6gZq8OINDc z1iejI^tIz%nPIEgLM8c!B97}G)U9}MYuaaqX9maC{@ye(B0cT!tp}^B_Ltc+XdC}H y{FsyD%w5*}!>h1nytE#Xt(196jiEFfO#P|1TrK4R*kj7hf4jWrH-5ss~v;i-ONoI)lmFQ(qS;c=@c&AJ9*`E89WediegV|10ijrsLjc(~#IQjw zCPp1DH6Z z)D7A1>+dEhOg+29{J?8_)qM#Qji#&K3`+?&(%Z7(zrON8-m)W;#p5MCQa8`|na#6- zdy8+Y#Ezv$4#YjE|JIdacKYh&_YJcgCD=TYH!JLZpgoDZBb8rB{Dj9J7Ip>|*$Kzm eTJIdV$PjRR@t>oU-Yo;Vg2B_(&t;ucLK6T)Y)2UY diff --git a/src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Gallery.cache b/src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Gallery.cache deleted file mode 100644 index a58b704b..00000000 --- a/src/main/resources/xia/assets/useless_mod/textures/block/multiblock_alloy_furnace/coils/Gallery.cache +++ /dev/null @@ -1 +0,0 @@ -[{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/Coli_base.png","LastWriteTime":639232982368819097,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAeklEQVQ4EWNgGGjAeL09/b+ilhrYHfev3WIglc24N8DrPyW+YJEylyXZVmRXMi60sP8vI8ENdsSTF18ZSGWzmPlrDLALtE2FGLilxMBe4H/2imQ2y9XT74CaQRgGSGOzILvgK5ILiGUPEhfISPwEBwAkHZDGhoXcwNEAUMej/MWS7qYAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_1.png","LastWriteTime":639232983458859097,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA20lEQVQ4EWPM/db3/+O/VwwgwM8kxgBig+gHf84zKLAYgsXxyTM6XHD7/+fbL7BCxg8/wDSI+C/AAWazcLEx4JWfvl2RQVFLDaz4/rVbCPZBJDayOIz9moEBpJ5xb4DXf7BuMgkWKXNZhK0w04GGobgGjzjjQgv7/zIS3GD7n7z4ykAqm8XMX2OAXaBtKsTALSUG9gL/s1cks1munn4H1AzCMEAamwXZBV+RXEAse5C4QEbiJzgAIOmANDaj76fY/9/ffIKFIJjmFOFjgIkhs2GKkMUYNZLFKMoLAFW21sUW51U4AAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/Coil_ctm.png","LastWriteTime":639232986264339098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABGklEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZqWX5j429/5FrSkJsDv9isN0s1HLA0fl7GUDtiWcnH4ONJIYNUsg4kC0isANGdDkADgFyywFQHMMAchuPWDZM/4C2CQdHCGibCjFwS4mBQ5P/2Sui2VLQ8P9Kgh6QFpgdMP3gfgHUrAGhWJBDANk3xLBBLiZGHS41IP2jIcBy9fQ7YN/uJyg0wGU5sWxYPgbpI1YPsh0w/VSrDUF1Cq64xiauWTmTurXhqY03QB4EgncQikg2ABJy7uTf9ldPAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_1_ctm.png","LastWriteTime":639232986121779098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABYklEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGtZzuzzZ/j47xWYw88kBmaD6Ad/zjMosBiCxYmRn7VXlKT2RKjjBbD5jA4X3P7/+fYLbBHjhx9gGkT8F+AAs1m42BiIkW/s4mIgpT1RX/YNbD7jQLaIQC5gHNHlADgEyC0HQPENA8htPGLZMP0D2iYcHCGgbSrEwC0lBg5N/meviGZLQcP/Kwl6QFpgdsD0g/sFULMGhGJBDgFk3xDDBrmYGHW41ID0j4YAy9XT74B9u5+g0ICW5cSxYfkYpI8S/Yy+n2L/f3/zCWQOHHCK8DHAxJDZMAXIYjD25JUSJKWH3PAXYONYbhfuhJlLEX3qqiZU/zskc3Czn9y5DlYHADwKIiFgYRAAAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_2.png","LastWriteTime":639232986616619098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAy0lEQVQ4EWO8lPvt/8eP/xhAgJ+fiQHEBtH3HvxhUFJgAYvjk2fsc7jw//ufb2CFb/98ANMgQphFAMzmZOFiwCfP4uk+nUFRSw2s+P61WySzGfcGeP0H6yaTYJEylyXZVmQXMy60sP8vI8ENtv/Ji68MpLJZzPw1BtgF2qZCDNxSYmAv8D97RTKb5erpd0DNIAwDpLFZkF3wFckFxLIHiQtkJH6CAwCSDkhjM27w/fT/zfc3sBAE0yKcIgwwMWQ2TBGyGKOWWDJFeQEA6CnWf/N4qL0AAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_2_ctm.png","LastWriteTime":639232986803259098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABXklEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZL+V++//x4z8wh5+fiQHEBtH3HvxhUFJgAYsTI28aPJOk9sSOOalg8xn7HC78//7nG9iit38+gGkQIcwiAGZzsnAxECNvIdLCQEp74sSbGrD5jAPZIgK5gHFElwPgECC3HADFNwwgt/GIZcP0D2ibcHCEgLapEAO3lBg4NPmfvSKaLQUN/68k6AFpgdkB0w/uF0DNGhCKBTkEkH1DDBvkYmLU4VID0j8aAixXT78D9u1+gkIDWpYTx4blY5A+SvQzbvD99P/N9zcgc+BAhFOEASaGzIYpQBaDsa2dO0lKD0f3loONY9QSS6ZKe6Bc6Q7MfUTRnfdUwOoAm/oejupeW+kAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_3.png","LastWriteTime":639232986969259098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA0ElEQVQ4EWP8ltv2/9/HvwwgwMTPzABig+g/D34zsCiwgsXxybPcuvyB4dufP2CFH/78B9MgQoCFkYHhPQMDFwsLXnkWdvePDBpaamCN96/dYlAkkc24N8ALYS3cfuIZLFLmsiTbiuxKxoUW9v9lJLjBVj558ZWBVDaLmb/GALtA21SIgVtKDOwF/mevSGazXD39DqgZhGGANDYLsgu+IrmAWPYgcYGMxE9wAEDSAWlsxk++jf/ffP8BC0EwLcLJwQATQ2bDFCGLMSaLeVKUFwADW9g0aWtYnwAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_3_ctm.png","LastWriteTime":639232987099019098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABe0lEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZv+XO+f/vI8QNTPyMDCA2iP7zgJGBRQEiTow8S/AnktoTv+YIgM1nvODQ9//bn99g13z48xceGAIszGA2FwsrAzHy30UOMpDSnuB8Yw82n4Xd/SaDBrxFdA9Lzfgf6DOYOAuKL0Em3L8G0++MIofcbsDFBulnHNHlADgEyC0HQPENA8htPGLZMP0D2iYcHCGgbSrEwC0lBg5N/meviGZLQcP/Kwl6QFpgdsD0g/sFULMGhGJBDgFk3xDDBrmYGHW41ID0j4YAy9XT74B9u5+g0ICW5cSxYfkYpI8S/YyffOf+f/P9G8gcOBDh5GKAiSGzYQqQxWDsn85XSEoP7Ht1wMYxJouFUqU9YKf0CuY+ouhD9yBZHwATDR8/pSfJtgAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_4.png","LastWriteTime":639232987250259098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAzElEQVQ4EWPM/fby/8d/nxlAgJ+JlwHEBtEP/jxmUGCRBYvjk2d0uLDs/59v38AK/3x4DaZBBIuAKJjNwsXFgE+e8Xp7+n9FLTWw4vvXbjGQymbcG+D1H6ybTIJFylyWZFuRXcm40ML+v4wEN9j+Jy++MpDKZjHz1xhgF2ibCjFwS4mBvcD/7BXJbJarp98BNYMwDJDGZkF2wVckFxDLHiQukJH4CQ4ASDogjc3o++nM/+9vXsFCEExziogxwMSQ2TBFyGKMYsnmFOUFAFol2G4PQYsKAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_4_ctm.png","LastWriteTime":639232987381299098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABbUlEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZc7+9/P/x32cwh5+JlwHEBtEP/jxmUGCRBYsTIz9r70aS2hOhjvZg81ku39rL8OfbN7BFfz68BtMggkVAlOE9wwUGFi4uouSPzt/LAGpPPDv5GGwGIfZ7UX6w+YwD2SICuZRxRJcD4BAgtxwAxTEMILfxiGXD9A9om3BwhIC2qRADt5QYODT5n70imi0FDf+vJOgBaYHZAdMP7hdAzRoQigU5BJB9Qwwb5GJi1OFSA9I/GgIsV0+/A/btfoJCA1yWE8uG5WOQPmL1INsB08/o++nM/+9vXoHk4IBTRIwBJobMhilAFoOxJ6/cSFJ6yA33BxvHKJZsTpX2QPdVDpj7iKJLtX+A1QEA0GMtWAgkeokAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_5.png","LastWriteTime":639232987587219098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAvElEQVQ4EWP8f/n/f4aPDBDAD6RAbBD9AIgVgBgE8MizMFwGKvgDVoagQVwWIH4PpfHIs9x4mMGgqKUG0sJw/9otktmMewO8/oN1k0mwSJnLkmwrsosZF1rY/5eR4Abb/+TFVwZS2Sxm/hoD7AJtUyEGbikxsBf4n70imc1y9fQ7oGYQhgHS2CzILviK5AJi2YPEBTISP8EBAEkHpLEZ/28G5sbvsACE0pxAGiaGzIYpQxJjOXLyFEyYLBoA23y94QBGKokAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_5_ctm.png","LastWriteTime":639232987729219098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABUUlEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZ/1/+/5/hI9QJ/EAaxAbRD4BYAYhBgAj5n2/7SGpPsDMVgc1n/L8M6IA/EHvgNIjLAhUD0UTI71vnzUBKe8IpaCvYAsaBbBGBXMA4ossBcAiQWw6A4hsGkNt4xLJh+ge0TTg4QkDbVIiBW0oMHJr8z14RzZaChv9XEvSAtMDsgOkH9wugZg0IxYIcAsi+IYYNcjEx6nCpAekfDQGWq6ffAft2P0GhAS3LiWPD8jFIHyX6Gf9vBlZG30HGIAFOIBsmhsyGKUEWg7Jv3M0gKT1oKM8Am8Zy5OQpmLEU0ff23IDqf4dkDm72GxeIvQDEwwUJbHgkZAAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_6.png","LastWriteTime":639232987868419098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAzElEQVQ4EWPckPvt/9uP/xhAQJifiQHEBtHXH/xh0FRgAYvjk2fMcrjw/8efb2CFH/58ANMgQoBFAMzmYOFiwCfPeL09/b+ilhpY8f1rtxhIZTPuDfD6D9ZNJsEiZS5Lsq3IrmRcaGH/X0aCG2z/kxdfGUhls5j5awywC7RNhRi4pcTAXuB/9opkNsvV0++AmkEYBkhjsyC74CuSC4hlDxIXyEj8BAcAJB2QxmZs9/30/933N7AQBNNCnCIMMDFkNkwRshijuFgyRXkBAG1f15qPmdtDAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_6_ctm.png","LastWriteTime":639232987988059098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABXUlEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGtZ+E23M7z9+A/MEeZnArNB9PUHfxg0FVjA4sTIRwfPJKk90T8nFWw+Y5bDhf8//nwDW/ThzwcwDSIEWATAbA4WLgZi5KNFWhhIaU8sfVMDNp9xIFtEIBcwjuhyABwC5JYDoPiGAeQ2HrFsmP4BbRMOjhDQNhVi4JYSA4cm/7NXRLOloOH/lQQ9IC0wO2D6wf0CqFkDQrEghwCyb4hhg1xMjDpcakD6R0OA5erpd8C+3U9QaEDLcuLYsHwM0keJfsZ230//331/AzIHDoQ4RRhgYshsmAJkMRg7ybmTpPQwb2852DhGcbFkqrQHupTuwNxHFF12TwWsDgCreBv7pfsz7AAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_7.png","LastWriteTime":639232988155019098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAyUlEQVQ4EWP08/P7/+nTJwYQ4OPjYwCxQfSjR48Y5OTkwOL45BmlpaX///r1C6zw27dvYBpEcHFxgdlsbGwM+ORZ9uT4MChqqYEV3792i2Q2494Ar/9g3WQSLFLmsiTbiuxixoUW9v9lJLjB9j958ZWBVDaLmb/GALtA21SIgVtKDOwF/mevSGazXD39DqgZhGGANDYLsgu+IrmAWPYgcYGMxE9wAEDSAWlsRgMDg/+fP3+GhSCY5uXlZYCJIbNhipDFGIGCFOUFAAl90kGnakYDAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_7_ctm.png","LastWriteTime":639232988300299098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABW0lEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGtZ1orxM3z69AnM4ePjA7NB9KNHjxjk5OTA4sTI7yj0Jak9YVG/GGw+o7S09P9fv36BLfr27RuYBhFcXFxgNhsbGwMx8iusTRlIaU9EHD0NNp9xIFtEIBcwjuhyABwC5JYDoPiGAeQ2HrFsmP4BbRMOjhDQNhVi4JYSA4cm/7NXRLOloOH/lQQ9IC0wO2D6wf0CqFkDQrEghwCyb4hhg1xMjDpcakD6R0OA5erpd8C+3U9QaEDLcuLYsHwM0keJfkYDA4P/nz9/BpkDB7y8vAwwMWQ2TAGyGIy9JcWFpPTgM2cP2DhGIEmV9gCwRIW5jyg6/sRBsDoASd8Y76KlEdwAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_8.png","LastWriteTime":639232988572019098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxklEQVQ4EWP0zXvy//PnLwwgwMvLwwBig+jnL94ySEoIg8XxyTM6+t38/+H9K7DC79/fgWkQwckpBGYLCIox4JNnvN6e/l9RSw2s+P61Wwykshn3Bnj9B+smk2CRMpcl2VZkVzIutLD/LyPBDbb/yYuvDKSyWcz8NQbYBdqmQgzcUmJgL/A/e0Uym+XqaVDcI+KfVDYLsgu+IrmAWPYgcYGMxE+kdEAam9Ek7OL/tx9+gA2AEcICHAwwMWQ2NnlGLp3JFOUFAK9v1sWmulCyAAAAAElFTkSuQmCC"},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_8_ctm.png","LastWriteTime":639232988713539098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABXklEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZffOe/P/8+QuYw8vLwwBig+jnL94ySEoIg8WJkd8RsJWk9oTNUhew+YyOfjf/f3j/CmzR9+/vwDSI4OQUArMFBMUYiJHvEW5nIKU9UfK2Emw+40C2iEAuYBzR5QA4BMgtB0DxDQPIbTxi2TD9A9omHBwhoG0qxMAtJQYOTf5nr4hmS0HD/ysJekBaYHbA9IP7BVCzBoRiQQ4BZN8Qwwa5mBh1uNSA9I+GAMvV0++AfbufoNCAluXEsWH5GKSPEv2MJmEX/7/98ANkDhwIC3AwwMSQ2TAFyGIw9jbHeSSlB6/9SWDjGLl0JlOlPTCdZw3MfUTRmV9CwOoAHd8dOiLLgEAAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_9.png","LastWriteTime":639232988828739098,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA2UlEQVQ4EWP8djf3/79PHxlAgImPnwHEBtF/Hj5gYJFXAIvjk2e8MMvh/7fvf8AKP7yG0CCOgCgLWIyLk4UBnzwL+1t1Bg0tNbDi+99uMSjC2NewsBUYGO6jiTPuDfD6D9ZNJsEiZS6L31agwei2IruScaGF/X8ZCW6w/U9efGUglc1i5q8xwC7QNhVi4JYSA3uB/9krktksV0+/A2oGYRggjc2C7IKvSC4glj1IXCAj8RMcAJB0QBqb8dM+3/9vXn+HhSCYFhHlZICJIbNhipDFGJMNxCjKCwAXvtbknEO04QAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_tier_9_ctm.png","LastWriteTime":639232988964099098,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABeUlEQVRYCWO83p7+X1FLjQEE7l+7xUAKmxw96HYwLrSw/y8jwQ12wJMXXxlIZYM0kqoHWT2Lmb8GSb5G9gFVQmBvgNd/sPcHiGCRMpcd2BAYTQOjITAaAqPlwGgaAIXAAFUDYGsZv93N/f/v00cwh4mPnwHEBtF/Hj5gYJFXAIsTI8/ySJ+k9sQv3gNg8xkvzHL4/+37H7BFH15DaBBHQJQFLMbFycJAjPz3/XwMpLQnOB0/gc1nYX+rzqABaxF9I9AiUkBtNYFMALUPwPoTUeWQ2w242CD9jCO6HACHALnlACi+YQC5jUcsG6Z/QNuEgyMEtE2FGLilxMChyf/sFdFsKWj4fyVBD0gLzA6YfnC/AGrWgFAsyCGA7Bti2CAXE6MOlxqQ/tEQYLl6+h2wb/cTFBrQspw4Niwfg/RRop/x0z7f/29efweZAwciopwMMDFkNkwBshiM/fOeMknpgV3pLtg4xmQDMaq0B+w4NGHuI4o+9OM6WB0Ampwdwfy7/RcAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_active.png","LastWriteTime":639232991040612591,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAd0lEQVQ4EWNgGGjA+P/48v8MWmoQd1y7xUAqm/HvhK7/lPiChclclmRbkV3J+LCi/r+MBDfYEU9efGUglU15GFDugrUT/zNIiUHC8dkrBlLZLI9OvwNqBmEYII3NImcqRLKtyK4cJC6QkfgJDgBIOiCNDQu5gaMBYmmS2q3ArSAAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useless_coil_active_ctm.png","LastWriteTime":639232991218532591,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCklEQVRYCWP8f3z5fwYtNQYwuHaLgSQ2SBOpetDUMz6sqP8vI8ENtv/Ji68MpLJBGknVg6yeccBD4O+Erv9g7w8QwcJkLktavCPHIcjRyHwy2KNpYDQERkOAcbQcGK0LQCEwQNUA2FpGaln+/+PZ/6TUC4z8xmC7WajlgH/z9zKA2xMnH4ONJIYNUjiw7QGQA0Z2OQAKAXLLAVAcwwByG49YNkz/wKeBgQ+BtRP/M0iJQULz2SsGktggXaTqQVYP1A5OAxDbB4ZkkTMVIs3XaD4YDQFKQ4Dl0el3wL7dT3ACAJffRLJh+RikkRL91KsNQb1s5PRBgM1oGUnd2vDRxhvQbPQOSoMowmwAXeSCb79zD5oAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useful_coil.png","LastWriteTime":639232991909492591,"Height":32,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAgCAYAAAAbifjMAAAA+klEQVRIDc1UsQqEMAxNoDgouimC4OLgIIjgJ7g7+xn+j3/l5uokuCk4uPRsDo/eItd26HVoHmnSvqbNw7Zt+bZtIEYQBCCwsPM8Q5qm5H9axyRJ+HmeFHgcB1kxua5L2HEceFrHYRh4nucUPE0TqGLs+55TtubEiqJQPlVmiV3X8TiO6fxlWUAVs6ZpLDMoyxLCMKQrRFGkjNk4jpr1f6cxmcG6rh8Gv+I/YaD69nI8VlXF933/KqTv+3D7ZHwHyT68nGa9cOkBaYDY3YoesLquzXohyzKzGhjrged5lvXAmIHcjTp6gILB/UV1rLEe/AkDub9VsX09eAFEiHGEsJ4ctQAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useful_coil_ctm.png","LastWriteTime":639232992375692591,"Height":64,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAABACAYAAAB7jnWuAAACJElEQVRoBe1YMaoCMRBNIFgoWikKgo2IgqCCYGFrby14B7G0thDvYO0lBO8gVlrYWAlaKVrY5P83EAlb/L+zLkQwA25esplk5pnMTiIXi4WuVqsCst/vBQdH0QnOIQeDgS4UCmTA6XQSXAxFro7dX/V6PZbXtgexMDAejzW57+ih6vW6Wwb8GvAMeAZ8HPBrAAw4+gzQtOrxeIjr9UqVTCZDGOXxeBSlUonaw7yfTqesfGI0GtH4slgs6ufzSRPBGCPJZJJgIpEQYd4Ph0PBySeWyyWNL11mRLBAfnUcIAaixgH830bsHC8sNvpOc8KPYEDOZjOdy+WIzfP5LDgYSlwduz/01Xa7RelMVKPRYHkd9MCuczG89gwQA2H3Ligz8d7sY7S9oy9brZa+3W4Y5yXpdFqYNhubDnabwZPJhLUj5vM5Dac2m40Z961yvV6z9A+HA/WX/X5f12o1qux2O8HBUOLqBPvLVCrl/n6A47XtQSwMlMtltzkh7gecMuDXgGfAM+DjgF8DYIC+xY4edDIKc/6HfX/dH3Q6HVZusFqt4r0fgHEmX4Sx/2HjtGq3286+hjBUfnUcIAaixoG4zgW0C1xlRB/BgOx2uzqbzcIYcblcBAdH0bHngD6dCwBciWo2myyvgx7YdS6G056ByGfD2OJApVJ53QWYiwac+Y3YGG3oY7eZ+wGcsPL5/Gs9hcEYT/7+YskHfiMqxgst9/ud+v4A2eER6ixJ9qYAAAAASUVORK5CYII="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useful_coil_active.png","LastWriteTime":639232992644252591,"Height":16,"Width":16,"Texture":"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAZElEQVQ4EWNgGHBw+/bt/zBADptxw4YN/ynyBTm2IruYccaMGf8lJCTAjnjx4gUDqWyGAXcBi56eHoOoqCjYC2JiYiSzWS5dukRRJKC44PXr13AXEMseJC4gNe6R1VMUgFTRDAAAbBb1b15/JwAAAABJRU5ErkJggg=="},{"Path":"/storage/emulated/0/Android/data/com.pixelstudio.pro/files/Storage/useless/coils/useful_coil_active_ctm.png","LastWriteTime":639232992863292591,"Height":32,"Width":32,"Texture":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA50lEQVRYCe1XQQ6EIAyExC+Y8AGuvtdn6AO4+gASTn6AhEewO00whMtaJelh6YXRdMCOpQV1nmcuxsXgcTmtv17XNRtjFCzGqLgYPC6n9lftF3HU6KLAtm0ZUYiZuAIjB4YCQ4FRB0YOQAGxPtBzYW5nLGtPBbwd932n80QIgabC2eIXJkfJbgjV9F/XAVLgaR3APy5Wn/Hu4osvngPSCujjOPI8z6RmSklxMEhcTu0P/uS9xyhm07IsrKjbCOpnLkbUQwFS4O7ehWTl/njt4++7N3yNSXsY6gknB6y1tHa3buicexTHB4sbDXoXJ2nZAAAAAElFTkSuQmCC"}] \ No newline at end of file diff --git a/src/main/resources/xia/assets/useless_mod/textures/block/xbai2024.png b/src/main/resources/xia/assets/useless_mod/textures/block/xbai2024.png deleted file mode 100644 index b6647078e5c972fd2e46538a0d0fe206e9e85798..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2981 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 bn8p79uRneFiLg?A00000NkvXXu0mjfN8!|} diff --git a/src/main/resources/xia/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png b/src/main/resources/xia/assets/useless_mod/textures/gui/advanced_alloy_furnace_tips.png deleted file mode 100644 index bc23b7dbd3583492d37485c9571439b56ac651b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)L!3HEN&baUbsWeX)#}En0 requirements() throws Exception { @Test void obsoleteApisAreRejectedButTheUpdatedPackVersionsRemainAllowed() throws Exception { var requirements = requirements(); for (var entry : Map.of("ae2", "15.4.10", "expatternprovider", "1.20-1.4.12-forge", - "jei", "15.48.0.177", "extendedcrafting", "6.1.5u", "mekanism", "10.4.15").entrySet()) { + "jei", "15.48.0.177", "extendedcrafting", "6.1.5u", "mekanism", "10.4.15", + "botanypots", "13.0.0", "mekanism_extras", "1.5.0").entrySet()) { var range = VersionRange.createFromVersionSpec(requirements.get(entry.getKey()).get("versionRange")); assertTrue(range.containsVersion(new DefaultArtifactVersion(entry.getValue())), entry.toString()); } for (var entry : Map.of("ae2", "14.0.0", "create", "0.5.1", "mekanism", "10.3.0", - "jei", "15.0.0", "exdeorum", "1.0").entrySet()) { + "jei", "15.0.0", "exdeorum", "1.0", + "botanypots", "12.0.0", "mekanism_extras", "1.4.1").entrySet()) { var range = VersionRange.createFromVersionSpec(requirements.get(entry.getKey()).get("versionRange")); assertFalse(range.containsVersion(new DefaultArtifactVersion(entry.getValue())), entry.toString()); } diff --git a/src/portBridgeTest/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegrationTest.java b/src/portBridgeTest/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegrationTest.java new file mode 100644 index 00000000..e2c6b694 --- /dev/null +++ b/src/portBridgeTest/java/com/sorrowmist/useless/compat/forge1201/OptionalIntegrationTest.java @@ -0,0 +1,18 @@ +package com.sorrowmist.useless.compat.forge1201; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OptionalIntegrationTest { + @Test + void missingOptionalClassFallsBackInsteadOfCrashing() { + assertEquals("fallback", OptionalIntegration.call( + "minecraft", + "com.sorrowmist.useless.integration.DoesNotExist", + "run", + String.class, + "fallback", + new Class[0])); + } +} From 868f7f1dbe763f6dcb4fdda60f5a647d844feddd Mon Sep 17 00:00:00 2001 From: AyaYumi Date: Sat, 24 Oct 2026 14:51:47 +0800 Subject: [PATCH 2/3] fix(1.20.1): remove unsupported Upgrade.saveMap redirect Mekanism 10.4.15.75 and 10.4.16.80 do not read Upgrade.maxStack in saveMap. The redirect therefore failed Mixin injection and crashed ATM9 during MekanismGenerators class initialization. Keep the constructor, getMax and buildMap coverage. --- .../useless/mixin/mek/UpgradeMixin.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java index aac224ed..09065fe1 100644 --- a/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java +++ b/src/main/java/com/sorrowmist/useless/mixin/mek/UpgradeMixin.java @@ -67,20 +67,4 @@ public abstract class UpgradeMixin { return upgrade.getMax(); } - /** - * NBT saving also reads maxStack directly; without this redirect a machine - * with more than 16 upgrades would be clamped back to 16 on save. - */ - @Redirect( - method = "saveMap", - at = @At( - value = "FIELD", - target = "Lmekanism/api/Upgrade;maxStack:I", - opcode = Opcodes.GETFIELD - ), - remap = false - ) - private static int useless$nbtSaveMax(Upgrade upgrade) { - return upgrade.getMax(); - } } From e8c7519047db8205b1544b85ea53820a517a5d9c Mon Sep 17 00:00:00 2001 From: AyaYumi Date: Sat, 24 Oct 2026 15:02:09 +0800 Subject: [PATCH 3/3] fix(1.20.1): accept ATM9 AdvancedAE and Blood Magic versions - relax optional AdvancedAE and Blood Magic ranges to the versions shipped by ATM9 - skip the AdvancedAE 1.3-only reaction chamber adapter on 1.2.x instead of throwing NoSuchFieldError - skip missing PneumaticCraft capability loaders at debug level - verified ATM9 reaches the title screen with the rebuilt jar --- .../content/recipe/adapters/RecipeAdapterCompatRegistry.java | 4 ++++ .../java/com/sorrowmist/useless/init/ModBlockEntities.java | 5 +++++ src/main/resources/META-INF/mods.toml | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java index edb455f0..2f976828 100644 --- a/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java +++ b/src/main/java/com/sorrowmist/useless/content/recipe/adapters/RecipeAdapterCompatRegistry.java @@ -323,6 +323,10 @@ private static void registerExtendedAE() { } private static void registerAdvancedAE() { + if (!isClassAvailable("net.pedroksl.ae2addonlib.recipes.IngredientStack$Item")) { + LOGGER.debug("AdvancedAE 1.2.x does not expose the 1.3 addon-lib recipe API; skipping reaction chamber adapter"); + return; + } registerByName("com.sorrowmist.useless.content.recipe.adapters.ae.advancedae.ReactionChamberRecipeAdapter"); } diff --git a/src/main/java/com/sorrowmist/useless/init/ModBlockEntities.java b/src/main/java/com/sorrowmist/useless/init/ModBlockEntities.java index e800ae43..e20a98d7 100644 --- a/src/main/java/com/sorrowmist/useless/init/ModBlockEntities.java +++ b/src/main/java/com/sorrowmist/useless/init/ModBlockEntities.java @@ -12,6 +12,7 @@ import com.sorrowmist.useless.content.blockentities.multiblock.PassiveCraftingHatchBlockEntity; import com.sorrowmist.useless.compat.draconicevolution.DraconicOpStorageCompat; import com.sorrowmist.useless.compat.fluxnetworks.FluxNetworksEnergyCompat; +import com.sorrowmist.useless.compat.forge1201.OptionalIntegration; import net.minecraft.core.registries.Registries; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.eventbus.api.IEventBus; @@ -109,6 +110,10 @@ private static void registerCapabilities(RegisterCapabilitiesEvent event) { * JVM must not resolve AppMek's capability types on a server that does not install AppMek. */ private static void invokeOptionalCapabilityLoader(String className, RegisterCapabilitiesEvent event) { + if (!OptionalIntegration.hasClass(className)) { + UselessMod.LOGGER.debug("Optional capability loader {} is not present in this build", className); + return; + } try { Class loader = Class.forName(className, true, ModBlockEntities.class.getClassLoader()); loader.getMethod("registerCapabilities", RegisterCapabilitiesEvent.class).invoke(null, event); diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 7ef42f4a..db7127d2 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -46,7 +46,7 @@ side="BOTH" [[dependencies.useless_mod]] modId="advanced_ae" mandatory=false -versionRange="[1.3.6-1.20.1,2)" +versionRange="[1.2.7-1.20.1,2)" ordering="AFTER" side="BOTH" @@ -340,7 +340,7 @@ side="BOTH" [[dependencies.useless_mod]] modId="bloodmagic" mandatory=false -versionRange="[3.3.5-47,3.4)" +versionRange="[3.3.3-45,3.4)" ordering="AFTER" side="BOTH"