From b4ffe68adb4d85fddf2af3a7cd5fc589f0d23772 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 13 May 2023 16:36:59 -0400 Subject: [PATCH 01/45] Replace Forge dynamic model bake event with modloader-independent custom solution --- .../embeddedt/modernfix/ModernFixClient.java | 14 +++++ .../api/constants/IntegrationConstants.java | 8 +++ .../ModernFixClientIntegration.java | 49 +++++++++++++++ .../modernfix/api/helpers/ModelHelpers.java | 55 +++++++++++++++++ .../modernfix/core/ModernFixMixinPlugin.java | 2 + .../platform/ModernFixPlatformHooks.java | 6 ++ .../fabric/ModernFixPlatformHooksImpl.java | 27 ++++++++ .../DynamicModelBakeEvent.java | 47 -------------- .../dynamic_resources/ModelBakeryMixin.java | 36 ++++++++--- .../ae2/RegistrationMixin.java | 61 +++++++++---------- .../ctm/CTMPackReloadListenerMixin.java | 40 ++++++------ .../ctm/TextureMetadataHandlerMixin.java | 25 ++++---- .../rs/ClientSetupMixin.java | 24 +++++--- .../ClientRegistrationHandlerMixin.java | 26 ++++---- .../forge/ModernFixPlatformHooksImpl.java | 24 ++++++++ 15 files changed, 301 insertions(+), 143 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/api/constants/IntegrationConstants.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java delete mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/dynamicresources/DynamicModelBakeEvent.java diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java index bf15ca24..f41da000 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java @@ -10,6 +10,8 @@ import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.world.entity.Entity; +import org.embeddedt.modernfix.api.constants.IntegrationConstants; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.packet.EntityIDSyncPacket; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; @@ -29,12 +31,24 @@ public class ModernFixClient { public String brandingString = null; + /** + * The list of loaded client integrations. + */ + public static List CLIENT_INTEGRATIONS = new ArrayList<>(); + public ModernFixClient() { // clear reserve as it's not needed Minecraft.reserve = new byte[0]; if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) { brandingString = "ModernFix " + ModernFixPlatformHooks.getVersionString(); } + for(String className : ModernFixPlatformHooks.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) { + try { + CLIENT_INTEGRATIONS.add((ModernFixClientIntegration)Class.forName(className).getDeclaredConstructor().newInstance()); + } catch(ReflectiveOperationException | ClassCastException e) { + ModernFix.LOGGER.error("Could not instantiate integration {}", className, e); + } + } } public void resetWorldLoadStateMachine() { diff --git a/common/src/main/java/org/embeddedt/modernfix/api/constants/IntegrationConstants.java b/common/src/main/java/org/embeddedt/modernfix/api/constants/IntegrationConstants.java new file mode 100644 index 00000000..92a9a5e1 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/api/constants/IntegrationConstants.java @@ -0,0 +1,8 @@ +package org.embeddedt.modernfix.api.constants; + +public class IntegrationConstants { + public static final String INTEGRATIONS_KEY = "modernfix:integration"; + + public static final String CLIENT_INTEGRATION_CLASS = "client_entrypoint"; + public static final String INTEGRATION_CLASS = "entrypoint"; +} diff --git a/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java new file mode 100644 index 00000000..f5757766 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java @@ -0,0 +1,49 @@ +package org.embeddedt.modernfix.api.entrypoint; + +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; + + +/** + * Implement this interface in a mod class and add it to "modernfix:integration_v1" in your mod metadata file + * to integrate with ModernFix's features. + */ +public interface ModernFixClientIntegration { + /** + * Called when the dynamic resources status has changed during a model reload so mods know whether to run their + * normal codepath or the dynamic version. + * + * @param enabled whether dynamic resources is enabled + */ + default void onDynamicResourcesStatusChange(boolean enabled) { + } + + /** + * Called to allow mods to observe the loading of an unbaked model and either make changes to it or wrap it with their + * own instance. + * @param location the ResourceLocation of the model (this may be a ModelResourceLocation) + * @param originalModel the original model + * @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect + * with dynamic resources on + * @return the model which should actually be loaded for this resource location + */ + default UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { + return originalModel; + } + + /** + * Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their + * own instance. + * @param location the ResourceLocation of the model (this may be a ModelResourceLocation) + * @param originalModel the original model + * @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect + * with dynamic resources on + * @return the model which should actually be loaded for this resource location + */ + default BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) { + return originalModel; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java b/common/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java new file mode 100644 index 00000000..33535a14 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java @@ -0,0 +1,55 @@ +package org.embeddedt.modernfix.api.helpers; + +import com.google.common.collect.ImmutableList; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.BlockModelRotation; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +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.dynamicresources.ModelBakeryHelpers; +import org.embeddedt.modernfix.util.DynamicMap; + +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; + +@SuppressWarnings("unused") +public final class ModelHelpers { + /** + * Allows converting a ModelResourceLocation back into the corresponding BlockState(s). Try to avoid calling this + * multiple times if possible. + * @param location the location of the model + * @return a list of all blockstates related to the model + */ + public static ImmutableList getBlockStateForLocation(ModelResourceLocation location) { + Optional blockOpt = Registry.BLOCK.getOptional(new ResourceLocation(location.getNamespace(), location.getPath())); + if(blockOpt.isPresent()) + return ModelBakeryHelpers.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), location); + else + return ImmutableList.of(); + } + + /** + * Allows converting a ModelResourceLocation back into the corresponding BlockState(s). Faster version of its + * companion function if and only if you know the corresponding Block already for some reason. + * @param definition the state definition for the Block + * @param location the location of the model + * @return a list of all blockstates related to the model + */ + public static ImmutableList getBlockStateForLocation(StateDefinition definition, ModelResourceLocation location) { + return ModelBakeryHelpers.getBlockStatesForMRL(definition, location); + } + + /** + * Compatibility helper for mods to use to get a map-like view of the model bakery. + * @param modelGetter the model getter function supplied by the integration class + * @return a fake map of the top-level models + */ + public static Map createFakeTopLevelMap(BiFunction modelGetter) { + return new DynamicMap<>(location -> modelGetter.apply(location, BlockModelRotation.X0_Y0)); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java b/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java index 49b5c487..850db8f2 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/ModernFixMixinPlugin.java @@ -20,6 +20,8 @@ public class ModernFixMixinPlugin implements IMixinConfigPlugin { public static ModernFixMixinPlugin instance; public ModernFixMixinPlugin() { + /* invoke early to ensure it gets read on one thread */ + ModernFixPlatformHooks.getCustomModOptions(); boolean firstConfig = instance == null; if(firstConfig) { instance = this; 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 39ca4d64..ee199cb2 100644 --- a/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java +++ b/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix.platform; +import com.google.common.collect.Multimap; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.brigadier.CommandDispatcher; import dev.architectury.injectables.annotations.ExpectPlatform; @@ -85,4 +86,9 @@ public class ModernFixPlatformHooks { public static void onServerCommandRegister(Consumer> handler) { throw new AssertionError(); } + + @ExpectPlatform + public static Multimap getCustomModOptions() { + throw new AssertionError(); + } } 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 cbaf273d..4a4a289b 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 @@ -1,11 +1,15 @@ package org.embeddedt.modernfix.platform.fabric; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.CustomValue; +import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.commands.CommandSourceStack; @@ -14,6 +18,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import org.embeddedt.modernfix.ModernFixFabric; +import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.objectweb.asm.tree.*; import java.nio.file.Path; @@ -82,4 +87,26 @@ public class ModernFixPlatformHooksImpl { public static void onServerCommandRegister(Consumer> handler) { CommandRegistrationCallback.EVENT.register((dispatcher, arg) -> handler.accept(dispatcher)); } + + private static Multimap modOptions; + public static Multimap getCustomModOptions() { + if(modOptions == null) { + modOptions = ArrayListMultimap.create(); + for (ModContainer container : FabricLoader.getInstance().getAllMods()) { + ModMetadata meta = container.getMetadata(); + if (meta.containsCustomValue(IntegrationConstants.INTEGRATIONS_KEY)) { + CustomValue integrations = meta.getCustomValue(IntegrationConstants.INTEGRATIONS_KEY); + if (integrations.getType() != CustomValue.CvType.OBJECT) { + continue; + } + for (Map.Entry entry : integrations.getAsObject()) { + if(entry.getValue().getType() != CustomValue.CvType.STRING) + continue; + modOptions.put(entry.getKey(), entry.getValue().getAsString()); + } + } + } + } + return modOptions; + } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynamicresources/DynamicModelBakeEvent.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynamicresources/DynamicModelBakeEvent.java deleted file mode 100644 index fc475ff6..00000000 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynamicresources/DynamicModelBakeEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.embeddedt.modernfix.forge.dynamicresources; - -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.eventbus.api.Event; - -/** - * Fired when a model is baked dynamically. Intended to be used as a replacement for ModelBakeEvent - * if mods want to replace a model. - *

- * Note that this event can fire many times for the same resource location, as models are unloaded - * if unused/under memory pressure. - */ -public class DynamicModelBakeEvent extends Event { - private final ResourceLocation location; - private BakedModel model; - private final UnbakedModel unbakedModel; - private final ModelLoader modelLoader; - public DynamicModelBakeEvent(ResourceLocation location, UnbakedModel unbakedModel, BakedModel model, ModelLoader loader) { - this.location = location; - this.model = model; - this.unbakedModel = unbakedModel; - this.modelLoader = loader; - } - - public ResourceLocation getLocation() { - return this.location; - } - - public BakedModel getModel() { - return this.model; - } - - public UnbakedModel getUnbakedModel() { - return this.unbakedModel; - } - - public ModelLoader getModelLoader() { - return this.modelLoader; - } - - public void setModel(BakedModel model) { - this.model = model; - } -} 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 a71b7ed7..7b75a2d8 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 @@ -26,26 +26,23 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; import net.minecraftforge.client.ForgeHooksClient; -import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoaderRegistry; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.packs.DelegatingResourcePack; import net.minecraftforge.fml.packs.ModFileResourcePack; import org.apache.commons.lang3.tuple.Triple; import org.apache.logging.log4j.Logger; 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.IExtendedModelBakery; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -90,6 +87,8 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @Shadow @Nullable public abstract BakedModel getBakedModel(ResourceLocation arg, ModelState arg2, Function textureGetter); + @Shadow @org.jetbrains.annotations.Nullable public abstract BakedModel bake(ResourceLocation location, ModelState transform); + private Cache, BakedModel> loadedBakedModels; private Cache loadedModels; @@ -217,6 +216,18 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return unbakedCache.get(rl); } + @ModifyVariable(method = "cacheAndQueueDependencies", at = @At("HEAD"), argsOnly = true) + private UnbakedModel fireUnbakedEvent(UnbakedModel model, ResourceLocation location) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + model = integration.onUnbakedModelLoad(location, model, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception firing model load event for {}", location, e); + } + } + return model; + } + @Inject(method = "cacheAndQueueDependencies", at = @At("RETURN")) private void addToSmallLoadingCache(ResourceLocation location, UnbakedModel model, CallbackInfo ci) { smallLoadingCache.put(location, model); @@ -329,10 +340,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { } else ibakedmodel = iunbakedmodel.bake((ModelBakery) (Object) this, textureGetter, arg2, arg); } - DynamicModelBakeEvent event = new DynamicModelBakeEvent(arg, iunbakedmodel, ibakedmodel, (ModelLoader)(Object)this); - MinecraftForge.EVENT_BUS.post(event); - this.bakedCache.put(triple, event.getModel()); - cir.setReturnValue(event.getModel()); + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + ibakedmodel = integration.onBakedModelLoad(arg, iunbakedmodel, ibakedmodel, arg2, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e); + } + } + this.bakedCache.put(triple, ibakedmodel); + cir.setReturnValue(ibakedmodel); } } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java index bcbfee97..bc838d13 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java @@ -4,21 +4,21 @@ import appeng.bootstrap.components.IModelBakeComponent; import appeng.bootstrap.components.ModelOverrideComponent; import appeng.core.Api; import appeng.core.AppEng; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; 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; import java.lang.reflect.Field; +import java.util.Iterator; import java.util.Map; import java.util.function.BiFunction; @@ -29,34 +29,33 @@ public class RegistrationMixin { private static Field customizerField; @Inject(method = "registerClientEvents", at = @At("TAIL"), remap = false) private void doRegisterDynBake(CallbackInfo ci) { - MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); customizerField = ObfuscationReflectionHelper.findField(ModelOverrideComponent.class, "customizer"); - } - - private void onDynamicModelBake(DynamicModelBakeEvent event) { - if (!event.getLocation().getNamespace().equals(AppEng.MOD_ID)) { - return; - } - BakedModel missing = event.getModelLoader().getBakedTopLevelModels().get(ModelBakery.MISSING_MODEL_LOCATION); - if(event.getModel() == missing) - return; - Api.INSTANCE.definitions().getRegistry().getBootstrapComponents(IModelBakeComponent.class).forEachRemaining(c -> { - if(c instanceof ModelOverrideComponent) - handleModelOverride((ModelOverrideComponent)c, event); + ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { + @Override + public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) { + if(location.getNamespace().equals(AppEng.MOD_ID)) { + BakedModel m = bakery.bake(ModelBakery.MISSING_MODEL_LOCATION, BlockModelRotation.X0_Y0); + if(originalModel == m) + return originalModel; + Iterator components = Api.INSTANCE.definitions().getRegistry().getBootstrapComponents(IModelBakeComponent.class); + while(components.hasNext()) { + IModelBakeComponent c = components.next(); + if(c instanceof ModelOverrideComponent) { + Map> customizer; + try { + customizer = (Map>)customizerField.get(c); + } catch(ReflectiveOperationException e) { + ModernFix.LOGGER.error("Can't replace model", e); + continue; + } + BiFunction fn = customizer.get(location.getPath()); + if(fn != null) + originalModel = fn.apply(location, originalModel); + } + } + } + return originalModel; + } }); } - - private void handleModelOverride(ModelOverrideComponent c, DynamicModelBakeEvent event) { - Map> customizer; - try { - customizer = (Map>)customizerField.get(c); - } catch(ReflectiveOperationException e) { - ModernFix.LOGGER.error("Can't replace model", e); - return; - } - BiFunction fn = customizer.get(event.getLocation().getPath()); - if(fn != null) { - event.setModel(fn.apply(event.getLocation(), event.getModel())); - } - } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/CTMPackReloadListenerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/CTMPackReloadListenerMixin.java index b6ef6ea2..4c8cc031 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/CTMPackReloadListenerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/CTMPackReloadListenerMixin.java @@ -3,23 +3,19 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ctm; import com.google.common.collect.ImmutableList; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.MultiPartBakedModel; -import net.minecraft.client.resources.model.WeightedBakedModel; +import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.IRegistryDelegate; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; -import org.embeddedt.modernfix.duck.IExtendedModelBakery; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; +import org.embeddedt.modernfix.api.helpers.ModelHelpers; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -37,7 +33,7 @@ import java.util.function.Predicate; @Mixin(CTMPackReloadListener.class) @RequiresMod("ctm") @ClientOnlyMixin -public abstract class CTMPackReloadListenerMixin { +public abstract class CTMPackReloadListenerMixin implements ModernFixClientIntegration { /* caches the original render checks */ @Shadow @Final private static Map, Predicate> blockRenderChecks; @@ -51,7 +47,7 @@ public abstract class CTMPackReloadListenerMixin { @Inject(method = "", at = @At("RETURN")) private void onInit(CallbackInfo ci) { - MinecraftForge.EVENT_BUS.addListener(EventPriority.LOW, this::onModelBake); + ModernFixClient.CLIENT_INTEGRATIONS.add(this); } @Overwrite(remap = false) @@ -75,27 +71,31 @@ public abstract class CTMPackReloadListenerMixin { return override.test(type); } - private void onModelBake(DynamicModelBakeEvent event) { - if(!(event.getModel() instanceof AbstractCTMBakedModel || event.getModel() instanceof WeightedBakedModel || event.getModel() instanceof MultiPartBakedModel)) - return; + @Override + public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState modelState, ModelBakery bakery) { + if(!(location instanceof ModelResourceLocation)) + return originalModel; + if(!(originalModel instanceof AbstractCTMBakedModel || originalModel instanceof WeightedBakedModel || originalModel instanceof MultiPartBakedModel)) + return originalModel; /* we construct a new ResourceLocation because an MRL is coming in */ - Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(event.getLocation().getNamespace(), event.getLocation().getPath())); + Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(location.getNamespace(), location.getPath())); if(block == null || block == Blocks.AIR || renderCheckOverrides.containsKey(block.delegate)) - return; + return originalModel; /* find all states that match this MRL */ ImmutableList allStates; try { - allStates = ((IExtendedModelBakery)(Object)event.getModelLoader()).getBlockStatesForMRL(block.getStateDefinition(), (ModelResourceLocation)event.getLocation()); + allStates = ModelHelpers.getBlockStateForLocation(block.getStateDefinition(), (ModelResourceLocation)location); } catch(RuntimeException e) { - ModernFix.LOGGER.error("Couldn't get state for MRL " + event.getLocation(), e); - return; + ModernFix.LOGGER.error("Couldn't get state for MRL " + location, e); + return originalModel; } for(BlockState state : allStates) { - Predicate newPredicate = this.getLayerCheck(state, event.getModel()); + Predicate newPredicate = this.getLayerCheck(state, originalModel); if(newPredicate != null) { renderCheckOverrides.put(block.delegate, newPredicate); - return; + return originalModel; } } + return originalModel; } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java index e1bc5547..c7ecb7ab 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java @@ -1,15 +1,13 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ctm; import com.mojang.datafixers.util.Pair; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.common.MinecraftForge; +import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -29,13 +27,13 @@ import java.util.*; @Mixin(TextureMetadataHandler.class) @RequiresMod("ctm") @ClientOnlyMixin -public abstract class TextureMetadataHandlerMixin { +public abstract class TextureMetadataHandlerMixin implements ModernFixClientIntegration { @Shadow @Nonnull protected abstract BakedModel wrap(ResourceLocation loc, UnbakedModel model, BakedModel object, ModelLoader loader) throws IOException; @Inject(method = "", at = @At("RETURN")) private void subscribeDynamic(CallbackInfo ci) { - MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); + ModernFixClient.CLIENT_INTEGRATIONS.add(this); } @Redirect(method = "onModelBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BakedModel;isCustomRenderer()Z")) @@ -43,10 +41,8 @@ public abstract class TextureMetadataHandlerMixin { return model == null || model.isCustomRenderer(); } - public void onDynamicModelBake(DynamicModelBakeEvent event) { - UnbakedModel rootModel = event.getUnbakedModel(); - BakedModel baked = event.getModel(); - ResourceLocation rl = event.getLocation(); + @Override + public BakedModel onBakedModelLoad(ResourceLocation rl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery) { if (!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) { Deque dependencies = new ArrayDeque<>(); Set seenModels = new HashSet<>(); @@ -59,12 +55,12 @@ public abstract class TextureMetadataHandlerMixin { ResourceLocation dep = dependencies.pop(); UnbakedModel model; try { - model = dep == rl ? rootModel : event.getModelLoader().getModel(dep); + model = dep == rl ? rootModel : bakery.getModel(dep); } catch (Exception e) { continue; } - Collection textures = model.getMaterials(event.getModelLoader()::getModel, errors); + Collection textures = model.getMaterials(bakery::getModel, errors); Collection newDependencies = model.getDependencies(); for (Material tex : textures) { IMetadataSectionCTM meta = null; @@ -86,12 +82,13 @@ public abstract class TextureMetadataHandlerMixin { } if (shouldWrap) { try { - event.setModel(wrap(rl, rootModel, baked, event.getModelLoader())); + baked = wrap(rl, rootModel, baked, (ModelLoader)bakery); dependencies.clear(); } catch (IOException e) { CTM.logger.error("Could not wrap model " + rl + ". Aborting...", e); } } } + return baked; } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/rs/ClientSetupMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/rs/ClientSetupMixin.java index 4369870e..26cf83b0 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/rs/ClientSetupMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/rs/ClientSetupMixin.java @@ -2,12 +2,12 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.rs; import com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry; import com.refinedmods.refinedstorage.setup.ClientSetup; -import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.MinecraftForge; +import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -15,6 +15,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + @Mixin(ClientSetup.class) @RequiresMod("refinedstorage") @ClientOnlyMixin @@ -23,12 +24,15 @@ public class ClientSetupMixin { @Inject(method = "", at = @At("RETURN")) private void addDynamicListener(CallbackInfo ci) { - MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); - } - - private void onDynamicModelBake(DynamicModelBakeEvent event) { - BakedModelOverrideRegistry.BakedModelOverrideFactory factory = bakedModelOverrideRegistry.get(event.getLocation() instanceof ModelResourceLocation ? new ResourceLocation(event.getLocation().getNamespace(), event.getLocation().getPath()) : event.getLocation()); - if(factory != null) - event.setModel(factory.create(event.getModel(), event.getModelLoader().getBakedTopLevelModels())); + ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { + @Override + public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) { + BakedModelOverrideRegistry.BakedModelOverrideFactory factory = bakedModelOverrideRegistry.get(location instanceof ModelResourceLocation ? new ResourceLocation(location.getNamespace(), location.getPath()) : location); + if(factory != null) + return factory.create(originalModel, bakery.getBakedTopLevelModels()); + else + return originalModel; + } + }); } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/supermartijncore/ClientRegistrationHandlerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/supermartijncore/ClientRegistrationHandlerMixin.java index 682484f1..e4cc3781 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/supermartijncore/ClientRegistrationHandlerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/supermartijncore/ClientRegistrationHandlerMixin.java @@ -4,12 +4,14 @@ import com.supermartijn642.core.registry.ClientRegistrationHandler; import com.supermartijn642.core.util.Pair; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.RequiresMod; -import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -48,13 +50,15 @@ public class ClientRegistrationHandlerMixin { @Inject(method = "", at = @At("RETURN")) private void registerDynBake(String modid, CallbackInfo ci) { - MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); - } - - @SubscribeEvent - public void onDynamicModelBake(DynamicModelBakeEvent event) { - Function replacer = modelOverwritesByLocation.get(event.getLocation()); - if(replacer != null) - event.setModel(replacer.apply(event.getModel())); + ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { + @Override + public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) { + Function replacer = modelOverwritesByLocation.get(location); + if(replacer != null) + return replacer.apply(originalModel); + else + return originalModel; + } + }); } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index f8eb19e6..af1208bb 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -1,5 +1,7 @@ package org.embeddedt.modernfix.platform.forge; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import com.google.common.io.Resources; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.brigadier.CommandDispatcher; @@ -23,8 +25,10 @@ import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; +import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.server.ServerLifecycleHooks; +import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.forge.classloading.ModernFixResourceFinder; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; @@ -255,4 +259,24 @@ public class ModernFixPlatformHooksImpl { handler.accept(event.getDispatcher()); }); } + + private static Multimap modOptions; + public static Multimap getCustomModOptions() { + if(modOptions == null) { + modOptions = ArrayListMultimap.create(); + for (ModInfo meta : LoadingModList.get().getMods()) { + meta.getConfigElement(IntegrationConstants.INTEGRATIONS_KEY).ifPresent(optionsObj -> { + if(optionsObj instanceof Map) { + Map options = (Map)optionsObj; + options.forEach((key, value) -> { + if(key instanceof String && value instanceof String) { + modOptions.put((String)key, (String)value); + } + }); + } + }); + } + } + return modOptions; + } } From a7e64f29476020e020707195368841f959d38cac Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 14 May 2023 19:23:36 -0400 Subject: [PATCH 02/45] Fix performance issue when loading large NBT maps Array map was not being changed to hash map until AFTER the insertions, which is bad --- .../org/embeddedt/modernfix/util/CanonizingStringMap.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java index e5bb2f2d..05bd219b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java +++ b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java @@ -77,11 +77,15 @@ public class CanonizingStringMap implements Map { public void putAll(@NotNull Map map) { if(map.size() == 0) return; + // grow early if we know there are enough non-overlapping keys + if((map.size() - backingMap.size()) > GROWTH_THRESHOLD && !(backingMap instanceof Object2ObjectOpenHashMap)) { + backingMap = new Object2ObjectOpenHashMap<>(backingMap); + } map.forEach((String key, T val) -> { key = KEY_INTERNER.intern(key); backingMap.put(key, val); }); - // if it's too big to be an array, grow it + // if it's still an array, and now too big, grow it if(backingMap.size() > GROWTH_THRESHOLD && !(backingMap instanceof Object2ObjectOpenHashMap)) { backingMap = new Object2ObjectOpenHashMap<>(backingMap); } From f67fa0754609186cb36daac63d7f3be8ff9983b7 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 17 May 2023 16:50:08 -0400 Subject: [PATCH 03/45] Synchronize LivingEntityRenderer layer list Related: #102 --- .../safety/LivingEntityRendererMixin.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/LivingEntityRendererMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/LivingEntityRendererMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/LivingEntityRendererMixin.java new file mode 100644 index 00000000..8e165b7b --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/LivingEntityRendererMixin.java @@ -0,0 +1,28 @@ +package org.embeddedt.modernfix.common.mixin.safety; + +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Collections; +import java.util.List; + +@Mixin(LivingEntityRenderer.class) +@ClientOnlyMixin +public class LivingEntityRendererMixin { + @Shadow @Final @Mutable + protected List> layers; + + @Inject(method = "", at = @At("RETURN")) + private void synchronizeLayerList(CallbackInfo ci) { + /* allows buggy mods to call addLayer concurrently, order is not deterministic but can't fix that */ + this.layers = Collections.synchronizedList(layers); + } +} From 0d4a12eafe5d87b05e792b200ab34a056ccd1b04 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 17 May 2023 16:51:25 -0400 Subject: [PATCH 04/45] Revert "Hopefully more stable version of the original packet fix" This reverts commit b21ee9a7e721f92aa0a8a1a44d79f871fdb1131e. --- .../ClientPlayNetHandlerMixin.java | 16 ++++++++++--- .../SCustomPayloadPlayPacketMixin.java | 23 ++++--------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java index cfc92448..630007a8 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java @@ -11,13 +11,23 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(ClientPacketListener.class) @ClientOnlyMixin -public class ClientPlayNetHandlerMixin { +public class ClientPlayNetHandlerMixin implements IClientNetHandler { + private FriendlyByteBuf savedCopy = null; /** * @author embeddedt - * @reason allow the other function to track use of the buffer + * @reason Release the packet buffer at the end. Needed in f */ @Redirect(method = "handleCustomPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;getData()Lnet/minecraft/network/FriendlyByteBuf;")) private FriendlyByteBuf saveCopyForRelease(ClientboundCustomPayloadPacket instance) { - return ((IClientNetHandler)instance).getCopiedCustomBuffer(); + FriendlyByteBuf copy = instance.getData(); + savedCopy = copy; + return copy; + } + + @Override + public FriendlyByteBuf getCopiedCustomBuffer() { + FriendlyByteBuf copy = savedCopy; + savedCopy = null; + return copy; } } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java index 8b0a8f37..083f0c0f 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java @@ -15,13 +15,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientboundCustomPayloadPacket.class) @ClientOnlyMixin -public abstract class SCustomPayloadPlayPacketMixin implements IClientNetHandler { +public class SCustomPayloadPlayPacketMixin { @Shadow private FriendlyByteBuf data; - @Shadow public abstract FriendlyByteBuf getData(); - - private FriendlyByteBuf usedByteBuf = null; - private boolean needsRelease; @Inject(method = "(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/network/FriendlyByteBuf;)V", at = @At("RETURN")) @@ -34,25 +30,16 @@ public abstract class SCustomPayloadPlayPacketMixin implements IClientNetHandler this.needsRelease = true; } - @Override - public FriendlyByteBuf getCopiedCustomBuffer() { - FriendlyByteBuf buf = this.getData(); - usedByteBuf = buf; - return buf; - } - @Redirect(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientGamePacketListener;handleCustomPayload(Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;)V")) private void handleAndFree(ClientGamePacketListener instance, ClientboundCustomPayloadPacket sCustomPayloadPlayPacket) { - usedByteBuf = null; try { instance.handleCustomPayload(sCustomPayloadPlayPacket); } finally { - FriendlyByteBuf buf = usedByteBuf; - if(buf != null && buf.refCnt() > 0) { - buf.release(); - } + FriendlyByteBuf copied = ((IClientNetHandler)instance).getCopiedCustomBuffer(); + if(copied != null) + copied.release(); } - if(this.needsRelease && this.data.refCnt() > 0) + if(this.needsRelease) this.data.release(); } } From c51d7ae6416910fe27e8beeb7a1255e835612507 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 17 May 2023 16:51:31 -0400 Subject: [PATCH 05/45] Use half fix for packet leak --- .../ClientPlayNetHandlerMixin.java | 33 ------------------- .../SCustomPayloadPlayPacketMixin.java | 12 ++----- .../modernfix/duck/IClientNetHandler.java | 7 ---- 3 files changed, 3 insertions(+), 49 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java delete mode 100644 common/src/main/java/org/embeddedt/modernfix/duck/IClientNetHandler.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java deleted file mode 100644 index 630007a8..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/ClientPlayNetHandlerMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.packet_leak; - -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IClientNetHandler; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ClientPacketListener.class) -@ClientOnlyMixin -public class ClientPlayNetHandlerMixin implements IClientNetHandler { - private FriendlyByteBuf savedCopy = null; - /** - * @author embeddedt - * @reason Release the packet buffer at the end. Needed in f - */ - @Redirect(method = "handleCustomPayload", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;getData()Lnet/minecraft/network/FriendlyByteBuf;")) - private FriendlyByteBuf saveCopyForRelease(ClientboundCustomPayloadPacket instance) { - FriendlyByteBuf copy = instance.getData(); - savedCopy = copy; - return copy; - } - - @Override - public FriendlyByteBuf getCopiedCustomBuffer() { - FriendlyByteBuf copy = savedCopy; - savedCopy = null; - return copy; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java index 083f0c0f..7e4af5f8 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/packet_leak/SCustomPayloadPlayPacketMixin.java @@ -5,7 +5,6 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IClientNetHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -32,14 +31,9 @@ public class SCustomPayloadPlayPacketMixin { @Redirect(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientGamePacketListener;handleCustomPayload(Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;)V")) private void handleAndFree(ClientGamePacketListener instance, ClientboundCustomPayloadPacket sCustomPayloadPlayPacket) { - try { - instance.handleCustomPayload(sCustomPayloadPlayPacket); - } finally { - FriendlyByteBuf copied = ((IClientNetHandler)instance).getCopiedCustomBuffer(); - if(copied != null) - copied.release(); - } + /* in 1.16, this method creates a copy inside it, but does not handle freeing correctly. fixing that breaks mods though */ + instance.handleCustomPayload(sCustomPayloadPlayPacket); if(this.needsRelease) - this.data.release(); + this.data.release(); /* free our own copy of the data if needed */ } } diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IClientNetHandler.java b/common/src/main/java/org/embeddedt/modernfix/duck/IClientNetHandler.java deleted file mode 100644 index 71b1a0a6..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IClientNetHandler.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import net.minecraft.network.FriendlyByteBuf; - -public interface IClientNetHandler { - FriendlyByteBuf getCopiedCustomBuffer(); -} From 962b843199286d8e429572f54d0212fde71c2bf5 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 20 May 2023 12:35:33 -0400 Subject: [PATCH 06/45] Avoid exposing mods to exceptions when baking models --- .../dynamicresources/DynamicBakedModelProvider.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicBakedModelProvider.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicBakedModelProvider.java index d11971b3..5803fb77 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicBakedModelProvider.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicBakedModelProvider.java @@ -13,6 +13,7 @@ import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.state.BlockState; import org.apache.commons.lang3.tuple.Triple; +import org.embeddedt.modernfix.ModernFix; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -106,7 +107,12 @@ public class DynamicBakedModelProvider implements Map Date: Sat, 20 May 2023 16:35:41 -0400 Subject: [PATCH 07/45] Only preserve window position if a non-default width/height was given Fixes #103 (in next release) --- .../WindowMixin.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/preserve_early_window_pos/WindowMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/preserve_early_window_pos/WindowMixin.java index a543b777..85702c55 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/preserve_early_window_pos/WindowMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/preserve_early_window_pos/WindowMixin.java @@ -1,8 +1,7 @@ package org.embeddedt.modernfix.forge.mixin.bugfix.preserve_early_window_pos; -import com.mojang.blaze3d.platform.Monitor; -import com.mojang.blaze3d.platform.ScreenManager; -import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.platform.*; +import net.minecraft.client.Minecraft; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; @@ -35,19 +34,26 @@ public class WindowMixin { } private Object getEarlyProgressVisualizer() { + Minecraft client = Minecraft.getInstance(); if(VISUALIZER == null || this.fullscreen) return null; Object o = ObfuscationReflectionHelper.getPrivateValue(EarlyProgressVisualization.class, EarlyProgressVisualization.INSTANCE, "visualization"); return VISUALIZER.isAssignableFrom(o.getClass()) ? o : null; } + private static boolean defaultDisplayData(DisplayData arg3) { + return arg3.width == 854 && arg3.height == 480 && !arg3.isFullscreen; + } + /** * Return a null monitor if not in fullscreen and the visualizer is present, so that the code grabs the * original X/Y position of the window. */ @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/ScreenManager;getMonitor(J)Lcom/mojang/blaze3d/platform/Monitor;")) - private Monitor getMonitor(ScreenManager manager, long id) { - return getEarlyProgressVisualizer() != null ? null : manager.getMonitor(id); + private Monitor getMonitor(ScreenManager manager, long id, WindowEventHandler arg, ScreenManager arg2, DisplayData arg3) { + if(defaultDisplayData(arg3) && getEarlyProgressVisualizer() != null) + return null; + return manager.getMonitor(id); } /** @@ -55,9 +61,9 @@ public class WindowMixin { */ @SuppressWarnings("unchecked") @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/loading/progress/EarlyProgressVisualization;handOffWindow(Ljava/util/function/IntSupplier;Ljava/util/function/IntSupplier;Ljava/util/function/Supplier;Ljava/util/function/LongSupplier;)J"), require = 0) - private long performHandoff(EarlyProgressVisualization instance, IntSupplier width, IntSupplier height, Supplier title, LongSupplier monitor) { + private long performHandoff(EarlyProgressVisualization instance, IntSupplier width, IntSupplier height, Supplier title, LongSupplier monitor, WindowEventHandler arg, ScreenManager arg2, DisplayData arg3) { Object visualizer = getEarlyProgressVisualizer(); - if(visualizer != null) { + if(visualizer != null && defaultDisplayData(arg3)) { long windowId = ObfuscationReflectionHelper.getPrivateValue((Class)visualizer.getClass(), visualizer, "window"); int[] w = new int[1]; int[] h = new int[1]; From bb6d498d58d0ca966a0f108f37e0bce3f4390029 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 14:10:50 -0400 Subject: [PATCH 08/45] Disable faster_texture_loading and faster_texture_stitching when Opticrash is present Fixes #91 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 3 ++- 1 file changed, 2 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 a7688484..2cbd9276 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 @@ -188,8 +188,9 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); disableIfModPresent("mixin.perf.reuse_datapacks", "tac"); disableIfModPresent("mixin.launch.class_search_cache", "optifine"); + disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); - disableIfModPresent("mixin.perf.faster_texture_loading", "stitch"); + disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine"); } private void disableIfModPresent(String configName, String... ids) { From 98da673cbef392d952c08e9a2980f1bd593813bf Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 17:04:22 -0400 Subject: [PATCH 09/45] Tweak point at which dummy models are cleared on Fabric --- .../perf/dynamic_resources/ModelBakeryMixin.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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 82b7ae6e..8b3a6757 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 @@ -244,6 +244,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { "entity/chest", "item", "items", + "part", "pipe", "ropebridge" }; @@ -266,6 +267,14 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return materialsSet; } + @Inject(method = "", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=textures")) + private void clearDummyModels(CallbackInfo ci) { + // discard unwrapped models + Predicate> isVanillaModel = entry -> entry.getValue() instanceof BlockModel || entry.getValue() instanceof MultiVariant || entry.getValue() instanceof MultiPart; + this.unbakedCache.entrySet().removeIf(isVanillaModel); + this.topLevelModels.entrySet().removeIf(isVanillaModel); + } + @Inject(method = "uploadTextures", at = @At(value = "FIELD", target = "Lnet/minecraft/client/resources/model/ModelBakery;topLevelModels:Ljava/util/Map;", ordinal = 0), cancellable = true) private void skipBake(TextureManager resourceManager, ProfilerFiller profiler, CallbackInfoReturnable cir) { profiler.pop(); @@ -287,10 +296,6 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return super.put(key, value); } }; - // discard unwrapped models - Predicate> isVanillaModel = entry -> entry.getValue() instanceof BlockModel || entry.getValue() instanceof MultiVariant || entry.getValue() instanceof MultiPart; - this.unbakedCache.entrySet().removeIf(isVanillaModel); - this.topLevelModels.entrySet().removeIf(isVanillaModel); // bake indigo models Stopwatch watch = Stopwatch.createStarted(); this.topLevelModels.forEach((key, value) -> { From a22308fb89a380d925778bb45ca3f148b6740cfa Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 17:08:45 -0400 Subject: [PATCH 10/45] Depend on full Fabric API at runtime --- fabric/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/fabric/build.gradle b/fabric/build.gradle index a68aea14..64ccca13 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -36,6 +36,7 @@ dependencies { modIncludeImplementation(fabricApi.module("fabric-models-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false } + modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}") { exclude group: 'net.fabricmc', module: 'fabric-loader' } // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}" From 0a035b6e0dc5317b16cd9012ff87d12c01d89f89 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 17:11:51 -0400 Subject: [PATCH 11/45] Back client integration list with COW arraylist --- .../src/main/java/org/embeddedt/modernfix/ModernFixClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java index f41da000..be5fd14a 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java @@ -20,6 +20,7 @@ import org.embeddedt.modernfix.world.IntegratedWatchdog; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; public class ModernFixClient { public static long worldLoadStartTime; @@ -34,7 +35,7 @@ public class ModernFixClient { /** * The list of loaded client integrations. */ - public static List CLIENT_INTEGRATIONS = new ArrayList<>(); + public static List CLIENT_INTEGRATIONS = new CopyOnWriteArrayList<>(); public ModernFixClient() { // clear reserve as it's not needed From fc65975252e66d6cbaabd890a3640a98f617d4d8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 20:08:17 -0400 Subject: [PATCH 12/45] Fix AE2 mod id --- .../mixin/perf/dynamic_resources/ae2/RegistrationMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java index f2e53627..45b1c686 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java @@ -21,13 +21,13 @@ import java.util.Map; import java.util.function.Function; @Mixin(InitAutoRotatingModel.class) -@RequiresMod("appliedenergistics2") +@RequiresMod("ae2") @ClientOnlyMixin public class RegistrationMixin { @Shadow @Final private static Map> CUSTOMIZERS; @Inject(method = "init", at = @At("TAIL"), remap = false) - private void doRegisterDynBake(CallbackInfo ci) { + private static void doRegisterDynBake(CallbackInfo ci) { ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { @Override public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) { From f48ed1212b049e3fedb4f09991163d48b68ade80 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 20:17:38 -0400 Subject: [PATCH 13/45] Move AE2 dynamic resources compat to common module --- common/build.gradle | 3 +++ .../mixin/perf/dynamic_resources/ae2/RegistrationMixin.java | 2 +- forge/build.gradle | 1 - gradle.properties | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) rename {forge/src/main/java/org/embeddedt/modernfix/forge => common/src/main/java/org/embeddedt/modernfix/common}/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java (96%) diff --git a/common/build.gradle b/common/build.gradle index f047ba1d..ce3ad020 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -23,6 +23,9 @@ dependencies { modCompileOnly("me.shedaniel:RoughlyEnoughItems-fabric:${rei_version}") { transitive = false } + modCompileOnly("appeng:appliedenergistics2-fabric:${appeng_version}") { + transitive = false + } // compile against the JEI API but do not include it at runtime modCompileOnly("mezz.jei:jei-${minecraft_version}-common:${jei_version}") // Remove the next line if you don't want to depend on the API diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java similarity index 96% rename from forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java rename to common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java index 45b1c686..d6bc85b6 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ae2/RegistrationMixin.java @@ -1,4 +1,4 @@ -package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ae2; +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.ae2; import appeng.core.AppEng; import appeng.init.client.InitAutoRotatingModel; diff --git a/forge/build.gradle b/forge/build.gradle index 287be48b..93defe66 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -45,7 +45,6 @@ dependencies { modCompileOnly("team.chisel.ctm:CTM:${ctm_version}") modCompileOnly("curse.maven:supermartijncore-454372:4455384") - modCompileOnly("appeng:appliedenergistics2-forge:11.7.3") modCompileOnly("vazkii.patchouli:Patchouli:1.18.2-71.1") common(project(path: ":common", configuration: "namedElements")) { transitive false } diff --git a/gradle.properties b/gradle.properties index 95bd8e12..44cfec12 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,3 +18,4 @@ fabric_loader_version=0.14.18 fabric_api_version=0.76.0+1.18.2 modmenu_version=3.2.5 +appeng_version=11.7.2 \ No newline at end of file From cfd542623c89ed28db207062fe056f2dc011ae51 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 20:24:28 -0400 Subject: [PATCH 14/45] Fire model integrations on Fabric --- .../dynamic_resources/ModelBakeryMixin.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) 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 8b3a6757..77e05a43 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 @@ -32,17 +32,16 @@ import net.minecraft.world.level.block.state.StateDefinition; import org.apache.commons.lang3.tuple.Triple; import org.apache.logging.log4j.Logger; 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.IExtendedModelBakery; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers; import org.embeddedt.modernfix.util.LayeredForwardingMap; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -333,6 +332,18 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { return unbakedCache.get(rl); } + @ModifyVariable(method = "cacheAndQueueDependencies", at = @At("HEAD"), argsOnly = true) + private UnbakedModel fireUnbakedEvent(UnbakedModel model, ResourceLocation location) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + model = integration.onUnbakedModelLoad(location, model, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception firing model load event for {}", location, e); + } + } + return model; + } + /** * @author embeddedt * @reason synchronize @@ -457,7 +468,13 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { ModernFix.LOGGER.error("Model {} returned null baked model", arg); ibakedmodel = bakedMissingModel; } - // TODO event + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + ibakedmodel = integration.onBakedModelLoad(arg, iunbakedmodel, ibakedmodel, arg2, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e); + } + } this.bakedCache.put(triple, ibakedmodel); cir.setReturnValue(ibakedmodel); } From 91c2d50d9728b68a5cfc4c9385542d638d056d05 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 21 May 2023 22:14:17 -0400 Subject: [PATCH 15/45] Add more texture paths --- .../mixin/perf/dynamic_resources/ModelBakeryMixin.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 77e05a43..a8551700 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 @@ -243,9 +243,12 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { "entity/chest", "item", "items", + "model", + "models", "part", "pipe", - "ropebridge" + "ropebridge", + "solid_block" }; for(String folder : extraFolders) { Collection textureLocations = this.resourceManager.listResources("textures/" + folder, p -> p.endsWith(".png")); From 80617c24f1cd6c7280cb50966f26a703410fa190 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 22 May 2023 13:25:14 -0400 Subject: [PATCH 16/45] Work around KeyMapping names being retrieved off-thread --- .../mixin/perf/blast_search_trees/MinecraftMixin.java | 6 ++++++ common/src/main/resources/modernfix.accesswidener | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java index d28c2fc0..73f6a358 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.blast_search_trees; +import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.searchtree.SearchRegistry; import org.embeddedt.modernfix.ModernFix; @@ -27,6 +28,11 @@ public class MinecraftMixin { this.searchRegistry.register(SearchRegistry.CREATIVE_NAMES, provider.getSearchTree(false)); this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, provider.getSearchTree(true)); this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, new DummySearchTree<>()); + // grab components for all key mappings in order to prevent them from being loaded off-thread later + // this populates the LazyLoadedValues + for(KeyMapping mapping : KeyMapping.ALL.values()) { + mapping.getTranslatedKeyMessage(); + } ci.cancel(); } } diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 459f6b00..6f44fc25 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -28,4 +28,5 @@ accessible class net/minecraft/server/level/ChunkMap$DistanceManager accessible class net/minecraft/world/level/chunk/PalettedContainer$Data accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources; accessible class net/minecraft/server/MinecraftServer$ReloadableResources -accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; \ No newline at end of file +accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; +accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; \ No newline at end of file From 675e3bb08b6289c3d5bab936a1f1b36a7fff9cc8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 22 May 2023 13:49:08 -0400 Subject: [PATCH 17/45] Fix startup crash introduced in last commit --- .../common/mixin/perf/blast_search_trees/MinecraftMixin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java index 73f6a358..cf5d0044 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/blast_search_trees/MinecraftMixin.java @@ -7,6 +7,8 @@ import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.searchtree.DummySearchTree; import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWErrorCallback; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -30,9 +32,12 @@ public class MinecraftMixin { this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, new DummySearchTree<>()); // grab components for all key mappings in order to prevent them from being loaded off-thread later // this populates the LazyLoadedValues + // we also need to suppress GLFW errors to prevent crashes if a key is missing + GLFWErrorCallback oldCb = GLFW.glfwSetErrorCallback(null); for(KeyMapping mapping : KeyMapping.ALL.values()) { mapping.getTranslatedKeyMessage(); } + GLFW.glfwSetErrorCallback(oldCb); ci.cancel(); } } From bd94b5dd2e902c0e1f5feaf7fc3519f4402aa119 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 22 May 2023 14:40:26 -0400 Subject: [PATCH 18/45] Spotless --- .../forge/mixin/perf/dynamic_resources/ModelBakerImplMixin.java | 1 - 1 file changed, 1 deletion(-) 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 8d26ba4a..a1e21bd9 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 @@ -4,7 +4,6 @@ import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.MinecraftForge; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; From be4c8607d46d5ee2c47f4743415119a5eac6c756 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 11:53:28 -0400 Subject: [PATCH 19/45] Disable faster texture loader if Changed:MC is installed Related: #108 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 2 +- 1 file changed, 1 insertion(+), 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 2cbd9276..3b4522a3 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 @@ -190,7 +190,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.launch.class_search_cache", "optifine"); disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); - disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine"); + disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine", "changed"); } private void disableIfModPresent(String configName, String... ids) { From baca029fd06b039036204ea836b79bf703fc6ce8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 14:59:46 -0400 Subject: [PATCH 20/45] Add support for Diagonal Fences --- common/build.gradle | 1 + .../MultipartAppenderMixin.java | 43 +++++++++++++++++++ .../main/resources/modernfix.accesswidener | 3 +- gradle.properties | 1 + 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java diff --git a/common/build.gradle b/common/build.gradle index bbf54231..bc9b8299 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -26,6 +26,7 @@ dependencies { modCompileOnly("appeng:appliedenergistics2-fabric:${appeng_version}") { transitive = false } + modCompileOnly("curse.maven:diagonal-fences-458048:${diagonal_fences_version}") // compile against the JEI API but do not include it at runtime modCompileOnly("mezz.jei:jei-${minecraft_version}-common:${jei_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-gui:${jei_version}") diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java new file mode 100644 index 00000000..7c702fba --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java @@ -0,0 +1,43 @@ +package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.diagonalfences; + +import fuzs.diagonalfences.api.world.level.block.DiagonalBlock; +import fuzs.diagonalfences.client.model.MultipartAppender; +import net.minecraft.client.renderer.block.model.multipart.MultiPart; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FenceBlock; +import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.annotation.RequiresMod; +import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MultipartAppender.class) +@RequiresMod("diagonalfences") +public abstract class MultipartAppenderMixin { + @Shadow(remap = false) + public static void appendDiagonalSelectors(ModelBakery modelBakery, MultiPart multiPart) { + throw new AssertionError(); + } + + @Inject(method = "onPrepareModelBaking", at = @At("RETURN")) + private static void setupHelper(CallbackInfo ci) { + ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { + @Override + public UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { + if(originalModel instanceof MultiPart multipart) { + Block block = multipart.definition.getOwner(); + if(block instanceof FenceBlock && block instanceof DiagonalBlock diagonalBlock && diagonalBlock.hasProperties()) { + appendDiagonalSelectors(bakery, multipart); + } + } + return originalModel; + } + }); + } +} diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 0873eccb..f43fe931 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -29,4 +29,5 @@ accessible class net/minecraft/world/level/chunk/PalettedContainer$Data accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources; accessible class net/minecraft/server/MinecraftServer$ReloadableResources accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; -accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; \ No newline at end of file +accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; +accessible field net/minecraft/client/renderer/block/model/multipart/MultiPart definition Lnet/minecraft/world/level/block/state/StateDefinition; \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index cfb24271..b59cb53a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,3 +18,4 @@ fabric_api_version=0.76.0+1.19.2 modmenu_version=4.1.2 appeng_version=12.9.3 +diagonal_fences_version=4545943 \ No newline at end of file From 2bd2fd7ef760bebbb598fbb6217684d72ad0e932 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 16:38:34 -0400 Subject: [PATCH 21/45] Only inject integration first time --- .../diagonalfences/MultipartAppenderMixin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java index 7c702fba..5be40715 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/diagonalfences/MultipartAppenderMixin.java @@ -25,8 +25,13 @@ public abstract class MultipartAppenderMixin { throw new AssertionError(); } + private static boolean handlerInjected = false; + @Inject(method = "onPrepareModelBaking", at = @At("RETURN")) private static void setupHelper(CallbackInfo ci) { + if(handlerInjected) + return; + handlerInjected = true; ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() { @Override public UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { From 74eb8a06197373f69fe110d527f11a65e9f31774 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 18:50:49 -0400 Subject: [PATCH 22/45] Split unbaked model load event into load and pre-bake stages Allows mods like Continuity to wrap the model being baked separately from the model in the cache --- .../api/entrypoint/ModernFixClientIntegration.java | 13 +++++++++++++ .../perf/dynamic_resources/ModelBakeryMixin.java | 11 +++++++++++ .../perf/dynamic_resources/ModelBakeryMixin.java | 11 +++++++++++ 3 files changed, 35 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java index f5757766..aa3b78bc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java +++ b/common/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java @@ -34,6 +34,19 @@ public interface ModernFixClientIntegration { return originalModel; } + /** + * Called to allow mods to observe the use of an unbaked model at bake time and either make changes to it or wrap it with their + * own instance. + * @param location the ResourceLocation of the model (this may be a ModelResourceLocation) + * @param originalModel the original model + * @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect + * with dynamic resources on + * @return the model which should actually be loaded for this resource location + */ + default UnbakedModel onUnbakedModelPreBake(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) { + return originalModel; + } + /** * Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their * own instance. 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 a8551700..311530f3 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 @@ -448,6 +448,17 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { if(iunbakedmodel == missingModel && debugDynamicModelLoading) LOGGER.warn("Model {} not present", arg); + + if(iunbakedmodel != missingModel) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception firing model pre-bake event for {}", arg, e); + } + } + } + BakedModel ibakedmodel = null; if (iunbakedmodel instanceof BlockModel) { BlockModel blockmodel = (BlockModel)iunbakedmodel; 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 7b75a2d8..3fe1d7cf 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 @@ -322,6 +322,17 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { iunbakedmodel.getMaterials(this::getModel, new HashSet<>()); if(iunbakedmodel == missingModel && debugDynamicModelLoading) LOGGER.warn("Model {} not present", arg); + + if(iunbakedmodel != missingModel) { + for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { + try { + iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, (ModelBakery)(Object)this); + } catch(RuntimeException e) { + ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e); + } + } + } + BakedModel ibakedmodel = null; if (iunbakedmodel instanceof BlockModel) { BlockModel blockmodel = (BlockModel)iunbakedmodel; From ddf2fc5a7413e3015a0c0dba3f81ac7778dc7eec Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 19:29:24 -0400 Subject: [PATCH 23/45] Provide more useful information if the image used in DynamicTexture is null --- .../mixin/safety/DynamicTextureMixin.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java new file mode 100644 index 00000000..388cc1eb --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java @@ -0,0 +1,24 @@ +package org.embeddedt.modernfix.common.mixin.safety; + +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.renderer.texture.DynamicTexture; +import org.embeddedt.modernfix.ModernFix; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(DynamicTexture.class) +public class DynamicTextureMixin { + @Shadow @Nullable private NativeImage pixels; + + @Redirect(method = "(Lcom/mojang/blaze3d/platform/NativeImage;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) + private void putNewPixel(DynamicTexture texture, NativeImage pixels) { + if(pixels == null) { + ModernFix.LOGGER.error("Null image provided to DynamicTexture", new Exception()); + pixels = new NativeImage(4, 4, false); + } + this.pixels = pixels; + } +} From a327b460bbe1ccd5977a8239e838077284057706 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 20:30:22 -0400 Subject: [PATCH 24/45] Tweak dynamic texture mixin --- .../mixin/safety/DynamicTextureMixin.java | 24 --------------- .../mixin/safety/DynamicTextureMixin.java | 30 +++++++++++++++++++ 2 files changed, 30 insertions(+), 24 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java create mode 100644 fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java deleted file mode 100644 index 388cc1eb..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/safety/DynamicTextureMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.safety; - -import com.mojang.blaze3d.platform.NativeImage; -import net.minecraft.client.renderer.texture.DynamicTexture; -import org.embeddedt.modernfix.ModernFix; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(DynamicTexture.class) -public class DynamicTextureMixin { - @Shadow @Nullable private NativeImage pixels; - - @Redirect(method = "(Lcom/mojang/blaze3d/platform/NativeImage;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) - private void putNewPixel(DynamicTexture texture, NativeImage pixels) { - if(pixels == null) { - ModernFix.LOGGER.error("Null image provided to DynamicTexture", new Exception()); - pixels = new NativeImage(4, 4, false); - } - this.pixels = pixels; - } -} 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 new file mode 100644 index 00000000..5cc7f1ac --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java @@ -0,0 +1,30 @@ +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.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(DynamicTexture.class) +public class DynamicTextureMixin { + @Shadow @Nullable private NativeImage pixels; + + private Exception closeTrace; + + @Inject(method = "method_22793", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;pixels:Lcom/mojang/blaze3d/platform/NativeImage;", ordinal = 0)) + private void checkNullPixels(CallbackInfo ci) { + if(pixels == null) { + ModernFix.LOGGER.error("Attempted to upload null texture! This is not allowed, closed here", closeTrace); + } + } + + @Inject(method = "close", at = @At("HEAD")) + private void storeCloseTrace(CallbackInfo ci) { + closeTrace = new Exception(); + } +} From 214b39ce8fdf1e80de12c97c9764f6855d877d0e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 23 May 2023 21:02:27 -0400 Subject: [PATCH 25/45] Fixes for LBG+Diagonal Fences together --- .../mixin/perf/dynamic_resources/ModelBakeryMixin.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 b97b8412..8094dfcc 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 @@ -44,10 +44,6 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -179,7 +175,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @Inject(method = "loadModel", at = @At(value = "HEAD"), cancellable = true) private void ignoreNonFabricModel(ResourceLocation modelLocation, CallbackInfo ci) throws Exception { - if(this.inTextureGatheringPass && !this.forceLoadModel && !this.injectedModels.contains(modelLocation)) { + if(this.inTextureGatheringPass && this.blockStateFiles != null && !this.forceLoadModel && !this.injectedModels.contains(modelLocation)) { // Custom model processor, try to avoid loading unwrapped models // First add this to the list of models to scan for textures ResourceLocation blockStateLocation = null; @@ -210,7 +206,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { this.cacheAndQueueDependencies(modelLocation, this.missingModel); this.forceLoadModel = false; if(this.smallLoadingCache.get(modelLocation) != this.missingModel) { - /* probably a wrapped model, allow it to load normally */ + // probably a wrapped model, allow it to load normally isWrappedModel = true; } this.smallLoadingCache.clear(); @@ -344,6 +340,8 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @ModifyVariable(method = "cacheAndQueueDependencies", at = @At("HEAD"), argsOnly = true) private UnbakedModel fireUnbakedEvent(UnbakedModel model, ResourceLocation location) { + if(this.inTextureGatheringPass) + return model; for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { try { model = integration.onUnbakedModelLoad(location, model, (ModelBakery)(Object)this); From b5d62b4bbb70ce28affbeadf2bb284b3fcaf749c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 26 May 2023 11:55:57 -0400 Subject: [PATCH 26/45] Add off-by-default feature to automatically thread dump every 60 seconds --- .../org/embeddedt/modernfix/ModernFix.java | 14 +++++++ .../core/config/ModernFixEarlyConfig.java | 1 + .../modernfix/world/IntegratedWatchdog.java | 40 ++++++++++--------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java index cbd44bf4..4e6e89d1 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -11,6 +11,7 @@ import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.resources.ReloadExecutor; import org.embeddedt.modernfix.util.ClassInfoManager; +import org.embeddedt.modernfix.world.IntegratedWatchdog; import java.lang.management.ManagementFactory; import java.util.concurrent.Executor; @@ -46,6 +47,19 @@ public class ModernFix { public ModernFix() { INSTANCE = this; ModernFixPlatformHooks.onServerCommandRegister(ModernFixCommands::register); + if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spam_thread_dump.ThreadDumper")) { + Thread t = new Thread() { + public void run() { + while(true) { + LOGGER.error("------ DEBUG THREAD DUMP (occurs every 60 seconds) ------"); + LOGGER.error(IntegratedWatchdog.obtainThreadDump()); + try { Thread.sleep(60000); } catch(InterruptedException e) {} + } + } + }; + t.setDaemon(true); + t.start(); + } } public void onServerStarted() { 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 3b4522a3..ca7e9333 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 @@ -147,6 +147,7 @@ public class ModernFixEarlyConfig { .put("mixin.perf.deduplicate_location", false) .put("mixin.feature.integrated_server_watchdog", true) .put("mixin.perf.faster_item_rendering", false) + .put("mixin.feature.spam_thread_dump", false) .put("mixin.perf.blast_search_trees", shouldReplaceSearchTrees) .put("mixin.devenv", isDevEnv) .put("mixin.perf.remove_spawn_chunks", isDevEnv) diff --git a/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java b/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java index 150269fe..1f8f0bc7 100644 --- a/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java +++ b/common/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java @@ -25,6 +25,27 @@ public class IntegratedWatchdog extends Thread { this.setName("ModernFix integrated server watchdog"); } + public static String obtainThreadDump() { + ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true); + StringBuilder sb = new StringBuilder(); + sb.append("Thread Dump:\n"); + for(ThreadInfo threadinfo : athreadinfo) { + sb.append(threadinfo); + StackTraceElement[] elements = threadinfo.getStackTrace(); + if(elements.length > 8) { + sb.append("extended trace:\n"); + for(int i = 8; i < elements.length; i++) { + sb.append("\tat "); + sb.append(elements[i]); + sb.append('\n'); + } + } + sb.append('\n'); + } + return sb.toString(); + } + public void run() { while(true) { MinecraftServer server = this.server.get(); @@ -35,24 +56,7 @@ public class IntegratedWatchdog extends Thread { long delta = curTime - nextTick; if(delta > MAX_TICK_DELTA) { LOGGER.error("A single server tick has taken {}, more than {} milliseconds", delta, MAX_TICK_DELTA); - ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean(); - ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true); - StringBuilder sb = new StringBuilder(); - sb.append("Thread Dump:\n"); - for(ThreadInfo threadinfo : athreadinfo) { - sb.append(threadinfo); - StackTraceElement[] elements = threadinfo.getStackTrace(); - if(elements.length > 8) { - sb.append("extended trace:\n"); - for(int i = 8; i < elements.length; i++) { - sb.append("\tat "); - sb.append(elements[i]); - sb.append('\n'); - } - } - sb.append('\n'); - } - LOGGER.error(sb); + LOGGER.error(obtainThreadDump()); nextTick = 0; curTime = 0; } From c4a50bb6e2a1fb9e31a4b46b9b9cfdd999c3cfa9 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 27 May 2023 10:12:05 -0400 Subject: [PATCH 27/45] Replace default backing map of NBT tags in more compatible way Related: #111 --- .../nbt_memory_usage/CompoundTagMixin.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java index 4a12e9b1..7b20e23d 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java @@ -6,27 +6,24 @@ import org.embeddedt.modernfix.util.CanonizingStringMap; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; @Mixin(CompoundTag.class) public class CompoundTagMixin { - @Shadow @Final @Mutable + @Shadow @Final private Map tags; /** - * Ensure that the backing map is always a CanonizingStringMap. + * Ensure that the default backing map is a CanonizingStringMap. */ - @Redirect(method = "(Ljava/util/Map;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/nbt/CompoundTag;tags:Ljava/util/Map;", ordinal = 0)) - private void replaceTagMap(CompoundTag tag, Map incomingMap) { - if(incomingMap instanceof CanonizingStringMap) - this.tags = incomingMap; - else { - this.tags = new CanonizingStringMap<>(); - this.tags.putAll(incomingMap); - } + @ModifyArg(method = "()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;(Ljava/util/Map;)V"), index = 0) + private static Map useCanonizingStringMap(Map incoming) { + CanonizingStringMap newMap = new CanonizingStringMap<>(); + newMap.putAll(incoming); + return newMap; } /** From b8850b2aae9ce722be61320d45057e82796f2349 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 28 May 2023 22:17:03 -0400 Subject: [PATCH 28/45] Only use JEI backed search tree if EMI is not installed --- .../org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java b/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java index 57a8ff25..6779e51c 100644 --- a/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java +++ b/common/src/main/java/org/embeddedt/modernfix/searchtree/JEIBackedSearchTree.java @@ -99,7 +99,7 @@ public class JEIBackedSearchTree extends DummySearchTree { @Override public boolean canUse() { - return ModernFixPlatformHooks.modPresent("jei") && getIngredientListUncached != null && filterField != null; + return ModernFixPlatformHooks.modPresent("jei") && !ModernFixPlatformHooks.modPresent("emi") && getIngredientListUncached != null && filterField != null; } @Override From 04f34a00fa5876576aa0a103fcc6dcf98f8ad71c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 10:15:18 -0400 Subject: [PATCH 29/45] Fix resource pack cache not working as well as it could --- .../mixin/perf/resourcepacks/ModFileResourcePackMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java index bfb3d510..ff0046d2 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/resourcepacks/ModFileResourcePackMixin.java @@ -70,7 +70,7 @@ public abstract class ModFileResourcePackMixin implements ICachingResourcePack { @Inject(method = "getResources", at = @At("HEAD"), cancellable = true) private void fastGetResources(PackType type, String resourceNamespace, String pathIn, int maxDepth, Predicate filter, CallbackInfoReturnable> cir) { - if(!PackTypeHelper.isVanillaPackType(type) || this.cacheEngine == null) + if(!PackTypeHelper.isVanillaPackType(type)) return; cir.setReturnValue(this.generateResourceCache().getResources(type, resourceNamespace, pathIn, maxDepth, filter)); } From a7d894cbc2fde0ad591f9c99eed1730eb5b60201 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 10:16:54 -0400 Subject: [PATCH 30/45] Disable cache invalidation outside dev Not needed as mod contents shouldn't change (right...) --- .../modernfix/resources/PackResourcesCacheEngine.java | 3 +++ .../modernfix/platform/forge/ModernFixPlatformHooksImpl.java | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java b/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java index 8c592cdf..ef5e2cbc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java +++ b/common/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.util.PackTypeHelper; import java.io.IOException; @@ -163,6 +164,8 @@ public class PackResourcesCacheEngine { } public static void invalidate() { + if(!ModernFixPlatformHooks.isDevEnv()) + return; synchronized (cachingPacks) { cachingPacks.keySet().forEach(pack -> { if(pack != null) diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index 525a7d47..8b31a33e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -22,7 +22,6 @@ import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; import net.minecraftforge.fml.loading.LoadingModList; -import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.server.ServerLifecycleHooks; @@ -76,7 +75,7 @@ public class ModernFixPlatformHooksImpl { } public static boolean isDevEnv() { - return !FMLLoader.isProduction() && FMLLoader.getLoadingModList().getModFileById("modernfix").getFile().getLocator() instanceof ExplodedDirectoryLocator; + return !FMLLoader.isProduction(); } public static MinecraftServer getCurrentServer() { From 3dbff477e936d7ffd02067b5c5705527f5c36934 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 29 May 2023 18:25:03 -0400 Subject: [PATCH 31/45] Improve structure cache wording --- .../modernfix/structure/CachingStructureManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java index 365fb4d7..9f96c0ee 100644 --- a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java +++ b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java @@ -62,7 +62,8 @@ public class CachingStructureManager { currentTag.putInt("DataVersion", 500); } int currentDataVersion = currentTag.getInt("DataVersion"); - if(currentDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) { + int requiredMinimumDataVersion = SharedConstants.getCurrentVersion().getWorldVersion(); + if(currentDataVersion < requiredMinimumDataVersion) { /* Needs upgrade, try looking up from cache */ MessageDigest hasher = digestThreadLocal.get(); hasher.reset(); @@ -70,13 +71,13 @@ public class CachingStructureManager { CompoundTag cachedUpgraded = getCachedUpgraded(location, truncateHash(hash)); if(cachedUpgraded == null) cachedUpgraded = getCachedUpgraded(location, hash); /* pick up old cache */ - if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == SharedConstants.getCurrentVersion().getWorldVersion()) { + if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == requiredMinimumDataVersion) { ModernFix.LOGGER.debug("Using cached upgraded version of {}", location); currentTag = cachedUpgraded; } else { synchronized (laggyStructureMods) { if(laggyStructureMods.add(location.getNamespace())) { - ModernFix.LOGGER.warn("Mod {} is shipping outdated structure files, which can cause worldgen lag; please report this to them.", location.getNamespace()); + ModernFix.LOGGER.warn("The namespace {} contains an outdated structure file, which can cause worldgen lag. Please view debug.log for the full filename, determine which mod provides the structure, and report to the mod/datapack author, including the debug log.", location.getNamespace()); } } ModernFix.LOGGER.debug("Structure {} is being run through DFU (hash {}), this will cause launch time delays", location, hash); From 8c061ec0703a9358a664c6d5b1b64c48ad116403 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 30 May 2023 10:27:47 -0400 Subject: [PATCH 32/45] Support new REI version Related: #116 --- .../searchtree/REIBackedSearchTree.java | 69 +++++++++++++++++-- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/searchtree/REIBackedSearchTree.java b/common/src/main/java/org/embeddedt/modernfix/searchtree/REIBackedSearchTree.java index da92a2d0..fdd5f3d0 100644 --- a/common/src/main/java/org/embeddedt/modernfix/searchtree/REIBackedSearchTree.java +++ b/common/src/main/java/org/embeddedt/modernfix/searchtree/REIBackedSearchTree.java @@ -1,22 +1,28 @@ package org.embeddedt.modernfix.searchtree; +import com.google.common.base.Predicates; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.impl.client.search.AsyncSearchManager; +import me.shedaniel.rei.impl.common.entry.type.EntryRegistryImpl; +import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper; import net.minecraft.client.searchtree.ReloadableIdSearchTree; import net.minecraft.world.item.ItemStack; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; public class REIBackedSearchTree extends DummySearchTree { - private final AsyncSearchManager searchManager = new AsyncSearchManager(EntryRegistry.getInstance()::getPreFilteredList, () -> { - return stack -> true; - }, EntryStack::normalize); + private final AsyncSearchManager searchManager = createSearchManager(); private final boolean filteringByTag; private String lastSearchText = ""; @@ -39,14 +45,23 @@ public class REIBackedSearchTree extends DummySearchTree { if(!pSearchText.equals(lastSearchText)) { listCache.clear(); this.searchManager.updateFilter(pSearchText); - List> stacks; + List stacks; try { stacks = this.searchManager.getNow(); } catch(RuntimeException e) { ModernFix.LOGGER.error("Couldn't search for '" + pSearchText + "'", e); stacks = Collections.emptyList(); } - for(EntryStack stack : stacks) { + for(Object o : stacks) { + EntryStack stack; + if(o instanceof EntryStack) + stack = (EntryStack)o; + else if(o instanceof HashedEntryStackWrapper) { + stack = ((HashedEntryStackWrapper)o).unwrap(); + } else { + ModernFix.LOGGER.error("Don't know how to handle {}", o.getClass().getName()); + continue; + } if(stack.getType() == VanillaEntryTypes.ITEM) { listCache.add(stack.cheatsAs().getValue()); } @@ -56,6 +71,50 @@ public class REIBackedSearchTree extends DummySearchTree { return listCache; } + @SuppressWarnings({"unchecked", "rawtypes"}) + private static AsyncSearchManager createSearchManager() { + Method m, normalizeMethod; + try { + try { + m = EntryRegistryImpl.class.getDeclaredMethod("getPreFilteredComplexList"); + m.setAccessible(true); + normalizeMethod = HashedEntryStackWrapper.class.getDeclaredMethod("normalize"); + normalizeMethod.setAccessible(true); + } catch(NoSuchMethodException e) { + m = EntryRegistryImpl.class.getDeclaredMethod("getPreFilteredList"); + m.setAccessible(true); + normalizeMethod = EntryStack.class.getDeclaredMethod("normalize"); + normalizeMethod.setAccessible(true); + } + final MethodHandle getListMethod = MethodHandles.publicLookup().unreflect(m); + final MethodHandle normalize = MethodHandles.publicLookup().unreflect(normalizeMethod); + final EntryRegistryImpl registry = (EntryRegistryImpl)EntryRegistry.getInstance(); + Supplier stackListSupplier = () -> { + try { + return (List)getListMethod.invokeExact(registry); + } catch(Throwable e) { + if(e instanceof RuntimeException) + throw (RuntimeException)e; + throw new RuntimeException(e); + } + }; + UnaryOperator normalizeOperator = o -> { + try { + return normalize.invoke(o); + } catch(Throwable e) { + if(e instanceof RuntimeException) + throw (RuntimeException)e; + throw new RuntimeException(e); + } + }; + return new AsyncSearchManager(stackListSupplier, () -> { + return Predicates.alwaysTrue(); + }, normalizeOperator); + } catch(ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + public static final SearchTreeProviderRegistry.Provider PROVIDER = new SearchTreeProviderRegistry.Provider() { @Override public ReloadableIdSearchTree getSearchTree(boolean tag) { From 76485b0cbaa505daaa5acfe5bdfaa05a60d49a5e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 30 May 2023 10:43:08 -0400 Subject: [PATCH 33/45] Fix Skyblock Builder crash Related: #117 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 2 +- 1 file changed, 1 insertion(+), 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 ca7e9333..0be68db5 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 @@ -183,7 +183,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.perf.thread_priorities", "smoothboot"); disableIfModPresent("mixin.perf.boost_worker_count", "smoothboot"); disableIfModPresent("mixin.perf.async_jei", "modernui"); - disableIfModPresent("mixin.perf.compress_biome_container", "chocolate", "betterendforge"); + disableIfModPresent("mixin.perf.compress_biome_container", "chocolate", "betterendforge" ,"skyblockbuilder"); disableIfModPresent("mixin.bugfix.mc218112", "performant"); disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); From 830eb19420931a2c550bde61e4523e7895c3f676 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Tue, 30 May 2023 11:18:27 -0400 Subject: [PATCH 34/45] Hopefully final fix for the 1.19.4 "missing model" bug on Fabric --- .../ModelBakerImplMixin.java | 35 ++++++++++--------- .../dynamic_resources/ModelBakeryMixin.java | 6 +--- 2 files changed, 20 insertions(+), 21 deletions(-) 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 22f450e6..c7cc45fb 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 @@ -76,23 +76,26 @@ public abstract class ModelBakerImplMixin { ModernFix.LOGGER.info("Baking {}", arg); IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571; if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) { - /* to emulate vanilla model loading, treat as top-level */ - Optional blockOpt = Objects.equals(((ModelResourceLocation)arg).getVariant(), "inventory") ? Optional.empty() : BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(arg.getNamespace(), arg.getPath())); - if(blockOpt.isPresent()) { - /* load via lambda for mods that expect blockstate to get loaded */ - for(BlockState state : extendedBakery.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), (ModelResourceLocation)arg)) { - try { - blockStateLoaderHandle.invokeExact(this.field_40571, state); - } catch(Throwable e) { - ModernFix.LOGGER.error("Error loading model", e); + // synchronized because we use topLevelModels + synchronized (this.field_40571) { + /* to emulate vanilla model loading, treat as top-level */ + Optional blockOpt = Objects.equals(((ModelResourceLocation)arg).getVariant(), "inventory") ? Optional.empty() : BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(arg.getNamespace(), arg.getPath())); + if(blockOpt.isPresent()) { + /* load via lambda for mods that expect blockstate to get loaded */ + for(BlockState state : extendedBakery.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), (ModelResourceLocation)arg)) { + try { + blockStateLoaderHandle.invokeExact(this.field_40571, state); + } catch(Throwable e) { + ModernFix.LOGGER.error("Error loading model", e); + } } + } else { + this.field_40571.loadTopLevel((ModelResourceLocation)arg); } - } else { - this.field_40571.loadTopLevel((ModelResourceLocation)arg); + cir.setReturnValue(this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel())); + // avoid leaks + this.field_40571.topLevelModels.clear(); } - cir.setReturnValue(this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel())); - // avoid leaks - this.field_40571.topLevelModels.clear(); } else cir.setReturnValue(this.field_40571.getModel(arg)); UnbakedModel toReplace = cir.getReturnValue(); @@ -106,14 +109,14 @@ public abstract class ModelBakerImplMixin { } } cir.setReturnValue(toReplace); + cir.getReturnValue().resolveParents(this.field_40571::getModel); + capturedModel = cir.getReturnValue(); if(cir.getReturnValue() == extendedBakery.mfix$getUnbakedMissingModel()) { if(arg != ModelBakery.MISSING_MODEL_LOCATION && debugDynamicModelLoading) ModernFix.LOGGER.warn("Model {} not present", arg); wasMissingModel = true; } else wasMissingModel = false; /* sometimes this runs more than once e.g. for recursive model baking */ - cir.getReturnValue().resolveParents(this.field_40571::getModel); - capturedModel = cir.getReturnValue(); } @ModifyVariable(method = "bake", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/resources/model/UnbakedModel;bake(Lnet/minecraft/client/resources/model/ModelBaker;Ljava/util/function/Function;Lnet/minecraft/client/resources/model/ModelState;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/resources/model/BakedModel;")) 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 f19e1863..36ef4dda 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 @@ -110,11 +110,6 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache); } - @Inject(method = "", at = @At("RETURN")) - private void stopIgnore(CallbackInfo ci) { - this.ignoreModelLoad = false; - } - private void onModelRemoved(RemovalNotification notification) { if(!debugDynamicModelLoading) return; @@ -174,6 +169,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @Inject(method = "bakeModels", at = @At("HEAD")) private void captureGetter(BiFunction getter, CallbackInfo ci) { + this.ignoreModelLoad = false; textureGetter = getter; } From b15537a32f7b3bc6bab4ddf99991d9bf2955a1d8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 31 May 2023 09:37:34 -0400 Subject: [PATCH 35/45] Make CanonizingStringMap not crash on null keys/values --- .../org/embeddedt/modernfix/util/CanonizingStringMap.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java index 05bd219b..1202500b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java +++ b/common/src/main/java/org/embeddedt/modernfix/util/CanonizingStringMap.java @@ -141,6 +141,7 @@ public class CanonizingStringMap implements Map { } public static CanonizingStringMap deepCopy(CanonizingStringMap inputMap, Function deepCopier) { + Objects.requireNonNull(deepCopier); Object2ObjectMap copiedBackingMap; int size = inputMap.backingMap.size(); if(size > GROWTH_THRESHOLD) { @@ -148,7 +149,8 @@ public class CanonizingStringMap implements Map { } else copiedBackingMap = new Object2ObjectArrayMap<>(size); inputMap.backingMap.object2ObjectEntrySet().forEach(entry -> { - copiedBackingMap.put(entry.getKey(), deepCopier.apply(entry.getValue())); + if(entry.getKey() != null && entry.getValue() != null) + copiedBackingMap.put(entry.getKey(), deepCopier.apply(entry.getValue())); }); return new CanonizingStringMap<>(copiedBackingMap); } From 1a7d5b3436d7a01edb92f113576672e0bee44e46 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 1 Jun 2023 19:39:21 -0400 Subject: [PATCH 36/45] Decommission the chunk saving fix Does not actually fix the issue, sadly --- .../ChunkManagerMixin.java | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/edge_chunk_not_saved/ChunkManagerMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/edge_chunk_not_saved/ChunkManagerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/edge_chunk_not_saved/ChunkManagerMixin.java deleted file mode 100644 index eff09266..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/edge_chunk_not_saved/ChunkManagerMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.edge_chunk_not_saved; - -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.ImposterProtoChunk; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; - -import java.util.function.Predicate; - -/* https://github.com/SuperCoder7979/chunksavingfix-fabric/blob/main/src/main/java/supercoder79/chunksavingfix/mixin/MixinThreadedAnvilChunkStorage.java */ -@Mixin(ChunkMap.class) -public class ChunkManagerMixin { - // TODO: hits both at the moment- check and re-evaluate - @ModifyArg(method = "saveAllChunks(Z)V", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 0), require = 0) - private Predicate alwaysAccessibleFlush(Predicate chunkHolder) { - return c -> true; - } - @ModifyArg(method = "saveAllChunks(Z)V", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 1), require = 0) - private Predicate allowProtoChunkFlush(Predicate chunk) { - return c -> c instanceof ProtoChunk || c instanceof ImposterProtoChunk || c instanceof LevelChunk; - } - - @ModifyArg(method = "saveAllChunks(Z)V", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 3), require = 0) - private Predicate alwaysAccessible(Predicate chunkHolder) { - return c -> true; - } -} From 4b73d699e41fe6289aca1283137a2f6be20c5659 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 1 Jun 2023 19:45:19 -0400 Subject: [PATCH 37/45] Disable packet leak fix when MemoryLeakFix is present on Fabric --- .../modernfix/core/config/ModernFixEarlyConfig.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 0be68db5..543cb6b6 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 @@ -59,6 +59,8 @@ public class ModernFixEarlyConfig { private final Set mixinOptions = new ObjectOpenHashSet<>(); private final Map mixinsMissingMods = new Object2ObjectOpenHashMap<>(); + public static boolean isFabric = false; + public Map getPermanentlyDisabledMixins() { return mixinsMissingMods; } @@ -71,6 +73,8 @@ public class ModernFixEarlyConfig { if(stream == null) continue; try(Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { + if(configFile.contains("fabric")) + isFabric = true; JsonObject configObject = (JsonObject)new JsonParser().parse(reader); JsonArray mixinList = configObject.getAsJsonArray("mixins"); String packageName = configObject.get("package").getAsString().replace('.', '/'); @@ -192,6 +196,9 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine", "changed"); + if(isFabric) { + disableIfModPresent("mixin.bugfix.packet_leak", "memoryleakfix"); + } } private void disableIfModPresent(String configName, String... ids) { From c8bce3e015574dab49402e12b0dd21d0e8e19144 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 1 Jun 2023 19:54:18 -0400 Subject: [PATCH 38/45] Disable bugfix.chunk_deadlock for DimThread Related: #118 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 2 ++ 1 file changed, 2 insertions(+) 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 543cb6b6..0f2e2b8c 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 @@ -191,6 +191,8 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.bugfix.mc218112", "performant"); disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); + // DimThread makes changes to the server chunk manager (understandably), C2ME probably does the same + disableIfModPresent("mixin.bugfix.chunk_deadlock", "c2me", "dimthread"); disableIfModPresent("mixin.perf.reuse_datapacks", "tac"); disableIfModPresent("mixin.launch.class_search_cache", "optifine"); disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine"); From 39e1ac0896cd97fda8be36dac3e4e41ede42d248 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 1 Jun 2023 21:11:54 -0400 Subject: [PATCH 39/45] Simplify item rendering optimization Now uses a wrapped item model instead of actually modifying the rendering code, to avoid disabling Sodium's optimization --- .../ItemRendererMixin.java | 72 +++----------- .../modernfix/render/SimpleItemModelView.java | 94 +++++++++++++++++++ 2 files changed, 106 insertions(+), 60 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java 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 9f936496..4ca3ff51 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 @@ -2,55 +2,33 @@ package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.color.item.ItemColors; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemTransform; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.SimpleBakedModel; -import net.minecraft.core.Direction; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import org.embeddedt.modernfix.render.FastItemRenderType; import org.embeddedt.modernfix.render.RenderState; -import org.spongepowered.asm.mixin.Final; +import org.embeddedt.modernfix.render.SimpleItemModelView; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.List; -import java.util.Random; - -@Mixin(ItemRenderer.class) +@Mixin(value = ItemRenderer.class, priority = 600) public abstract class ItemRendererMixin { - @Shadow @Final private ItemColors itemColors; - - private final Random dummyRandom = new Random(); - - private static final float[] COLOR_MULTIPLIER = new float[]{1.0F, 1.0F, 1.0F, 1.0F}; - private ItemTransforms.TransformType transformType; + private final SimpleItemModelView modelView = new SimpleItemModelView(); @Inject(method = "render", at = @At("HEAD")) private void markRenderingType(ItemStack itemStack, ItemTransforms.TransformType transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model, CallbackInfo ci) { this.transformType = transformType; } - private static final Direction[] ITEM_DIRECTIONS = new Direction[] { Direction.SOUTH }; - private static final Direction[] BLOCK_DIRECTIONS = new Direction[] { Direction.UP, Direction.EAST, Direction.NORTH }; - - private boolean isCorrectDirectionForType(FastItemRenderType type, Direction direction) { - if(type == FastItemRenderType.SIMPLE_ITEM) - return direction == Direction.SOUTH; - else { - return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH; - } - } - /** * If a model * - is a vanilla item model (SimpleBakedModel), @@ -59,8 +37,8 @@ public abstract class ItemRendererMixin { * we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the * camera). */ - @Inject(method = "renderModelLists", at = @At("HEAD"), cancellable = true) - private void fasterItemRender(BakedModel model, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer, CallbackInfo ci) { + @ModifyVariable(method = "renderModelLists", at = @At("HEAD"), index = 1, argsOnly = true) + private BakedModel useSimpleWrappedItemModel(BakedModel model, BakedModel arg, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer) { if(!RenderState.IS_RENDERING_LEVEL && !stack.isEmpty() && model.getClass() == SimpleBakedModel.class && transformType == ItemTransforms.TransformType.GUI) { FastItemRenderType type; ItemTransform transform = model.getTransforms().gui; @@ -69,26 +47,12 @@ public abstract class ItemRendererMixin { else if(stack.getItem() instanceof BlockItem && isBlockTransforms(transform)) type = FastItemRenderType.SIMPLE_BLOCK; else - return; - ci.cancel(); - PoseStack.Pose pose = matrixStack.last(); - int[] combinedLights = new int[] {combinedLight, combinedLight, combinedLight, combinedLight}; - Direction[] directions = type == FastItemRenderType.SIMPLE_ITEM ? ITEM_DIRECTIONS : BLOCK_DIRECTIONS; - for(Direction direction : directions) { - List culledFaces = model.getQuads(null, direction, dummyRandom); - /* check size to avoid instantiating iterator when the list is empty */ - if(culledFaces.size() > 0) { - for(BakedQuad quad : culledFaces) { - render2dItemFace(quad, stack, buffer, pose, combinedLights, combinedOverlay); - } - } - } - List unculledFaces = model.getQuads(null, null, dummyRandom); - for(BakedQuad quad : unculledFaces) { - if(isCorrectDirectionForType(type, quad.getDirection())) - render2dItemFace(quad, stack, buffer, pose, combinedLights, combinedOverlay); - } - } + return model; + modelView.setItem(model); + modelView.setType(type); + return modelView; + } else + return model; } private boolean isBlockTransforms(ItemTransform transform) { @@ -96,16 +60,4 @@ public abstract class ItemRendererMixin { && transform.rotation.y() == 225f && transform.rotation.z() == 0f; } - - private void render2dItemFace(BakedQuad quad, ItemStack stack, VertexConsumer buffer, PoseStack.Pose pose, int[] combinedLights, int combinedOverlay) { - int i = -1; - if (quad.isTinted()) { - i = this.itemColors.getColor(stack, quad.getTintIndex()); - } - - float f = (float)(i >> 16 & 255) / 255.0F; - float f1 = (float)(i >> 8 & 255) / 255.0F; - float f2 = (float)(i & 255) / 255.0F; - buffer.putBulkData(pose, quad, COLOR_MULTIPLIER, f, f1, f2, combinedLights, combinedOverlay, true); - } } diff --git a/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java b/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java new file mode 100644 index 00000000..0b745c3f --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java @@ -0,0 +1,94 @@ +package org.embeddedt.modernfix.render; + +import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Random; + +/** + * Wrapper class that presents a fake view of item models (only showing the simple front-facing quads), rather + * than every quad. + */ +public class SimpleItemModelView implements BakedModel { + private BakedModel wrappedItem; + private FastItemRenderType type; + + public void setItem(BakedModel model) { + this.wrappedItem = model; + } + + public void setType(FastItemRenderType type) { + this.type = type; + } + + private boolean isCorrectDirectionForType(Direction direction) { + if(type == FastItemRenderType.SIMPLE_ITEM) + return direction == Direction.SOUTH; + else { + return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH; + } + } + + private final List nullQuadList = new ObjectArrayList<>(); + + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { + if(side != null) { + return isCorrectDirectionForType(side) ? wrappedItem.getQuads(state, side, rand) : ImmutableList.of(); + } else { + nullQuadList.clear(); + List realList = wrappedItem.getQuads(state, null, rand); + for(int i = 0; i < realList.size(); i++) { + BakedQuad quad = realList.get(i); + if(isCorrectDirectionForType(quad.getDirection())) { + nullQuadList.add(quad); + } + } + return nullQuadList; + } + } + + @Override + public boolean useAmbientOcclusion() { + return wrappedItem.useAmbientOcclusion(); + } + + @Override + public boolean isGui3d() { + return wrappedItem.isGui3d(); + } + + @Override + public boolean usesBlockLight() { + return wrappedItem.usesBlockLight(); + } + + @Override + public boolean isCustomRenderer() { + return wrappedItem.isCustomRenderer(); + } + + @Override + public TextureAtlasSprite getParticleIcon() { + return wrappedItem.getParticleIcon(); + } + + @Override + public ItemTransforms getTransforms() { + return wrappedItem.getTransforms(); + } + + @Override + public ItemOverrides getOverrides() { + return wrappedItem.getOverrides(); + } +} From db223b62a088161d2f9858ce63cebbd5d50c01d3 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:06:34 -0400 Subject: [PATCH 40/45] Advancement recursion speedup on Forge, based off Advancements Debug --- .../PlayerAdvancementsMixin.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/faster_advancements/PlayerAdvancementsMixin.java diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/faster_advancements/PlayerAdvancementsMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/faster_advancements/PlayerAdvancementsMixin.java new file mode 100644 index 00000000..a4ba971e --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/faster_advancements/PlayerAdvancementsMixin.java @@ -0,0 +1,65 @@ +package org.embeddedt.modernfix.forge.mixin.perf.faster_advancements; + +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementProgress; +import net.minecraft.server.PlayerAdvancements; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.Set; + +@Mixin(PlayerAdvancements.class) +public abstract class PlayerAdvancementsMixin { + + @Shadow protected abstract boolean shouldBeVisible(Advancement advancement); + + @Shadow @Final private Set visible; + + @Shadow @Final private Set visibilityChanged; + + @Shadow @Final private Map advancements; + + @Shadow @Final private Set progressChanged; + + /** + * Avoids checking the same advancement many times. + */ + private void ensureVisibilityDfs(Advancement advancement, Set visited) { + if(visited.add(advancement)) { + boolean bl = this.shouldBeVisible(advancement); + boolean bl2 = this.visible.contains(advancement); + if (bl && !bl2) { + this.visible.add(advancement); + this.visibilityChanged.add(advancement); + if (this.advancements.containsKey(advancement)) { + this.progressChanged.add(advancement); + } + } else if (!bl && bl2) { + this.visible.remove(advancement); + this.visibilityChanged.add(advancement); + } + + for(Advancement child : advancement.getChildren()) { + ensureVisibilityDfs(child, visited); + } + + Advancement parent = advancement.getParent(); + if (bl != bl2 && parent != null) { + ensureVisibilityDfs(parent, visited); + } + } + } + + /** + * @author embeddedt + * @reason avoid checking the same advancement many times + */ + @Overwrite + private void ensureVisibility(Advancement advancement) { + ensureVisibilityDfs(advancement, new ReferenceOpenHashSet<>()); + } +} From a635671276044d8432020af6831d0188c53de9cd Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 2 Jun 2023 20:17:13 -0400 Subject: [PATCH 41/45] This will likely be the last ever 1.19.4 release --- .../mixin/perf/faster_item_rendering/ItemRendererMixin.java | 1 - 1 file changed, 1 deletion(-) 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 7d20362c..2326798b 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 @@ -7,7 +7,6 @@ import net.minecraft.client.renderer.block.model.ItemTransform; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.SimpleBakedModel; -import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; From 941331f90a59b724534e4773eac5209b92c2a444 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 3 Jun 2023 11:26:44 -0400 Subject: [PATCH 42/45] Compatibility improvements for mixin.perf.nbt_memory_usage Related: #119 --- .../nbt_memory_usage/CompoundTag1Mixin.java | 20 +++++++++++++++++++ .../nbt_memory_usage/CompoundTagMixin.java | 3 ++- .../core/config/ModernFixEarlyConfig.java | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTag1Mixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTag1Mixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTag1Mixin.java new file mode 100644 index 00000000..8034f856 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTag1Mixin.java @@ -0,0 +1,20 @@ +package org.embeddedt.modernfix.common.mixin.perf.nbt_memory_usage; + +import net.minecraft.nbt.Tag; +import org.embeddedt.modernfix.util.CanonizingStringMap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.util.Map; + +@Mixin(targets = "net/minecraft/nbt/CompoundTag$1") +public class CompoundTag1Mixin { + @ModifyVariable(method = "load(Ljava/io/DataInput;ILnet/minecraft/nbt/NbtAccounter;)Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE_ASSIGN", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;", remap = false)) + private Map modifyMap(Map map) { + CanonizingStringMap newMap = new CanonizingStringMap<>(); + if(map != null) + newMap.putAll(map); + return newMap; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java index 7b20e23d..30ee5d6f 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/nbt_memory_usage/CompoundTagMixin.java @@ -22,7 +22,8 @@ public class CompoundTagMixin { @ModifyArg(method = "()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;(Ljava/util/Map;)V"), index = 0) private static Map useCanonizingStringMap(Map incoming) { CanonizingStringMap newMap = new CanonizingStringMap<>(); - newMap.putAll(incoming); + if(incoming != null) + newMap.putAll(incoming); return newMap; } 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 0f2e2b8c..befc9a5b 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 @@ -191,6 +191,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.bugfix.mc218112", "performant"); disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); + disableIfModPresent("mixin.perf.nbt_memory_usage", "c2me"); // DimThread makes changes to the server chunk manager (understandably), C2ME probably does the same disableIfModPresent("mixin.bugfix.chunk_deadlock", "c2me", "dimthread"); disableIfModPresent("mixin.perf.reuse_datapacks", "tac"); From 41c2bb733e42f8448f2724ce3a653769da4ea6dd Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 3 Jun 2023 20:01:19 -0400 Subject: [PATCH 43/45] Add name change easter egg when running on snapshots --- common/src/main/java/org/embeddedt/modernfix/ModernFix.java | 5 +++++ .../main/java/org/embeddedt/modernfix/ModernFixClient.java | 2 +- .../modernfix/core/config/ModernFixEarlyConfig.java | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java index 4e6e89d1..73dd1ac1 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix; +import net.minecraft.SharedConstants; import net.minecraft.Util; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; @@ -24,6 +25,8 @@ public class ModernFix { public static final String MODID = "modernfix"; + public static String NAME = "ModernFix"; + public static ModernFix INSTANCE; // Used to skip computing the blockstate caches twice @@ -46,6 +49,8 @@ public class ModernFix { public ModernFix() { INSTANCE = this; + if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.snapshot_easter_egg.NameChange") && !SharedConstants.getCurrentVersion().isStable()) + NAME = "PreemptiveFix"; ModernFixPlatformHooks.onServerCommandRegister(ModernFixCommands::register); if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spam_thread_dump.ThreadDumper")) { Thread t = new Thread() { diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java index be5fd14a..1c1c74dc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFixClient.java @@ -41,7 +41,7 @@ public class ModernFixClient { // clear reserve as it's not needed Minecraft.reserve = new byte[0]; if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) { - brandingString = "ModernFix " + ModernFixPlatformHooks.getVersionString(); + brandingString = ModernFix.NAME + " " + ModernFixPlatformHooks.getVersionString(); } for(String className : ModernFixPlatformHooks.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) { try { 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 befc9a5b..a9540db6 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 @@ -152,6 +152,7 @@ public class ModernFixEarlyConfig { .put("mixin.feature.integrated_server_watchdog", true) .put("mixin.perf.faster_item_rendering", false) .put("mixin.feature.spam_thread_dump", false) + .put("mixin.feature.snapshot_easter_egg", true) .put("mixin.perf.blast_search_trees", shouldReplaceSearchTrees) .put("mixin.devenv", isDevEnv) .put("mixin.perf.remove_spawn_chunks", isDevEnv) From 54759008e5ddcc3bdeb1bb619cdabcc4734c0b4b Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sat, 3 Jun 2023 20:01:34 -0400 Subject: [PATCH 44/45] Allow Fabric version to run on >=1.16.2 --- fabric/src/main/resources/fabric.mod.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 40277be7..57145e29 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -33,7 +33,7 @@ "fabric-screen-api-v1": "*", "fabric-command-api-v1": "*", "fabric-models-v0": "*", - "minecraft": ">=1.16.5" + "minecraft": ">=1.16.2" }, "breaks": { "dashloader": "*" From b430b670524793d15bc47475a9b4b44a05e983be Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 5 Jun 2023 19:43:25 -0400 Subject: [PATCH 45/45] Return missing model for null BlockState --- .../perf/dynamic_resources/BlockModelShaperMixin.java | 8 +++++++- .../modernfix/dynamicresources/ModelLocationCache.java | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java index c5c70db9..3f737e53 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java @@ -3,6 +3,7 @@ package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; import net.minecraft.client.renderer.block.BlockModelShaper; 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.level.block.state.BlockState; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; @@ -37,9 +38,14 @@ public class BlockModelShaperMixin { public void rebuildCache() { } + /** + * @author embeddedt + * @reason get the model from the dynamic model provider + */ @Overwrite public BakedModel getBlockModel(BlockState state) { - BakedModel model = modelManager.getModel(ModelLocationCache.get(state)); + ModelResourceLocation mrl = ModelLocationCache.get(state); + BakedModel model = mrl == null ? null : modelManager.getModel(mrl); if (model == null) { model = modelManager.getMissingModel(); } diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java index 7370d58a..2d737bbd 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java @@ -31,6 +31,8 @@ public class ModelLocationCache { }); public static ModelResourceLocation get(BlockState state) { + if(state == null) + return null; try { return blockLocationCache.get(state); } catch(ExecutionException e) { @@ -39,6 +41,8 @@ public class ModelLocationCache { } public static ModelResourceLocation get(Item item) { + if(item == null) + return null; try { return itemLocationCache.get(item); } catch(ExecutionException e) {