Skip to content

Commit 4a96bb3

Browse files
committed
Fix optional transformer model registration
1 parent 5c2dda5 commit 4a96bb3

4 files changed

Lines changed: 163 additions & 37 deletions

File tree

‎CHANGELOG.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ Power Advantage 2.4.1.112021
66
- Pin optional compile APIs and keep Base Metals and OreSpawn off the build classpath.
77
- Add reproducible release jars, dependency and artifact audits, checksums, and GitHub CI.
88
- Preserve the poweradvantage runtime identity and cyano.poweradvantage.api compatibility surface.
9+
- Register optional RF and Tech Reborn converters before the 1.12 model-baking phase.
10+
- Keep compile-only RF and RebornCore APIs out of generated Eclipse production launches.

‎build.gradle‎

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,42 @@ tasks.register('isolateEclipseProductionRuns') {
765765
' <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>'
766766
contents = contents.replace(marker, attribute + '\n' + marker)
767767
}
768+
769+
// Buildship exposes compileOnly dependencies through its project
770+
// container. Replace that container in production launches with
771+
// Gradle's actual runtime classpath so API-only jars cannot be
772+
// discovered by FML as installed mods.
773+
Set<File> mainOutputs = sourceSets.main.output.files.collect {
774+
it.canonicalFile
775+
} as Set<File>
776+
List<File> productionRuntime = configurations.runtimeClasspath.files.collect {
777+
it.canonicalFile
778+
}.findAll { File runtimeFile ->
779+
!mainOutputs.contains(runtimeFile)
780+
}.sort { File left, File right ->
781+
left.canonicalPath <=> right.canonicalPath
782+
}
783+
List<String> launchLines = contents.readLines()
784+
int buildshipContainerLine = launchLines.findIndexOf {
785+
it.contains('org.eclipse.buildship.core.gradleclasspathcontainer')
786+
}
787+
if (buildshipContainerLine < 0) {
788+
throw new GradleException("${name} is missing the Buildship classpath container")
789+
}
790+
List<String> runtimeEntries = productionRuntime.collect { File runtimeFile ->
791+
String escapedPath = runtimeFile.canonicalPath
792+
.replace('&', '&amp;amp;')
793+
.replace('<', '&amp;lt;')
794+
.replace('>', '&amp;gt;')
795+
(' <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; '
796+
+ 'standalone=&quot;no&quot;?&gt;&lt;runtimeClasspathEntry externalArchive=&quot;'
797+
+ escapedPath
798+
+ '&quot; type=&quot;2&quot; path=&quot;5&quot; /&gt;"/>')
799+
}
800+
launchLines.remove(buildshipContainerLine)
801+
launchLines.addAll(buildshipContainerLine, runtimeEntries)
802+
contents = launchLines.join('\n') + '\n'
803+
768804
['--cache', '--metadata', '--to-srg', '--to-obf'].each { option ->
769805
String prefix = option + ' '
770806
int valueStart = contents.indexOf(prefix)
@@ -823,6 +859,18 @@ tasks.register('verifyEclipseProductionClasspath') {
823859
if (!contents.contains('PROJECT_ATTR" value="PowerAdvantage"')) {
824860
throw new GradleException("${name} targets the wrong Eclipse project")
825861
}
862+
if (contents.contains('org.eclipse.buildship.core.gradleclasspathcontainer')) {
863+
throw new GradleException("${name} exposes compileOnly dependencies at runtime")
864+
}
865+
['RF-API.jar', 'RebornCore-1.12.2'].each { forbiddenDependency ->
866+
if (contents.toLowerCase(Locale.ROOT).contains(forbiddenDependency.toLowerCase(Locale.ROOT))) {
867+
throw new GradleException(
868+
"${name} includes compile-only dependency ${forbiddenDependency}")
869+
}
870+
}
871+
if (!contents.contains("forge-${project.minecraft_version}-${project.forge_version}")) {
872+
throw new GradleException("${name} is missing the Forge development runtime")
873+
}
826874
if (contents.contains('${MC_VERSION}')
827875
|| !contents.contains(
828876
"key=\"MC_VERSION\" value=\"${project.minecraft_version}\"")) {
@@ -832,6 +880,67 @@ tasks.register('verifyEclipseProductionClasspath') {
832880
}
833881
}
834882

883+
tasks.register('verifyModelAssets') {
884+
group = 'verification'
885+
description = 'Verifies that PowerAdvantage model references resolve to packaged assets.'
886+
File resourceRoot = file('src/main/resources')
887+
File modelRoot = new File(resourceRoot, "assets/${project.mod_id}/models")
888+
File blockstateRoot = new File(resourceRoot, "assets/${project.mod_id}/blockstates")
889+
inputs.dir(modelRoot)
890+
inputs.dir(blockstateRoot)
891+
892+
doLast {
893+
def verifyReference = { String reference, String assetType, String sourcePath ->
894+
if (reference.startsWith('#')) return
895+
int separator = reference.indexOf(':')
896+
String namespace = separator >= 0 ? reference.substring(0, separator) : 'minecraft'
897+
String path = separator >= 0 ? reference.substring(separator + 1) : reference
898+
if (namespace != project.mod_id) return
899+
900+
File target = new File(resourceRoot,
901+
"assets/${namespace}/${assetType}/${path}.json")
902+
if (assetType == 'textures') {
903+
target = new File(resourceRoot, "assets/${namespace}/textures/${path}.png")
904+
}
905+
if (!target.isFile()) {
906+
throw new GradleException(
907+
"${sourcePath} references missing ${assetType} asset ${reference}")
908+
}
909+
}
910+
911+
fileTree(modelRoot) { include '**/*.json' }.files.sort().each { File modelFile ->
912+
def model = new JsonSlurper().parse(modelFile)
913+
if (model.parent instanceof String) {
914+
verifyReference(model.parent, 'models', modelFile.path)
915+
}
916+
if (model.textures instanceof Map) {
917+
model.textures.values().findAll { it instanceof String }.each { String texture ->
918+
verifyReference(texture, 'textures', modelFile.path)
919+
}
920+
}
921+
}
922+
923+
Closure verifyBlockstateModels
924+
verifyBlockstateModels = { Object node, String sourcePath ->
925+
if (node instanceof Map) {
926+
node.each { key, value ->
927+
if (key == 'model' && value instanceof String) {
928+
verifyReference(value, 'models/block', sourcePath)
929+
} else {
930+
verifyBlockstateModels(value, sourcePath)
931+
}
932+
}
933+
} else if (node instanceof Collection) {
934+
node.each { verifyBlockstateModels(it, sourcePath) }
935+
}
936+
}
937+
fileTree(blockstateRoot) { include '**/*.json' }.files.sort().each { File blockstateFile ->
938+
verifyBlockstateModels(new JsonSlurper().parse(blockstateFile), blockstateFile.path)
939+
}
940+
}
941+
}
942+
835943
tasks.named('check') {
836944
dependsOn tasks.named('verifyReleaseConfiguration')
945+
dependsOn tasks.named('verifyModelAssets')
837946
}

‎src/main/java/com/mcmoddev/poweradvantage/PowerAdvantage.java‎

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ public void preInit(FMLPreInitializationEvent event)
395395
com.mcmoddev.poweradvantage.init.Blocks.init();
396396
com.mcmoddev.poweradvantage.init.Items.init();
397397
com.mcmoddev.poweradvantage.init.TreasureChests.init(event.getSuggestedConfigurationFile().toPath().getParent());
398+
detectOptionalPowerApis();
399+
com.mcmoddev.poweradvantage.init.ModSupport.registerContent(detectedRF, detectedTechReborn);
398400

399401
// keep this next comment, it is useful for finding Vanilla recipes
400402
//OreDictionary.initVanillaEntries();
@@ -412,6 +414,7 @@ public void preInit(FMLPreInitializationEvent event)
412414
private void clientPreInit(FMLPreInitializationEvent event){
413415
// client-only code
414416
com.mcmoddev.poweradvantage.init.Blocks.bakeModels();
417+
com.mcmoddev.poweradvantage.init.ModSupport.bakeModels();
415418
}
416419
@SideOnly(Side.SERVER)
417420
private void serverPreInit(FMLPreInitializationEvent event){
@@ -428,25 +431,6 @@ public void init(FMLInitializationEvent event)
428431
{
429432

430433
FMLLog.info("%s: starting main inititalization", MODID);
431-
try {
432-
FMLLog.info("%s: testing whether we have to support redstone flux", MODID);
433-
Class<?> rfClass = Class.forName("cofh.api.energy.IEnergyReceiver", false, getClass().getClassLoader());
434-
detectedRF = rfClass != null;
435-
FMLLog.info("%s: RF class detected: %s", MODID, rfClass);
436-
} catch (ClassNotFoundException e) {
437-
detectedRF = false;
438-
FMLLog.info("%s: did not detect RF classes: %s", MODID, e.getMessage());
439-
}
440-
try {
441-
FMLLog.info("%s: testing whether we have to support Tech Reborn", MODID);
442-
Class<?> trClass = Class.forName("reborncore.api.power.IEnergyInterfaceTile", false, getClass().getClassLoader());
443-
detectedTechReborn = trClass != null;
444-
FMLLog.info("%s: Tech Reborn class detected: %s", MODID, trClass);
445-
} catch (ClassNotFoundException e) {
446-
detectedTechReborn = false;
447-
FMLLog.info("%s: did not detect Tech Reborn classes: %s", MODID, e.getMessage());
448-
}
449-
450434

451435
FMLLog.info("%s: adding GUI handler", MODID);
452436
NetworkRegistry.INSTANCE.registerGuiHandler(PowerAdvantage.getInstance(), MachineGUIRegistry.getInstance());
@@ -461,7 +445,7 @@ public void init(FMLInitializationEvent event)
461445
com.mcmoddev.poweradvantage.init.GUI.init();
462446

463447
FMLLog.info("%s: mod support data registries", MODID);
464-
com.mcmoddev.poweradvantage.init.ModSupport.init(detectedRF,detectedTechReborn);
448+
com.mcmoddev.poweradvantage.init.ModSupport.registerRecipes();
465449

466450

467451
if(event.getSide() == Side.CLIENT){
@@ -474,14 +458,34 @@ public void init(FMLInitializationEvent event)
474458
FMLLog.info("%s: initialize phase complete", MODID);
475459
}
476460

461+
private void detectOptionalPowerApis() {
462+
try {
463+
FMLLog.info("%s: testing whether we have to support redstone flux", MODID);
464+
Class<?> rfClass = Class.forName("cofh.api.energy.IEnergyReceiver", false, getClass().getClassLoader());
465+
detectedRF = rfClass != null;
466+
FMLLog.info("%s: RF class detected: %s", MODID, rfClass);
467+
} catch (ClassNotFoundException e) {
468+
detectedRF = false;
469+
FMLLog.info("%s: did not detect RF classes: %s", MODID, e.getMessage());
470+
}
471+
try {
472+
FMLLog.info("%s: testing whether we have to support Tech Reborn", MODID);
473+
Class<?> trClass = Class.forName("reborncore.api.power.IEnergyInterfaceTile", false, getClass().getClassLoader());
474+
detectedTechReborn = trClass != null;
475+
FMLLog.info("%s: Tech Reborn class detected: %s", MODID, trClass);
476+
} catch (ClassNotFoundException e) {
477+
detectedTechReborn = false;
478+
FMLLog.info("%s: did not detect Tech Reborn classes: %s", MODID, e.getMessage());
479+
}
480+
}
481+
477482

478483
@SideOnly(Side.CLIENT)
479484
private void clientInit(FMLInitializationEvent event){
480485
// client-only code
481486
FMLLog.info("%s: initializing renders", MODID);
482487
com.mcmoddev.poweradvantage.init.Items.registerItemRenders(event);
483488
com.mcmoddev.poweradvantage.init.Blocks.registerItemRenders(event);
484-
com.mcmoddev.poweradvantage.init.ModSupport.registerItemRenders(event);
485489
}
486490
@SideOnly(Side.SERVER)
487491
private void serverInit(FMLInitializationEvent event){

‎src/main/java/com/mcmoddev/poweradvantage/init/ModSupport.java‎

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import cyano.poweradvantage.api.modsupport.techreborn.TileEntityTRElectricityConverter;
1111
import net.minecraft.block.Block;
1212
import net.minecraft.block.material.Material;
13-
import net.minecraft.client.Minecraft;
1413
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
14+
import net.minecraft.item.Item;
1515
import net.minecraft.item.ItemBlock;
1616
import net.minecraft.item.ItemStack;
1717
import net.minecraft.util.ResourceLocation;
18+
import net.minecraftforge.client.model.ModelLoader;
1819
import net.minecraftforge.fluids.BlockFluidBase;
1920
import net.minecraftforge.fml.common.FMLLog;
20-
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
2121
import net.minecraftforge.fml.common.registry.ForgeRegistries;
2222
import net.minecraftforge.fml.relauncher.Side;
2323
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -36,11 +36,12 @@ public abstract class ModSupport {
3636

3737
private static final Map<String, Block> allBlocks = new HashMap<>();
3838

39-
private static boolean initDone = false;
39+
private static boolean contentRegistrationDone = false;
40+
private static boolean recipeRegistrationDone = false;
4041
private static int generatedRecipeId = 0;
4142

42-
public static void init(boolean rfSupport, boolean techRebornSupport) {
43-
if (initDone) return;
43+
public static void registerContent(boolean rfSupport, boolean techRebornSupport) {
44+
if (contentRegistrationDone) return;
4445

4546
final float defaultMachineHardness = 0.75f;
4647
final Material defaultMachineMaterial = Material.PISTON;
@@ -55,6 +56,22 @@ public static void init(boolean rfSupport, boolean techRebornSupport) {
5556
Entities.registerTileEntity(TileEntityRFElectricityConverter.class, "rf_electricity_converter_tileentity");
5657
Entities.registerTileEntity(TileEntityRFQuantumConverter.class, "rf_quantum_converter_tileentity");
5758

59+
}
60+
if (techRebornSupport) {
61+
FMLLog.info("Initializing Tech Reborn interface content");
62+
converter_tr_electricity = addBlock(new BlockTRConverter(defaultMachineMaterial, defaultMachineHardness, new ConduitType("electricity"), TileEntityTRElectricityConverter.class), "converter_tr_electricity");
63+
Entities.registerTileEntity(TileEntityTRElectricityConverter.class, "tr_electricity_converter_tileentity");
64+
}
65+
contentRegistrationDone = true;
66+
}
67+
68+
public static void registerRecipes() {
69+
if (recipeRegistrationDone) return;
70+
if (!contentRegistrationDone) {
71+
throw new IllegalStateException("Mod support content must be registered before its recipes");
72+
}
73+
74+
if (converter_rf_steam != null) {
5875
ForgeRegistries.RECIPES.register(recipe(new ItemStack(converter_rf_steam, 1),
5976
"xyz",
6077
'x', "governor", 'y', "frameSteel", 'z', "blockRedstone"));
@@ -65,16 +82,11 @@ public static void init(boolean rfSupport, boolean techRebornSupport) {
6582
"xyz",
6683
'x', net.minecraft.init.Items.ENDER_PEARL, 'y', "frameSteel", 'z', "blockRedstone"));
6784
}
68-
if (techRebornSupport) {
69-
FMLLog.info("Initializing Tech Reborn interface content");
70-
// first, register transformers in Ore Dictionary
71-
72-
converter_tr_electricity = addBlock(new BlockTRConverter(defaultMachineMaterial, defaultMachineHardness, new ConduitType("electricity"), TileEntityTRElectricityConverter.class), "converter_tr_electricity");
73-
Entities.registerTileEntity(TileEntityTRElectricityConverter.class, "tr_electricity_converter_tileentity");
85+
if (converter_tr_electricity != null) {
7486
ForgeRegistries.RECIPES.register(recipe(new ItemStack(converter_tr_electricity, 1), "XXX", "XZX", "XXX",
7587
'Z', "PSU", 'X', "ingotRefinedIron"));
7688
}
77-
initDone = true;
89+
recipeRegistrationDone = true;
7890
}
7991

8092
private static ShapedOreRecipe recipe(ItemStack output, Object... params) {
@@ -101,13 +113,12 @@ private static Block addBlock(Block block, String name) {
101113

102114

103115
@SideOnly(Side.CLIENT)
104-
public static void registerItemRenders(FMLInitializationEvent event) {
116+
public static void bakeModels() {
105117
for (Map.Entry<String, Block> e : allBlocks.entrySet()) {
106118
String name = e.getKey();
107119
Block block = e.getValue();
108-
Minecraft.getMinecraft().getRenderItem().getItemModelMesher()
109-
.register(net.minecraft.item.Item.getItemFromBlock(block), 0,
110-
new ModelResourceLocation(PowerAdvantage.MODID + ":" + name, "inventory"));
120+
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0,
121+
new ModelResourceLocation(PowerAdvantage.MODID + ":" + name, "inventory"));
111122
}
112123
}
113124
}

0 commit comments

Comments
 (0)