diff --git a/common/build.gradle b/common/build.gradle index b8c30714..b470fc68 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -21,7 +21,11 @@ dependencies { modCompileOnly "curse.maven:spark-361579:${rootProject.spark_version}" - modCompileOnly fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version) + try { + modCompileOnly fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version) + } catch(ignored) { + println "Model Loading API not found for this Minecraft version!" + } // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury:${rootProject.architectury_version}" } 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 d6310537..3d49ff1c 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 @@ -1,11 +1,5 @@ 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.ModelResourceLocation; -import net.minecraft.client.resources.model.ModelState; -import net.minecraft.client.resources.model.UnbakedModel; - /** * 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. @@ -19,19 +13,4 @@ public interface ModernFixClientIntegration { */ default void onDynamicResourcesStatusChange(boolean enabled) { } - - /** - * 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 - * @param textureGetter function to retrieve textures for this model - * @return the model which should actually be loaded for this resource location - */ - default BakedModel onBakedModelLoad(ModelResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery, ModelBakery.TextureGetter textureGetter) { - 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 deleted file mode 100644 index 32ae00b2..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.embeddedt.modernfix.api.helpers; - -import com.google.common.collect.ImmutableList; -import net.minecraft.client.resources.model.*; -import net.minecraft.core.registries.BuiltInRegistries; -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 = BuiltInRegistries.BLOCK.getOptional(location.id()); - 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<>(ResourceLocation.class, location -> modelGetter.apply(location, BlockModelRotation.X0_Y0)); - } - - /** - * Provides a ModelBaker for mods to use. - * @param bakery the ModelBakery supplied to your integration - * @return an appropriate ModelBaker - */ - public static ModelBaker adaptBakery(ModelBakery bakery) { - throw new UnsupportedOperationException("TODO"); - /* - return new ModelBaker() { - @Override - public UnbakedModel getModel(ResourceLocation resourceLocation) { - return bakery.getModel(resourceLocation); - } - - @Nullable - @Override - public BakedModel bake(ResourceLocation resourceLocation, ModelState modelState) { - return ((IExtendedModelBakery)bakery).bakeDefault(resourceLocation, modelState); - } - }; - - */ - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java index 3893b9f3..95198cf5 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java @@ -47,8 +47,7 @@ public abstract class ServerLevelMixin extends Level implements IServerLevel { @Inject(method = "", at = @At("TAIL")) private void ensureGeneration(CallbackInfo ci) { mfix$strongholdCache = this.getDataStorage().computeIfAbsent( - StrongholdLocationCache.factory((ServerLevel)(Object)this), - StrongholdLocationCache.getFileId(this.dimensionTypeRegistration())); + StrongholdLocationCache.TYPE); this.chunkSource.getGeneratorState().ensureStructuresGenerated(); } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java index 09532efc..8d9952cb 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java @@ -16,6 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; /** * Most wall blocks use the default set of vanilla properties, and the default sizes for their shapes. This means @@ -31,36 +32,5 @@ public abstract class WallBlockMixin extends Block { super(properties); } - @Inject(method = "makeShapes", at = @At("HEAD"), cancellable = true) - private synchronized void useCachedShapeMap(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable> cir) { - ImmutableList key = ImmutableList.of(f1, f2, f3, f4, f5, f6); - Pair, Comparable>, VoxelShape>, StateDefinition> cache = CACHE_BY_SHAPE_VALS.get(key); - // require the properties to be identical - if(cache == null || !cache.getSecond().getProperties().equals(this.stateDefinition.getProperties())) - return; - ImmutableMap.Builder builder = ImmutableMap.builder(); - for(BlockState state : this.stateDefinition.getPossibleStates()) { - VoxelShape shape = cache.getFirst().get(state.getValues()); - if(shape == null) - return; // fallback to vanilla logic - builder.put(state, shape); - } - cir.setReturnValue(builder.build()); - } - - @Inject(method = "makeShapes", at = @At("RETURN")) - private synchronized void storeCachedShapesByProperty(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable> cir) { - // never populate cache as a non-vanilla block - if((Class)this.getClass() != WallBlock.class) - return; - ImmutableList key = ImmutableList.of(f1, f2, f3, f4, f5, f6); - if(!CACHE_BY_SHAPE_VALS.containsKey(key)) { - Map, Comparable>, VoxelShape> cacheByProperties = new HashMap<>(); - Map shapeMap = cir.getReturnValue(); - for(Map.Entry entry : shapeMap.entrySet()) { - cacheByProperties.put(entry.getKey().getValues(), entry.getValue()); - } - CACHE_BY_SHAPE_VALS.put(key, Pair.of(cacheByProperties, this.stateDefinition)); - } - } + // TODO reimplement for 1.21.5 } 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 deleted file mode 100644 index 609e8fc7..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java +++ /dev/null @@ -1,75 +0,0 @@ -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.core.registries.BuiltInRegistries; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IModelHoldingBlockState; -import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; -import org.embeddedt.modernfix.util.DynamicOverridableMap; -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.callback.CallbackInfo; - -import java.util.Map; - -@Mixin(BlockModelShaper.class) -@ClientOnlyMixin -public class BlockModelShaperMixin { - @Shadow @Final private ModelManager modelManager; - - @Shadow - private Map modelByStateCache; - - @Inject(method = { "", "replaceCache" }, at = @At("RETURN")) - private void replaceModelMap(CallbackInfo ci) { - // replace the backing map for mods which will access it - this.modelByStateCache = new DynamicOverridableMap<>(BlockState.class, state -> modelManager.getModel(ModelLocationCache.get(state))); - // Clear the cached models on blockstate objects - for(Block block : BuiltInRegistries.BLOCK) { - for(BlockState state : block.getStateDefinition().getPossibleStates()) { - if(state instanceof IModelHoldingBlockState modelHolder) { - modelHolder.mfix$setModel(null); - } - } - } - } - - private BakedModel cacheBlockModel(BlockState state) { - // Do all model system accesses in the unlocked path - ModelResourceLocation mrl = ModelLocationCache.get(state); - BakedModel model = mrl == null ? null : modelManager.getModel(mrl); - if (model == null) { - model = modelManager.getMissingModel(); - } - - return model; - } - - /** - * @author embeddedt - * @reason get the model from the dynamic model provider - */ - @Overwrite - public BakedModel getBlockModel(BlockState state) { - if(state instanceof IModelHoldingBlockState modelHolder) { - BakedModel model = modelHolder.mfix$getModel(); - - if(model != null) { - return model; - } - - model = this.cacheBlockModel(state); - modelHolder.mfix$setModel(model); - return model; - } else { - return this.cacheBlockModel(state); - } - } -} - diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java index 1948eca2..37f5a9bd 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java @@ -1,6 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; -import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.world.level.block.state.BlockBehaviour; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.duck.IModelHoldingBlockState; @@ -11,16 +11,16 @@ import java.lang.ref.SoftReference; @Mixin(BlockBehaviour.BlockStateBase.class) @ClientOnlyMixin public class BlockStateBaseMixin implements IModelHoldingBlockState { - private volatile SoftReference mfix$model; + private volatile SoftReference mfix$model; @Override - public BakedModel mfix$getModel() { + public BlockStateModel mfix$getModel() { var ref = mfix$model; return ref != null ? ref.get() : null; } @Override - public void mfix$setModel(BakedModel model) { + public void mfix$setModel(BlockStateModel model) { mfix$model = model != null ? new SoftReference<>(model) : null; } } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelDiscoveryMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelDiscoveryMixin.java index e3ae9523..36c38aa3 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelDiscoveryMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelDiscoveryMixin.java @@ -15,7 +15,7 @@ public class ModelDiscoveryMixin { * @reason We will show the warning ourselves later when loading the model dynamically, this is just spam since * the models don't exist during early loading */ - @Redirect(method = "loadBlockModel", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V")) + @Redirect(method = "method_68027", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V")) private void disableMissingModelWarning(Logger instance, String s, Object o) { } diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java index 61c0c949..838b8e55 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java @@ -1,24 +1,26 @@ package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; +import com.google.common.collect.ForwardingMap; import com.google.common.collect.Maps; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.Minecraft; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.renderer.item.ItemModel; import net.minecraft.client.resources.model.AtlasSet; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BlockStateModelLoader; import net.minecraft.client.resources.model.ClientItemInfoLoader; import net.minecraft.client.resources.model.ModelManager; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.apache.commons.lang3.ArrayUtils; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.embeddedt.modernfix.duck.IModelHoldingBlockState; import org.embeddedt.modernfix.dynamicresources.DynamicModelProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -32,13 +34,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.lang.ref.WeakReference; import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @Mixin(ModelManager.class) @ClientOnlyMixin public class ModelManagerMixin implements DynamicModelProvider.ModelManagerExtension { - @Shadow private Map bakedBlockStateModels; @Shadow private Map bakedItemStackModels; @Shadow private Map itemProperties; @@ -50,18 +52,43 @@ public class ModelManagerMixin implements DynamicModelProvider.ModelManagerExten return CompletableFuture.completedFuture(Map.of()); } - @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BlockStateModelLoader;loadBlockStates(Lnet/minecraft/client/resources/model/UnbakedModel;Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) - private CompletableFuture deferBlockStateLoad(UnbakedModel unbakedModel, ResourceManager resourceManager, Executor executor) { + @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BlockStateModelLoader;loadBlockStates(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture deferBlockStateLoad(ResourceManager resourceManager, Executor executor) { return CompletableFuture.completedFuture(new BlockStateModelLoader.LoadedModels(Map.of())); } /** * @author embeddedt - * @reason disable map creation + * @reason disable map creation, use dynamic dispatch */ @Overwrite - private static Map createBlockStateToModelDispatch(Map map, BakedModel bakedModel) { - return Map.of(); + private static Map createBlockStateToModelDispatch(Map map, BlockStateModel missingModel) { + var dynamicProvider = Objects.requireNonNull(DynamicModelProvider.currentReloadingModelProvider.get()); + + var dynamicRegistry = dynamicProvider.getTopLevelEmulatedRegistry(); + + return new ForwardingMap<>() { + @Override + protected Map delegate() { + return dynamicRegistry; + } + + @Override + public BlockStateModel get(Object key) { + BlockStateModel result; + if (key instanceof IModelHoldingBlockState state) { + result = state.mfix$getModel(); + if (result != null) { + return result; + } + } + result = dynamicRegistry.getOrDefault(key, dynamicProvider.getMissingBakedModel()); + if (key instanceof IModelHoldingBlockState state) { + state.mfix$setModel(result); + } + return result; + } + }; } @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ClientItemInfoLoader;scheduleLoad(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) @@ -86,9 +113,15 @@ public class ModelManagerMixin implements DynamicModelProvider.ModelManagerExten @Inject(method = "apply", at = @At("RETURN")) private void setModelRegistries(CallbackInfo ci) { - this.bakedBlockStateModels = this.mfix$modelProvider.getTopLevelEmulatedRegistry(); this.bakedItemStackModels = this.mfix$modelProvider.getItemModelEmulatedRegistry(); this.itemProperties = this.mfix$modelProvider.getItemPropertiesEmulatedRegistry(); + for(Block block : BuiltInRegistries.BLOCK) { + for(BlockState state : block.getStateDefinition().getPossibleStates()) { + if(state instanceof IModelHoldingBlockState modelHolder) { + modelHolder.mfix$setModel(null); + } + } + } } @Override diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java deleted file mode 100644 index 13ffced3..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/LayerRenderStateMixin.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; - -import net.minecraft.client.renderer.block.model.ItemTransform; -import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.SimpleBakedModel; -import net.minecraft.world.item.ItemDisplayContext; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.render.FastItemRenderType; -import org.embeddedt.modernfix.render.RenderState; -import org.embeddedt.modernfix.render.SimpleItemModelView; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; - -@Mixin(value = ItemStackRenderState.LayerRenderState.class, priority = 600) -@ClientOnlyMixin -public abstract class LayerRenderStateMixin { - @Shadow(aliases = {"this$0"}) @Final private ItemStackRenderState field_55345; - - @Shadow abstract ItemTransform transform(); - - @Unique - private final SimpleItemModelView modelView = new SimpleItemModelView(); - - /** - * If a model - * - is a vanilla item model (SimpleBakedModel), - * - has no custom GUI transforms, and - * - is being rendered in 2D on a GUI - * we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the - * camera). - */ - @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;renderItem(Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;II[ILnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/client/renderer/RenderType;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V"), index = 6) - private BakedModel useSimpleWrappedItemModel(BakedModel model) { - var transformType = ((ItemStackRenderStateAccessor)this.field_55345).getDisplayContext(); - // Forge composite models split themselves into a smaller simple model, we need to detect that the parent - // was not simple - // TODO 1.21.4 - I don't think that is needed anymore with the changes to item rendering - /* - if(originalModel != null && originalModel.getClass() != SimpleBakedModel.class) { - return model; - } - */ - - if(!RenderState.IS_RENDERING_LEVEL && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) { - FastItemRenderType type; - ItemTransform transform = this.transform(); - if(transform == ItemTransform.NO_TRANSFORM) - type = FastItemRenderType.SIMPLE_ITEM; - else if(model.isGui3d() && isBlockTransforms(transform)) - type = FastItemRenderType.SIMPLE_BLOCK; - else - return model; - modelView.setItem(model); - modelView.setType(type); - return modelView; - } else - return model; - } - - private boolean isBlockTransforms(ItemTransform transform) { - return transform.rotation.x() == 30f - && transform.rotation.y() == 225f - && transform.rotation.z() == 0f; - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java deleted file mode 100644 index e4c818c7..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.client.renderer.block.model.multipart.Selector; -import net.minecraft.world.level.block.state.StateDefinition; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; - -@Mixin(Selector.class) -@ClientOnlyMixin -public class SelectorMixin { - private ConcurrentHashMap, Predicate> predicateCache = new ConcurrentHashMap<>(); - @Inject(method = "getPredicate", at = @At("HEAD"), cancellable = true) - private void useCachedPredicate(StateDefinition pState, CallbackInfoReturnable> cir) { - Predicate cached = this.predicateCache.get(pState); - if(cached != null) - cir.setReturnValue(cached); - } - - @Inject(method = "getPredicate", at = @At("RETURN")) - private void storeCachedPredicate(StateDefinition pState, CallbackInfoReturnable> cir) { - this.predicateCache.put(pState, cir.getReturnValue()); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java index d495ceb3..abd62020 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java @@ -1,8 +1,8 @@ package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; import com.mojang.math.Transformation; -import org.joml.Matrix4f; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; +import org.joml.Matrix4fc; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -13,7 +13,7 @@ import java.util.Objects; @Mixin(Transformation.class) @ClientOnlyMixin public class TransformationMatrixMixin { - @Shadow @Final private Matrix4f matrix; + @Shadow @Final private Matrix4fc matrix; private Integer cachedHashCode = null; /** * @author embeddedt diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java b/common/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java deleted file mode 100644 index 87c96c66..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import net.minecraft.client.resources.model.ModelResourceLocation; - -public interface IBlockStateModelLoader { - void loadSpecificBlock(ModelResourceLocation location); -} diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java b/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java deleted file mode 100644 index c37c495d..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; - -import java.util.concurrent.locks.ReentrantLock; - -public interface IExtendedModelBakery { - void mfix$tick(); - void mfix$finishLoading(); - UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location); - UnbakedModel mfix$getMissingModel(); - ReentrantLock mfix$getLock(); -} diff --git a/common/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java b/common/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java index 0471e64c..6ec9cd49 100644 --- a/common/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java +++ b/common/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java @@ -1,8 +1,8 @@ package org.embeddedt.modernfix.duck; -import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.renderer.block.model.BlockStateModel; public interface IModelHoldingBlockState { - BakedModel mfix$getModel(); - void mfix$setModel(BakedModel model); + BlockStateModel mfix$getModel(); + void mfix$setModel(BlockStateModel model); } diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/BlockStateSet.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/BlockStateSet.java new file mode 100644 index 00000000..8b4564f4 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/BlockStateSet.java @@ -0,0 +1,86 @@ +package org.embeddedt.modernfix.dynamicresources; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public class BlockStateSet implements Set { + private static final BlockStateSet INSTANCE = new BlockStateSet(); + + private BlockStateSet() { + + } + + public static BlockStateSet instance() { + return INSTANCE; + } + + @Override + public int size() { + return Block.BLOCK_STATE_REGISTRY.size(); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return o instanceof BlockState; + } + + @Override + public @NotNull Iterator iterator() { + return Block.BLOCK_STATE_REGISTRY.iterator(); + } + + @Override + public @NotNull Object[] toArray() { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull T[] toArray(@NotNull T[] a) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean add(BlockState blockState) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + return c.stream().allMatch(o -> o instanceof BlockState); + } + + @Override + public boolean addAll(@NotNull Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(@NotNull Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(@NotNull Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java index 91d05577..4c543238 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java @@ -10,28 +10,34 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mojang.serialization.JsonOps; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceSets; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.block.BlockModelShaper; import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModelDefinition; +import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.block.model.ItemModelGenerator; -import net.minecraft.client.renderer.block.model.UnbakedBlockStateModel; +import net.minecraft.client.renderer.block.model.SimpleModelWrapper; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.renderer.item.ItemModel; import net.minecraft.client.renderer.item.MissingItemModel; +import net.minecraft.client.renderer.item.ModelRenderProperties; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.AtlasSet; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BlockModelRotation; +import net.minecraft.client.resources.model.BlockStateDefinitions; import net.minecraft.client.resources.model.BlockStateModelLoader; import net.minecraft.client.resources.model.Material; import net.minecraft.client.resources.model.MissingBlockModel; import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelDebugName; -import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.ModelDiscovery; import net.minecraft.client.resources.model.ModelState; +import net.minecraft.client.resources.model.ResolvableModel; +import net.minecraft.client.resources.model.ResolvedModel; import net.minecraft.client.resources.model.SpriteGetter; import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.core.registries.BuiltInRegistries; @@ -75,7 +81,10 @@ public class DynamicModelProvider { private final LoadingCache> loadedBlockModels = this.makeLoadingCache(this::loadBlockModel); - private final LoadingCache> loadedBakedModels = + private final LoadingCache> resolvedBlockModels = + this.makeLoadingCache(this::resolveBlockModel); + + private final LoadingCache> loadedBakedModels = this.makeLoadingCache(this::loadBakedModel); private final LoadingCache> loadedClientItemProperties = @@ -84,23 +93,26 @@ public class DynamicModelProvider { private final LoadingCache> loadedItemModels = this.makeLoadingCache(this::loadItemModel); + /* private final LoadingCache> loadedStandaloneModels = this.makeLoadingCache(this::loadStandaloneModel); - private final BakedModel missingModel; + */ + + private final BlockStateModel missingModel; + private final ModelDiscovery.ModelWrapper resolvedMissingModel; private final ItemModel missingItemModel; private final UnbakedModel unbakedMissingModel; private final Function> stateMapper; private final ResourceManager resourceManager; - private final ModelBakery.TextureGetter textureGetter; - private final DynamicResolver resolver; + private final SpriteGetter textureGetter; private final EntityModelSet entityModelSet; private final ItemModelGenerator itemModelGenerator; - private final Map mrlModelOverrides = new ConcurrentHashMap<>(); + private final Map mrlModelOverrides = new ConcurrentHashMap<>(); private final Map itemStackModelOverrides = new ConcurrentHashMap<>(); - private final Map standaloneModelOverrides = new ConcurrentHashMap<>(); - private final Map unbakedBlockStateModelOverrides = new ConcurrentHashMap<>(); + //private final Map standaloneModelOverrides = new ConcurrentHashMap<>(); + private final Map unbakedBlockStateModelOverrides = new ConcurrentHashMap<>(); private final List pluginList = new ArrayList<>(); @@ -111,39 +123,54 @@ public class DynamicModelProvider { this.unbakedMissingModel = MissingBlockModel.missingModel(); this.entityModelSet = entityModelSet; var missing = atlasMap.get(TextureAtlas.LOCATION_BLOCKS).missing(); - this.textureGetter = new ModelBakery.TextureGetter() { + this.textureGetter = new SpriteGetter() { @Override - public TextureAtlasSprite get(ModelDebugName modelDebugName, Material material) { + public TextureAtlasSprite get(Material material, ModelDebugName modelDebugName) { var atlas = atlasMap.get(material.atlasLocation()); var sprite = atlas.getSprite(material.texture()); if (sprite != null) { return sprite; } else { - ModernFix.LOGGER.warn("Unable to find sprite '{}' referenced by model '{}'", material.texture(), modelDebugName.get()); + ModernFix.LOGGER.warn("Unable to find sprite '{}' referenced by model '{}'", material.texture(), modelDebugName.debugName()); return missing; } } @Override - public TextureAtlasSprite reportMissingReference(ModelDebugName modelDebugName, String string) { + public TextureAtlasSprite reportMissingReference(String string, ModelDebugName modelDebugName) { return missing; } }; - this.stateMapper = BlockStateModelLoader.definitionLocationToBlockMapper(); + this.stateMapper = BlockStateDefinitions.definitionLocationToBlockStateMapper(); this.resourceManager = resourceManager; - this.resolver = new DynamicResolver(); this.itemModelGenerator = new ItemModelGenerator(); - this.missingModel = this.bakeMissingModel(); - this.missingItemModel = new MissingItemModel(this.missingModel); + this.resolvedMissingModel = new ModelDiscovery.ModelWrapper(MissingBlockModel.LOCATION, this.unbakedMissingModel, true); + var missingModelBaker = new ModelBaker() { + @Override + public ResolvedModel getModel(ResourceLocation resourceLocation) { + throw new IllegalStateException("Missing model should not have dependencies"); + } + + @Override + public SpriteGetter sprites() { + return DynamicModelProvider.this.textureGetter; + } + }; + var textureSlots = this.resolvedMissingModel.getTopTextureSlots(); + var quadCollection = this.resolvedMissingModel.bakeTopGeometry(textureSlots, missingModelBaker, BlockModelRotation.X0_Y0); + var particleSprite = this.resolvedMissingModel.resolveParticleSprite(textureSlots, missingModelBaker); + this.missingModel = new SimpleModelWrapper(quadCollection, resolvedMissingModel.getTopAmbientOcclusion(), particleSprite); + this.missingItemModel = new MissingItemModel(quadCollection.getAll(), new ModelRenderProperties(resolvedMissingModel.getTopGuiLight().lightLikeBlock(), particleSprite, resolvedMissingModel.getTopTransforms())); try { Class.forName("net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin"); - pluginList.add(new FabricDynamicModelHandler(this, this.resourceManager)); + // TODO + //pluginList.add(new FabricDynamicModelHandler(this, this.resourceManager)); } catch(Exception ignored) { // Fabric API likely not present } } - public BakedModel getMissingBakedModel() { + public BlockStateModel getMissingBakedModel() { return this.missingModel; } @@ -151,25 +178,15 @@ public class DynamicModelProvider { return this.missingItemModel; } - private static final Supplier> TOP_LEVEL_LOCATIONS_SUPPLIER = Suppliers.memoizeWithExpiration(() -> { - Set set = new HashSet<>(); - // Skip going through ModelLocationCache because most of the accesses will be misses - BuiltInRegistries.BLOCK.entrySet().forEach(entry -> { - var location = entry.getKey().location(); - for(BlockState state : entry.getValue().getStateDefinition().getPossibleStates()) { - set.add(BlockModelShaper.stateToModelLocation(location, state)); - } - }); - return Collections.unmodifiableSet(set); - }, 2, TimeUnit.MINUTES); - - public Map getTopLevelEmulatedRegistry() { - return new EmulatedRegistry<>(ModelResourceLocation.class, this.loadedBakedModels, TOP_LEVEL_LOCATIONS_SUPPLIER, this.mrlModelOverrides); + public Map getTopLevelEmulatedRegistry() { + return new EmulatedRegistry<>(BlockState.class, this.loadedBakedModels, BlockStateSet::instance, this.mrlModelOverrides); } + /* public Map getStandaloneEmulatedRegistry() { return new EmulatedRegistry<>(ResourceLocation.class, this.loadedStandaloneModels, Set::of, this.standaloneModelOverrides); } + */ public Map getItemModelEmulatedRegistry() { return new EmulatedRegistry<>(ResourceLocation.class, this.loadedItemModels, BuiltInRegistries.ITEM::keySet, this.itemStackModelOverrides); @@ -348,62 +365,31 @@ public class DynamicModelProvider { for(Resource resource : resources) { try(Reader reader = resource.openAsReader()) { JsonObject jsonObject = GsonHelper.parse(reader); - BlockModelDefinition blockModelDefinition = BlockModelDefinition.fromJsonElement(jsonObject); + BlockModelDefinition blockModelDefinition = BlockModelDefinition.CODEC.decode(JsonOps.INSTANCE, jsonObject).getOrThrow().getFirst(); loadedDefinitions.add(new BlockStateModelLoader.LoadedBlockModelDefinition(resource.sourcePackId(), blockModelDefinition)); } catch(Exception e) { ModernFix.LOGGER.error("Failed to load blockstate definition {} from pack '{}'", location, resource.sourcePackId(), e); } } - var loadedModels = new HashMap<>(BlockStateModelLoader.loadBlockStateDefinitionStack(location, stateDefinition, loadedDefinitions, this.unbakedMissingModel).models()); + var loadedModels = new HashMap<>(BlockStateModelLoader.loadBlockStateDefinitionStack(location, stateDefinition, loadedDefinitions).models()); if (!pluginList.isEmpty()) { loadedModels.replaceAll((mrl, oldModel) -> { - UnbakedBlockStateModel ubm = oldModel.model(); + BlockStateModel.Unbaked ubm = oldModel; for (var plugin : pluginList) { - ubm = plugin.modifyBlockModelOnLoad(ubm, mrl, oldModel.state()); - } - if (ubm == oldModel.model()) { - return oldModel; - } else { - return new BlockStateModelLoader.LoadedModel(oldModel.state(), ubm); + ubm = plugin.modifyBlockModelOnLoad(oldModel, mrl); } + return ubm; }); } return Optional.of(new BlockStateModelLoader.LoadedModels(loadedModels)); } - private BakedModel bakeMissingModel() { - this.resolver.clearResolver(); - this.unbakedMissingModel.resolveDependencies(this.resolver); - var modelBaker = new DynamicBaker(() -> "missing"); - return UnbakedModel.bakeWithTopModelValues(this.unbakedMissingModel, modelBaker, BlockModelRotation.X0_Y0); - } - - private BakedModel bakeModel(UnbakedModel model, ResourceLocation location) { - if (DEBUG_DYNAMIC_MODEL_LOADING) { - ModernFix.LOGGER.info("Baking model '{}'", location); - } - synchronized (this) { - this.resolver.clearResolver(); - model.resolveDependencies(this.resolver); - var modelBaker = new DynamicBaker(location::toString); - for (var plugin : pluginList) { - model = plugin.modifyModelBeforeBake(model, location, BlockModelRotation.X0_Y0, modelBaker); - } - var bakedModel = UnbakedModel.bakeWithTopModelValues(model, modelBaker, BlockModelRotation.X0_Y0); - for (var plugin : pluginList) { - bakedModel = plugin.modifyModelAfterBake(bakedModel, model, location, BlockModelRotation.X0_Y0, modelBaker); - } - return bakedModel; - } - } - - private BakedModel bakeModel(UnbakedBlockStateModel model, ModelResourceLocation mrl) { + private BlockStateModel bakeModel(BlockStateModel.Unbaked model, BlockState mrl) { if (DEBUG_DYNAMIC_MODEL_LOADING) { ModernFix.LOGGER.info("Baking model '{}'", mrl); } synchronized (this) { - this.resolver.clearResolver(); - model.resolveDependencies(this.resolver); + model.resolveDependencies(dep -> {}); var modelBaker = new DynamicBaker(mrl::toString); for (var plugin : pluginList) { model = plugin.modifyBlockModelBeforeBake(model, mrl, modelBaker); @@ -416,32 +402,26 @@ public class DynamicModelProvider { } } - private Optional loadBakedModel(ModelResourceLocation location) { - var override = this.mrlModelOverrides.get(location); + private Optional loadBakedModel(BlockState state) { + var override = this.mrlModelOverrides.get(state); if (override != null) { return Optional.of(override); } - if (location.variant().equals("standalone") || location.variant().equals("fabric_resource")) { - return this.loadStandaloneModel(location.id()); + if (false) { //location.variant().equals("standalone") || location.variant().equals("fabric_resource")) { + throw new UnsupportedOperationException(); //return this.loadStandaloneModel(location.id()); } else { - Optional unbakedModelOpt = Optional.ofNullable(this.unbakedBlockStateModelOverrides.get(location)); + Optional unbakedModelOpt = Optional.ofNullable(this.unbakedBlockStateModelOverrides.get(state)); if (unbakedModelOpt.isEmpty()) { - var optLoadedModels = this.loadedStateDefinitions.getUnchecked(location.id()); - unbakedModelOpt = optLoadedModels.map(loadedModels -> { - var loadedModel = loadedModels.models().get(location); - if(loadedModel != null) { - return loadedModel.model(); - } else { - return null; - } - }); + var optLoadedModels = this.loadedStateDefinitions.getUnchecked(state.getBlock().builtInRegistryHolder().key().location()); + unbakedModelOpt = optLoadedModels.map(loadedModels -> loadedModels.models().get(state)); } return unbakedModelOpt.map(unbakedModel -> { - return this.bakeModel(unbakedModel, location); + return this.bakeModel(unbakedModel, state); }); } } + /* private Optional loadStandaloneModel(ResourceLocation location) { var override = this.standaloneModelOverrides.get(location); if (override != null) { @@ -451,6 +431,7 @@ public class DynamicModelProvider { return this.bakeModel(unbakedModel, location); }); } + */ private Optional loadBlockModelDefault(ResourceLocation location) { if (DEBUG_DYNAMIC_MODEL_LOADING) { @@ -484,6 +465,29 @@ public class DynamicModelProvider { return value; } + private Optional resolveBlockModel(ResourceLocation location) { + var unbakedOpt = this.loadedBlockModels.getUnchecked(location); + if (unbakedOpt.isEmpty()) { + return Optional.empty(); + } + ModelDiscovery.ModelWrapper wrapper = new ModelDiscovery.ModelWrapper(location, unbakedOpt.get(), true); + var parent = wrapper.wrapped().parent(); + if (parent != null) { + Optional resolvedParentOpt; + try { + resolvedParentOpt = this.resolvedBlockModels.getUnchecked(parent); + } catch (Exception e) { + // Possible recursive load, etc. + ModernFix.LOGGER.error("Error while resolving model '{}'", location, e); + return Optional.empty(); + } + if (resolvedParentOpt.isPresent()) { + wrapper.parent = resolvedParentOpt.get(); + } + } + return Optional.of(wrapper); + } + private Optional loadClientItemProperties(ResourceLocation location) { if (DEBUG_DYNAMIC_MODEL_LOADING) { @@ -513,12 +517,12 @@ public class DynamicModelProvider { return Optional.of(override); } return this.loadedClientItemProperties.getUnchecked(location).map(clientItem -> { - var bakingContext = new ItemModel.BakingContext(new DynamicBaker(location::toString), this.entityModelSet, this.missingItemModel); + var bakingContext = new ItemModel.BakingContext(new DynamicBaker(location::toString), this.entityModelSet, this.missingItemModel, clientItem.registrySwapper()); return clientItem.model().bake(bakingContext); }); } - public BakedModel getModel(ModelResourceLocation location) { + public BlockStateModel getModel(BlockState location) { return this.loadedBakedModels.getUnchecked(location).orElse(this.missingModel); } @@ -530,11 +534,14 @@ public class DynamicModelProvider { return this.loadedItemModels.getUnchecked(location).orElse(this.missingItemModel); } + /* public BakedModel getStandaloneModel(ResourceLocation location) { return this.loadedStandaloneModels.getUnchecked(location).orElse(this.missingModel); } - public void addUnbakedBlockStateOverride(ModelResourceLocation location, UnbakedBlockStateModel model) { + */ + + public void addUnbakedBlockStateOverride(BlockState location, BlockStateModel.Unbaked model) { this.unbakedBlockStateModelOverrides.put(location, model); } @@ -546,56 +553,13 @@ public class DynamicModelProvider { } @Override - public BakedModel bake(ResourceLocation location, ModelState transform) { - return DynamicModelProvider.this.loadedBlockModels.getUnchecked(location).map(unbakedModel -> { - DynamicModelProvider.this.resolver.clearResolver(); - unbakedModel.resolveDependencies(DynamicModelProvider.this.resolver); - return UnbakedModel.bakeWithTopModelValues(unbakedModel, this, transform); - }).orElse(DynamicModelProvider.this.missingModel); + public ResolvedModel getModel(ResourceLocation location) { + return DynamicModelProvider.this.resolvedBlockModels.getUnchecked(location).orElse(DynamicModelProvider.this.resolvedMissingModel); } @Override public SpriteGetter sprites() { - return DynamicModelProvider.this.textureGetter.bind(this.modelDebugName); - } - - @Override - public ModelDebugName rootName() { - return this.modelDebugName; - } - } - - /** - * Based on the Mojang impl but with some changes to make it slightly more efficient. - */ - private class DynamicResolver implements UnbakedModel.Resolver { - private final Set stack = new ObjectOpenHashSet<>(4); - private final Set resolvedModels = new ObjectOpenHashSet<>(); - - @Override - public UnbakedModel resolve(ResourceLocation resourceLocation) { - if (this.stack.contains(resourceLocation)) { - ModernFix.LOGGER.warn("Detected model loading loop: {}->{}", this.stacktraceToString(), resourceLocation); - return DynamicModelProvider.this.unbakedMissingModel; - } else { - UnbakedModel unbakedModel = DynamicModelProvider.this.loadedBlockModels.getUnchecked(resourceLocation).orElse(DynamicModelProvider.this.unbakedMissingModel); - if (this.resolvedModels.add(resourceLocation)) { - this.stack.add(resourceLocation); - unbakedModel.resolveDependencies(this); - this.stack.remove(resourceLocation); - } - - return unbakedModel; - } - } - - private String stacktraceToString() { - return this.stack.stream().map(ResourceLocation::toString).collect(Collectors.joining("->")); - } - - public void clearResolver() { - this.stack.clear(); - this.resolvedModels.clear(); + return DynamicModelProvider.this.textureGetter; } } @@ -607,12 +571,12 @@ public class DynamicModelProvider { public interface DynamicModelPlugin { Optional modifyModelOnLoad(Optional model, ResourceLocation id); - UnbakedBlockStateModel modifyBlockModelOnLoad(UnbakedBlockStateModel model, ModelResourceLocation id, BlockState state); + BlockStateModel.Unbaked modifyBlockModelOnLoad(BlockStateModel.Unbaked model, BlockState state); UnbakedModel modifyModelBeforeBake(UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker); - BakedModel modifyModelAfterBake(BakedModel bakedModel, UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker); + //BakedModel modifyModelAfterBake(BakedModel bakedModel, UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker); - UnbakedBlockStateModel modifyBlockModelBeforeBake(UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker); - BakedModel modifyBlockModelAfterBake(BakedModel bakedModel, UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker); + BlockStateModel.Unbaked modifyBlockModelBeforeBake(BlockStateModel.Unbaked model, BlockState state, ModelBaker baker); + BlockStateModel modifyBlockModelAfterBake(BlockStateModel bakedModel, BlockStateModel.Unbaked unbaked, BlockState state, ModelBaker baker); } } diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/FabricDynamicModelHandler.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/FabricDynamicModelHandler.java index c44d5267..68457e54 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/FabricDynamicModelHandler.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/FabricDynamicModelHandler.java @@ -1,301 +1,301 @@ -package org.embeddedt.modernfix.dynamicresources; - -import net.fabricmc.fabric.api.client.model.loading.v1.BlockStateResolver; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; -import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.renderer.block.model.UnbakedBlockStateModel; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelBaker; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.ModelState; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import org.embeddedt.modernfix.ModernFix; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -public class FabricDynamicModelHandler implements DynamicModelProvider.DynamicModelPlugin { - // Borrowed from Fabric API, this dispatching logic is extremely trivial - - private static final ResourceLocation[] MODEL_MODIFIER_PHASES = new ResourceLocation[] { ModelModifier.OVERRIDE_PHASE, ModelModifier.DEFAULT_PHASE, ModelModifier.WRAP_PHASE, ModelModifier.WRAP_LAST_PHASE }; - - private final Event onLoadModifiers = EventFactory.createWithPhases(ModelModifier.OnLoad.class, modifiers -> (model, context) -> { - for (ModelModifier.OnLoad modifier : modifiers) { - try { - model = modifier.modifyModelOnLoad(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify unbaked model on load", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - - private final Event onLoadBlockModifiers = EventFactory.createWithPhases(ModelModifier.OnLoadBlock.class, modifiers -> (model, context) -> { - for (ModelModifier.OnLoadBlock modifier : modifiers) { - try { - model = modifier.modifyModelOnLoad(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify unbaked block model on load", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - - private final Event beforeBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBakeBlock.class, modifiers -> (model, context) -> { - for (ModelModifier.BeforeBakeBlock modifier : modifiers) { - try { - model = modifier.modifyModelBeforeBake(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify unbaked block model before bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - private final Event afterBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.AfterBakeBlock.class, modifiers -> (model, context) -> { - for (ModelModifier.AfterBakeBlock modifier : modifiers) { - try { - model = modifier.modifyModelAfterBake(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify baked block model after bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - private final Event beforeBakeModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBake.class, modifiers -> (model, context) -> { - for (ModelModifier.BeforeBake modifier : modifiers) { - try { - model = modifier.modifyModelBeforeBake(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify unbaked model before bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - private final Event afterBakeModifiers = EventFactory.createWithPhases(ModelModifier.AfterBake.class, modifiers -> (model, context) -> { - for (ModelModifier.AfterBake modifier : modifiers) { - try { - model = modifier.modifyModelAfterBake(model, context); - } catch (Exception exception) { - ModernFix.LOGGER.error("Failed to modify baked model after bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - - record PreparablePluginData(CompletableFuture data, PreparableModelLoadingPlugin.Holder plugin) { - void initialize(ModelLoadingPlugin.Context context) { - plugin.plugin().initialize(data.join(), context); - } - } - - private PreparablePluginData makeDataRecord(ResourceManager manager, PreparableModelLoadingPlugin.Holder holder) { - return new PreparablePluginData<>(holder.loader().load(manager, ModernFix.resourceReloadExecutor()), holder); - } - - public FabricDynamicModelHandler(DynamicModelProvider provider, ResourceManager manager) { - List pluginList = new ArrayList<>(ModelLoadingPlugin.getAll()); - var preparablePluginData = new ArrayList>(); - for (var holder : PreparableModelLoadingPlugin.getAll()) { - preparablePluginData.add(makeDataRecord(manager, holder)); - } - // Wait for all the preparable plugins to finish loading - CompletableFuture.allOf(preparablePluginData.stream().map(PreparablePluginData::data).toArray(CompletableFuture[]::new)).join(); - var context = new PluginContext(provider); - for (var plugin : pluginList) { - plugin.initialize(context); - } - for (var data : preparablePluginData) { - data.initialize(context); - } - context.fireResolvers(); - } - - @Override - public Optional modifyModelOnLoad(Optional model, ResourceLocation id) { - return Optional.ofNullable(this.onLoadModifiers.invoker().modifyModelOnLoad(model.orElse(null), () -> id)); - } - - @Override - public UnbakedBlockStateModel modifyBlockModelOnLoad(UnbakedBlockStateModel model, ModelResourceLocation id, BlockState state) { - return this.onLoadBlockModifiers.invoker().modifyModelOnLoad(model, new ModelModifier.OnLoadBlock.Context() { - @Override - public ModelResourceLocation id() { - return id; - } - - @Override - public BlockState state() { - return state; - } - }); - } - - @Override - public UnbakedModel modifyModelBeforeBake(UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker) { - return beforeBakeModifiers.invoker().modifyModelBeforeBake(model, new ModelModifier.BeforeBake.Context() { - @Override - public ResourceLocation id() { - return id; - } - - @Override - public ModelState settings() { - return state; - } - - @Override - public ModelBaker baker() { - return baker; - } - }); - } - - @Override - public BakedModel modifyModelAfterBake(BakedModel bakedModel, UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker) { - return afterBakeModifiers.invoker().modifyModelAfterBake(bakedModel, new ModelModifier.AfterBake.Context() { - @Override - public ResourceLocation id() { - return id; - } - - @Override - public UnbakedModel sourceModel() { - return model; - } - - @Override - public ModelState settings() { - return state; - } - - @Override - public ModelBaker baker() { - return baker; - } - }); - } - - @Override - public UnbakedBlockStateModel modifyBlockModelBeforeBake(UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker) { - return beforeBakeBlockModifiers.invoker().modifyModelBeforeBake(model, new ModelModifier.BeforeBakeBlock.Context() { - @Override - public ModelResourceLocation id() { - return id; - } - - @Override - public ModelBaker baker() { - return baker; - } - }); - } - - @Override - public BakedModel modifyBlockModelAfterBake(BakedModel bakedModel, UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker) { - return afterBakeBlockModifiers.invoker().modifyModelAfterBake(bakedModel, new ModelModifier.AfterBakeBlock.Context() { - @Override - public ModelResourceLocation id() { - return id; - } - - @Override - public UnbakedBlockStateModel sourceModel() { - return model; - } - - @Override - public ModelBaker baker() { - return baker; - } - }); - } - - private class PluginContext implements ModelLoadingPlugin.Context { - private final DynamicModelProvider provider; - private final Map resolvers = new HashMap<>(); - - private PluginContext(DynamicModelProvider provider) { - this.provider = provider; - } - - @Override - public void addModels(ResourceLocation... ids) { - /* no-op on dynamic model loader */ - } - - @Override - public void addModels(Collection ids) { - /* no-op on dynamic model loader */ - } - - @Override - public void registerBlockStateResolver(Block block, BlockStateResolver resolver) { - resolvers.put(block, resolver); - } - - public void fireResolvers() { - resolvers.forEach((block, resolver) -> { - resolver.resolveBlockStates(new BlockStateResolver.Context() { - @Override - public Block block() { - return block; - } - - @Override - public void setModel(BlockState state, UnbakedBlockStateModel model) { - provider.addUnbakedBlockStateOverride(BlockModelShaper.stateToModelLocation(state), model); - } - }); - }); - } - - @Override - public Event modifyModelOnLoad() { - return onLoadModifiers; - } - - @Override - public Event modifyBlockModelOnLoad() { - return onLoadBlockModifiers; - } - - @Override - public Event modifyModelBeforeBake() { - return beforeBakeModifiers; - } - - @Override - public Event modifyModelAfterBake() { - return afterBakeModifiers; - } - - @Override - public Event modifyBlockModelBeforeBake() { - return beforeBakeBlockModifiers; - } - - @Override - public Event modifyBlockModelAfterBake() { - return afterBakeBlockModifiers; - } - } -} +//package org.embeddedt.modernfix.dynamicresources; +// +//import net.fabricmc.fabric.api.client.model.loading.v1.BlockStateResolver; +//import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; +//import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; +//import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; +//import net.fabricmc.fabric.api.event.Event; +//import net.fabricmc.fabric.api.event.EventFactory; +//import net.minecraft.client.renderer.block.BlockModelShaper; +//import net.minecraft.client.renderer.block.model.UnbakedBlockStateModel; +//import net.minecraft.client.resources.model.BakedModel; +//import net.minecraft.client.resources.model.ModelBaker; +//import net.minecraft.client.resources.model.ModelResourceLocation; +//import net.minecraft.client.resources.model.ModelState; +//import net.minecraft.client.resources.model.UnbakedModel; +//import net.minecraft.resources.ResourceLocation; +//import net.minecraft.server.packs.resources.ResourceManager; +//import net.minecraft.world.level.block.Block; +//import net.minecraft.world.level.block.state.BlockState; +//import org.embeddedt.modernfix.ModernFix; +// +//import java.util.ArrayList; +//import java.util.Collection; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +//import java.util.Optional; +//import java.util.concurrent.CompletableFuture; +// +//public class FabricDynamicModelHandler implements DynamicModelProvider.DynamicModelPlugin { +// // Borrowed from Fabric API, this dispatching logic is extremely trivial +// +// private static final ResourceLocation[] MODEL_MODIFIER_PHASES = new ResourceLocation[] { ModelModifier.OVERRIDE_PHASE, ModelModifier.DEFAULT_PHASE, ModelModifier.WRAP_PHASE, ModelModifier.WRAP_LAST_PHASE }; +// +// private final Event onLoadModifiers = EventFactory.createWithPhases(ModelModifier.OnLoad.class, modifiers -> (model, context) -> { +// for (ModelModifier.OnLoad modifier : modifiers) { +// try { +// model = modifier.modifyModelOnLoad(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify unbaked model on load", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// +// private final Event onLoadBlockModifiers = EventFactory.createWithPhases(ModelModifier.OnLoadBlock.class, modifiers -> (model, context) -> { +// for (ModelModifier.OnLoadBlock modifier : modifiers) { +// try { +// model = modifier.modifyModelOnLoad(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify unbaked block model on load", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// +// private final Event beforeBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBakeBlock.class, modifiers -> (model, context) -> { +// for (ModelModifier.BeforeBakeBlock modifier : modifiers) { +// try { +// model = modifier.modifyModelBeforeBake(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify unbaked block model before bake", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// private final Event afterBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.AfterBakeBlock.class, modifiers -> (model, context) -> { +// for (ModelModifier.AfterBakeBlock modifier : modifiers) { +// try { +// model = modifier.modifyModelAfterBake(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify baked block model after bake", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// private final Event beforeBakeModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBake.class, modifiers -> (model, context) -> { +// for (ModelModifier.BeforeBake modifier : modifiers) { +// try { +// model = modifier.modifyModelBeforeBake(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify unbaked model before bake", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// private final Event afterBakeModifiers = EventFactory.createWithPhases(ModelModifier.AfterBake.class, modifiers -> (model, context) -> { +// for (ModelModifier.AfterBake modifier : modifiers) { +// try { +// model = modifier.modifyModelAfterBake(model, context); +// } catch (Exception exception) { +// ModernFix.LOGGER.error("Failed to modify baked model after bake", exception); +// } +// } +// +// return model; +// }, MODEL_MODIFIER_PHASES); +// +// record PreparablePluginData(CompletableFuture data, PreparableModelLoadingPlugin.Holder plugin) { +// void initialize(ModelLoadingPlugin.Context context) { +// plugin.plugin().initialize(data.join(), context); +// } +// } +// +// private PreparablePluginData makeDataRecord(ResourceManager manager, PreparableModelLoadingPlugin.Holder holder) { +// return new PreparablePluginData<>(holder.loader().load(manager, ModernFix.resourceReloadExecutor()), holder); +// } +// +// public FabricDynamicModelHandler(DynamicModelProvider provider, ResourceManager manager) { +// List pluginList = new ArrayList<>(ModelLoadingPlugin.getAll()); +// var preparablePluginData = new ArrayList>(); +// for (var holder : PreparableModelLoadingPlugin.getAll()) { +// preparablePluginData.add(makeDataRecord(manager, holder)); +// } +// // Wait for all the preparable plugins to finish loading +// CompletableFuture.allOf(preparablePluginData.stream().map(PreparablePluginData::data).toArray(CompletableFuture[]::new)).join(); +// var context = new PluginContext(provider); +// for (var plugin : pluginList) { +// plugin.initialize(context); +// } +// for (var data : preparablePluginData) { +// data.initialize(context); +// } +// context.fireResolvers(); +// } +// +// @Override +// public Optional modifyModelOnLoad(Optional model, ResourceLocation id) { +// return Optional.ofNullable(this.onLoadModifiers.invoker().modifyModelOnLoad(model.orElse(null), () -> id)); +// } +// +// @Override +// public UnbakedBlockStateModel modifyBlockModelOnLoad(UnbakedBlockStateModel model, ModelResourceLocation id, BlockState state) { +// return this.onLoadBlockModifiers.invoker().modifyModelOnLoad(model, new ModelModifier.OnLoadBlock.Context() { +// @Override +// public ModelResourceLocation id() { +// return id; +// } +// +// @Override +// public BlockState state() { +// return state; +// } +// }); +// } +// +// @Override +// public UnbakedModel modifyModelBeforeBake(UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker) { +// return beforeBakeModifiers.invoker().modifyModelBeforeBake(model, new ModelModifier.BeforeBake.Context() { +// @Override +// public ResourceLocation id() { +// return id; +// } +// +// @Override +// public ModelState settings() { +// return state; +// } +// +// @Override +// public ModelBaker baker() { +// return baker; +// } +// }); +// } +// +// @Override +// public BakedModel modifyModelAfterBake(BakedModel bakedModel, UnbakedModel model, ResourceLocation id, ModelState state, ModelBaker baker) { +// return afterBakeModifiers.invoker().modifyModelAfterBake(bakedModel, new ModelModifier.AfterBake.Context() { +// @Override +// public ResourceLocation id() { +// return id; +// } +// +// @Override +// public UnbakedModel sourceModel() { +// return model; +// } +// +// @Override +// public ModelState settings() { +// return state; +// } +// +// @Override +// public ModelBaker baker() { +// return baker; +// } +// }); +// } +// +// @Override +// public UnbakedBlockStateModel modifyBlockModelBeforeBake(UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker) { +// return beforeBakeBlockModifiers.invoker().modifyModelBeforeBake(model, new ModelModifier.BeforeBakeBlock.Context() { +// @Override +// public ModelResourceLocation id() { +// return id; +// } +// +// @Override +// public ModelBaker baker() { +// return baker; +// } +// }); +// } +// +// @Override +// public BakedModel modifyBlockModelAfterBake(BakedModel bakedModel, UnbakedBlockStateModel model, ModelResourceLocation id, ModelBaker baker) { +// return afterBakeBlockModifiers.invoker().modifyModelAfterBake(bakedModel, new ModelModifier.AfterBakeBlock.Context() { +// @Override +// public ModelResourceLocation id() { +// return id; +// } +// +// @Override +// public UnbakedBlockStateModel sourceModel() { +// return model; +// } +// +// @Override +// public ModelBaker baker() { +// return baker; +// } +// }); +// } +// +// private class PluginContext implements ModelLoadingPlugin.Context { +// private final DynamicModelProvider provider; +// private final Map resolvers = new HashMap<>(); +// +// private PluginContext(DynamicModelProvider provider) { +// this.provider = provider; +// } +// +// @Override +// public void addModels(ResourceLocation... ids) { +// /* no-op on dynamic model loader */ +// } +// +// @Override +// public void addModels(Collection ids) { +// /* no-op on dynamic model loader */ +// } +// +// @Override +// public void registerBlockStateResolver(Block block, BlockStateResolver resolver) { +// resolvers.put(block, resolver); +// } +// +// public void fireResolvers() { +// resolvers.forEach((block, resolver) -> { +// resolver.resolveBlockStates(new BlockStateResolver.Context() { +// @Override +// public Block block() { +// return block; +// } +// +// @Override +// public void setModel(BlockState state, UnbakedBlockStateModel model) { +// provider.addUnbakedBlockStateOverride(BlockModelShaper.stateToModelLocation(state), model); +// } +// }); +// }); +// } +// +// @Override +// public Event modifyModelOnLoad() { +// return onLoadModifiers; +// } +// +// @Override +// public Event modifyBlockModelOnLoad() { +// return onLoadBlockModifiers; +// } +// +// @Override +// public Event modifyModelBeforeBake() { +// return beforeBakeModifiers; +// } +// +// @Override +// public Event modifyModelAfterBake() { +// return afterBakeModifiers; +// } +// +// @Override +// public Event modifyBlockModelBeforeBake() { +// return beforeBakeBlockModifiers; +// } +// +// @Override +// public Event modifyBlockModelAfterBake() { +// return afterBakeBlockModifiers; +// } +// } +//} diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java deleted file mode 100644 index 27dc727d..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import net.minecraft.client.resources.model.*; -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 java.util.*; - -public class ModelBakeryHelpers { - private static , V extends T> BlockState setPropertyGeneric(BlockState state, Property prop, Object o) { - return state.setValue(prop, (V)o); - } - - private static > T getValueHelper(Property property, String value) { - return property.getValue(value).orElse(null); - } - - private static final Splitter COMMA_SPLITTER = Splitter.on(','); - private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2); - - public static ImmutableList getBlockStatesForMRL(StateDefinition stateDefinition, ModelResourceLocation location) { - if(Objects.equals(location.getVariant(), "inventory")) - return ImmutableList.of(); - Set> fixedProperties = new HashSet<>(); - BlockState fixedState = stateDefinition.any(); - for(String s : COMMA_SPLITTER.split(location.getVariant())) { - Iterator iterator = EQUAL_SPLITTER.split(s).iterator(); - if (iterator.hasNext()) { - String s1 = iterator.next(); - Property property = stateDefinition.getProperty(s1); - if (property != null && iterator.hasNext()) { - String s2 = iterator.next(); - Object value = getValueHelper(property, s2); - if (value == null) { - throw new RuntimeException("Unknown value: '" + s2 + "' for blockstate property: '" + s1 + "' " + property.getPossibleValues()); - } - fixedState = setPropertyGeneric(fixedState, property, value); - fixedProperties.add(property); - } else if (!s1.isEmpty()) { - throw new RuntimeException("Unknown blockstate property: '" + s1 + "'"); - } - } - } - // check if there is only one possible state - if(fixedProperties.size() == stateDefinition.getProperties().size()) { - return ImmutableList.of(fixedState); - } - // generate all possible blockstates from the remaining properties - ArrayList> anyProperties = new ArrayList<>(stateDefinition.getProperties()); - anyProperties.removeAll(fixedProperties); - ArrayList finalList = new ArrayList<>(); - finalList.add(fixedState); - for(Property property : anyProperties) { - ArrayList newPermutations = new ArrayList<>(); - for(BlockState state : finalList) { - for(Comparable value : property.getPossibleValues()) { - newPermutations.add(setPropertyGeneric(state, property, value)); - } - } - finalList = newPermutations; - } - return ImmutableList.copyOf(finalList); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java deleted file mode 100644 index 6b0a1d45..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.concurrent.ExecutionException; - -public class ModelLocationCache { - private static final LoadingCache blockLocationCache = CacheBuilder.newBuilder() - .maximumSize(10000) - .build(new CacheLoader() { - @Override - public ModelResourceLocation load(BlockState key) throws Exception { - return BlockModelShaper.stateToModelLocation(key); - } - }); - - private static final LoadingCache itemLocationCache = CacheBuilder.newBuilder() - .maximumSize(10000) - .build(new CacheLoader() { - @Override - public ModelResourceLocation load(Item key) throws Exception { - return new ModelResourceLocation(BuiltInRegistries.ITEM.getKey(key), "inventory"); - } - }); - - public static ModelResourceLocation get(BlockState state) { - if(state == null) - return null; - try { - return blockLocationCache.get(state); - } catch(ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - } - - public static ModelResourceLocation get(Item item) { - if(item == null) - return null; - try { - return itemLocationCache.get(item); - } catch(ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java b/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java deleted file mode 100644 index 61a06b19..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.embeddedt.modernfix.render; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.client.renderer.block.model.BakedQuad; -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.util.RandomSource; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * 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, RandomSource rand) { - boolean isWholeListValid = isCorrectDirectionForType(side); - List realList = wrappedItem.getQuads(state, side, rand); - if (isWholeListValid) { - return realList; - } - nullQuadList.clear(); - //noinspection ForLoopReplaceableByForEach - 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 TextureAtlasSprite getParticleIcon() { - return wrappedItem.getParticleIcon(); - } - - @Override - public ItemTransforms getTransforms() { - return wrappedItem.getTransforms(); - } -} - diff --git a/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java b/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java index 9de52fcc..f18ca47a 100644 --- a/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java +++ b/common/src/main/java/org/embeddedt/modernfix/screen/OptionList.java @@ -41,7 +41,7 @@ public class OptionList extends ContainerObjectSelectionList { String friendlyKey = "modernfix.option.name." + option.getName(); MutableComponent baseComponent = Component.literal(option.getSelfName()); if(I18n.exists(friendlyKey)) - return Component.translatable(friendlyKey).withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, baseComponent))); + return Component.translatable(friendlyKey).withStyle(style -> style.withHoverEvent(new HoverEvent.ShowText(baseComponent))); else return baseComponent; } @@ -78,7 +78,7 @@ public class OptionList extends ContainerObjectSelectionList { for(String category : theCategories) { String categoryTranslationKey = "modernfix.option.category." + category; this.addEntry(new CategoryEntry(Component.translatable(categoryTranslationKey) - .withStyle(Style.EMPTY.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable(categoryTranslationKey + ".description")))) + .withStyle(Style.EMPTY.withHoverEvent(new HoverEvent.ShowText(Component.translatable(categoryTranslationKey + ".description")))) )); optionsByCategory.get(category).stream().filter(key -> { int dotCount = 0; diff --git a/common/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java b/common/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java deleted file mode 100644 index e2f61b6a..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.embeddedt.modernfix.util; - -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -public class ItemMesherMap implements Map { - private final Function getLocation; - - public ItemMesherMap(Function getLocation) { - this.getLocation = getLocation; - } - - @Override - public int size() { - return BuiltInRegistries.ITEM.keySet().size(); - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean containsKey(Object key) { - return true; - } - - @Override - public boolean containsValue(Object value) { - return false; - } - - @Override - public ModelResourceLocation get(Object key) { - return getLocation.apply((K)key); - } - - @Nullable - @Override - public ModelResourceLocation put(K key, ModelResourceLocation value) { - throw new UnsupportedOperationException(); - } - - @Override - public ModelResourceLocation remove(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(@NotNull Map m) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set keySet() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Collection values() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java b/common/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java index 37c8d223..b273f423 100644 --- a/common/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java +++ b/common/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java @@ -1,5 +1,7 @@ package org.embeddedt.modernfix.world; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; @@ -9,6 +11,7 @@ import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.saveddata.SavedDataType; import java.util.ArrayList; import java.util.List; @@ -20,11 +23,22 @@ public class StrongholdLocationCache extends SavedData { chunkPosList = new ArrayList<>(); } - public static SavedData.Factory factory(ServerLevel serverLevel) { - // FIXME datafixer will probably throw on update - return new SavedData.Factory<>(StrongholdLocationCache::new, StrongholdLocationCache::load, DataFixTypes.SAVED_DATA_FORCED_CHUNKS); + private StrongholdLocationCache(List list) { + this.chunkPosList = new ArrayList<>(list); } + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group(ChunkPos.CODEC.listOf().optionalFieldOf("stronghold_positions", List.of()).forGetter(StrongholdLocationCache::getChunkPosList)) + .apply(instance, StrongholdLocationCache::new) + ); + + public static final SavedDataType TYPE = new SavedDataType<>( + "modernfix_stronghold_cache", + StrongholdLocationCache::new, + CODEC, + DataFixTypes.SAVED_DATA_FORCED_CHUNKS + ); + public List getChunkPosList() { return new ArrayList<>(chunkPosList); } @@ -33,30 +47,4 @@ public class StrongholdLocationCache extends SavedData { this.chunkPosList = new ArrayList<>(positions); this.setDirty(); } - - public static StrongholdLocationCache load(CompoundTag arg, HolderLookup.Provider provider) { - StrongholdLocationCache cache = new StrongholdLocationCache(); - if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) { - long[] positions = arg.getLongArray("Positions"); - for(long position : positions) { - cache.chunkPosList.add(new ChunkPos(position)); - } - } - return cache; - } - - @Override - public CompoundTag save(CompoundTag compoundTag, HolderLookup.Provider provider) { - long[] serialized = new long[chunkPosList.size()]; - for(int i = 0; i < chunkPosList.size(); i++) { - ChunkPos thePos = chunkPosList.get(i); - serialized[i] = thePos.toLong(); - } - compoundTag.putLongArray("Positions", serialized); - return compoundTag; - } - - public static String getFileId(Holder dimensionType) { - return "mfix_strongholds"; - } } diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 58225424..dd046d83 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -43,7 +43,7 @@ accessible method net/minecraft/client/resources/model/ModelBakery$BakedCacheKey accessible class net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl accessible class net/minecraft/client/resources/model/ModelManager$ReloadState accessible method net/minecraft/client/resources/model/BlockStateModelLoader definitionLocationToBlockMapper ()Ljava/util/function/Function; -accessible method net/minecraft/client/resources/model/BlockStateModelLoader loadBlockStateDefinitionStack (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/level/block/state/StateDefinition;Ljava/util/List;Lnet/minecraft/client/resources/model/UnbakedModel;)Lnet/minecraft/client/resources/model/BlockStateModelLoader$LoadedModels; +accessible method net/minecraft/client/resources/model/BlockStateModelLoader loadBlockStateDefinitionStack (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/level/block/state/StateDefinition;Ljava/util/List;)Lnet/minecraft/client/resources/model/BlockStateModelLoader$LoadedModels; accessible class net/minecraft/client/resources/model/BlockStateModelLoader$LoadedBlockModelDefinition accessible method net/minecraft/client/resources/model/BlockStateModelLoader$LoadedBlockModelDefinition (Ljava/lang/String;Lnet/minecraft/client/renderer/block/model/BlockModelDefinition;)V accessible class net/minecraft/world/level/chunk/PalettedContainer$Data @@ -53,3 +53,8 @@ accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (L accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map; accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec; accessible class net/minecraft/client/multiplayer/SessionSearchTrees$Key + +accessible class net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper +accessible method net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/UnbakedModel;Z)V +accessible field net/minecraft/client/resources/model/ModelDiscovery$ModelWrapper parent Lnet/minecraft/client/resources/model/ModelDiscovery$ModelWrapper; +accessible method net/minecraft/client/resources/model/BlockStateDefinitions definitionLocationToBlockStateMapper ()Ljava/util/function/Function; \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 14e6b112..26a3b60e 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -33,7 +33,11 @@ dependencies { modCompileOnly(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } - modCompileOnly(fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + try { + modCompileOnly(fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + } catch(ignored) { + // already reported in common + } modCompileOnly(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false } 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 deleted file mode 100644 index e120bc91..00000000 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/safety/DynamicTextureMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.embeddedt.modernfix.fabric.mixin.safety; - -import com.mojang.blaze3d.platform.NativeImage; -import net.minecraft.client.renderer.texture.DynamicTexture; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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) -@ClientOnlyMixin -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(); - } -} diff --git a/gradle.properties b/gradle.properties index c65e72b1..9dd79b73 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,8 +5,8 @@ junit_version=5.10.0-M1 mixinextras_version=0.4.1 mod_id=modernfix -minecraft_version=1.21.4 -enabled_platforms=fabric,neoforge +minecraft_version=25w07a +enabled_platforms=fabric forge_version=21.4.47-beta parchment_version=2024.12.22 parchment_mc_version=1.21.4 @@ -17,10 +17,10 @@ ctm_version=1.21-1.2.0+2 ldlib_version=5782845 kubejs_version=1902.6.0-build.142 rhino_version=1902.2.2-build.268 -supported_minecraft_versions=1.21.4 +supported_minecraft_versions=25w07a fabric_loader_version=0.16.10 -fabric_api_version=0.113.0+1.21.4 +fabric_api_version=0.116.1+1.21.5 continuity_version=3.0.0-beta.4+1.20.2