Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ 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.

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.

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
Expand Down
16 changes: 11 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ dependencies {
modCompileOnly 'maven.modrinth:rxYaglEe:orFPvySe' // advancedae-1.2.7-1.20.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:XxWD5pD3:Zfyso1sP' // appliedenergistics2-forge-15.4.8
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
modCompileOnly 'curse.maven:applied-flux-965012:6755986' // appliedflux-1.20-1.3.2-forge
modCompileOnly 'maven.modrinth:lhGA9TYQ:1MKTLiiG' // architectury-9.2.14-forge
modCompileOnly 'maven.modrinth:uy4Cnpcm:tNwsir0K' // bookshelf-forge-1.20.1-20.2.13
Expand All @@ -54,7 +56,7 @@ dependencies {
modCompileOnly 'maven.modrinth:49ZofO4f:1na1IiE8' // enderio-1.20.1-6.2.13-beta-all
modCompileOnly 'curse.maven:ex-deorum-901420:6614784' // exdeorum-1.46
modCompileOnly 'curse.maven:extendedae-892005:7005572' // extendedae-1.20-1.4.6-forge
modCompileOnly 'maven.modrinth:5JMG1gql:NtEZsGjO' // extendedcrafting-1.20.1-6.1.5u
modCompileOnly 'maven.modrinth:5JMG1gql:NtEZsGjO' // extendedcrafting-1.20.1-6.0.10 (tier-5 pack extension resolved at runtime)
modCompileOnly 'curse.maven:flux-networks-248020:5234697' // fluxnetworks-1.20.1-7.2.1.15
modCompileOnly 'curse.maven:ftb-chunks-314906:6431735' // ftb-chunks-forge-2001.3.6
modCompileOnly 'curse.maven:ftb-teams-404468:6130786' // ftb-teams-forge-2001.3.1
Expand Down Expand Up @@ -86,19 +88,23 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.mockito:mockito-core:5.15.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testRuntimeOnly 'org.slf4j:slf4j-api:2.0.9'
}
mixin {
add sourceSets.main, "${mod_id}.refmap.json"
["${mod_id}.mixins.json", "${mod_id}.create.mixins.json", "${mod_id}.mekanism.mixins.json", "${mod_id}.jade.mixins.json"].each { config it }
["${mod_id}.mixins.json", "${mod_id}.create.mixins.json", "${mod_id}.mekanism.mixins.json", "${mod_id}.jade.mixins.json", "${mod_id}.compact.mixins.json"].each { config it }
}
tasks.named('jar') {
manifest.attributes('MixinConfigs': ["${mod_id}.mixins.json", "${mod_id}.create.mixins.json", "${mod_id}.mekanism.mixins.json", "${mod_id}.jade.mixins.json"].join(','))
manifest.attributes('MixinConfigs': ["${mod_id}.mixins.json", "${mod_id}.create.mixins.json", "${mod_id}.mekanism.mixins.json", "${mod_id}.jade.mixins.json", "${mod_id}.compact.mixins.json"].join(','))
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.compilerArgs += ['-Xmaxerrs', '10000']
}
tasks.named('test', Test) { useJUnitPlatform() }
tasks.named('test', Test) {
useJUnitPlatform()
classpath = classpath.filter { !it.name.startsWith('slf4j-api-1.') }
}
tasks.named('processResources', ProcessResources) {
inputs.property 'mod_version', mod_version
filesMatching('META-INF/mods.toml') {
Expand Down
6 changes: 3 additions & 3 deletions gradle/forge1201-pack-profile.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Optional integrations without a Forge 1.20.1 implementation remain outside this build.
def profile = new groovy.json.JsonSlurper().parse(file('gradle/forge1201-pack-profile.json'))
sourceSets.main.java { profile.excludes.each { exclude it } }
sourceSets.test.java {
exclude 'com/sorrowmist/useless/compat/neoecoae/NeoEcoPlanningCompatTest.java'
}
tasks.named('processResources', ProcessResources) {
exclude 'META-INF/neoforge.mods.toml', 'META-INF/enumextensions.json'
// These blocks are not registered without NeoEcoAE in the target profile.
exclude 'data/useless_mod/loot_tables/blocks/useless_compact_*.json'
}

// These tests require the NeoForge-only NeoEcoAE integration excluded above.
sourceSets.test.java.exclude 'com/sorrowmist/useless/compat/neoecoae/**'
6 changes: 4 additions & 2 deletions gradle/forge1201-pack-profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
"com/sorrowmist/useless/compat/lychee/**",
"com/sorrowmist/useless/compat/mekanismmoremachine/**",
"com/sorrowmist/useless/compat/modernindustrialization/**",
"com/sorrowmist/useless/compat/neoecoae/**",
"com/sorrowmist/useless/compat/neoecoae/NeoEcoCompat.java",
"com/sorrowmist/useless/compat/neoecoae/NeoEcoDynamicJobAttachment.java",
"com/sorrowmist/useless/compat/neoecoae/NeoEcoDynamicOutputCompat.java",
"com/sorrowmist/useless/compat/neoecoae/NeoEcoPlanningCompat.java",
"com/sorrowmist/useless/compat/neovitae/**",
"com/sorrowmist/useless/compat/nomadsdelight/**",
"com/sorrowmist/useless/compat/occultism/**",
Expand All @@ -60,7 +63,6 @@
"com/sorrowmist/useless/mixin/malum/**",
"com/sorrowmist/useless/mixin/itemobliterator/**",
"com/sorrowmist/useless/mixin/pneumaticcraft/**",
"com/sorrowmist/useless/mixin/compact/**",
"com/sorrowmist/useless/datagen/**",
"com/sorrowmist/useless/content/recipe/adapters/industrialforegoing/InfuserRecipeAdapter.java",
"com/sorrowmist/useless/content/recipe/adapters/industrialforegoing/PrecisionShapedRecipeAdapter.java",
Expand Down
6 changes: 6 additions & 0 deletions gradle/port-bridge-tests.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ sourceSets {
java.include 'com/sorrowmist/useless/api/recipe/IRecipeAdapter.java'
java.include 'com/sorrowmist/useless/content/recipe/IRecipeAdapter.java'
java.include 'com/sorrowmist/useless/content/blockentities/HighStackItemStackHandler.java'
java.include 'com/sorrowmist/useless/content/blockentities/RecoverableItemStackHandler.java'
java.include 'com/sorrowmist/useless/content/blockentities/OreGeneratorSampleHandler.java'
java.include 'com/sorrowmist/useless/api/enums/AlloyFurnaceMode.java'
java.include 'com/sorrowmist/useless/content/recipe/AdvancedAlloyFurnaceRecipe.java'
java.include 'com/sorrowmist/useless/content/recipe/AdvancedAlloyFurnaceRecipeSerializer.java'
Expand Down Expand Up @@ -96,6 +98,10 @@ tasks.register('portBridgeTest', Test) {
classpath = sourceSets.portBridgeTest.runtimeClasspath
useJUnitPlatform()
maxHeapSize = '1G'
inputs.file 'src/main/resources/META-INF/mods.toml'
doFirst {
systemProperty 'uselessMod.compileClasspath', sourceSets.main.compileClasspath.asPath
}
}

// ModDev's test logging adapter requires SLF4J 2; this does not affect runtime dependencies.
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/sorrowmist/useless/UselessMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ public UselessMod() {

// 无用型紧凑 C9/F9/L9:只在 ECO 存在时注册。
// 这里的类加载是条件性的——ECO 缺席时 NeoEcoCompactRegistry 永远不会被初始化。
if (ModList.get().isLoaded("neoecoae")) {
OptionalIntegration.call("neoecoae", "com.sorrowmist.useless.compat.neoecoae.compact.NeoEcoCompactRegistry",
String compactEcoRegistry = "com.sorrowmist.useless.compat.neoecoae.compact.NeoEcoCompactRegistry";
if (ModList.get().isLoaded("neoecoae") && OptionalIntegration.hasClass(compactEcoRegistry)) {
OptionalIntegration.call("neoecoae", compactEcoRegistry,
"init", Void.class, null, new Class<?>[]{IEventBus.class}, modEventBus);
}

Expand All @@ -111,8 +112,9 @@ public static ResourceLocation id(String path) {

private void commonSetup(FMLCommonSetupEvent event) {
RecipeAdapterCompatRegistry.init(event);
if (ModList.get().isLoaded("neoecoae")) {
OptionalIntegration.call("neoecoae", "com.sorrowmist.useless.compat.neoecoae.NeoEcoCompat",
String ecoCompat = "com.sorrowmist.useless.compat.neoecoae.NeoEcoCompat";
if (ModList.get().isLoaded("neoecoae") && OptionalIntegration.hasClass(ecoCompat)) {
OptionalIntegration.call("neoecoae", ecoCompat,
"initialize", Void.class, null, new Class<?>[]{});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
/** Optional source boundaries: no class linkage when the corresponding mod is absent. */
public final class OptionalIntegration {
private OptionalIntegration() {}

public static boolean hasClass(String className) {
return OptionalIntegration.class.getClassLoader()
.getResource(className.replace('.', '/') + ".class") != null;
}

public static <T> T call(String modId,String className,String method,Class<T> resultType,T absent,
Class<?>[] signature,Object... arguments) {
if (!ModList.get().isLoaded(modId)) return absent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import appeng.block.AEBaseEntityBlock;
import appeng.blockentity.AEBaseBlockEntity;
import cn.dancingsnow.neoecoae.blocks.entity.computation.ECOComputationSystemBlockEntity;
import cn.dancingsnow.neoecoae.blocks.entity.ECOMachineInterfaceBlockEntity;
import cn.dancingsnow.neoecoae.blocks.entity.crafting.ECOCraftingPatternBusBlockEntity;
import cn.dancingsnow.neoecoae.blocks.entity.crafting.ECOCraftingSystemBlockEntity;
import cn.dancingsnow.neoecoae.blocks.entity.storage.ECOStorageSystemBlockEntity;
Expand All @@ -32,7 +31,6 @@
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowCraftingWorkerBlockEntity;
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowFluidInputHatchBlockEntity;
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowFluidOutputHatchBlockEntity;
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowInterfaceBlockEntity;
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowPatternBusBlockEntity;
import com.sorrowmist.useless.compat.neoecoae.compact.shadow.ShadowThreadingCoreBlockEntity;
import net.minecraft.core.BlockPos;
Expand Down Expand Up @@ -208,9 +206,7 @@ public static void init(IEventBus modEventBus) {
CompactMachineClassMap.register(CompactC9BlockEntity.class, ECOComputationSystemBlockEntity.class);
CompactMachineClassMap.register(CompactF9BlockEntity.class, ECOCraftingSystemBlockEntity.class);
CompactMachineClassMap.register(CompactL9BlockEntity.class, ECOStorageSystemBlockEntity.class);
// 影子接口与聚合总线也各自带着「假身份」的网格节点:ECO 的界面与样板终端是按
// ECOMachineInterfaceBlockEntity / ECOCraftingPatternBusBlockEntity 这两个类去查网格的。
CompactMachineClassMap.register(ShadowInterfaceBlockEntity.class, ECOMachineInterfaceBlockEntity.class);
// ECO queries pattern buses by their native block-entity type in the grid index.
CompactMachineClassMap.register(ExposedPatternBusBlockEntity.class, ECOCraftingPatternBusBlockEntity.class);

BLOCKS.register(modEventBus);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,15 @@
package com.sorrowmist.useless.compat.neoecoae.compact.block;

import cn.dancingsnow.neoecoae.blocks.computation.ECOComputationSystem;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.phys.BlockHitResult;

/**
* 无用型紧凑 C9 的方块形态。
*
* <p>直接继承 ECO 的计算系统主机方块,于是「右键开 GUI」「玩家距离校验」「掉落物带设置」
* 这些行为全部沿用 ECO 的实现,本类只提供一个自己的方块实体。</p>
* <p>直接继承 ECO 的计算系统主机方块,复用 ECO 20.4.x 的 LDLib 原生界面入口。</p>
*/
public class CompactC9Block extends ECOComputationSystem {

public CompactC9Block(Properties properties) {
super(properties);
registerDefaultState(defaultBlockState().setValue(CompactInterfaceAccess.INTERFACE, false));
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(CompactInterfaceAccess.INTERFACE);
}

@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player,
BlockHitResult hitResult) {
if (!CompactInterfaceAccess.isPlayerCloseEnough(this, level, pos, player)) {
return InteractionResult.FAIL;
}
if (player.isShiftKeyDown()) {
if (player instanceof ServerPlayer serverPlayer) {
CompactInterfaceAccess.open(this, state, pos, serverPlayer);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
if (player instanceof ServerPlayer serverPlayer) {
CompactInterfaceAccess.openMain(this, state, pos, serverPlayer);
return InteractionResult.CONSUME;
}
return InteractionResult.SUCCESS;
}
}
Loading
Loading