diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/supermartijncore/ModelBakerImplMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakerImplMixin.java similarity index 97% rename from src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/supermartijncore/ModelBakerImplMixin.java rename to src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakerImplMixin.java index c14a1158..305f3ba2 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/supermartijncore/ModelBakerImplMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakerImplMixin.java @@ -1,4 +1,4 @@ -package org.embeddedt.modernfix.mixin.perf.dynamic_resources.supermartijncore; +package org.embeddedt.modernfix.mixin.perf.dynamic_resources; import com.mojang.math.Transformation; import net.minecraft.client.renderer.block.model.BlockModel; diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java index fefd9717..827655ab 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -1,47 +1,27 @@ package org.embeddedt.modernfix.mixin.perf.dynamic_resources; import com.google.common.base.Splitter; -import com.google.common.base.Stopwatch; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.RemovalNotification; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.gson.*; -import com.mojang.datafixers.util.Pair; import com.mojang.math.Transformation; -import net.minecraft.Util; -import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.ItemModelGenerator; -import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; 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.ExtendedBlockModelDeserializer; import net.minecraftforge.client.model.geometry.GeometryLoaderManager; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.ModLoader; -import net.minecraftforge.registries.ForgeRegistries; import org.apache.commons.lang3.tuple.Triple; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.duck.IDynamicModelBakery; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; -import org.embeddedt.modernfix.dynamicresources.DynamicModelBakeEvent; -import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; -import org.embeddedt.modernfix.dynamicresources.ResourcePackHandler; -import org.embeddedt.modernfix.mixin.perf.dynamic_resources.supermartijncore.ModelBakerImplMixin; import org.slf4j.Logger; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; @@ -52,17 +32,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import javax.annotation.Nullable; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; /* high priority so that our injectors are added before other mods' */ @Mixin(value = ModelBakery.class, priority = 600) @@ -76,9 +49,6 @@ public abstract class ModelBakeryMixin implements IDynamicModelBakery { @Shadow protected abstract BlockModel loadBlockModel(ResourceLocation location) throws IOException; - @Shadow @Final protected static Set UNREFERENCED_TEXTURES; - @Shadow @Final protected ResourceManager resourceManager; - @Shadow @Nullable private AtlasSet atlasSet; @Shadow @Final private Set loadingStack; @Shadow protected abstract void loadModel(ResourceLocation blockstateLocation) throws Exception; @@ -96,23 +66,14 @@ public abstract class ModelBakeryMixin implements IDynamicModelBakery { @Shadow @Final @Mutable private Map bakedCache; - @Shadow @Final public static BlockModel GENERATION_MARKER; - - @Shadow @Final private static ItemModelGenerator ITEM_MODEL_GENERATOR; - - @Shadow @Final public static BlockModel BLOCK_ENTITY_MARKER; - - @Shadow public abstract UnbakedModel getModel(ResourceLocation modelLocation); - private Cache loadedBakedModels; private Cache loadedModels; private HashMap smallLoadingCache = new HashMap<>(); - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/model/geometry/GeometryLoaderManager;init()V", remap = false)) - private void replaceTopLevelBakedModels() { - GeometryLoaderManager.init(); + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;push(Ljava/lang/String;)V", ordinal = 0)) + private void replaceTopLevelBakedModels(ProfilerFiller profiler, String arg) { this.loadedBakedModels = CacheBuilder.newBuilder() .expireAfterAccess(3, TimeUnit.MINUTES) .maximumSize(1000) @@ -130,6 +91,7 @@ public abstract class ModelBakeryMixin implements IDynamicModelBakery { this.bakedCache = loadedBakedModels.asMap(); this.unbakedCache = loadedModels.asMap(); this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache); + profiler.push(arg); } private void onModelRemoved(RemovalNotification notification) { diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelManagerMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelManagerMixin.java index 30022fee..7fe27361 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelManagerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelManagerMixin.java @@ -1,30 +1,65 @@ package org.embeddedt.modernfix.mixin.perf.dynamic_resources; +import com.google.common.collect.ImmutableList; import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.util.LambdaMap; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.io.IOException; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.stream.Collectors; @Mixin(ModelManager.class) public class ModelManagerMixin { - @Inject(method = "loadBlockModels", at = @At("HEAD"), cancellable = true) - private static void deferBlockModelLoad(ResourceManager manager, Executor executor, CallbackInfoReturnable>> cir) { - cir.setReturnValue(CompletableFuture.completedFuture(new HashMap<>())); + @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockModels(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture> deferBlockModelLoad(ResourceManager manager, Executor executor) { + return CompletableFuture.completedFuture(new LambdaMap<>(location -> loadSingleBlockModel(manager, location))); } - @Inject(method = "loadBlockStates", at = @At("HEAD"), cancellable = true) - private static void deferBlockStateLoad(ResourceManager manager, Executor executor, CallbackInfoReturnable>>> cir) { - cir.setReturnValue(CompletableFuture.completedFuture(new HashMap<>())); + @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockStates(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture>> deferBlockStateLoad(ResourceManager manager, Executor executor) { + return CompletableFuture.completedFuture(new LambdaMap<>(location -> loadSingleBlockState(manager, location))); + } + + @Redirect(method = "loadModels", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;")) + private ImmutableList skipCollection(StateDefinition definition) { + return ImmutableList.of(); + } + + private BlockModel loadSingleBlockModel(ResourceManager manager, ResourceLocation location) { + return manager.getResource(location).map(resource -> { + try { + return BlockModel.fromStream(resource.openAsReader()); + } catch(IOException e) { + ModernFix.LOGGER.error("Couldn't load model", e); + return null; + } + }).orElse(null); + } + + private List loadSingleBlockState(ResourceManager manager, ResourceLocation location) { + return manager.getResourceStack(location).stream().map(resource -> { + try { + return new ModelBakery.LoadedJson(resource.sourcePackId(), GsonHelper.parse(resource.openAsReader())); + } catch(IOException e) { + ModernFix.LOGGER.error("Couldn't load blockstate", e); + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toList()); } } diff --git a/src/main/java/org/embeddedt/modernfix/util/LambdaMap.java b/src/main/java/org/embeddedt/modernfix/util/LambdaMap.java new file mode 100644 index 00000000..ba93d7c7 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/util/LambdaMap.java @@ -0,0 +1,82 @@ +package org.embeddedt.modernfix.util; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +public class LambdaMap implements Map { + private final Function mapSupplier; + + public LambdaMap(Function supplier) { + this.mapSupplier = supplier; + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object o) { + return true; + } + + @Override + public boolean containsValue(Object o) { + return true; + } + + @Override + public V get(Object o) { + return this.mapSupplier.apply((K)o); + } + + @Nullable + @Override + public V put(K k, V v) { + throw new UnsupportedOperationException(); + } + + @Override + public V remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(@NotNull Map map) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + + } + + @NotNull + @Override + public Set keySet() { + return Collections.emptySet(); + } + + @NotNull + @Override + public Collection values() { + return Collections.emptyList(); + } + + @NotNull + @Override + public Set> entrySet() { + return Collections.emptySet(); + } +} diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index d05ad324..f1387d17 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -40,7 +40,9 @@ "bugfix.concurrency.MinecraftMixin", "perf.dynamic_resources.BlockModelShaperMixin", "perf.dynamic_resources.ItemModelShaperMixin", + "perf.dynamic_resources.ModelBakerImplMixin", "perf.dynamic_resources.ModelBakeryMixin", + "perf.dynamic_resources.ModelManagerMixin", "perf.dynamic_resources.ctm.TextureMetadataHandlerMixin", "perf.dynamic_resources.ctm.CTMPackReloadListenerMixin", "perf.dynamic_resources.supermartijncore.ClientRegistrationHandlerMixin",