diff --git a/build.gradle.kts b/build.gradle.kts index 249576adb..9d8b2cfc7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,13 +25,12 @@ import net.fabricmc.loom.task.RemapJarTask import org.gradle.configurationcache.extensions.capitalized import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassWriter +import org.objectweb.asm.Type import org.objectweb.asm.tree.AnnotationNode import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.FieldNode import org.objectweb.asm.tree.MethodNode import java.io.ByteArrayOutputStream import java.util.* -import java.util.function.Predicate import java.util.jar.JarEntry import java.util.jar.JarFile import java.util.jar.JarOutputStream @@ -288,26 +287,64 @@ fun transformClass(bytes: ByteArray): ByteArray { // Disabled as I don't feel ok with people being able to remove these //node.fields.removeIf { fieldNode: FieldNode -> removeIfDevMixin(fieldNode.visibleAnnotations) } + if (node.visibleAnnotations != null) { + // Cache the field, so we don't CME the list during the remove + val annotationNodes = node.visibleAnnotations.toList() + for (annotationNode in annotationNodes) { + if (annotationNode.desc.equals("Lcom/railwayteam/railways/annotation/compiletime/ImplementsToExtends;")) { + node.visibleAnnotations.remove(annotationNode) + + val type = getValueFromAnnotation(annotationNode, "value")!! + val loaderEnum = getValueFromAnnotation>(annotationNode, "loader")!! + + if (project.name == loaderEnum[1]) { + node.interfaces.remove(type.internalName) + + node.superName = type.internalName + } + } + } + } + return ClassWriter(0).also { node.accept(it) }.toByteArray() } fun removeIfDevMixin(nodeName: String, visibleAnnotations: List?): Boolean { // Don't remove methods if it's not a GHA build/Release build - if (buildNumber == null || !nodeName.lowercase(Locale.ROOT).matches(Regex(".*\\/mixin\\/.*Mixin"))) + if (buildNumber == null && !nodeName.lowercase(Locale.ROOT).matches(Regex(".*\\/mixin\\/.*Mixin"))) return false if (visibleAnnotations != null) { for (annotationNode in visibleAnnotations) { - if (annotationNode.desc == "Lcom/railwayteam/railways/annotation/mixin/DevEnvMixin;") { - println("Removed Method/Field Annotated With @DevEnvMixin from: $nodeName") + if (annotationNode.desc == "Lcom/railwayteam/railways/annotation/mixin/DevEnvMixin;") return true - } } } return false } +fun getValueFromAnnotation(annotation: AnnotationNode?, key: String): T? { + var getNextValue = false + + if (annotation?.values == null) { + return null + } + + // Keys and value are stored in successive pairs, search for the key and if found return the following entry + for (value in annotation.values) { + if (getNextValue) { + @Suppress("UNCHECKED_CAST") + return value as T + } + if (value == key) { + getNextValue = true + } + } + + return null +} + tasks.create("railwaysPublish") { when (val platform = System.getenv("PLATFORM")) { "both" -> { diff --git a/common/src/main/java/com/railwayteam/railways/annotation/compiletime/ImplementsToExtends.java b/common/src/main/java/com/railwayteam/railways/annotation/compiletime/ImplementsToExtends.java new file mode 100644 index 000000000..8a00214f5 --- /dev/null +++ b/common/src/main/java/com/railwayteam/railways/annotation/compiletime/ImplementsToExtends.java @@ -0,0 +1,37 @@ +/* + * Steam 'n' Rails + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.railwayteam.railways.annotation.compiletime; + +import com.railwayteam.railways.multiloader.Loader; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Remapping doesn't exist for this hell, don't expect this to work with minecraft classes/interfaces + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface ImplementsToExtends { + Class value(); + + Loader loader(); +} diff --git a/common/src/main/java/com/railwayteam/railways/content/palettes/boiler/BoilerBlock.java b/common/src/main/java/com/railwayteam/railways/content/palettes/boiler/BoilerBlock.java index 858d6cb6f..870432cc3 100644 --- a/common/src/main/java/com/railwayteam/railways/content/palettes/boiler/BoilerBlock.java +++ b/common/src/main/java/com/railwayteam/railways/content/palettes/boiler/BoilerBlock.java @@ -21,8 +21,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Vector3f; +import com.railwayteam.railways.annotation.compiletime.ImplementsToExtends; import com.railwayteam.railways.mixin_interfaces.IForceRenderingSodium; import com.railwayteam.railways.mixin_interfaces.IHasCustomOutline; +import com.railwayteam.railways.multiloader.Loader; import com.railwayteam.railways.registry.CRShapes; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; import com.simibubi.create.content.equipment.wrench.IWrenchable; @@ -67,6 +69,7 @@ import java.util.Locale; import java.util.function.Predicate; +@ImplementsToExtends(value = ReducedDestroyEffects.class, loader = Loader.FORGE) public class BoilerBlock extends Block implements IWrenchable, IForceRenderingSodium, IHasCustomOutline, ReducedDestroyEffects { public static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());