From ecef37ac607d27c3dcabadecfe8c342bb8d74b64 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 15:26:36 -0500 Subject: [PATCH 01/31] Make handlers not static --- .../bugfix/model_data_manager_cme/ModelDataManagerMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java index b0b5843e..e79f7973 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java @@ -29,7 +29,7 @@ public abstract class ModelDataManagerMixin { * because the returned iterator won't be thread-safe otherwise. See https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/7511 */ @ModifyArg(method = "requestRefresh", at = @At(value = "INVOKE", target = "Ljava/util/Map;computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;", ordinal = 0), index = 1, remap = false) - private static Function> changeTypeOfSetUsed(Function> mappingFunction) { + private Function> changeTypeOfSetUsed(Function> mappingFunction) { return pos -> Collections.newSetFromMap(new ConcurrentHashMap<>()); } From d76fd84b76bb29e8604f3a209b27e6f615c94902 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 15:56:52 -0500 Subject: [PATCH 02/31] Support replaceAll on the wrapping model registry --- .../forge/dynresources/ModelBakeEventHelper.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index c05dd603..7c82021f 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -21,6 +21,7 @@ import org.embeddedt.modernfix.util.ForwardingInclDefaultsMap; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.BiFunction; /** * Stores a list of all known default block/item models in the game, and provides a namespaced version @@ -79,7 +80,7 @@ public class ModelBakeEventHelper { private void logWarning() { if(!WARNED_MOD_IDS.add(modId)) return; - ModernFix.LOGGER.warn("Mod '{}' is accessing Map#keySet/entrySet/values on the model registry map inside its event handler." + + ModernFix.LOGGER.warn("Mod '{}' is accessing Map#keySet/entrySet/values/replaceAll on the model registry map inside its event handler." + " This probably won't work as expected with dynamic resources on. Prefer using Map#get/put and constructing ModelResourceLocations another way.", modId); } @@ -100,6 +101,12 @@ public class ModelBakeEventHelper { logWarning(); return super.values(); } + + @Override + public void replaceAll(BiFunction function) { + logWarning(); + super.replaceAll(function); + } }; } @@ -139,6 +146,13 @@ public class ModelBakeEventHelper { public boolean containsKey(@Nullable Object key) { return ourModelLocations.contains(key) || super.containsKey(key); } + + @Override + public void replaceAll(BiFunction function) { + for(ResourceLocation location : keySet()) { + put(location, function.apply(location, get(location))); + } + } }; } } From aee0b2a47dbaa4f5263327d66fd93a2d27cf9539 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 15:59:51 -0500 Subject: [PATCH 03/31] Add Mekanism to model bake event helper --- .../modernfix/forge/dynresources/ModelBakeEventHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index 7c82021f..ee98dc5e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -29,7 +29,11 @@ import java.util.function.BiFunction; */ public class ModelBakeEventHelper { // TODO: make into config option - private static final Set INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism", "elevatorid"); + private static final Set INCOMPATIBLE_MODS = ImmutableSet.of( + "industrialforegoing", + "mekanism", + "vampirism", + "elevatorid"); private final Map modelRegistry; private final Set topLevelModelLocations; private final MutableGraph dependencyGraph; From 11508fbe07e1f8e0c8c37a1e7723a164d399e503 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:03:54 -0500 Subject: [PATCH 04/31] Track duration of model bake events when dynamic resources is enabled --- .../perf/dynamic_resources/ForgeHooksClientMixin.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java index 1a631860..96d69295 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources; +import com.google.common.base.Stopwatch; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.client.ForgeHooksClient; @@ -9,6 +10,7 @@ import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.forge.dynresources.ModelBakeEventHelper; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -16,6 +18,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import java.lang.reflect.Method; import java.util.Map; +import java.util.concurrent.TimeUnit; @Mixin(ForgeHooksClient.class) public class ForgeHooksClientMixin { @@ -32,11 +35,16 @@ public class ForgeHooksClientMixin { ModList.get().forEachModContainer((id, mc) -> { Map newRegistry = helper.wrapRegistry(id); ModelBakeEvent postedEvent = new ModelBakeEvent(bakeEvent.getModelManager(), newRegistry, bakeEvent.getModelLoader()); + Stopwatch timer = Stopwatch.createStarted(); try { acceptEv.invoke(mc, postedEvent); } catch(ReflectiveOperationException e) { e.printStackTrace(); } + timer.stop(); + if(timer.elapsed(TimeUnit.SECONDS) >= 1) { + ModernFix.LOGGER.warn("Mod '{}' took {} in the model bake event", id, timer); + } }); } } From d1863cc66e77934e60fc402ddb290ff87ca420ad Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:06:22 -0500 Subject: [PATCH 05/31] Make replaceAll implementation more robust, add warning --- .../modernfix/forge/dynresources/ModelBakeEventHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index ee98dc5e..0e3dfca6 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -153,7 +153,9 @@ public class ModelBakeEventHelper { @Override public void replaceAll(BiFunction function) { - for(ResourceLocation location : keySet()) { + ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. This requires temporarily loading every model for that mod, which is slow.", modId); + List locations = new ArrayList<>(keySet()); + for(ResourceLocation location : locations) { put(location, function.apply(location, get(location))); } } From 675c58a437f68b42f9daa7bfc4b143d0003f7dba Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:13:45 -0500 Subject: [PATCH 06/31] Only call put on the model map if the replacement model is different --- .../modernfix/forge/dynresources/ModelBakeEventHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index 0e3dfca6..0aeb9fac 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -156,7 +156,11 @@ public class ModelBakeEventHelper { ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. This requires temporarily loading every model for that mod, which is slow.", modId); List locations = new ArrayList<>(keySet()); for(ResourceLocation location : locations) { - put(location, function.apply(location, get(location))); + BakedModel existing = get(location); + BakedModel replacement = function.apply(location, existing); + if(replacement != existing) { + put(location, replacement); + } } } }; From a79ea9766aba1ba08ca111649347ab09e5bad5b6 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 18:41:51 -0500 Subject: [PATCH 07/31] Prevent mod mixins from applying if there is a Forge loading error --- .../forge/classloading/ATInjector.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/classloading/ATInjector.java b/forge/src/main/java/org/embeddedt/modernfix/forge/classloading/ATInjector.java index f86b9623..35092190 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/classloading/ATInjector.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/classloading/ATInjector.java @@ -1,5 +1,10 @@ package org.embeddedt.modernfix.forge.classloading; +import cpw.mods.jarhandling.SecureJar; +import cpw.mods.modlauncher.LaunchPluginHandler; +import cpw.mods.modlauncher.Launcher; +import cpw.mods.modlauncher.api.NamedPath; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModValidator; @@ -7,9 +12,15 @@ import net.minecraftforge.fml.util.ObfuscationReflectionHelper; import org.apache.commons.lang3.tuple.Pair; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.util.CommonModUtil; +import org.objectweb.asm.Type; +import java.lang.reflect.Field; import java.nio.file.Path; +import java.util.EnumSet; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.function.Consumer; import java.util.stream.Collectors; public class ATInjector { @@ -31,6 +42,80 @@ public class ATInjector { } } } + + // inject into Launcher.INSTANCE.launchPlugins and wrap the mixin plugin, so that mixin transformations + // are not applied + try { + Launcher launcher = Launcher.INSTANCE; + Field launchPlugins = Launcher.class.getDeclaredField("launchPlugins"); + launchPlugins.setAccessible(true); + + LaunchPluginHandler handler = (LaunchPluginHandler) launchPlugins.get(launcher); + Field plugins = LaunchPluginHandler.class.getDeclaredField("plugins"); + plugins.setAccessible(true); + + //noinspection unchecked + Map map = (Map) plugins.get(handler); + Map newMap = new HashMap<>(map); + NonTransformingLaunchPluginService.class.getName(); // trigger classloading, just to be safe + newMap.replaceAll((name, plugin) -> { + if(plugin.getClass().getName().startsWith("org.spongepowered.asm.launch.MixinLaunchPlugin")) { + ModernFixMixinPlugin.instance.logger.warn("Disabling plugin '{}': {}", name, plugin.getClass().getName()); + return new NonTransformingLaunchPluginService(plugin); + } else { + return plugin; + } + }); + plugins.set(handler, newMap); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } }, "applying mod ATs in errored state"); } + + static class NonTransformingLaunchPluginService implements ILaunchPluginService { + + private final ILaunchPluginService delegate; + + NonTransformingLaunchPluginService(ILaunchPluginService delegate) { + this.delegate = delegate; + } + + @Override + public String name() { + return delegate.name(); + } + + private static final EnumSet NEVER = EnumSet.noneOf(Phase.class); + + @Override + public EnumSet handlesClass(Type classType, boolean isEmpty) { + return NEVER; + } + + @Override + public void offerResource(Path resource, String name) { + delegate.offerResource(resource, name); + } + + @Override + public void addResources(List resources) { + delegate.addResources(resources); + } + + @Override + public void initializeLaunch(ITransformerLoader transformerLoader, NamedPath[] specialPaths) { + delegate.initializeLaunch(transformerLoader, specialPaths); + } + + @Override + public T getExtension() { + return delegate.getExtension(); + } + + @Override + public void customAuditConsumer(String className, Consumer auditDataAcceptor) { + delegate.customAuditConsumer(className, auditDataAcceptor); + } + } } From ae8cfbaa3d880a20b70a418f4ae276312fa30981 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 27 Dec 2023 19:12:11 -0500 Subject: [PATCH 08/31] Disable dynamic DFU when Litematica is installed --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index f40c07b7..302dabd0 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -215,6 +215,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); disableIfModPresent("mixin.bugfix.preserve_early_window_pos", "better_loading_screen"); + disableIfModPresent("mixin.perf.dynamic_dfu", "litematica"); disableIfModPresent("mixin.perf.cache_strongholds", "littletiles", "c2me"); // content overlap disableIfModPresent("mixin.perf.deduplicate_wall_shapes", "dashloader"); From 06bfd71d0758dd9f3469102e08a9b63c4070f50f Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 28 Dec 2023 06:36:49 -0800 Subject: [PATCH 09/31] Generate mixin configs automatically using custom AP (#305) --- annotation-processor/build.gradle | 60 ++++++ .../annotation/ClientMixinValidator.java | 189 ++++++++++++++++++ .../mixinAp/annotation/MixinProcessor.java | 115 +++++++++++ .../mixinAp/config/MixinConfig.java | 65 ++++++ .../mixinAp/util/TypedAccessorMap.java | 37 ++++ annotations/build.gradle | 6 + .../modernfix/annotation/ClientOnlyMixin.java | 0 .../modernfix/annotation/IgnoreMixin.java | 11 + .../annotation/IgnoreOutsideDev.java | 0 .../modernfix/annotation/RequiresMod.java | 0 build.gradle | 2 +- buildSrc/build.gradle | 2 +- .../modernfix.common-conventions.gradle | 2 +- .../modernfix.mod-common-conventions.gradle | 43 ++-- .../ItemModelShaperMixin.java | 2 + .../GameRendererMixin.java | 2 + .../ItemRendererMixin.java | 2 + .../resources/modernfix-common.mixins.json | 16 -- fabric/build.gradle | 4 +- .../resources/modernfix-fabric.mixins.json | 16 -- forge/build.gradle | 4 +- .../perf/async_jei/InputConstantsMixin.java | 2 + .../perf/async_locator/EyeOfEnderAccess.java | 6 +- .../perf/async_locator/EyeOfEnderMixin.java | 48 ++--- .../resources/modernfix-forge.mixins.json | 16 -- gradle.properties | 4 +- settings.gradle | 9 + 27 files changed, 555 insertions(+), 108 deletions(-) create mode 100644 annotation-processor/build.gradle create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java create mode 100644 annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java create mode 100644 annotations/build.gradle rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java (100%) create mode 100644 annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java (100%) rename {common => annotations}/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java (100%) delete mode 100644 common/src/main/resources/modernfix-common.mixins.json delete mode 100644 fabric/src/main/resources/modernfix-fabric.mixins.json delete mode 100644 forge/src/main/resources/modernfix-forge.mixins.json diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle new file mode 100644 index 00000000..223d94bc --- /dev/null +++ b/annotation-processor/build.gradle @@ -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' diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java new file mode 100644 index 00000000..139c6b20 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -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 markers = new TypedAccessorMap<>(); + + private static final Map.Entry, Function> + FabricAccessor = new SimpleImmutableEntry<>(Environment.class, Environment::value); + + private static final Map.Entry< + Class, + Function> + ForgeAccessor = new SimpleImmutableEntry<>( + net.minecraftforge.api.distmarker.OnlyIn.class, + net.minecraftforge.api.distmarker.OnlyIn::value + ); + + private static final Map.Entry< + Class, + Function> + 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 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 + 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 getTargets(TypeElement annotatedMixinClass) { + Collection clzsses = Set.of(); + Collection 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) + getAnnotationValue(mirror, "value").getValue(); + + clzsses = wrappedClzss.stream() + .map(AnnotationValue::getValue) + .map(TypeMirror.class::cast) + .collect(Collectors.toSet()); + + @SuppressWarnings("unchecked") + var wrappedStrings = (List) + 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("\\/", "."); + } +} diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java new file mode 100644 index 00000000..747f8865 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -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 aliases = Map.of( + "Mixin", "mixins", + "ClientOnlyMixin", "client" + ); + + private final Map> mixinConfigList = new HashMap<>(); + + @Override + public boolean process(Set 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 annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + Set annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation); + + Stream mixinStream = + annotatedMixins.stream() + .map(TypeElement.class::cast); + + validateCommonMixins(annotation, mixinStream); + + List 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 commonSet = mixinConfigList.get("mixins"); + if(commonSet == null) return; + commonSet.removeAll(mixinConfigList.get("client")); + } + + private void validateCommonMixins(TypeElement annotation, Stream 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 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]); + } + } +} diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java new file mode 100644 index 00000000..9d1e6c91 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -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 commonMixins, + @SerializedName("client") + List clientMixins, + InjectorOptions injectors, OverwriteOptions overwrites + ) { + public MixinConfig(String packageName, List commonMixins, List 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 rootProjectName, Optional projectName) { + return "resources/" + + rootProjectName.get() + + (projectName.isPresent() ? "-" : "") + + projectName.orElse("") + + ".mixins.json"; + } +} diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java new file mode 100644 index 00000000..5632a917 --- /dev/null +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/util/TypedAccessorMap.java @@ -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 The supertype of desired types. + * This is useful in cases such as . + */ +public class TypedAccessorMap { + private final Map, Function> typedAccessors = new HashMap<>(); + + public void put(Class key, Function func) { + Objects.requireNonNull(func); + typedAccessors.put(Objects.requireNonNull(key), o -> func.apply(key.cast(o))); + } + + public void put(Entry, Function> entry) { + put(entry.getKey(), entry.getValue()); + } + + public Function get(Class key) { + return typedAccessors.get(key); + } + + public Set, Function>> entrySet() { + return typedAccessors.entrySet(); + } +} diff --git a/annotations/build.gradle b/annotations/build.gradle new file mode 100644 index 00000000..5271e5b3 --- /dev/null +++ b/annotations/build.gradle @@ -0,0 +1,6 @@ +plugins { + id 'modernfix.common-conventions' + id 'java-library' +} + +version = '1.1.0' diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/ClientOnlyMixin.java diff --git a/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java new file mode 100644 index 00000000..00ae1fb7 --- /dev/null +++ b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreMixin.java @@ -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 { +} + diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/IgnoreOutsideDev.java diff --git a/common/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java b/annotations/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java similarity index 100% rename from common/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java rename to annotations/src/main/java/org/embeddedt/modernfix/annotation/RequiresMod.java diff --git a/build.gradle b/build.gradle index f943a7a3..0390ec97 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'org.ajoberstar.grgit' version '5.2.0' id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0' 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 } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 1957c339..67840524 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,3 +1,3 @@ plugins { id 'groovy-gradle-plugin' -} \ No newline at end of file +} diff --git a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle index ebce0241..ecf68ba0 100644 --- a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle @@ -78,4 +78,4 @@ repositories { url 'https://maven.terraformersmc.com/releases' } maven { url = "https://jitpack.io" } -} \ No newline at end of file +} diff --git a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle index 3362ce37..2997c5cd 100644 --- a/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.mod-common-conventions.gradle @@ -16,37 +16,26 @@ dependencies { 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 { processResources { - def mixinFileList = [] - 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 - } - } + dependsOn compileJava + } +} - def mixinClassesStringB = new StringBuilder() - for(int i = 0; i < mixinFileList.size(); i++) { - mixinClassesStringB.append(" \"") - mixinClassesStringB.append(mixinFileList.get(i)) - mixinClassesStringB.append('"') - if(i < (mixinFileList.size() - 1)) - 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 +tasks.withType(JavaCompile) { + options.fork = true + options.forkOptions.jvmArgs << '--enable-preview' + configure(options) { + if (!name.toLowerCase().contains('test')) { + options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}" } } -} \ No newline at end of file +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java index 9e31ecd7..dfe8c84d 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java @@ -6,6 +6,7 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.item.Item; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.dynamicresources.DynamicModelCache; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; import org.embeddedt.modernfix.util.DynamicInt2ObjectMap; @@ -18,6 +19,7 @@ import java.util.HashMap; import java.util.Map; @Mixin(ItemModelShaper.class) +@ClientOnlyMixin public abstract class ItemModelShaperMixin { @Shadow public abstract ModelManager getModelManager(); diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java index ee3a0f9d..d457b5d4 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java @@ -1,6 +1,7 @@ package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; import net.minecraft.client.renderer.GameRenderer; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.render.RenderState; import org.spongepowered.asm.mixin.Mixin; 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; @Mixin(GameRenderer.class) +@ClientOnlyMixin 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)) private void markRenderingLevel(CallbackInfo ci) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java index 7e2ddd69..97201457 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java @@ -11,6 +11,7 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.SimpleBakedModel; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.render.FastItemRenderType; import org.embeddedt.modernfix.render.RenderState; 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; @Mixin(value = ItemRenderer.class, priority = 600) +@ClientOnlyMixin public abstract class ItemRendererMixin { private ItemTransforms.TransformType transformType; private final SimpleItemModelView modelView = new SimpleItemModelView(); diff --git a/common/src/main/resources/modernfix-common.mixins.json b/common/src/main/resources/modernfix-common.mixins.json deleted file mode 100644 index 94a4e091..00000000 --- a/common/src/main/resources/modernfix-common.mixins.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "org.embeddedt.modernfix.common.mixin", - "plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin", - "compatibilityLevel": "JAVA_8", - "mixins": [ -${mixin_classes} - ], - "injectors": { - "defaultRequire": 1 - }, - "overwrites": { - "conformVisibility": true - } -} diff --git a/fabric/build.gradle b/fabric/build.gradle index 6eefad32..c2047731 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ 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 "modernfix.mod-common-conventions" id "modernfix.platform-conventions" @@ -122,4 +122,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} diff --git a/fabric/src/main/resources/modernfix-fabric.mixins.json b/fabric/src/main/resources/modernfix-fabric.mixins.json deleted file mode 100644 index 3d94ea0d..00000000 --- a/fabric/src/main/resources/modernfix-fabric.mixins.json +++ /dev/null @@ -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 - } -} \ No newline at end of file diff --git a/forge/build.gradle b/forge/build.gradle index 5d783901..ea515fab 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" + id "com.github.johnrengelman.shadow" id "modernfix.mod-common-conventions" id "modernfix.platform-conventions" } @@ -141,4 +141,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java index e5b49c66..5b632f72 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_jei/InputConstantsMixin.java @@ -2,6 +2,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_jei; import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; @@ -9,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(InputConstants.class) +@ClientOnlyMixin @RequiresMod("jei") public class InputConstantsMixin { @Redirect(method = "isKeyDown", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwGetKey(JI)I", remap = false)) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java index c35be48b..5f24fa1c 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderAccess.java @@ -1,11 +1,13 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; +import org.embeddedt.modernfix.annotation.IgnoreMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(EyeOfEnder.class) +@IgnoreMixin public interface EyeOfEnderAccess { - @Accessor - void setLife(int life); + @Accessor + void setLife(int life); } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java index 74205bf3..7b1463f8 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/EyeOfEnderMixin.java @@ -1,6 +1,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.async_locator; import net.minecraft.world.entity.projectile.EyeOfEnder; +import org.embeddedt.modernfix.annotation.IgnoreMixin; import org.embeddedt.modernfix.forge.structure.logic.EyeOfEnderData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -8,30 +9,31 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EyeOfEnder.class) +@IgnoreMixin public class EyeOfEnderMixin implements EyeOfEnderData { - private boolean locateTaskOngoing = false; + private boolean locateTaskOngoing = false; - @Override - public void setLocateTaskOngoing(boolean locateTaskOngoing) { - this.locateTaskOngoing = locateTaskOngoing; - } + @Override + public void setLocateTaskOngoing(boolean locateTaskOngoing) { + this.locateTaskOngoing = locateTaskOngoing; + } - /* - Intercept EyeOfEnder#tick call and return after the super call if there's an ongoing locate task. This is to - prevent the entity from moving or dying until we have a location result. - */ - @Inject( - method = "tick", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/entity/Entity;tick()V", - shift = At.Shift.AFTER - ), - cancellable = true - ) - public void skipTick(CallbackInfo ci) { - if (locateTaskOngoing) { - ci.cancel(); - } - } + /* + Intercept EyeOfEnder#tick call and return after the super call if there's an ongoing locate task. This is to + prevent the entity from moving or dying until we have a location result. + */ + @Inject( + method = "tick", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;tick()V", + shift = At.Shift.AFTER + ), + cancellable = true + ) + public void skipTick(CallbackInfo ci) { + if (locateTaskOngoing) { + ci.cancel(); + } + } } diff --git a/forge/src/main/resources/modernfix-forge.mixins.json b/forge/src/main/resources/modernfix-forge.mixins.json deleted file mode 100644 index f63f1dfc..00000000 --- a/forge/src/main/resources/modernfix-forge.mixins.json +++ /dev/null @@ -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 - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1cb73b92..a6657167 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,8 @@ refined_storage_version=3807951 kubejs_version=1605.3.19-build.299 ctm_version=MC1.16.1-1.1.2.6 supported_minecraft_versions=1.16.4,1.16.5 +// Look up maven coordinates when changing shadow_version +shadow_version=7.1.2 fabric_loader_version=0.14.21 fabric_api_version=0.42.0+1.16 @@ -25,4 +27,4 @@ modmenu_version=1.16.23 spark_forge_version=3767277 spark_fabric_version=3337642 -use_fabric_api_at_runtime=true \ No newline at end of file +use_fabric_api_at_runtime=true diff --git a/settings.gradle b/settings.gradle index 514910c1..dbf3afdd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,8 +5,17 @@ pluginManagement { maven { url "https://maven.architectury.dev/" } 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("common") From 7e53a8bc73889afb1993e1b6aef5eb42de8e3af5 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 28 Dec 2023 06:38:54 -0800 Subject: [PATCH 10/31] Eliminate extraneous casts (#327) --- .../modernfix/dynamicresources/ModelBakeryHelpers.java | 2 +- .../java/org/embeddedt/modernfix/registry/RegistryStorage.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java index 17150999..21b0ede2 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java @@ -350,7 +350,7 @@ public class ModelBakeryHelpers { } private static > T getValueHelper(Property property, String value) { - return property.getValue(value).orElse((T) null); + return property.getValue(value).orElse(null); } private static final Splitter COMMA_SPLITTER = Splitter.on(','); diff --git a/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java b/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java index 252676d2..5d2fb207 100644 --- a/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java +++ b/common/src/main/java/org/embeddedt/modernfix/registry/RegistryStorage.java @@ -15,9 +15,8 @@ public class RegistryStorage { public static BiMap, DirectStorageRegistryObject> createKeyStorage(ResourceKey> registryKey, BiMap storage) { if(storage instanceof DirectStorageBiMap) { - DirectStorageBiMap directStorageBiMap = (DirectStorageBiMap)storage; // silently ignore put/putAll calls on this map - return new TransformingBiMap, DirectStorageRegistryObject>(directStorageBiMap, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) { + return new TransformingBiMap, DirectStorageRegistryObject>(storage, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) { @Override public DirectStorageRegistryObject put(ResourceKey key, DirectStorageRegistryObject value) { return null; From 34bc295b3c8cad9c326113c062ab1b016bf46017 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com> Date: Thu, 28 Dec 2023 09:41:37 -0500 Subject: [PATCH 11/31] Mark some more mixins as ClientOnlyMixin --- .../disable_unihex_font/UnihexProviderDefinitionMixin.java | 2 ++ .../common/mixin/perf/dynamic_resources/ModelManagerMixin.java | 2 ++ .../fabric/mixin/core/ClientCommonPacketListenerImplMixin.java | 2 ++ .../mixin/perf/dynamic_resources/ModelBakerImplMixin.java | 2 ++ .../mixin/perf/dynamic_resources/ModelBakerImplMixin.java | 2 ++ 5 files changed, 10 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java index bb5aebb7..114577c1 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java @@ -7,6 +7,7 @@ import net.minecraft.client.gui.font.providers.GlyphProviderDefinition; import net.minecraft.client.gui.font.providers.UnihexProvider; import net.minecraft.server.packs.resources.ResourceManager; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,6 +17,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; @Mixin(UnihexProvider.Definition.class) +@ClientOnlyMixin public class UnihexProviderDefinitionMixin { @Inject(method = "unpack", at = @At("HEAD"), cancellable = true) private void disableProvider(CallbackInfoReturnable> cir) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java index 683f4169..04351172 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.util.LambdaMap; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -26,6 +27,7 @@ import java.util.concurrent.Executor; import java.util.stream.Collectors; @Mixin(ModelManager.class) +@ClientOnlyMixin public class ModelManagerMixin { @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockModels(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) private CompletableFuture> deferBlockModelLoad(ResourceManager manager, Executor executor) { diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/core/ClientCommonPacketListenerImplMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/core/ClientCommonPacketListenerImplMixin.java index 7dacc520..f0130601 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/core/ClientCommonPacketListenerImplMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/core/ClientCommonPacketListenerImplMixin.java @@ -2,12 +2,14 @@ package org.embeddedt.modernfix.fabric.mixin.core; import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl; import org.embeddedt.modernfix.ModernFixClientFabric; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientCommonPacketListenerImpl.class) +@ClientOnlyMixin public class ClientCommonPacketListenerImplMixin { @Inject(method = "handleUpdateTags", at = @At("RETURN")) private void signalTags(CallbackInfo ci) { diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 4db81275..5d88e0ec 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.duck.IExtendedModelBaker; import org.embeddedt.modernfix.duck.IExtendedModelBakery; @@ -29,6 +30,7 @@ import java.util.Optional; import java.util.function.Function; @Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600) +@ClientOnlyMixin public abstract class ModelBakerImplMixin implements IExtendedModelBaker { private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading"); @Shadow @Final private ModelBakery field_40571; diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 634a84fe..fa233250 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -8,6 +8,7 @@ import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.duck.IExtendedModelBaker; import org.embeddedt.modernfix.duck.IExtendedModelBakery; @@ -23,6 +24,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.function.Function; @Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600) +@ClientOnlyMixin public abstract class ModelBakerImplMixin implements IModelBakerImpl, IExtendedModelBaker { private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading"); @Shadow @Final private ModelBakery field_40571; From 4f49ba3f9b90b1b32f0939f6fbdd7e9028a7f77b Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 12:31:00 -0500 Subject: [PATCH 12/31] Apply excludedTaskNames in the testmod subproject rather than globally --- fabric/testmod/build.gradle | 2 ++ settings.gradle | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fabric/testmod/build.gradle b/fabric/testmod/build.gradle index fd7f0a5e..13355261 100644 --- a/fabric/testmod/build.gradle +++ b/fabric/testmod/build.gradle @@ -40,3 +40,5 @@ processResources { } } +// Make genSources do nothing in this project +project.gradle.startParameter.excludedTaskNames.add("genSources") \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index dbf3afdd..37fd1368 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,8 +19,6 @@ include("annotations") include("test_agent") include("common") -startParameter.excludedTaskNames.add(':fabric:testmod:genSources') - def current_platforms = getProperty("enabled_platforms").tokenize(',') current_platforms.each { it -> def platform_name = it.trim() From 4512bc6fbd4fe37a28453764a83bc10a5bea78dd Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 12:31:29 -0500 Subject: [PATCH 13/31] Generate config options from both 'mixins' and 'client' keys --- .../modernfix/core/config/ModernFixEarlyConfig.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 302dabd0..6af610ef 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -25,6 +25,8 @@ import java.util.*; import java.util.function.BooleanSupplier; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; public class ModernFixEarlyConfig { private static final Logger LOGGER = LogManager.getLogger("ModernFixConfig"); @@ -84,7 +86,10 @@ public class ModernFixEarlyConfig { continue; try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { JsonObject configObject = (JsonObject)new JsonParser().parse(reader); - JsonArray mixinList = configObject.getAsJsonArray("mixins"); + List 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('.', '/'); for(JsonElement mixin : mixinList) { mixinPaths.add(packageName + "/" + mixin.getAsString().replace('.', '/') + ".class"); From 8d6a344ded6271c2706f8f64378453473d5e6bae Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:08:25 -0500 Subject: [PATCH 14/31] Use correct comment style --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index a6657167..18ee8ec7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ refined_storage_version=3807951 kubejs_version=1605.3.19-build.299 ctm_version=MC1.16.1-1.1.2.6 supported_minecraft_versions=1.16.4,1.16.5 -// Look up maven coordinates when changing shadow_version +# Look up maven coordinates when changing shadow_version shadow_version=7.1.2 fabric_loader_version=0.14.21 From e301d7d48070b332c30d5951a1045732ae373017 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:08:32 -0500 Subject: [PATCH 15/31] Shadow annotations project so they are in the production jar --- fabric/build.gradle | 1 + forge/build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/fabric/build.gradle b/fabric/build.gradle index c2047731..e4667614 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -50,6 +50,7 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { 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("org.junit.jupiter:junit-jupiter-api") diff --git a/forge/build.gradle b/forge/build.gradle index ea515fab..467bca07 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -82,6 +82,7 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } + shadowCommon(project(path: ":annotations")) } processResources { From 35c82b81c8633936a94a46bd2ed667190470df31 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:33:39 -0500 Subject: [PATCH 16/31] Mark WorldSelectionList mixin as client-only --- .../bugfix/world_screen_skipped/WorldSelectionListMixin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_screen_skipped/WorldSelectionListMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_screen_skipped/WorldSelectionListMixin.java index 27f67f7a..7d816acd 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_screen_skipped/WorldSelectionListMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_screen_skipped/WorldSelectionListMixin.java @@ -3,6 +3,7 @@ package org.embeddedt.modernfix.common.mixin.bugfix.world_screen_skipped; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.client.gui.screens.worldselection.WorldSelectionList; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -11,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldSelectionList.WorldListEntry.class) +@ClientOnlyMixin public class WorldSelectionListMixin { @Shadow @Final private Minecraft minecraft; From cc1be852bbb660b6ae278de338f63e6a9253763e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:42:01 -0500 Subject: [PATCH 17/31] More ClientOnlyMixin --- .../modernfix/fabric/mixin/safety/DynamicTextureMixin.java | 2 ++ .../extra_experimental_screen/CreateWorldScreenMixin.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java index 5cc7f1ac..e120bc91 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java @@ -3,6 +3,7 @@ package org.embeddedt.modernfix.fabric.mixin.safety; import com.mojang.blaze3d.platform.NativeImage; import net.minecraft.client.renderer.texture.DynamicTexture; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -11,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(DynamicTexture.class) +@ClientOnlyMixin public class DynamicTextureMixin { @Shadow @Nullable private NativeImage pixels; diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/extra_experimental_screen/CreateWorldScreenMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/extra_experimental_screen/CreateWorldScreenMixin.java index a8696b54..10c3b6dd 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/extra_experimental_screen/CreateWorldScreenMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/extra_experimental_screen/CreateWorldScreenMixin.java @@ -4,11 +4,13 @@ import com.mojang.serialization.Lifecycle; import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.WorldData; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; @Mixin(CreateWorldScreen.class) +@ClientOnlyMixin public class CreateWorldScreenMixin { /** * Fix experimental world dialog still being shown the first time you reopen a world that was created From 8b97ebf94543728aa3316019b122d2085e6398eb Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:45:15 -0500 Subject: [PATCH 18/31] Even More ClientOnlyMixin --- .../disable_unihex_font/UnihexProviderDefinitionMixin.java | 2 ++ .../common/mixin/perf/dynamic_resources/ModelManagerMixin.java | 2 ++ .../mixin/perf/dynamic_resources/ModelBakerImplMixin.java | 2 ++ .../forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java | 2 ++ 4 files changed, 8 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java index bb5aebb7..114577c1 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/feature/disable_unihex_font/UnihexProviderDefinitionMixin.java @@ -7,6 +7,7 @@ import net.minecraft.client.gui.font.providers.GlyphProviderDefinition; import net.minecraft.client.gui.font.providers.UnihexProvider; import net.minecraft.server.packs.resources.ResourceManager; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,6 +17,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; @Mixin(UnihexProvider.Definition.class) +@ClientOnlyMixin public class UnihexProviderDefinitionMixin { @Inject(method = "unpack", at = @At("HEAD"), cancellable = true) private void disableProvider(CallbackInfoReturnable> cir) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java index 683f4169..04351172 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.util.LambdaMap; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -26,6 +27,7 @@ import java.util.concurrent.Executor; import java.util.stream.Collectors; @Mixin(ModelManager.class) +@ClientOnlyMixin public class ModelManagerMixin { @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockModels(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) private CompletableFuture> deferBlockModelLoad(ResourceManager manager, Executor executor) { diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 4db81275..5d88e0ec 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.duck.IExtendedModelBaker; import org.embeddedt.modernfix.duck.IExtendedModelBakery; @@ -29,6 +30,7 @@ import java.util.Optional; import java.util.function.Function; @Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600) +@ClientOnlyMixin public abstract class ModelBakerImplMixin implements IExtendedModelBaker { private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading"); @Shadow @Final private ModelBakery field_40571; diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 7cd6d6d9..e55ffc39 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -8,6 +8,7 @@ import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.duck.IExtendedModelBaker; import org.embeddedt.modernfix.duck.IExtendedModelBakery; @@ -23,6 +24,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.function.Function; @Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600) +@ClientOnlyMixin public abstract class ModelBakerImplMixin implements IModelBakerImpl, IExtendedModelBaker { private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading"); @Shadow @Final private ModelBakery field_40571; From db5a3234d28c54fda4618dfd2e57e51930608936 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 30 Dec 2023 18:59:44 -0500 Subject: [PATCH 19/31] Update MixinExtras --- buildSrc/src/main/groovy/modernfix.common-conventions.gradle | 1 - common/build.gradle | 2 +- fabric/build.gradle | 2 +- forge/build.gradle | 4 ++-- gradle.properties | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle index ecf68ba0..9db93bad 100644 --- a/buildSrc/src/main/groovy/modernfix.common-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.common-conventions.gradle @@ -77,5 +77,4 @@ repositories { maven { url 'https://maven.terraformersmc.com/releases' } - maven { url = "https://jitpack.io" } } diff --git a/common/build.gradle b/common/build.gradle index 0f40cb30..f1f251f8 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -10,7 +10,7 @@ dependencies { // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // Do NOT use other classes from fabric loader modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}")) + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}")) modCompileOnly("dev.latvian.mods:kubejs:${kubejs_version}") { transitive = false diff --git a/fabric/build.gradle b/fabric/build.gradle index e4667614..40e363a9 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -29,7 +29,7 @@ configurations { dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" testImplementation "net.fabricmc:fabric-loader-junit:${rootProject.fabric_loader_version}" - include(implementation(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-fabric:${rootProject.mixinextras_version}"))) + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${rootProject.mixinextras_version}"))) modCompileOnly(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } diff --git a/forge/build.gradle b/forge/build.gradle index 467bca07..d7abef5f 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -45,8 +45,8 @@ repositories { dependencies { forge "net.minecraftforge:forge:${rootProject.forge_version}" - shadow(annotationProcessor("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}")) - runtimeOnly("com.github.llamalad7.mixinextras:mixinextras-common:${rootProject.mixinextras_version}") + shadow(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}")) + runtimeOnly("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}") // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury-forge:${rootProject.architectury_version}" diff --git a/gradle.properties b/gradle.properties index 18ee8ec7..ac30c0ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx2G junit_version=5.10.0-M1 -mixinextras_version=0.2.0-beta.9 +mixinextras_version=0.3.2 mod_id=modernfix minecraft_version=1.16.5 From 1da264e5a767012708d71e8aca0580267572326d Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 30 Dec 2023 19:05:20 -0500 Subject: [PATCH 20/31] Bump Fabric Loader --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ac30c0ed..402fb89b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ supported_minecraft_versions=1.16.4,1.16.5 # Look up maven coordinates when changing shadow_version shadow_version=7.1.2 -fabric_loader_version=0.14.21 +fabric_loader_version=0.14.25 fabric_api_version=0.42.0+1.16 modmenu_version=1.16.23 From d6fc939f41556fe87ff658617b5cb27943e96a4a Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 31 Dec 2023 20:30:04 -0500 Subject: [PATCH 21/31] Workaround AP throwing exception if there is a compile error in the file --- .../fury_phoenix/mixinAp/annotation/ClientMixinValidator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java index 139c6b20..2d76bcef 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/ClientMixinValidator.java @@ -166,6 +166,7 @@ public class ClientMixinValidator { clzsses = wrappedClzss.stream() .map(AnnotationValue::getValue) + .filter(o -> o instanceof TypeMirror) .map(TypeMirror.class::cast) .collect(Collectors.toSet()); From dcee8b416953022d954a90f56a5a282d6bdde00e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 31 Dec 2023 21:07:32 -0500 Subject: [PATCH 22/31] Update to NeoForge 20.4.70-beta --- .../modernfix/packet/EntityIDSyncPacket.java | 22 +++++++------ .../platform/ModernFixPlatformHooks.java | 3 +- .../fabric/ModernFixPlatformHooksImpl.java | 3 +- gradle.properties | 2 +- .../RecipeBookSettingsMixin.java | 10 ++---- .../neoforge/mixin/core/BootstrapMixin.java | 7 ----- .../mixin/core/NetworkHooksMixin.java | 17 ---------- .../neoforge/packet/NetworkUtils.java | 5 --- .../neoforge/packet/PacketHandler.java | 31 +++++++------------ .../neoforge/ModernFixPlatformHooksImpl.java | 5 +-- .../src/main/resources/META-INF/mods.toml | 8 ++--- 11 files changed, 39 insertions(+), 74 deletions(-) delete mode 100644 neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/NetworkHooksMixin.java delete mode 100644 neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/NetworkUtils.java diff --git a/common/src/main/java/org/embeddedt/modernfix/packet/EntityIDSyncPacket.java b/common/src/main/java/org/embeddedt/modernfix/packet/EntityIDSyncPacket.java index 6fe2c6b1..9db7642b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/packet/EntityIDSyncPacket.java +++ b/common/src/main/java/org/embeddedt/modernfix/packet/EntityIDSyncPacket.java @@ -2,7 +2,9 @@ package org.embeddedt.modernfix.packet; import com.mojang.datafixers.util.Pair; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import org.embeddedt.modernfix.ModernFix; @@ -10,7 +12,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; -public class EntityIDSyncPacket { +public class EntityIDSyncPacket implements CustomPacketPayload { + public static final ResourceLocation ID = new ResourceLocation(ModernFix.MODID, "entity_id_sync"); private Map, List>> map; public EntityIDSyncPacket(Map, List>> map) { @@ -21,11 +24,8 @@ public class EntityIDSyncPacket { return this.map; } - public EntityIDSyncPacket() { - this.map = new HashMap<>(); - } - - public void serialize(FriendlyByteBuf buf) { + @Override + public void write(FriendlyByteBuf buf) { buf.writeVarInt(map.keySet().size()); for(Map.Entry, List>> entry : map.entrySet()) { buf.writeUtf(entry.getKey().getName()); @@ -38,8 +38,8 @@ public class EntityIDSyncPacket { } @SuppressWarnings("unchecked") - public static EntityIDSyncPacket deserialize(FriendlyByteBuf buf) { - EntityIDSyncPacket self = new EntityIDSyncPacket(); + public EntityIDSyncPacket(FriendlyByteBuf buf) { + EntityIDSyncPacket self = this; int numEntityClasses = buf.readVarInt(); for(int i = 0; i < numEntityClasses; i++) { String clzName = buf.readUtf(); @@ -73,6 +73,10 @@ public class EntityIDSyncPacket { ModernFix.LOGGER.error("Error deserializing packet", e); } } - return self; + } + + @Override + public ResourceLocation id() { + return ID; } } diff --git a/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java b/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java index 0a805814..1f38dff9 100644 --- a/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java +++ b/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java @@ -4,6 +4,7 @@ import com.google.common.collect.Multimap; import com.mojang.brigadier.CommandDispatcher; import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; @@ -39,7 +40,7 @@ public interface ModernFixPlatformHooks { Path getGameDirectory(); - void sendPacket(ServerPlayer player, Object packet); + void sendPacket(ServerPlayer player, CustomPacketPayload packet); Multimap getCustomModOptions(); diff --git a/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java b/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java index c87b50cd..e9e6ebcb 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java @@ -11,6 +11,7 @@ import net.fabricmc.loader.api.metadata.CustomValue; import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.CreativeModeTabs; @@ -72,7 +73,7 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { return FabricLoader.getInstance().getGameDir(); } - public void sendPacket(ServerPlayer player, Object packet) { + public void sendPacket(ServerPlayer player, CustomPacketPayload packet) { //PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet); } diff --git a/gradle.properties b/gradle.properties index 151e54b2..002eea63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ mixinextras_version=0.3.2 mod_id=modernfix minecraft_version=1.20.4 enabled_platforms=fabric,neoforge -forge_version=20.4.22-beta +forge_version=20.4.70-beta # parchment_version=2023.07.09 refined_storage_version=4392788 jei_version=16.0.0.28 diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/recipe_book_type_desync/RecipeBookSettingsMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/recipe_book_type_desync/RecipeBookSettingsMixin.java index f18ad746..774c05e0 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/recipe_book_type_desync/RecipeBookSettingsMixin.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/bugfix/recipe_book_type_desync/RecipeBookSettingsMixin.java @@ -1,15 +1,9 @@ package org.embeddedt.modernfix.neoforge.mixin.bugfix.recipe_book_type_desync; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.stats.RecipeBookSettings; import net.minecraft.world.inventory.RecipeBookType; -import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.neoforge.packet.NetworkUtils; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -36,12 +30,14 @@ public class RecipeBookSettingsMixin { } mfix$maxVanillaOrdinal = ord; } + /* @Redirect(method = "read(Lnet/minecraft/network/FriendlyByteBuf;)Lnet/minecraft/stats/RecipeBookSettings;", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/FriendlyByteBuf;readBoolean()Z")) private static boolean useDefaultBooleanIfVanilla(FriendlyByteBuf buf, @Local(ordinal = 0) RecipeBookType type) { - if(type.ordinal() >= (mfix$maxVanillaOrdinal + 1) && NetworkUtils.isCurrentlyVanilla) { + if(type.ordinal() >= (mfix$maxVanillaOrdinal + 1)) { ModernFix.LOGGER.warn("Not reading recipe book data for type '{}' as we are using vanilla connection", type.name()); return false; // skip actually reading buffer } return buf.readBoolean(); } + */ } diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/BootstrapMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/BootstrapMixin.java index 369fc6f3..ec7e849e 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/BootstrapMixin.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/BootstrapMixin.java @@ -1,7 +1,6 @@ package org.embeddedt.modernfix.neoforge.mixin.core; import net.minecraft.server.Bootstrap; -import net.neoforged.neoforge.network.NetworkConstants; import org.embeddedt.modernfix.util.TimeFormatter; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; @@ -25,10 +24,4 @@ public class BootstrapMixin { LOGGER.info("ModernFix reached bootstrap stage ({} after launch)", TimeFormatter.formatNanos(ManagementFactory.getRuntimeMXBean().getUptime() * 1000L * 1000L)); } } - - /* for https://github.com/MinecraftForge/MinecraftForge/issues/9505 */ - @Inject(method = "bootStrap", at = @At("RETURN")) - private static void doClassloadHack(CallbackInfo ci) { - NetworkConstants.init(); - } } diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/NetworkHooksMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/NetworkHooksMixin.java deleted file mode 100644 index aaee04e9..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/core/NetworkHooksMixin.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.embeddedt.modernfix.neoforge.mixin.core; - -import net.minecraft.network.Connection; -import net.neoforged.neoforge.network.NetworkHooks; -import org.embeddedt.modernfix.neoforge.packet.NetworkUtils; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(NetworkHooks.class) -public abstract class NetworkHooksMixin { - @Inject(method = "handleClientLoginSuccess", at = @At("RETURN"), remap = false) - private static void setVanillaGlobalFlag(Connection manager, CallbackInfo ci) { - NetworkUtils.isCurrentlyVanilla = NetworkHooks.isVanillaConnection(manager); - } -} diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/NetworkUtils.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/NetworkUtils.java deleted file mode 100644 index 4f1d88dd..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/NetworkUtils.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.embeddedt.modernfix.neoforge.packet; - -public class NetworkUtils { - public static boolean isCurrentlyVanilla; -} diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/PacketHandler.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/PacketHandler.java index 4c9bba7a..9f6caaf2 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/PacketHandler.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/packet/PacketHandler.java @@ -1,33 +1,24 @@ package org.embeddedt.modernfix.neoforge.packet; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.fml.DistExecutor; -import net.neoforged.neoforge.network.NetworkEvent; -import net.neoforged.neoforge.network.NetworkRegistry; -import net.neoforged.neoforge.network.simple.SimpleChannel; +import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent; +import net.neoforged.neoforge.network.handling.PlayPayloadContext; +import net.neoforged.neoforge.network.registration.IPayloadRegistrar; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.packet.EntityIDSyncPacket; public class PacketHandler { - private static final String PROTOCOL_VERSION = "1"; - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation(ModernFix.MODID, "main"), - () -> PROTOCOL_VERSION, - NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION), - NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION) - ); + private static void registerPackets(final RegisterPayloadHandlerEvent event) { + final IPayloadRegistrar registrar = event.registrar(ModernFix.MODID).optional(); + registrar.play(EntityIDSyncPacket.ID, EntityIDSyncPacket::new, PacketHandler::handleSyncPacket); + } public static void register() { - int id = 1; - INSTANCE.registerMessage(id++, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, PacketHandler::handleSyncPacket); + FMLJavaModLoadingContext.get().getModEventBus().addListener(PacketHandler::registerPackets); } - private static void handleSyncPacket(EntityIDSyncPacket packet, NetworkEvent.Context contextSupplier) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - contextSupplier.enqueueWork(() -> ModernFixClient.handleEntityIDSync(packet)); - contextSupplier.setPacketHandled(true); - }); + private static void handleSyncPacket(EntityIDSyncPacket packet, PlayPayloadContext context) { + context.workHandler().execute(() -> ModernFixClient.handleEntityIDSync(packet)); } } diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java index 58f45578..565535a9 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java @@ -5,6 +5,7 @@ import com.google.common.collect.Multimap; import com.mojang.brigadier.CommandDispatcher; import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.CreativeModeTab; @@ -87,8 +88,8 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { return FMLPaths.GAMEDIR.get(); } - public void sendPacket(ServerPlayer player, Object packet) { - PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet); + public void sendPacket(ServerPlayer player, CustomPacketPayload packet) { + PacketDistributor.PLAYER.with(player).send(packet); } public void injectPlatformSpecificHacks() { diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml index 37477b8e..17114291 100644 --- a/neoforge/src/main/resources/META-INF/mods.toml +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -45,9 +45,9 @@ Egregious, yet effective performance improvements for modern Minecraft # the modid of the dependency modId = "neoforge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified -mandatory = true #mandatory +type = "required" #mandatory # The version range of the dependency -versionRange = "[20.4.22-beta,)" #mandatory +versionRange = "[20.4.70-beta,)" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory ordering = "NONE" # Side this dependency is applied on - BOTH, CLIENT or SERVER @@ -55,14 +55,14 @@ side = "BOTH" # Here's another dependency [[dependencies.modernfix]] modId = "minecraft" -mandatory = true +type = "required" # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange = "[1.20, 1.21)" ordering = "NONE" side = "BOTH" [[dependencies.modernfix]] modId = "jei" -mandatory = false +type = "optional" # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange = "[13,)" ordering = "BEFORE" From c65fdbccc0746a051be3cadb0fda8492b3af3729 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 31 Dec 2023 21:14:39 -0500 Subject: [PATCH 23/31] Spotless --- .../modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java index 565535a9..5e455b81 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java @@ -25,7 +25,6 @@ import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.neoforge.config.NightConfigFixer; import org.embeddedt.modernfix.neoforge.init.ModernFixForge; -import org.embeddedt.modernfix.neoforge.packet.PacketHandler; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.spark.SparkLaunchProfiler; import org.embeddedt.modernfix.util.CommonModUtil; From d0fd498682a60a4ee0c4bb6bc9b6b42059f15c0c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 1 Jan 2024 12:25:16 -0500 Subject: [PATCH 24/31] Suppress mixin forceload logging when clear_mixin_info is on --- .../modernfix/util/ClassInfoManager.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java b/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java index 8efaa4f1..1daa97a8 100644 --- a/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java +++ b/common/src/main/java/org/embeddedt/modernfix/util/ClassInfoManager.java @@ -3,16 +3,22 @@ package org.embeddedt.modernfix.util; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.logging.ILogger; +import org.spongepowered.asm.logging.LoggerAdapterDefault; import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import org.spongepowered.asm.mixin.transformer.ClassInfo; +import org.spongepowered.asm.service.MixinServiceAbstract; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; public class ClassInfoManager { private static boolean hasRun = false; + private static final List loggersToRestore = new ArrayList<>(); public static void clear() { if (!ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_mixin_classinfo.ClassInfoManager") || hasRun) return; @@ -25,11 +31,33 @@ public class ClassInfoManager { return f; } + private static void changeLoggerAndRestoreLater(Map map, ILogger newLogger) { + ILogger oldLogger = map.put("mixin.audit", newLogger); + loggersToRestore.add(() -> map.put("mixin.audit", oldLogger)); + } + + private static void disableLoggers() throws ReflectiveOperationException { + // Disable default audit logger + Field loggersField = accessible(MixinServiceAbstract.class.getDeclaredField("loggers")); + changeLoggerAndRestoreLater((Map)loggersField.get(null), new LoggerAdapterDefault("mixin.audit")); + Class fabricLogger = null; + try { + fabricLogger = Class.forName("net.fabricmc.loader.impl.knot.MixinLogger"); + } catch(Throwable e) { + // Probably not Fabric + return; + } + // Disable Fabric audit logger + loggersField = accessible(fabricLogger.getDeclaredField("LOGGER_MAP")); + changeLoggerAndRestoreLater((Map)loggersField.get(null), new LoggerAdapterDefault("mixin.audit")); + } + private static void doClear() { Map classInfoCache; Field mixinField, stateField, classNodeField, methodsField, fieldsField; Class stateClz; try { + disableLoggers(); Field field = accessible(ClassInfo.class.getDeclaredField("cache")); classInfoCache = (Map) field.get(null); mixinField = accessible(ClassInfo.class.getDeclaredField("mixin")); @@ -70,6 +98,9 @@ public class ClassInfoManager { } catch (RuntimeException e) { e.printStackTrace(); } + // Put back the old logger + loggersToRestore.forEach(Runnable::run); + loggersToRestore.clear(); ModernFix.LOGGER.warn("Cleared mixin data structures"); } } From 3214311bb6f1b51b3dd081a86689c5da428f00f2 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:03:52 -0500 Subject: [PATCH 25/31] Slightly optimize entity capability retrieval --- .../LivingEntityMixin.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java new file mode 100644 index 00000000..60935b4f --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java @@ -0,0 +1,24 @@ +package org.embeddedt.modernfix.forge.mixin.perf.forge_cap_retrieval; + +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.items.CapabilityItemHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import javax.annotation.Nullable; + +@Mixin(LivingEntity.class) +public class LivingEntityMixin { + /** + * @author embeddedt (issue noted by XFactHD) + * @reason check capability equality before checking that entity is alive, the latter requires a lot more + * indirection + */ + @Redirect(method = "getCapability", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isAlive()Z")) + private boolean checkAliveAfterCap(LivingEntity entity, Capability capability, @Nullable Direction facing) { + return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && entity.isAlive(); + } +} From 17fdccddfed8773ac8d7827671a0bf8dd1f534de Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:52:17 -0500 Subject: [PATCH 26/31] Allow missing models on item overrides Please ask your servers to stop shipping the client invalid model files. Related: #343 --- .../dynamic_resources/ItemOverridesMixin.java | 26 ++++++++++++++ .../modernfix/duck/IExtendedModelBaker.java | 3 +- .../ItemOverridesFabricMixin.java | 31 +++++++++++++++++ .../ModelBakerImplMixin.java | 6 ++-- .../dynamic_resources/ModelBakeryMixin.java | 2 +- .../ItemOverridesForgeMixin.java | 34 +++++++++++++++++++ .../ModelBakerImplMixin.java | 6 ++-- 7 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java create mode 100644 fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java new file mode 100644 index 00000000..5de98b42 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemOverridesMixin.java @@ -0,0 +1,26 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesMixin { + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;getModel(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/resources/model/UnbakedModel;")) + private UnbakedModel preventThrowForMissing(ModelBaker instance, ResourceLocation resourceLocation, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java b/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java index 5a26ed55..b50f65d4 100644 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java +++ b/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBaker.java @@ -3,6 +3,7 @@ package org.embeddedt.modernfix.duck; public interface IExtendedModelBaker { /** * Causes the ModelBaker to throw when it finds a missing model instead of proceeding with the bake. + * @return the previous value of this flag */ - void throwOnMissingModel(); + boolean throwOnMissingModel(boolean flag); } diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java new file mode 100644 index 00000000..140f0737 --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ItemOverridesFabricMixin.java @@ -0,0 +1,31 @@ +package org.embeddedt.modernfix.fabric.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesFabricMixin { + /** + * @author embeddedt + * @reason servers insist on generating invalid item overrides that have missing models + */ + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;)Lnet/minecraft/client/resources/model/BakedModel;")) + private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation, modelState); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index 5d88e0ec..2324eda4 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -59,8 +59,10 @@ public abstract class ModelBakerImplMixin implements IExtendedModelBaker { private boolean throwIfMissing; @Override - public void throwOnMissingModel() { - throwIfMissing = true; + public boolean throwOnMissingModel(boolean flag) { + boolean old = throwIfMissing; + throwIfMissing = flag; + return old; } @Inject(method = "getModel", at = @At("HEAD"), cancellable = true) diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java index fd51fc97..39ac1fb3 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -310,7 +310,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return m; ModelBakery self = (ModelBakery) (Object) this; ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); - ((IExtendedModelBaker)theBaker).throwOnMissingModel(); + ((IExtendedModelBaker)theBaker).throwOnMissingModel(true); synchronized(this) { m = theBaker.bake(modelLocation, state); } if(m != null) loadedBakedModels.put(key, m); diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java new file mode 100644 index 00000000..12c35328 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java @@ -0,0 +1,34 @@ +package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IExtendedModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.function.Function; + +@Mixin(ItemOverrides.class) +@ClientOnlyMixin +public class ItemOverridesForgeMixin { + /** + * @author embeddedt + * @reason servers insist on generating invalid item overrides that have missing models + */ + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;")) + private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Function spriteGetter, Operation original) { + boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); + try { + return original.call(instance, resourceLocation, modelState, spriteGetter); + } finally { + ((IExtendedModelBaker)instance).throwOnMissingModel(prevState); + } + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index e55ffc39..11036e83 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -41,8 +41,10 @@ public abstract class ModelBakerImplMixin implements IModelBakerImpl, IExtendedM private boolean throwIfMissing; @Override - public void throwOnMissingModel() { - throwIfMissing = true; + public boolean throwOnMissingModel(boolean flag) { + boolean old = throwIfMissing; + throwIfMissing = flag; + return old; } @Inject(method = "getModel", at = @At("HEAD"), cancellable = true) From 9375a4233b1b04222509d5babf7afaf2b640dc60 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:55:55 -0500 Subject: [PATCH 27/31] Fix Forge errors --- .../mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java | 2 +- .../forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java index 12c35328..3118b7b8 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ItemOverridesForgeMixin.java @@ -22,7 +22,7 @@ public class ItemOverridesForgeMixin { * @author embeddedt * @reason servers insist on generating invalid item overrides that have missing models */ - @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;")) + @WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;"), remap = false) private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Function spriteGetter, Operation original) { boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false); try { diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java index 2f36b941..1a388a3c 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -316,7 +316,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return m; ModelBakery self = (ModelBakery) (Object) this; ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); - ((IExtendedModelBaker)theBaker).throwOnMissingModel(); + ((IExtendedModelBaker)theBaker).throwOnMissingModel(true); synchronized(this) { m = theBaker.bake(modelLocation, state, theBaker.getModelTextureGetter()); } if(m != null) loadedBakedModels.put(key, m); From 7174ae1454c91ae0ab6917063becd6c23ed221be Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:17:53 -0500 Subject: [PATCH 28/31] Do not actually load all models in replaceAll, use clever trick instead Otherwise, it takes 20 seconds to run this with just Mekanism+Additions+Pneumaticcraft --- .../dynresources/ModelBakeEventHelper.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index 0aeb9fac..1aa4609f 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -153,13 +153,26 @@ public class ModelBakeEventHelper { @Override public void replaceAll(BiFunction function) { - ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. This requires temporarily loading every model for that mod, which is slow.", modId); + ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. Some hacks will be used to keep this fast, but they may not be 100% compatible.", modId); List locations = new ArrayList<>(keySet()); for(ResourceLocation location : locations) { - BakedModel existing = get(location); - BakedModel replacement = function.apply(location, existing); - if(replacement != existing) { - put(location, replacement); + /* + * Fetching every model is insanely slow. So we call the function with a null object first, since it + * probably isn't expecting that. If we get an exception thrown, or it returns nonnull, then we know + * it actually cares about the given model. + */ + boolean needsReplacement; + try { + needsReplacement = function.apply(location, null) != null; + } catch(Throwable e) { + needsReplacement = true; + } + if(needsReplacement) { + BakedModel existing = get(location); + BakedModel replacement = function.apply(location, existing); + if(replacement != existing) { + put(location, replacement); + } } } } From c678ebbb918e25a2c28e0e2a638b4e837491c0a7 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:30:13 -0500 Subject: [PATCH 29/31] Avoid refresh loop if no model data needs refreshing --- .../model_data_manager_cme/ModelDataManagerMixin.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java index 45836c89..ebca1644 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java @@ -6,6 +6,7 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraftforge.client.model.ModelDataManager; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -13,6 +14,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import java.util.Collections; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -27,6 +29,8 @@ public abstract class ModelDataManagerMixin { throw new AssertionError(); } + @Shadow @Final private static Map> needModelDataRefresh; + /** * Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet, * because the returned iterator won't be thread-safe otherwise. See https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/7511 @@ -40,7 +44,8 @@ public abstract class ModelDataManagerMixin { private static void onlyRefreshOnMainThread(Level toUpdate, ChunkPos pos) { // Only refresh model data on the main thread. This prevents calling getBlockEntity from worker threads // which could cause weird CMEs or other behavior. - if(Minecraft.getInstance().isSameThread()) { + // Avoid the loop if no model data needs to be refreshed, to prevent unnecessary allocation. + if(Minecraft.getInstance().isSameThread() && !needModelDataRefresh.isEmpty()) { // Refresh the given chunk, and all its neighbors. This is less efficient than the default code // but we have no choice since we need to not do refreshing on workers, and blocks might // try to access model data in neighboring chunks. From 2e88482344bb0d9d5602321ea2e259177fccd70c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:31:44 -0500 Subject: [PATCH 30/31] Update for 1.19 model data manager changes --- .../bugfix/model_data_manager_cme/ModelDataManagerMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java index e379b69a..5fba1b2e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/model_data_manager_cme/ModelDataManagerMixin.java @@ -26,7 +26,7 @@ import java.util.function.Function; public abstract class ModelDataManagerMixin { @Shadow protected abstract void refreshAt(ChunkPos chunk); - @Shadow @Final private static Map> needModelDataRefresh; + @Shadow @Final private Map> needModelDataRefresh; /** * Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet, From 9d95a5363f9502faf3854bce9f9f5a056e181050 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:35:41 -0500 Subject: [PATCH 31/31] Update cap mixin for 1.20 changes --- .../mixin/perf/forge_cap_retrieval/LivingEntityMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java index 60935b4f..68e86aab 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/forge_cap_retrieval/LivingEntityMixin.java @@ -3,7 +3,7 @@ package org.embeddedt.modernfix.forge.mixin.perf.forge_cap_retrieval; import net.minecraft.core.Direction; import net.minecraft.world.entity.LivingEntity; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.common.capabilities.ForgeCapabilities; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -19,6 +19,6 @@ public class LivingEntityMixin { */ @Redirect(method = "getCapability", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isAlive()Z")) private boolean checkAliveAfterCap(LivingEntity entity, Capability capability, @Nullable Direction facing) { - return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && entity.isAlive(); + return capability == ForgeCapabilities.ITEM_HANDLER && entity.isAlive(); } }