Merge remote-tracking branch 'origin/1.19.2' into 1.20
This commit is contained in:
commit
357d421f5a
60
annotation-processor/build.gradle
Normal file
60
annotation-processor/build.gradle
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
plugins {
|
||||||
|
id 'com.github.johnrengelman.shadow'
|
||||||
|
id 'java-library'
|
||||||
|
id 'com.diffplug.spotless'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url uri("https://maven.fabricmc.net") }
|
||||||
|
maven { url "https://maven.neoforged.net/releases" }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
annotationProcessor 'com.google.auto.service:auto-service:1.1.1'
|
||||||
|
compileOnly 'com.google.auto.service:auto-service:1.1.1'
|
||||||
|
|
||||||
|
implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
shadow 'com.google.code.gson:gson:2.10.1'
|
||||||
|
implementation 'com.google.auto:auto-common:1.2.1'
|
||||||
|
shadow 'com.google.auto:auto-common:1.2.1'
|
||||||
|
implementation 'com.google.guava:guava:21.0'
|
||||||
|
shadow 'com.google.guava:guava:21.0'
|
||||||
|
|
||||||
|
implementation project(":annotations")
|
||||||
|
shadow project(":annotations")
|
||||||
|
// Shadow annotations
|
||||||
|
implementation 'net.fabricmc:sponge-mixin:0.12.5+'
|
||||||
|
implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||||
|
implementation 'net.minecraftforge:mergetool:1.1.7'
|
||||||
|
implementation 'net.neoforged:mergetool:2.0.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs += '--enable-preview'
|
||||||
|
options.release = 17
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
dependencies {
|
||||||
|
include(dependency('net.fabricmc:sponge-mixin:'))
|
||||||
|
include(dependency('net.fabricmc:fabric-loader:'))
|
||||||
|
include(dependency(':mergetool:'))
|
||||||
|
}
|
||||||
|
// shadowJar bug
|
||||||
|
include '*.jar'
|
||||||
|
include 'META-INF/services/javax.annotation.processing.Processor'
|
||||||
|
include 'org/spongepowered/asm/mixin/Mixin.class'
|
||||||
|
include 'org/fury_phoenix/**/*'
|
||||||
|
include {it.getName() == 'OnlyIn.class'}
|
||||||
|
include {it.getName() == 'Dist.class'}
|
||||||
|
include {it.getName() == 'Environment.class'}
|
||||||
|
include {it.getName() == 'EnvType.class'}
|
||||||
|
}
|
||||||
|
|
||||||
|
spotless {
|
||||||
|
java {
|
||||||
|
removeUnusedImports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = '1.1.4'
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
package org.fury_phoenix.mixinAp.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.annotation.processing.Messager;
|
||||||
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
|
import javax.lang.model.element.AnnotationValue;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
import javax.lang.model.util.Elements;
|
||||||
|
import javax.lang.model.util.Types;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
|
||||||
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
|
import org.embeddedt.modernfix.annotation.IgnoreMixin;
|
||||||
|
import org.fury_phoenix.mixinAp.util.TypedAccessorMap;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
|
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
|
||||||
|
import static java.util.AbstractMap.SimpleImmutableEntry;
|
||||||
|
|
||||||
|
public class ClientMixinValidator {
|
||||||
|
|
||||||
|
private final Messager messager;
|
||||||
|
|
||||||
|
private final Elements elemUtils;
|
||||||
|
|
||||||
|
private final Types types;
|
||||||
|
|
||||||
|
private final boolean debug;
|
||||||
|
|
||||||
|
private static final TypedAccessorMap<Annotation> markers = new TypedAccessorMap<>();
|
||||||
|
|
||||||
|
private static final Map.Entry<Class<Environment>, Function<? super Environment, ?>>
|
||||||
|
FabricAccessor = new SimpleImmutableEntry<>(Environment.class, Environment::value);
|
||||||
|
|
||||||
|
private static final Map.Entry<
|
||||||
|
Class<net.minecraftforge.api.distmarker.OnlyIn>,
|
||||||
|
Function<? super net.minecraftforge.api.distmarker.OnlyIn, ?>>
|
||||||
|
ForgeAccessor = new SimpleImmutableEntry<>(
|
||||||
|
net.minecraftforge.api.distmarker.OnlyIn.class,
|
||||||
|
net.minecraftforge.api.distmarker.OnlyIn::value
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final Map.Entry<
|
||||||
|
Class<net.neoforged.api.distmarker.OnlyIn>,
|
||||||
|
Function<? super net.neoforged.api.distmarker.OnlyIn, ?>>
|
||||||
|
NeoForgeAccessor = new SimpleImmutableEntry<>(
|
||||||
|
net.neoforged.api.distmarker.OnlyIn.class,
|
||||||
|
net.neoforged.api.distmarker.OnlyIn::value
|
||||||
|
);
|
||||||
|
|
||||||
|
static {
|
||||||
|
markers.put(FabricAccessor);
|
||||||
|
markers.put(ForgeAccessor);
|
||||||
|
markers.put(NeoForgeAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Collection<String> unannotatedClasses = new HashSet<>();
|
||||||
|
|
||||||
|
public ClientMixinValidator(ProcessingEnvironment env) {
|
||||||
|
debug = Boolean.valueOf(env.getOptions().get("org.fury_phoenix.mixinAp.validator.debug"));
|
||||||
|
messager = env.getMessager();
|
||||||
|
elemUtils = env.getElementUtils();
|
||||||
|
types = env.getTypeUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateMixin(TypeElement annotatedMixinClass) {
|
||||||
|
return targetsClient(annotatedMixinClass) &&
|
||||||
|
(annotatedMixinClass.getAnnotation(ClientOnlyMixin.class) == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean targetsClient(TypeElement annotatedMixinClass) {
|
||||||
|
return targetsClient(getTargets(annotatedMixinClass)) &&
|
||||||
|
!isIgnored(annotatedMixinClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean targetsClient(Collection<?> classTargets) {
|
||||||
|
return classTargets.stream().anyMatch(this::targetsClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean targetsClient(Object classTarget) {
|
||||||
|
return switch (classTarget) {
|
||||||
|
case TypeElement te ->
|
||||||
|
isClientMarked(te);
|
||||||
|
case TypeMirror tm -> {
|
||||||
|
var el = types.asElement(tm);
|
||||||
|
yield el != null ? targetsClient(el) : warn("TypeMirror of " + tm);
|
||||||
|
}
|
||||||
|
// If you're using a dollar sign in class names you are insane
|
||||||
|
case String s -> {
|
||||||
|
var te =
|
||||||
|
elemUtils.getTypeElement(toSourceString(s.split("\\$")[0]));
|
||||||
|
yield te != null ? targetsClient(te) : warn(s);
|
||||||
|
}
|
||||||
|
default ->
|
||||||
|
throw new IllegalArgumentException("Unhandled type: "
|
||||||
|
+ classTarget.getClass() + "\n" + "Stringified contents: "
|
||||||
|
+ classTarget.toString());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isClientMarked(TypeElement te) {
|
||||||
|
for (var entry : markers.entrySet()) {
|
||||||
|
var marker = te.getAnnotation(entry.getKey());
|
||||||
|
if(marker == null) continue;
|
||||||
|
|
||||||
|
return entry.getValue().apply(marker).toString().equals("CLIENT");
|
||||||
|
}
|
||||||
|
if(debug && unannotatedClasses.add(te.toString())) {
|
||||||
|
messager.printMessage(Diagnostic.Kind.WARNING,
|
||||||
|
"No marker annotations present on " + te + "!");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIgnored(TypeElement te) {
|
||||||
|
if(te.getAnnotation(IgnoreMixin.class) != null) {
|
||||||
|
messager.printMessage(Diagnostic.Kind.WARNING,
|
||||||
|
toSourceString(te.toString()) + " is ignored!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean warn(Object o) {
|
||||||
|
messager.printMessage(Diagnostic.Kind.WARNING,
|
||||||
|
toSourceString(o.toString()) + " can't be loaded, so it is skipped!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map.Entry<? extends CharSequence, ? extends CharSequence>
|
||||||
|
getClientMixinEntry(TypeElement annotatedMixinClass) {
|
||||||
|
return new SimpleImmutableEntry<>(
|
||||||
|
annotatedMixinClass.getQualifiedName(),
|
||||||
|
getTargets(annotatedMixinClass)
|
||||||
|
.stream()
|
||||||
|
.filter(this::targetsClient)
|
||||||
|
.map(Object::toString)
|
||||||
|
.map(ClientMixinValidator::toSourceString)
|
||||||
|
.collect(Collectors.joining(", "))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Object> getTargets(TypeElement annotatedMixinClass) {
|
||||||
|
Collection<? extends TypeMirror> clzsses = Set.of();
|
||||||
|
Collection<? extends String> imaginaries = Set.of();
|
||||||
|
TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType();
|
||||||
|
for (var mirror : annotatedMixinClass.getAnnotationMirrors()) {
|
||||||
|
if(!types.isSameType(mirror.getAnnotationType(), MixinElement))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
var wrappedClzss = (List<? extends AnnotationValue>)
|
||||||
|
getAnnotationValue(mirror, "value").getValue();
|
||||||
|
|
||||||
|
clzsses = wrappedClzss.stream()
|
||||||
|
.map(AnnotationValue::getValue)
|
||||||
|
.map(TypeMirror.class::cast)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
var wrappedStrings = (List<? extends AnnotationValue>)
|
||||||
|
getAnnotationValue(mirror, "targets").getValue();
|
||||||
|
|
||||||
|
imaginaries = wrappedStrings.stream()
|
||||||
|
.map(AnnotationValue::getValue)
|
||||||
|
.map(String.class::cast)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
return Stream.of(clzsses, imaginaries)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toSourceString(String bytecodeName) {
|
||||||
|
return bytecodeName.replaceAll("\\/", ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
package org.fury_phoenix.mixinAp.annotation;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.annotation.processing.AbstractProcessor;
|
||||||
|
import javax.annotation.processing.Processor;
|
||||||
|
import javax.annotation.processing.RoundEnvironment;
|
||||||
|
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
|
import javax.annotation.processing.SupportedOptions;
|
||||||
|
import javax.annotation.processing.SupportedSourceVersion;
|
||||||
|
import javax.lang.model.SourceVersion;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
|
import org.fury_phoenix.mixinAp.config.MixinConfig;
|
||||||
|
|
||||||
|
@SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"})
|
||||||
|
@SupportedOptions({"rootProject.name", "project.name", "org.fury_phoenix.mixinAp.validator.debug"})
|
||||||
|
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||||
|
@AutoService(Processor.class)
|
||||||
|
public class MixinProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
|
// Remember to call toString when using aliases
|
||||||
|
private static final Map<String, String> aliases = Map.of(
|
||||||
|
"Mixin", "mixins",
|
||||||
|
"ClientOnlyMixin", "client"
|
||||||
|
);
|
||||||
|
|
||||||
|
private final Map<String, List<String>> mixinConfigList = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
|
try {
|
||||||
|
if(roundEnv.processingOver()){
|
||||||
|
filterMixinSets();
|
||||||
|
// create record for serialization, compute package name
|
||||||
|
String packageName = Optional.ofNullable(mixinConfigList.get("mixins"))
|
||||||
|
.orElse(mixinConfigList.get("client"))
|
||||||
|
.get(0).split("(?<=mixin)")[0];
|
||||||
|
finalizeMixinConfig();
|
||||||
|
new MixinConfig(packageName,
|
||||||
|
mixinConfigList.get("mixins"),
|
||||||
|
mixinConfigList.get("client")
|
||||||
|
).generateMixinConfig(processingEnv);
|
||||||
|
} else {
|
||||||
|
processMixins(annotations, roundEnv);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" +
|
||||||
|
Throwables.getStackTraceAsString(e));
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
// Halt the AP to prevent nonsense errors
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMixins(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
|
for (TypeElement annotation : annotations) {
|
||||||
|
Set<? extends Element> annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation);
|
||||||
|
|
||||||
|
Stream<TypeElement> mixinStream =
|
||||||
|
annotatedMixins.stream()
|
||||||
|
.map(TypeElement.class::cast);
|
||||||
|
|
||||||
|
validateCommonMixins(annotation, mixinStream);
|
||||||
|
|
||||||
|
List<String> mixins =
|
||||||
|
annotatedMixins.stream()
|
||||||
|
.map(TypeElement.class::cast)
|
||||||
|
.map(TypeElement::toString)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterMixinSets() {
|
||||||
|
List<String> commonSet = mixinConfigList.get("mixins");
|
||||||
|
if(commonSet == null) return;
|
||||||
|
commonSet.removeAll(mixinConfigList.get("client"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateCommonMixins(TypeElement annotation, Stream<TypeElement> mixins) {
|
||||||
|
if(!annotation.getSimpleName().toString().equals("Mixin"))
|
||||||
|
return;
|
||||||
|
ClientMixinValidator validator = new ClientMixinValidator(processingEnv);
|
||||||
|
// The implementation may throw a CME
|
||||||
|
mixins.sequential()
|
||||||
|
.filter(validator::validateMixin)
|
||||||
|
.map(validator::getClientMixinEntry)
|
||||||
|
.forEach(this::logClientClassTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logClientClassTarget(Map.Entry<? extends CharSequence, ? extends CharSequence> mixin) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
|
||||||
|
"Mixin " + mixin.getKey() + " targets client-side classes: " + mixin.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finalizeMixinConfig() {
|
||||||
|
// relativize class names
|
||||||
|
for(var list : mixinConfigList.values()) {
|
||||||
|
list.replaceAll(className -> className.split("(?<=mixin.)")[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package org.fury_phoenix.mixinAp.config;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
|
|
||||||
|
public record MixinConfig(
|
||||||
|
boolean required,
|
||||||
|
String minVersion,
|
||||||
|
@SerializedName("package")
|
||||||
|
String packageName,
|
||||||
|
String plugin,
|
||||||
|
String compatabilityLevel,
|
||||||
|
@SerializedName("mixins")
|
||||||
|
List<String> commonMixins,
|
||||||
|
@SerializedName("client")
|
||||||
|
List<String> clientMixins,
|
||||||
|
InjectorOptions injectors, OverwriteOptions overwrites
|
||||||
|
) {
|
||||||
|
public MixinConfig(String packageName, List<String> commonMixins, List<String> clientMixins) {
|
||||||
|
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_8",
|
||||||
|
commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT);
|
||||||
|
}
|
||||||
|
public record InjectorOptions(int defaultRequire) {
|
||||||
|
public static final InjectorOptions DEFAULT = new InjectorOptions(1);
|
||||||
|
}
|
||||||
|
public record OverwriteOptions(boolean conformVisibility) {
|
||||||
|
public static final OverwriteOptions DEFAULT = new OverwriteOptions(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateMixinConfig(ProcessingEnvironment env) throws IOException {
|
||||||
|
try (
|
||||||
|
Writer mixinConfigWriter = env.getFiler()
|
||||||
|
.createResource(StandardLocation.SOURCE_OUTPUT, "",
|
||||||
|
MixinConfig.computeMixinConfigPath(
|
||||||
|
Optional.of(env.getOptions().get("rootProject.name")),
|
||||||
|
Optional.ofNullable(env.getOptions().get("project.name"))
|
||||||
|
)
|
||||||
|
).openWriter()
|
||||||
|
) {
|
||||||
|
String mixinConfig = new GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.create()
|
||||||
|
.toJson(this);
|
||||||
|
|
||||||
|
mixinConfigWriter.write(mixinConfig);
|
||||||
|
mixinConfigWriter.write("\n");
|
||||||
|
} catch (IOException e) { throw e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String computeMixinConfigPath(Optional<String> rootProjectName, Optional<String> projectName) {
|
||||||
|
return "resources/" +
|
||||||
|
rootProjectName.get() +
|
||||||
|
(projectName.isPresent() ? "-" : "") +
|
||||||
|
projectName.orElse("") +
|
||||||
|
".mixins.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.fury_phoenix.mixinAp.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static java.util.Map.Entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-safe heterogenous map of accessors
|
||||||
|
* @author Fury_Phoenix
|
||||||
|
* @reason Type-safety since K, V of Map are non-identical
|
||||||
|
* @param <SuperType> The supertype of desired types.
|
||||||
|
* This is useful in cases such as <A extends Annotation>.
|
||||||
|
*/
|
||||||
|
public class TypedAccessorMap<SuperType> {
|
||||||
|
private final Map<Class<? extends SuperType>, Function<Object, ?>> typedAccessors = new HashMap<>();
|
||||||
|
|
||||||
|
public <T extends SuperType> void put(Class<T> key, Function<? super T, ?> func) {
|
||||||
|
Objects.requireNonNull(func);
|
||||||
|
typedAccessors.put(Objects.requireNonNull(key), o -> func.apply(key.cast(o)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends SuperType> void put(Entry<Class<T>, Function<? super T, ?>> entry) {
|
||||||
|
put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends SuperType> Function<Object, ?> get(Class<T> key) {
|
||||||
|
return typedAccessors.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Entry<Class<? extends SuperType>, Function<Object, ?>>> entrySet() {
|
||||||
|
return typedAccessors.entrySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
annotations/build.gradle
Normal file
6
annotations/build.gradle
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
plugins {
|
||||||
|
id 'modernfix.common-conventions'
|
||||||
|
id 'java-library'
|
||||||
|
}
|
||||||
|
|
||||||
|
version = '1.1.0'
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.embeddedt.modernfix.annotation;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface IgnoreMixin {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ plugins {
|
||||||
id 'org.ajoberstar.grgit' version '5.2.0'
|
id 'org.ajoberstar.grgit' version '5.2.0'
|
||||||
id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0'
|
id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0'
|
||||||
id "com.modrinth.minotaur" version "2.+" apply false
|
id "com.modrinth.minotaur" version "2.+" apply false
|
||||||
id("com.diffplug.spotless") version "6.18.0" apply false
|
id("com.diffplug.spotless") version "6.18.0" apply false
|
||||||
id 'modernfix.common-conventions' apply false
|
id 'modernfix.common-conventions' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'groovy-gradle-plugin'
|
id 'groovy-gradle-plugin'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,4 @@ repositories {
|
||||||
url 'https://maven.terraformersmc.com/releases'
|
url 'https://maven.terraformersmc.com/releases'
|
||||||
}
|
}
|
||||||
maven { url = "https://jitpack.io" }
|
maven { url = "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,37 +16,26 @@ dependencies {
|
||||||
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
|
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
implementation project(":annotations")
|
||||||
|
annotationProcessor project(path: ":annotation-processor", configuration: 'shadow')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.sourceSets {
|
||||||
|
main.resources.srcDirs += [layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main/resources")]
|
||||||
|
}
|
||||||
|
// hack to shut up gradle about the hack to include generated resources
|
||||||
tasks {
|
tasks {
|
||||||
processResources {
|
processResources {
|
||||||
def mixinFileList = []
|
dependsOn compileJava
|
||||||
def mixinDirectory = file("src/main/java/org/embeddedt/modernfix/" + project.name + "/mixin")
|
}
|
||||||
fileTree(mixinDirectory).visit { FileVisitDetails details ->
|
}
|
||||||
if(details.file.isFile()) {
|
|
||||||
def fileName = mixinDirectory.relativePath(details.file).toString().replaceFirst(/\.java$/, "").replace('/', '.')
|
|
||||||
mixinFileList << fileName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def mixinClassesStringB = new StringBuilder()
|
tasks.withType(JavaCompile) {
|
||||||
for(int i = 0; i < mixinFileList.size(); i++) {
|
options.fork = true
|
||||||
mixinClassesStringB.append(" \"")
|
options.forkOptions.jvmArgs << '--enable-preview'
|
||||||
mixinClassesStringB.append(mixinFileList.get(i))
|
configure(options) {
|
||||||
mixinClassesStringB.append('"')
|
if (!name.toLowerCase().contains('test')) {
|
||||||
if(i < (mixinFileList.size() - 1))
|
options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}"
|
||||||
mixinClassesStringB.append(',')
|
|
||||||
mixinClassesStringB.append('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
def replacements = [
|
|
||||||
mixin_classes: mixinClassesStringB.toString()
|
|
||||||
]
|
|
||||||
|
|
||||||
inputs.properties replacements
|
|
||||||
def filePattern = "modernfix-" + project.name + ".mixins.json"
|
|
||||||
filesMatching(filePattern) {
|
|
||||||
expand replacements
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import net.minecraft.client.resources.model.ModelManager;
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.dynamicresources.DynamicModelCache;
|
import org.embeddedt.modernfix.dynamicresources.DynamicModelCache;
|
||||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||||
import org.embeddedt.modernfix.util.DynamicInt2ObjectMap;
|
import org.embeddedt.modernfix.util.DynamicInt2ObjectMap;
|
||||||
|
|
@ -19,6 +20,7 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Mixin(ItemModelShaper.class)
|
@Mixin(ItemModelShaper.class)
|
||||||
|
@ClientOnlyMixin
|
||||||
public abstract class ItemModelShaperMixin {
|
public abstract class ItemModelShaperMixin {
|
||||||
|
|
||||||
@Shadow public abstract ModelManager getModelManager();
|
@Shadow public abstract ModelManager getModelManager();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
|
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.render.RenderState;
|
import org.embeddedt.modernfix.render.RenderState;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
@ -8,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(GameRenderer.class)
|
@Mixin(GameRenderer.class)
|
||||||
|
@ClientOnlyMixin
|
||||||
public class GameRendererMixin {
|
public class GameRendererMixin {
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V", shift = At.Shift.BEFORE))
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V", shift = At.Shift.BEFORE))
|
||||||
private void markRenderingLevel(CallbackInfo ci) {
|
private void markRenderingLevel(CallbackInfo ci) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import net.minecraft.client.resources.model.SimpleBakedModel;
|
||||||
import net.minecraft.world.item.ItemDisplayContext;
|
import net.minecraft.world.item.ItemDisplayContext;
|
||||||
import net.minecraft.world.item.BlockItem;
|
import net.minecraft.world.item.BlockItem;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.render.FastItemRenderType;
|
import org.embeddedt.modernfix.render.FastItemRenderType;
|
||||||
import org.embeddedt.modernfix.render.RenderState;
|
import org.embeddedt.modernfix.render.RenderState;
|
||||||
import org.embeddedt.modernfix.render.SimpleItemModelView;
|
import org.embeddedt.modernfix.render.SimpleItemModelView;
|
||||||
|
|
@ -21,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(value = ItemRenderer.class, priority = 600)
|
@Mixin(value = ItemRenderer.class, priority = 600)
|
||||||
|
@ClientOnlyMixin
|
||||||
public abstract class ItemRendererMixin {
|
public abstract class ItemRendererMixin {
|
||||||
private ItemDisplayContext transformType;
|
private ItemDisplayContext transformType;
|
||||||
private final SimpleItemModelView modelView = new SimpleItemModelView();
|
private final SimpleItemModelView modelView = new SimpleItemModelView();
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import java.util.*;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
public class ModernFixEarlyConfig {
|
public class ModernFixEarlyConfig {
|
||||||
private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig");
|
private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig");
|
||||||
|
|
@ -85,7 +87,10 @@ public class ModernFixEarlyConfig {
|
||||||
continue;
|
continue;
|
||||||
try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
|
try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
|
||||||
JsonObject configObject = (JsonObject)new JsonParser().parse(reader);
|
JsonObject configObject = (JsonObject)new JsonParser().parse(reader);
|
||||||
JsonArray mixinList = configObject.getAsJsonArray("mixins");
|
List<JsonElement> mixinList = Stream.of("mixins", "client")
|
||||||
|
.map(key -> Optional.ofNullable(configObject.getAsJsonArray(key)))
|
||||||
|
.flatMap(arr -> arr.map(jsonElements -> StreamSupport.stream(jsonElements.spliterator(), false)).orElseGet(Stream::of))
|
||||||
|
.collect(Collectors.toList());
|
||||||
String packageName = configObject.get("package").getAsString().replace('.', '/');
|
String packageName = configObject.get("package").getAsString().replace('.', '/');
|
||||||
for(JsonElement mixin : mixinList) {
|
for(JsonElement mixin : mixinList) {
|
||||||
mixinPaths.add(packageName + "/" + mixin.getAsString().replace('.', '/') + ".class");
|
mixinPaths.add(packageName + "/" + mixin.getAsString().replace('.', '/') + ".class");
|
||||||
|
|
@ -213,6 +218,7 @@ public class ModernFixEarlyConfig {
|
||||||
disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant");
|
disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant");
|
||||||
disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me");
|
disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me");
|
||||||
disableIfModPresent("mixin.bugfix.preserve_early_window_pos", "better_loading_screen");
|
disableIfModPresent("mixin.bugfix.preserve_early_window_pos", "better_loading_screen");
|
||||||
|
disableIfModPresent("mixin.perf.dynamic_dfu", "litematica");
|
||||||
disableIfModPresent("mixin.perf.cache_strongholds", "littletiles", "c2me");
|
disableIfModPresent("mixin.perf.cache_strongholds", "littletiles", "c2me");
|
||||||
// content overlap
|
// content overlap
|
||||||
disableIfModPresent("mixin.perf.deduplicate_wall_shapes", "dashloader");
|
disableIfModPresent("mixin.perf.deduplicate_wall_shapes", "dashloader");
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ public class ModelBakeryHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends Comparable<T>> T getValueHelper(Property<T> property, String value) {
|
private static <T extends Comparable<T>> T getValueHelper(Property<T> property, String value) {
|
||||||
return property.getValue(value).orElse((T) null);
|
return property.getValue(value).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
|
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,8 @@ public class RegistryStorage {
|
||||||
|
|
||||||
public static <T> BiMap<ResourceKey<T>, DirectStorageRegistryObject> createKeyStorage(ResourceKey<? extends Registry<T>> registryKey, BiMap<ResourceLocation, DirectStorageRegistryObject> storage) {
|
public static <T> BiMap<ResourceKey<T>, DirectStorageRegistryObject> createKeyStorage(ResourceKey<? extends Registry<T>> registryKey, BiMap<ResourceLocation, DirectStorageRegistryObject> storage) {
|
||||||
if(storage instanceof DirectStorageBiMap) {
|
if(storage instanceof DirectStorageBiMap) {
|
||||||
DirectStorageBiMap<ResourceLocation, DirectStorageRegistryObject> directStorageBiMap = (DirectStorageBiMap<ResourceLocation, DirectStorageRegistryObject>)storage;
|
|
||||||
// silently ignore put/putAll calls on this map
|
// silently ignore put/putAll calls on this map
|
||||||
return new TransformingBiMap<ResourceLocation, DirectStorageRegistryObject, ResourceKey<T>, DirectStorageRegistryObject>(directStorageBiMap, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) {
|
return new TransformingBiMap<ResourceLocation, DirectStorageRegistryObject, ResourceKey<T>, DirectStorageRegistryObject>(storage, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) {
|
||||||
@Override
|
@Override
|
||||||
public DirectStorageRegistryObject put(ResourceKey<T> key, DirectStorageRegistryObject value) {
|
public DirectStorageRegistryObject put(ResourceKey<T> key, DirectStorageRegistryObject value) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"required": true,
|
|
||||||
"minVersion": "0.8",
|
|
||||||
"package": "org.embeddedt.modernfix.common.mixin",
|
|
||||||
"plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin",
|
|
||||||
"compatibilityLevel": "JAVA_17",
|
|
||||||
"mixins": [
|
|
||||||
${mixin_classes}
|
|
||||||
],
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
},
|
|
||||||
"overwrites": {
|
|
||||||
"conformVisibility": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
plugins {
|
plugins {
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
id "com.github.johnrengelman.shadow"
|
||||||
id 'com.adarshr.test-logger' version '3.2.0'
|
id 'com.adarshr.test-logger' version '3.2.0'
|
||||||
id "modernfix.mod-common-conventions"
|
id "modernfix.mod-common-conventions"
|
||||||
id "modernfix.platform-conventions"
|
id "modernfix.platform-conventions"
|
||||||
|
|
@ -64,6 +64,7 @@ dependencies {
|
||||||
|
|
||||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||||
testImplementation(shadowCommon(project(path: ":common", configuration: "transformProductionFabric"))) { transitive false }
|
testImplementation(shadowCommon(project(path: ":common", configuration: "transformProductionFabric"))) { transitive false }
|
||||||
|
shadowCommon(project(path: ":annotations"))
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:${project.junit_version}"))
|
testImplementation(platform("org.junit:junit-bom:${project.junit_version}"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"required": true,
|
|
||||||
"package": "org.embeddedt.modernfix.fabric.mixin",
|
|
||||||
"plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin",
|
|
||||||
"compatibilityLevel": "JAVA_8",
|
|
||||||
"minVersion": "0.8",
|
|
||||||
"mixins": [
|
|
||||||
${mixin_classes}
|
|
||||||
],
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
},
|
|
||||||
"overwrites": {
|
|
||||||
"conformVisibility": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -41,3 +41,5 @@ processResources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make genSources do nothing in this project
|
||||||
|
project.gradle.startParameter.excludedTaskNames.add("genSources")
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
plugins {
|
plugins {
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
id "com.github.johnrengelman.shadow"
|
||||||
id "modernfix.mod-common-conventions"
|
id "modernfix.mod-common-conventions"
|
||||||
id "modernfix.platform-conventions"
|
id "modernfix.platform-conventions"
|
||||||
}
|
}
|
||||||
|
|
@ -75,6 +75,8 @@ dependencies {
|
||||||
|
|
||||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||||
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
|
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
|
||||||
|
shadowCommon(project(path: ":annotations"))
|
||||||
|
forgeRuntimeLibrary(project(path: ":annotations"))
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"required": true,
|
|
||||||
"package": "org.embeddedt.modernfix.forge.mixin",
|
|
||||||
"plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin",
|
|
||||||
"compatibilityLevel": "JAVA_8",
|
|
||||||
"minVersion": "0.8",
|
|
||||||
"mixins": [
|
|
||||||
${mixin_classes}
|
|
||||||
],
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
},
|
|
||||||
"overwrites": {
|
|
||||||
"conformVisibility": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,3 +28,6 @@ diagonal_fences_version=4558828
|
||||||
spark_version=4587310
|
spark_version=4587310
|
||||||
|
|
||||||
use_fabric_api_at_runtime=true
|
use_fabric_api_at_runtime=true
|
||||||
|
|
||||||
|
# Look up maven coordinates when changing shadow_version
|
||||||
|
shadow_version=7.1.2
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,20 @@ pluginManagement {
|
||||||
maven { url "https://maven.architectury.dev/" }
|
maven { url "https://maven.architectury.dev/" }
|
||||||
maven { url "https://maven.minecraftforge.net/" }
|
maven { url "https://maven.minecraftforge.net/" }
|
||||||
}
|
}
|
||||||
|
resolutionStrategy {
|
||||||
|
eachPlugin {
|
||||||
|
if (requested.id.id == "com.github.johnrengelman.shadow") {
|
||||||
|
useModule("gradle.plugin.com.github.johnrengelman:shadow:${shadow_version}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include("annotation-processor")
|
||||||
|
include("annotations")
|
||||||
include("test_agent")
|
include("test_agent")
|
||||||
include("common")
|
include("common")
|
||||||
|
|
||||||
startParameter.excludedTaskNames.add(':fabric:testmod:genSources')
|
|
||||||
|
|
||||||
def current_platforms = getProperty("enabled_platforms").tokenize(',')
|
def current_platforms = getProperty("enabled_platforms").tokenize(',')
|
||||||
current_platforms.each { it ->
|
current_platforms.each { it ->
|
||||||
def platform_name = it.trim()
|
def platform_name = it.trim()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user