diff --git a/build.gradle b/build.gradle index 878398f6d..fcdff827e 100644 --- a/build.gradle +++ b/build.gradle @@ -291,7 +291,7 @@ project(':forge') { installer 'cpw.mods:modlauncher:1.0.+' installer 'net.minecraftforge:accesstransformers:0.16.+:shadowed' installer 'net.minecraftforge:eventbus:0.8.+:service' - installer 'net.minecraftforge:forgespi:0.11.+' + installer 'net.minecraftforge:forgespi:0.12.+' installer 'net.minecraftforge:coremods:0.4.+' installer 'net.minecraftforge:unsafe:0.2.+' installer 'com.electronwill.night-config:core:3.6.0' diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/RuntimeDistCleaner.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/RuntimeDistCleaner.java index f8cb738cb..ed4dde391 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/RuntimeDistCleaner.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/RuntimeDistCleaner.java @@ -20,17 +20,20 @@ package net.minecraftforge.fml.loading; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; +import java.util.stream.Collectors; import com.google.common.collect.Streams; import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.api.distmarker.OnlyIns; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -51,6 +54,7 @@ public class RuntimeDistCleaner implements ILaunchPluginService private static final Marker DISTXFORM = MarkerManager.getMarker("DISTXFORM"); private static String DIST; private static final String ONLYIN = Type.getDescriptor(OnlyIn.class); + private static final String ONLYINS = Type.getDescriptor(OnlyIns.class); @Override public String name() { @@ -67,6 +71,34 @@ public class RuntimeDistCleaner implements ILaunchPluginService throw new RuntimeException("Attempted to load class "+ classNode.name + " for invalid dist "+ DIST); } + if (classNode.interfaces != null ) + { + unpack(classNode.visibleAnnotations).stream() + .filter(ann->Objects.equals(ann.desc, ONLYIN)) + .filter(ann->ann.values.indexOf("_interface") != -1) + .filter(ann->!Objects.equals(((String[])ann.values.get(ann.values.indexOf("value") + 1))[1], DIST)) + .map(ann -> ((Type)ann.values.get(ann.values.indexOf("_interface") + 1)).getInternalName()) + .forEach(intf -> { + if (classNode.interfaces.remove(intf)) { + LOGGER.debug(DISTXFORM,"Removing Interface: {} implements {}", classNode.name, intf); + changes.compareAndSet(false, true); + } + }); + + //Remove Class level @OnlyIn/@OnlyIns annotations, this is important if anyone gets ambitious and tries to reflect an annotation with _interface set. + if (classNode.visibleAnnotations != null) { + Iterator itr = classNode.visibleAnnotations.iterator(); + while (itr.hasNext()) { + AnnotationNode ann = itr.next(); + if (Objects.equals(ann.desc, ONLYIN) || Objects.equals(ann.desc, ONLYINS)) { + LOGGER.debug(DISTXFORM,"Removing Class Annotation: {} @{}", classNode.name, ann.desc); + itr.remove(); + changes.compareAndSet(false, true); + } + } + } + } + Iterator fields = classNode.fields.iterator(); while(fields.hasNext()) { @@ -118,10 +150,22 @@ public class RuntimeDistCleaner implements ILaunchPluginService return changes.get(); } + @SuppressWarnings("unchecked") + private static List unpack(final List anns) { + if (anns == null) return Collections.emptyList(); + List ret = anns.stream().filter(ann->Objects.equals(ann.desc, ONLYIN)).collect(Collectors.toList()); + anns.stream().filter(ann->Objects.equals(ann.desc, ONLYINS) && ann.values != null) + .map( ann -> (List)ann.values.get(ann.values.indexOf("value") + 1)) + .filter(v -> v != null) + .forEach(v -> v.forEach(ret::add)); + return ret; + } + private boolean remove(final List anns, final String side) { - return !(anns == null) && anns.stream(). + return unpack(anns).stream(). filter(ann->Objects.equals(ann.desc, ONLYIN)). + filter(ann->ann.values.indexOf("_interface") == -1). anyMatch(ann -> !Objects.equals(((String[])ann.values.get(ann.values.indexOf("value")+1))[1], side)); } diff --git a/src/main/java/net/minecraftforge/fml/VersionChecker.java b/src/main/java/net/minecraftforge/fml/VersionChecker.java index 96f351a87..49a44a421 100644 --- a/src/main/java/net/minecraftforge/fml/VersionChecker.java +++ b/src/main/java/net/minecraftforge/fml/VersionChecker.java @@ -235,17 +235,15 @@ public class VersionChecker { ComparableVersion latest = new ComparableVersion(lat); if (current.compareTo(latest) < 0) - { status = BETA_OUTDATED; - target = latest; - } else status = BETA; + target = latest; } else status = BETA; - LOGGER.info("[{}] Found status: {} Target: {}", mod.getModId(), status, target); + LOGGER.info("[{}] Found status: {} Current: {} Target: {}", mod.getModId(), status, current, target); changes = new LinkedHashMap<>(); @SuppressWarnings("unchecked")