diff --git a/fabric-model-loading-api-v1/build.gradle b/fabric-model-loading-api-v1/build.gradle index b2e004433..2f932885f 100644 --- a/fabric-model-loading-api-v1/build.gradle +++ b/fabric-model-loading-api-v1/build.gradle @@ -3,12 +3,8 @@ version = getSubprojectVersion(project) moduleDependencies(project, ['fabric-api-base']) testDependencies(project, [ - ':fabric-renderer-api-v1', - ':fabric-renderer-indigo', +// ':fabric-renderer-api-v1', +// ':fabric-renderer-indigo', ':fabric-rendering-v1', ':fabric-resource-loader-v0' ]) - -loom { - accessWidenerPath = file('src/client/resources/fabric-model-loading-api-v1.accesswidener') -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/BlockStateResolver.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/BlockStateResolver.java index f8623a266..0b2cd29f9 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/BlockStateResolver.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/BlockStateResolver.java @@ -20,20 +20,21 @@ import org.jetbrains.annotations.ApiStatus; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.GroupableModel; +import net.minecraft.client.render.model.BlockStateModel; /** - * Block state resolvers are responsible for mapping each {@link BlockState} of a block to a {@link GroupableModel}. - * They replace the {@code blockstates/} JSON files. One block can be mapped to only one block state resolver; multiple - * resolvers will not receive the same block. + * Block state resolvers are responsible for mapping each {@link BlockState} of a block to a + * {@link BlockStateModel.UnbakedGrouped}. They replace the {@code blockstates/} JSON files. One block can be mapped to + * only one block state resolver; multiple resolvers will not receive the same block. * * <p>Block state resolvers can be used to create custom block state formats or dynamically resolve block state models. * * <p>Use {@link ModelModifier.OnLoad} instead of this interface if interacting with the block and block states directly - * is not necessary. This includes custom model deserializers and loaders. + * is not necessary. Use {@link UnbakedModelDeserializer} for custom model deserializers and loaders. * * @see ModelModifier.OnLoad * @see ModelModifier.OnLoadBlock + * @see UnbakedModelDeserializer */ @FunctionalInterface public interface BlockStateResolver { @@ -64,6 +65,6 @@ public interface BlockStateResolver { * @param state the block state for which this model should be used * @param model the unbaked model for this block state */ - void setModel(BlockState state, GroupableModel model); + void setModel(BlockState state, BlockStateModel.UnbakedGrouped model); } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/FabricBakedModelManager.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/FabricBakedModelManager.java deleted file mode 100644 index e0b8caba0..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/FabricBakedModelManager.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.api.client.model.loading.v1; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.util.Identifier; - -/** - * Fabric-provided helper methods for {@link BakedModelManager}. - * - * <p>Note: This interface is automatically implemented on the {@link BakedModelManager} via Mixin and interface injection. - */ -public interface FabricBakedModelManager { - /** - * Similar to {@link BakedModelManager#getModel(ModelIdentifier)}, but accepts an {@link Identifier} instead of a - * {@link ModelIdentifier}. Use this method to retrieve models loaded using - * {@link ModelLoadingPlugin.Context#addModels}, since those models do not have corresponding - * {@link ModelIdentifier}s. - * - * <p><b>This method, as well as its vanilla counterpart, should only be used after the - * {@link BakedModelManager} has completed reloading.</b> Otherwise, the result will be - * outdated or an exception will be thrown. - * - * @param id the id of the model - * @return the model - */ - default BakedModel getModel(Identifier id) { - throw new UnsupportedOperationException("Implemented via mixin."); - } -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelLoadingPlugin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelLoadingPlugin.java index a9138c92e..800e47cb5 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelLoadingPlugin.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelLoadingPlugin.java @@ -16,7 +16,6 @@ package net.fabricmc.fabric.api.client.model.loading.v1; -import java.util.Collection; import java.util.List; import org.jetbrains.annotations.ApiStatus; @@ -24,7 +23,6 @@ import org.jetbrains.annotations.UnmodifiableView; import net.minecraft.block.Block; import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingPluginManager; @@ -60,18 +58,6 @@ public interface ModelLoadingPlugin { @ApiStatus.NonExtendable interface Context { - /** - * Adds one or more models that will be loaded, baked, and made available through - * {@link FabricBakedModelManager#getModel(Identifier)}. - */ - void addModels(Identifier... ids); - - /** - * Adds multiple models that will be loaded, baked, and made available through - * {@link FabricBakedModelManager#getModel(Identifier)}. - */ - void addModels(Collection<? extends Identifier> ids); - /** * Registers a block state resolver for a block. * @@ -83,24 +69,11 @@ public interface ModelLoadingPlugin { /** * Event access to monitor unbaked model loads and replace the loaded model. * - * <p>Replacements done by listeners of this callback <b>do</b> affect child models (that is, models whose - * parent hierarchy contains the replaced model), unlike {@link #modifyModelBeforeBake}. + * <p>Replacements done by listeners of this callback affect child models (that is, models whose + * parent hierarchy contains the replaced model). */ Event<ModelModifier.OnLoad> modifyModelOnLoad(); - /** - * Event access to replace the unbaked model used for baking without replacing the cached model. - * - * <p>Replacements done by listeners of this callback <b>do not</b> affect child models (that is, models whose - * parent hierarchy contains the replaced model), unlike {@link #modifyModelOnLoad}. - */ - Event<ModelModifier.BeforeBake> modifyModelBeforeBake(); - - /** - * Event access to replace the baked model. - */ - Event<ModelModifier.AfterBake> modifyModelAfterBake(); - /** * Event access to monitor unbaked block model loads and replace the loaded model. */ @@ -115,5 +88,15 @@ public interface ModelLoadingPlugin { * Event access to replace the baked block model. */ Event<ModelModifier.AfterBakeBlock> modifyBlockModelAfterBake(); + + /** + * Event access to replace the unbaked item model used for baking. + */ + Event<ModelModifier.BeforeBakeItem> modifyItemModelBeforeBake(); + + /** + * Event access to replace the baked item model. + */ + Event<ModelModifier.AfterBakeItem> modifyItemModelAfterBake(); } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java index 95ad0a464..93b0eb40a 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/ModelModifier.java @@ -17,16 +17,13 @@ package net.fabricmc.fabric.api.client.model.loading.v1; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.item.model.ItemModel; import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.GroupableModel; -import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.client.render.model.ResolvableModel; import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.util.ModelIdentifier; import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.event.Event; @@ -37,8 +34,8 @@ import net.fabricmc.fabric.api.event.Event; * * <p>Example use cases: * <ul> - * <li>Overriding the model for a particular block state - check if the given identifier matches the identifier - * for that block state. If so, return your desired model, otherwise return the given model.</li> + * <li>Overriding the model for a particular block state - check if the given block state matches the desired block + * state. If so, return your desired model, otherwise return the given model.</li> * <li>Wrapping a model to override certain behaviors - simply return a new model instance and delegate calls * to the original model as needed.</li> * </ul> @@ -47,6 +44,10 @@ import net.fabricmc.fabric.api.event.Event; * and separate phases are provided for mods that wrap their own models and mods that need to wrap models of other mods * or wrap models arbitrarily. * + * <p>Any event may be invoked concurrently with other invocations of the same event or other events, subject to + * reasonable constraints. For example, a block/item model and its dependencies must be loaded before the block/item + * model is baked. + * * <p>These callbacks are invoked for <b>every single model that is loaded or baked</b>, so implementations should be * as efficient as possible. */ @@ -72,15 +73,7 @@ public final class ModelModifier { @FunctionalInterface public interface OnLoad { /** - * This handler is invoked to allow modification of an unbaked model right after it is first loaded and before - * it is cached. - * - * <p>If the given model is {@code null}, its corresponding identifier was requested during - * {@linkplain ResolvableModel#resolve resolution} but the model was not loaded normally; i.e. through a JSON - * file, possibly because that file did not exist. If a non-{@code null} model is returned in this case, - * resolution will continue without warnings or errors. This callback can return a {@code null} model, which - * has the same meaning as described earlier, so it is unlikely that an implementor should need to return - * {@code null} unless directly returning the given model. + * This handler is invoked to allow modification of an unbaked model right after it is first loaded. * * <p>For further information, see the docs of {@link ModelLoadingPlugin.Context#modifyModelOnLoad()}. * @@ -89,8 +82,7 @@ public final class ModelModifier { * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. * @see ModelLoadingPlugin.Context#modifyModelOnLoad */ - @Nullable - UnbakedModel modifyModelOnLoad(@Nullable UnbakedModel model, Context context); + UnbakedModel modifyModelOnLoad(UnbakedModel model, Context context); /** * The context for an on load model modification event. @@ -104,86 +96,6 @@ public final class ModelModifier { } } - @FunctionalInterface - public interface BeforeBake { - /** - * This handler is invoked to allow modification of the unbaked model instance right before it is baked. - * - * <p>For further information, see the docs of {@link ModelLoadingPlugin.Context#modifyModelBeforeBake()}. - * - * @param model the current unbaked model instance - * @param context context with additional information about the model/loader - * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. - * @see ModelLoadingPlugin.Context#modifyModelBeforeBake - */ - UnbakedModel modifyModelBeforeBake(UnbakedModel model, Context context); - - /** - * The context for a before bake model modification event. - */ - @ApiStatus.NonExtendable - interface Context { - /** - * The identifier of the model being baked. - */ - Identifier id(); - - /** - * The settings this model is being baked with. - */ - ModelBakeSettings settings(); - - /** - * The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and - * {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously - * {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model. - */ - Baker baker(); - } - } - - @FunctionalInterface - public interface AfterBake { - /** - * This handler is invoked to allow modification of the baked model instance right after it is baked and before - * it is cached. - * - * @param model the current baked model instance - * @param context context with additional information about the model/loader - * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. - * @see ModelLoadingPlugin.Context#modifyModelAfterBake - */ - BakedModel modifyModelAfterBake(BakedModel model, Context context); - - /** - * The context for an after bake model modification event. - */ - @ApiStatus.NonExtendable - interface Context { - /** - * The identifier of the model being baked. - */ - Identifier id(); - - /** - * The unbaked model that is being baked. - */ - UnbakedModel sourceModel(); - - /** - * The settings this model is being baked with. - */ - ModelBakeSettings settings(); - - /** - * The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and - * {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously - * {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model. - */ - Baker baker(); - } - } - @FunctionalInterface public interface OnLoadBlock { /** @@ -194,18 +106,13 @@ public final class ModelModifier { * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. * @see ModelLoadingPlugin.Context#modifyBlockModelOnLoad */ - GroupableModel modifyModelOnLoad(GroupableModel model, Context context); + BlockStateModel.UnbakedGrouped modifyModelOnLoad(BlockStateModel.UnbakedGrouped model, Context context); /** * The context for an on load block model modification event. */ @ApiStatus.NonExtendable interface Context { - /** - * The identifier of the model that was loaded. - */ - ModelIdentifier id(); - /** * The corresponding block state of the model that was loaded. */ @@ -223,7 +130,7 @@ public final class ModelModifier { * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. * @see ModelLoadingPlugin.Context#modifyBlockModelBeforeBake */ - GroupableModel modifyModelBeforeBake(GroupableModel model, Context context); + BlockStateModel.UnbakedGrouped modifyModelBeforeBake(BlockStateModel.UnbakedGrouped model, Context context); /** * The context for a before bake block model modification event. @@ -231,14 +138,16 @@ public final class ModelModifier { @ApiStatus.NonExtendable interface Context { /** - * The identifier of the model being baked. + * The corresponding block state of the model being baked. */ - ModelIdentifier id(); + BlockState state(); /** - * The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and - * {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously - * {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model. + * The baker being used to bake this model. It can be used to + * {@linkplain Baker#getModel get resolved models} and {@linkplain Baker#getSpriteGetter get sprites}. Note + * that retrieving a model which was not previously + * {@linkplain ResolvableModel.Resolver#markDependency discovered} will log a warning and return the missing + * model. */ Baker baker(); } @@ -254,7 +163,7 @@ public final class ModelModifier { * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. * @see ModelLoadingPlugin.Context#modifyBlockModelAfterBake */ - BakedModel modifyModelAfterBake(BakedModel model, Context context); + BlockStateModel modifyModelAfterBake(BlockStateModel model, Context context); /** * The context for an after bake block model modification event. @@ -262,23 +171,88 @@ public final class ModelModifier { @ApiStatus.NonExtendable interface Context { /** - * The identifier of the model being baked. + * The corresponding block state of the model being baked. */ - ModelIdentifier id(); + BlockState state(); /** * The unbaked model that is being baked. */ - GroupableModel sourceModel(); + BlockStateModel.UnbakedGrouped sourceModel(); /** - * The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and - * {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously - * {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model. + * The baker being used to bake this model. It can be used to + * {@linkplain Baker#getModel get resolved models} and {@linkplain Baker#getSpriteGetter get sprites}. Note + * that retrieving a model which was not previously + * {@linkplain ResolvableModel.Resolver#markDependency discovered} will log a warning and return the missing + * model. */ Baker baker(); } } + @FunctionalInterface + public interface BeforeBakeItem { + /** + * This handler is invoked to allow modification of the unbaked item model instance right before it is baked. + * + * @param model the current unbaked model instance + * @param context context with additional information about the model/loader + * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. + * @see ModelLoadingPlugin.Context#modifyItemModelBeforeBake + */ + ItemModel.Unbaked modifyModelBeforeBake(ItemModel.Unbaked model, Context context); + + /** + * The context for a before bake item model modification event. + */ + @ApiStatus.NonExtendable + interface Context { + /** + * The corresponding item ID of the model being baked. + */ + Identifier itemId(); + + /** + * The vanilla context being used to bake this model. + */ + ItemModel.BakeContext bakeContext(); + } + } + + @FunctionalInterface + public interface AfterBakeItem { + /** + * This handler is invoked to allow modification of the baked item model instance right after it is baked. + * + * @param model the current baked model instance + * @param context context with additional information about the model/loader + * @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is. + * @see ModelLoadingPlugin.Context#modifyItemModelAfterBake + */ + ItemModel modifyModelAfterBake(ItemModel model, Context context); + + /** + * The context for an after bake item model modification event. + */ + @ApiStatus.NonExtendable + interface Context { + /** + * The corresponding item ID of the model being baked. + */ + Identifier itemId(); + + /** + * The unbaked model that is being baked. + */ + ItemModel.Unbaked sourceModel(); + + /** + * The vanilla context being used to bake this model. + */ + ItemModel.BakeContext bakeContext(); + } + } + private ModelModifier() { } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnbakedModelDeserializer.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnbakedModelDeserializer.java index d975e6d2f..dbec5586d 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnbakedModelDeserializer.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnbakedModelDeserializer.java @@ -27,7 +27,6 @@ import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.json.JsonUnbakedModel; import net.minecraft.client.render.model.json.ModelElement; import net.minecraft.client.render.model.json.ModelElementFace; -import net.minecraft.client.render.model.json.ModelElementTexture; import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.render.model.json.Transformation; import net.minecraft.util.Identifier; @@ -87,7 +86,6 @@ public interface UnbakedModelDeserializer { * <li>{@link UnbakedModel}</li> * <li>{@link ModelElement}</li> * <li>{@link ModelElementFace}</li> - * <li>{@link ModelElementTexture}</li> * <li>{@link Transformation}</li> * <li>{@link ModelTransformation}</li> * </ul> diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnwrappableBakedModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnwrappableBakedModel.java deleted file mode 100644 index 7ce825380..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/UnwrappableBakedModel.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.api.client.model.loading.v1; - -import java.util.function.Predicate; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.WrapperBakedModel; - -/** - * An interface to be implemented by models that wrap and replace another model, such as {@link WrapperBakedModel}. - * This allows mods to access the wrapped model without having to know the exact type of the wrapper model. - * - * <p>If you need to access data stored in one of your {@link BakedModel} subclasses, - * and you would normally access the model by its identifier and then cast it: - * call {@link #unwrap(BakedModel, Predicate)} on the model first, in case another - * mod is wrapping your model to alter its rendering. - * - * <p>Note: This interface is automatically implemented on {@link WrapperBakedModel} and subclasses via Mixin and - * interface injection. - */ -public interface UnwrappableBakedModel { - /** - * Return the wrapped model, if there is one at the moment, or {@code null} otherwise. - * - * <p>If there are multiple layers of wrapping, this method does not necessarily return the innermost model. - */ - @Nullable - default BakedModel getWrappedModel() { - return null; - } - - /** - * Iteratively unwrap the given model until the given condition returns true or all models in the hierarchy have - * been tested. If no model passes the condition, null is returned. - * - * <p>A good use of this method is to safely cast a model to an expected type, by passing - * {@code model -> model instanceof MyCustomBakedModel} as the condition. - */ - @Nullable - static BakedModel unwrap(BakedModel model, Predicate<BakedModel> condition) { - while (!condition.test(model)) { - if (model instanceof UnwrappableBakedModel wrapper) { - BakedModel wrapped = wrapper.getWrappedModel(); - - if (wrapped == null) { - return null; - } else if (wrapped == model) { - throw new IllegalArgumentException("Model " + model + " is wrapping itself!"); - } else { - model = wrapped; - } - } else { - return null; - } - } - - return model; - } - - /** - * Fully unwrap a model, i.e. return the innermost model. - */ - static BakedModel unwrap(BakedModel model) { - while (model instanceof UnwrappableBakedModel wrapper) { - BakedModel wrapped = wrapper.getWrappedModel(); - - if (wrapped == null) { - return model; - } else if (wrapped == model) { - throw new IllegalArgumentException("Model " + model + " is wrapping itself!"); - } else { - model = wrapped; - } - } - - return model; - } -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBakedItemModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBakedItemModel.java new file mode 100644 index 000000000..c23df337b --- /dev/null +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBakedItemModel.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.model.loading.v1.wrapper; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.client.item.ItemModelManager; +import net.minecraft.client.render.item.ItemRenderState; +import net.minecraft.client.render.item.model.ItemModel; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemDisplayContext; +import net.minecraft.item.ItemStack; + +/** + * A simple implementation of {@link ItemModel} that delegates all method calls to the {@link #wrapped} field. + * Implementations must set the {@link #wrapped} field somehow. + */ +public abstract class WrapperBakedItemModel implements ItemModel { + protected ItemModel wrapped; + + protected WrapperBakedItemModel() { + } + + protected WrapperBakedItemModel(ItemModel wrapped) { + this.wrapped = wrapped; + } + + @Override + public void update(ItemRenderState state, ItemStack stack, ItemModelManager resolver, ItemDisplayContext displayContext, @Nullable ClientWorld world, @Nullable LivingEntity user, int seed) { + wrapped.update(state, stack, resolver, displayContext, world, user, seed); + } +} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java new file mode 100644 index 000000000..8e204bb81 --- /dev/null +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperBlockStateModel.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.model.loading.v1.wrapper; + +import java.util.List; + +import net.minecraft.client.render.model.BlockModelPart; +import net.minecraft.client.render.model.BlockStateModel; +import net.minecraft.client.texture.Sprite; +import net.minecraft.util.math.random.Random; + +// TODO: FRAPI overrides +/** + * A simple implementation of {@link BlockStateModel} that delegates all method calls to the {@link #wrapped} field. + * Implementations must set the {@link #wrapped} field somehow. + */ +public abstract class WrapperBlockStateModel implements BlockStateModel { + protected BlockStateModel wrapped; + + protected WrapperBlockStateModel() { + } + + protected WrapperBlockStateModel(BlockStateModel wrapped) { + this.wrapped = wrapped; + } + + @Override + public void addParts(Random random, List<BlockModelPart> parts) { + wrapped.addParts(random, parts); + } + + @Override + public List<BlockModelPart> getParts(Random random) { + return wrapped.getParts(random); + } + + @Override + public Sprite particleSprite() { + return wrapped.particleSprite(); + } +} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperGroupableModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedGroupedBlockStateModel.java similarity index 57% rename from fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperGroupableModel.java rename to fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedGroupedBlockStateModel.java index 8a65c11a6..5f81c9517 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperGroupableModel.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedGroupedBlockStateModel.java @@ -14,39 +14,38 @@ * limitations under the License. */ -package net.fabricmc.fabric.api.client.model.loading.v1; +package net.fabricmc.fabric.api.client.model.loading.v1.wrapper; import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.GroupableModel; +import net.minecraft.client.render.model.BlockStateModel; /** - * A simple implementation of {@link GroupableModel} that delegates all method calls to the {@link #wrapped} field. - * Implementations must set the {@link #wrapped} field somehow. + * A simple implementation of {@link BlockStateModel.UnbakedGrouped} that delegates all method calls to the + * {@link #wrapped} field. Implementations must set the {@link #wrapped} field somehow. */ -public abstract class WrapperGroupableModel implements GroupableModel { - protected GroupableModel wrapped; +public abstract class WrapperUnbakedGroupedBlockStateModel implements BlockStateModel.UnbakedGrouped { + protected BlockStateModel.UnbakedGrouped wrapped; - protected WrapperGroupableModel() { + protected WrapperUnbakedGroupedBlockStateModel() { } - protected WrapperGroupableModel(GroupableModel wrapped) { + protected WrapperUnbakedGroupedBlockStateModel(BlockStateModel.UnbakedGrouped wrapped) { this.wrapped = wrapped; } @Override - public void resolve(Resolver resolver) { - wrapped.resolve(resolver); - } - - @Override - public BakedModel bake(Baker baker) { - return wrapped.bake(baker); + public BlockStateModel getModel(BlockState state, Baker baker) { + return wrapped.getModel(state, baker); } @Override public Object getEqualityGroup(BlockState state) { return wrapped.getEqualityGroup(state); } + + @Override + public void resolve(Resolver resolver) { + wrapped.resolve(resolver); + } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedItemModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedItemModel.java new file mode 100644 index 000000000..4669ca371 --- /dev/null +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedItemModel.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.model.loading.v1.wrapper; + +import com.mojang.serialization.MapCodec; + +import net.minecraft.client.render.item.model.ItemModel; + +/** + * A simple implementation of {@link ItemModel.Unbaked} that delegates all method calls to the {@link #wrapped} field. + * Implementations must set the {@link #wrapped} field somehow. + */ +public abstract class WrapperUnbakedItemModel implements ItemModel.Unbaked { + protected ItemModel.Unbaked wrapped; + + protected WrapperUnbakedItemModel() { + } + + protected WrapperUnbakedItemModel(ItemModel.Unbaked wrapped) { + this.wrapped = wrapped; + } + + @Override + public void resolve(Resolver resolver) { + wrapped.resolve(resolver); + } + + @Override + public MapCodec<? extends ItemModel.Unbaked> getCodec() { + return wrapped.getCodec(); + } + + @Override + public ItemModel bake(ItemModel.BakeContext context) { + return wrapped.bake(context); + } +} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperUnbakedModel.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedModel.java similarity index 59% rename from fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperUnbakedModel.java rename to fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedModel.java index 7a4f382a2..3fbc52914 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/WrapperUnbakedModel.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/api/client/model/loading/v1/wrapper/WrapperUnbakedModel.java @@ -14,16 +14,15 @@ * limitations under the License. */ -package net.fabricmc.fabric.api.client.model.loading.v1; +package net.fabricmc.fabric.api.client.model.loading.v1.wrapper; import org.jetbrains.annotations.Nullable; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.Geometry; import net.minecraft.client.render.model.ModelTextures; import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.util.Identifier; /** * A simple implementation of {@link UnbakedModel} that delegates all method calls to the {@link #wrapped} field. @@ -40,41 +39,37 @@ public abstract class WrapperUnbakedModel implements UnbakedModel { } @Override - public void resolve(Resolver resolver) { - wrapped.resolve(resolver); - } - - @Override - public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) { - return wrapped.bake(textures, baker, settings, ambientOcclusion, isSideLit, transformation); + @Nullable + public Boolean ambientOcclusion() { + return wrapped.ambientOcclusion(); } @Override @Nullable - public Boolean getAmbientOcclusion() { - return wrapped.getAmbientOcclusion(); + public GuiLight guiLight() { + return wrapped.guiLight(); } @Override @Nullable - public GuiLight getGuiLight() { - return wrapped.getGuiLight(); + public ModelTransformation transformations() { + return wrapped.transformations(); + } + + @Override + public ModelTextures.Textures textures() { + return wrapped.textures(); } @Override @Nullable - public ModelTransformation getTransformation() { - return wrapped.getTransformation(); - } - - @Override - public ModelTextures.Textures getTextures() { - return wrapped.getTextures(); + public Geometry geometry() { + return wrapped.geometry(); } @Override @Nullable - public UnbakedModel getParent() { - return wrapped.getParent(); + public Identifier parent() { + return wrapped.parent(); } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/BakedModelsHooks.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/BakedModelsHooks.java deleted file mode 100644 index 94f202ec1..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/BakedModelsHooks.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.client.model.loading; - -import java.util.Map; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.util.Identifier; - -public interface BakedModelsHooks { - @Nullable - Map<Identifier, BakedModel> fabric_getExtraModels(); - - void fabric_setExtraModels(@Nullable Map<Identifier, BakedModel> extraModels); -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelBakerHooks.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelBakerHooks.java deleted file mode 100644 index c6a245e6e..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelBakerHooks.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.client.model.loading; - -import org.jetbrains.annotations.Nullable; - -public interface ModelBakerHooks { - @Nullable - ModelLoadingEventDispatcher fabric_getDispatcher(); -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingEventDispatcher.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingEventDispatcher.java index ad9be411c..8004dca95 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingEventDispatcher.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingEventDispatcher.java @@ -20,12 +20,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.function.BiConsumer; -import java.util.function.Consumer; import com.google.common.collect.ImmutableList; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; import org.jetbrains.annotations.Nullable; @@ -34,16 +32,11 @@ import org.slf4j.LoggerFactory; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.client.render.block.BlockModels; -import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.item.model.ItemModel; import net.minecraft.client.render.model.Baker; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.client.render.model.BlockStatesLoader; -import net.minecraft.client.render.model.GroupableModel; -import net.minecraft.client.render.model.ModelBakeSettings; import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.client.model.loading.v1.BlockStateResolver; @@ -57,14 +50,8 @@ public class ModelLoadingEventDispatcher { private final ModelLoadingPluginContextImpl pluginContext; private final BlockStateResolverContext blockStateResolverContext = new BlockStateResolverContext(); - private final OnLoadModifierContext onLoadModifierContext = new OnLoadModifierContext(); - private final ObjectArrayList<BeforeBakeModifierContext> beforeBakeModifierContextStack = new ObjectArrayList<>(); - private final ObjectArrayList<AfterBakeModifierContext> afterBakeModifierContextStack = new ObjectArrayList<>(); - private final OnLoadBlockModifierContext onLoadBlockModifierContext = new OnLoadBlockModifierContext(); - private final BeforeBakeBlockModifierContext beforeBakeBlockModifierContext = new BeforeBakeBlockModifierContext(); - private final AfterBakeBlockModifierContext afterBakeBlockModifierContext = new AfterBakeBlockModifierContext(); public ModelLoadingEventDispatcher(List<ModelLoadingPlugin> plugins) { this.pluginContext = new ModelLoadingPluginContextImpl(); @@ -78,90 +65,45 @@ public class ModelLoadingEventDispatcher { } } - public void forEachExtraModel(Consumer<Identifier> extraModelConsumer) { - pluginContext.extraModels.forEach(extraModelConsumer); + public Map<Identifier, UnbakedModel> modifyModelsOnLoad(Map<Identifier, UnbakedModel> models) { + if (!(models instanceof HashMap)) { + models = new HashMap<>(models); + } + + models.replaceAll(this::modifyModelOnLoad); + return models; } - @Nullable - public UnbakedModel modifyModelOnLoad(@Nullable UnbakedModel model, Identifier id) { + private UnbakedModel modifyModelOnLoad(Identifier id, UnbakedModel model) { onLoadModifierContext.prepare(id); return pluginContext.modifyModelOnLoad().invoker().modifyModelOnLoad(model, onLoadModifierContext); } - public UnbakedModel modifyModelBeforeBake(UnbakedModel model, Identifier id, ModelBakeSettings settings, Baker baker) { - if (beforeBakeModifierContextStack.isEmpty()) { - beforeBakeModifierContextStack.add(new BeforeBakeModifierContext()); - } - - BeforeBakeModifierContext context = beforeBakeModifierContextStack.pop(); - context.prepare(id, settings, baker); - - model = pluginContext.modifyModelBeforeBake().invoker().modifyModelBeforeBake(model, context); - - beforeBakeModifierContextStack.push(context); - return model; - } - - public BakedModel modifyModelAfterBake(BakedModel model, Identifier id, UnbakedModel sourceModel, ModelBakeSettings settings, Baker baker) { - if (afterBakeModifierContextStack.isEmpty()) { - afterBakeModifierContextStack.add(new AfterBakeModifierContext()); - } - - AfterBakeModifierContext context = afterBakeModifierContextStack.pop(); - context.prepare(id, sourceModel, settings, baker); - - model = pluginContext.modifyModelAfterBake().invoker().modifyModelAfterBake(model, context); - - afterBakeModifierContextStack.push(context); - return model; - } - - public BlockStatesLoader.BlockStateDefinition modifyBlockModelsOnLoad(BlockStatesLoader.BlockStateDefinition models) { - Map<ModelIdentifier, BlockStatesLoader.BlockModel> map = models.models(); + public BlockStatesLoader.LoadedModels modifyBlockModelsOnLoad(BlockStatesLoader.LoadedModels models) { + Map<BlockState, BlockStateModel.UnbakedGrouped> map = models.models(); if (!(map instanceof HashMap)) { map = new HashMap<>(map); - models = new BlockStatesLoader.BlockStateDefinition(map); + models = new BlockStatesLoader.LoadedModels(map); } putResolvedBlockStates(map); - - map.replaceAll((id, blockModel) -> { - GroupableModel original = blockModel.model(); - GroupableModel modified = modifyBlockModelOnLoad(original, id, blockModel.state()); - - if (original != modified) { - return new BlockStatesLoader.BlockModel(blockModel.state(), modified); - } - - return blockModel; - }); + map.replaceAll(this::modifyBlockModelOnLoad); return models; } - private void putResolvedBlockStates(Map<ModelIdentifier, BlockStatesLoader.BlockModel> map) { + private void putResolvedBlockStates(Map<BlockState, BlockStateModel.UnbakedGrouped> map) { pluginContext.blockStateResolvers.forEach((block, resolver) -> { - Optional<RegistryKey<Block>> optionalKey = Registries.BLOCK.getKey(block); - - if (optionalKey.isEmpty()) { - return; - } - - Identifier blockId = optionalKey.get().getValue(); - - resolveBlockStates(resolver, block, (state, model) -> { - ModelIdentifier modelId = BlockModels.getModelId(blockId, state); - map.put(modelId, new BlockStatesLoader.BlockModel(state, model)); - }); + resolveBlockStates(resolver, block, map::put); }); } - private void resolveBlockStates(BlockStateResolver resolver, Block block, BiConsumer<BlockState, GroupableModel> output) { + private void resolveBlockStates(BlockStateResolver resolver, Block block, BiConsumer<BlockState, BlockStateModel.UnbakedGrouped> output) { BlockStateResolverContext context = blockStateResolverContext; context.prepare(block); - Reference2ReferenceMap<BlockState, GroupableModel> resolvedModels = context.models; + Reference2ReferenceMap<BlockState, BlockStateModel.UnbakedGrouped> resolvedModels = context.models; ImmutableList<BlockState> allStates = block.getStateManager().getStates(); boolean thrown = false; @@ -180,7 +122,7 @@ public class ModelLoadingEventDispatcher { } else { for (BlockState state : allStates) { @Nullable - GroupableModel model = resolvedModels.get(state); + BlockStateModel.UnbakedGrouped model = resolvedModels.get(state); if (model == null) { LOGGER.error("Block state resolver did not provide a model for state {} in block {}. Using missing model.", state, block); @@ -194,24 +136,30 @@ public class ModelLoadingEventDispatcher { resolvedModels.clear(); } - private GroupableModel modifyBlockModelOnLoad(GroupableModel model, ModelIdentifier id, BlockState state) { - onLoadBlockModifierContext.prepare(id, state); + private BlockStateModel.UnbakedGrouped modifyBlockModelOnLoad(BlockState state, BlockStateModel.UnbakedGrouped model) { + onLoadBlockModifierContext.prepare(state); return pluginContext.modifyBlockModelOnLoad().invoker().modifyModelOnLoad(model, onLoadBlockModifierContext); } - public GroupableModel modifyBlockModelBeforeBake(GroupableModel model, ModelIdentifier id, Baker baker) { - beforeBakeBlockModifierContext.prepare(id, baker); - return pluginContext.modifyBlockModelBeforeBake().invoker().modifyModelBeforeBake(model, beforeBakeBlockModifierContext); + public BlockStateModel modifyBlockModel(BlockStateModel.UnbakedGrouped unbakedModel, BlockState state, Baker baker, Operation<BlockStateModel> bakeOperation) { + BakeBlockModifierContext modifierContext = new BakeBlockModifierContext(state, baker); + unbakedModel = pluginContext.modifyBlockModelBeforeBake().invoker().modifyModelBeforeBake(unbakedModel, modifierContext); + BlockStateModel model = bakeOperation.call(unbakedModel, state, baker); + modifierContext.prepareAfterBake(unbakedModel); + return pluginContext.modifyBlockModelAfterBake().invoker().modifyModelAfterBake(model, modifierContext); } - public BakedModel modifyBlockModelAfterBake(BakedModel model, ModelIdentifier id, GroupableModel sourceModel, Baker baker) { - afterBakeBlockModifierContext.prepare(id, sourceModel, baker); - return pluginContext.modifyBlockModelAfterBake().invoker().modifyModelAfterBake(model, afterBakeBlockModifierContext); + public ItemModel modifyItemModel(ItemModel.Unbaked unbakedModel, Identifier itemId, ItemModel.BakeContext bakeContext, Operation<ItemModel> bakeOperation) { + BakeItemModifierContext modifierContext = new BakeItemModifierContext(itemId, bakeContext); + unbakedModel = pluginContext.modifyItemModelBeforeBake().invoker().modifyModelBeforeBake(unbakedModel, modifierContext); + ItemModel model = bakeOperation.call(unbakedModel, bakeContext); + modifierContext.prepareAfterBake(unbakedModel); + return pluginContext.modifyItemModelAfterBake().invoker().modifyModelAfterBake(model, modifierContext); } private static class BlockStateResolverContext implements BlockStateResolver.Context { private Block block; - private final Reference2ReferenceMap<BlockState, GroupableModel> models = new Reference2ReferenceOpenHashMap<>(); + private final Reference2ReferenceMap<BlockState, BlockStateModel.UnbakedGrouped> models = new Reference2ReferenceOpenHashMap<>(); private void prepare(Block block) { this.block = block; @@ -224,7 +172,7 @@ public class ModelLoadingEventDispatcher { } @Override - public void setModel(BlockState state, GroupableModel model) { + public void setModel(BlockState state, BlockStateModel.UnbakedGrouped model) { Objects.requireNonNull(state, "state cannot be null"); Objects.requireNonNull(model, "model cannot be null"); @@ -251,131 +199,76 @@ public class ModelLoadingEventDispatcher { } } - private static class BeforeBakeModifierContext implements ModelModifier.BeforeBake.Context { - private Identifier id; - private ModelBakeSettings settings; - private Baker baker; - - private void prepare(Identifier id, ModelBakeSettings settings, Baker baker) { - this.id = id; - this.settings = settings; - this.baker = baker; - } - - @Override - public Identifier id() { - return id; - } - - @Override - public ModelBakeSettings settings() { - return settings; - } - - @Override - public Baker baker() { - return baker; - } - } - - private static class AfterBakeModifierContext implements ModelModifier.AfterBake.Context { - private Identifier id; - private UnbakedModel sourceModel; - private ModelBakeSettings settings; - private Baker baker; - - private void prepare(Identifier id, UnbakedModel sourceModel, ModelBakeSettings settings, Baker baker) { - this.id = id; - this.sourceModel = sourceModel; - this.settings = settings; - this.baker = baker; - } - - @Override - public Identifier id() { - return id; - } - - @Override - public UnbakedModel sourceModel() { - return sourceModel; - } - - @Override - public ModelBakeSettings settings() { - return settings; - } - - @Override - public Baker baker() { - return baker; - } - } - private static class OnLoadBlockModifierContext implements ModelModifier.OnLoadBlock.Context { - private ModelIdentifier id; private BlockState state; - private void prepare(ModelIdentifier id, BlockState state) { - this.id = id; + private void prepare(BlockState state) { this.state = state; } - @Override - public ModelIdentifier id() { - return id; - } - @Override public BlockState state() { return state; } } - private static class BeforeBakeBlockModifierContext implements ModelModifier.BeforeBakeBlock.Context { - private ModelIdentifier id; - private Baker baker; + private static class BakeBlockModifierContext implements ModelModifier.BeforeBakeBlock.Context, ModelModifier.AfterBakeBlock.Context { + private final BlockState state; + private final Baker baker; + private BlockStateModel.UnbakedGrouped sourceModel; - private void prepare(ModelIdentifier id, Baker baker) { - this.id = id; + private BakeBlockModifierContext(BlockState state, Baker baker) { + this.state = state; this.baker = baker; } + private void prepareAfterBake(BlockStateModel.UnbakedGrouped sourceModel) { + this.sourceModel = sourceModel; + } + @Override - public ModelIdentifier id() { - return id; + public BlockState state() { + return state; } @Override public Baker baker() { return baker; } + + @Override + public BlockStateModel.UnbakedGrouped sourceModel() { + return sourceModel; + } } - private static class AfterBakeBlockModifierContext implements ModelModifier.AfterBakeBlock.Context { - private ModelIdentifier id; - private GroupableModel sourceModel; - private Baker baker; + private static class BakeItemModifierContext implements ModelModifier.BeforeBakeItem.Context, ModelModifier.AfterBakeItem.Context { + private final Identifier itemId; + private final ItemModel.BakeContext bakeContext; + private ItemModel.Unbaked sourceModel; - private void prepare(ModelIdentifier id, GroupableModel sourceModel, Baker baker) { - this.id = id; + private BakeItemModifierContext(Identifier itemId, ItemModel.BakeContext bakeContext) { + this.itemId = itemId; + this.bakeContext = bakeContext; + } + + private void prepareAfterBake(ItemModel.Unbaked sourceModel) { this.sourceModel = sourceModel; - this.baker = baker; } @Override - public ModelIdentifier id() { - return id; + public Identifier itemId() { + return itemId; } @Override - public GroupableModel sourceModel() { + public ItemModel.BakeContext bakeContext() { + return bakeContext; + } + + @Override + public ItemModel.Unbaked sourceModel() { return sourceModel; } - - @Override - public Baker baker() { - return baker; - } } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingPluginContextImpl.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingPluginContextImpl.java index c0a605f88..c2f299949 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingPluginContextImpl.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelLoadingPluginContextImpl.java @@ -16,13 +16,10 @@ package net.fabricmc.fabric.impl.client.model.loading; -import java.util.Collection; import java.util.IdentityHashMap; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +38,6 @@ import net.fabricmc.fabric.api.event.EventFactory; public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context { private static final Logger LOGGER = LoggerFactory.getLogger(ModelLoadingPluginContextImpl.class); - final Set<Identifier> extraModels = new LinkedHashSet<>(); final Map<Block, BlockStateResolver> blockStateResolvers = new IdentityHashMap<>(); private static final Identifier[] MODEL_MODIFIER_PHASES = new Identifier[] { ModelModifier.OVERRIDE_PHASE, ModelModifier.DEFAULT_PHASE, ModelModifier.WRAP_PHASE, ModelModifier.WRAP_LAST_PHASE }; @@ -57,28 +53,6 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context return model; }, MODEL_MODIFIER_PHASES); - private final Event<ModelModifier.BeforeBake> beforeBakeModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBake.class, modifiers -> (model, context) -> { - for (ModelModifier.BeforeBake modifier : modifiers) { - try { - model = modifier.modifyModelBeforeBake(model, context); - } catch (Exception exception) { - LOGGER.error("Failed to modify unbaked model before bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); - private final Event<ModelModifier.AfterBake> afterBakeModifiers = EventFactory.createWithPhases(ModelModifier.AfterBake.class, modifiers -> (model, context) -> { - for (ModelModifier.AfterBake modifier : modifiers) { - try { - model = modifier.modifyModelAfterBake(model, context); - } catch (Exception exception) { - LOGGER.error("Failed to modify baked model after bake", exception); - } - } - - return model; - }, MODEL_MODIFIER_PHASES); private final Event<ModelModifier.OnLoadBlock> onLoadBlockModifiers = EventFactory.createWithPhases(ModelModifier.OnLoadBlock.class, modifiers -> (model, context) -> { for (ModelModifier.OnLoadBlock modifier : modifiers) { try { @@ -112,18 +86,28 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context return model; }, MODEL_MODIFIER_PHASES); - - @Override - public void addModels(Identifier... ids) { - for (Identifier id : ids) { - extraModels.add(id); + private final Event<ModelModifier.BeforeBakeItem> beforeBakeItemModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBakeItem.class, modifiers -> (model, context) -> { + for (ModelModifier.BeforeBakeItem modifier : modifiers) { + try { + model = modifier.modifyModelBeforeBake(model, context); + } catch (Exception exception) { + LOGGER.error("Failed to modify unbaked item model before bake", exception); + } } - } - @Override - public void addModels(Collection<? extends Identifier> ids) { - extraModels.addAll(ids); - } + return model; + }, MODEL_MODIFIER_PHASES); + private final Event<ModelModifier.AfterBakeItem> afterBakeItemModifiers = EventFactory.createWithPhases(ModelModifier.AfterBakeItem.class, modifiers -> (model, context) -> { + for (ModelModifier.AfterBakeItem modifier : modifiers) { + try { + model = modifier.modifyModelAfterBake(model, context); + } catch (Exception exception) { + LOGGER.error("Failed to modify baked item model after bake", exception); + } + } + + return model; + }, MODEL_MODIFIER_PHASES); @Override public void registerBlockStateResolver(Block block, BlockStateResolver resolver) { @@ -146,16 +130,6 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context return onLoadModifiers; } - @Override - public Event<ModelModifier.BeforeBake> modifyModelBeforeBake() { - return beforeBakeModifiers; - } - - @Override - public Event<ModelModifier.AfterBake> modifyModelAfterBake() { - return afterBakeModifiers; - } - @Override public Event<ModelModifier.OnLoadBlock> modifyBlockModelOnLoad() { return onLoadBlockModifiers; @@ -170,4 +144,14 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context public Event<ModelModifier.AfterBakeBlock> modifyBlockModelAfterBake() { return afterBakeBlockModifiers; } + + @Override + public Event<ModelModifier.BeforeBakeItem> modifyItemModelBeforeBake() { + return beforeBakeItemModifiers; + } + + @Override + public Event<ModelModifier.AfterBakeItem> modifyItemModelAfterBake() { + return afterBakeItemModifiers; + } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/BakedModelManagerMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/BakedModelManagerMixin.java index 76fcaef9a..d5d404898 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/BakedModelManagerMixin.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/BakedModelManagerMixin.java @@ -26,56 +26,32 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.sugar.Local; import org.jetbrains.annotations.Nullable; -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.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModelManager; import net.minecraft.client.render.model.BlockStatesLoader; -import net.minecraft.client.render.model.ModelBaker; -import net.minecraft.client.render.model.ReferencedModelsCollector; +import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.render.model.json.JsonUnbakedModel; import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceReloader; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.api.client.model.loading.v1.FabricBakedModelManager; import net.fabricmc.fabric.api.client.model.loading.v1.UnbakedModelDeserializer; -import net.fabricmc.fabric.impl.client.model.loading.BakedModelsHooks; import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingEventDispatcher; import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingPluginManager; @Mixin(BakedModelManager.class) -abstract class BakedModelManagerMixin implements FabricBakedModelManager { - @Shadow - @Final - private BakedModel missingBlockModel; - +abstract class BakedModelManagerMixin { @Unique @Nullable private volatile CompletableFuture<ModelLoadingEventDispatcher> eventDispatcherFuture; - @Unique - @Nullable - private Map<Identifier, BakedModel> extraModels; - - @Override - public BakedModel getModel(Identifier id) { - if (extraModels == null) { - return missingBlockModel; - } - - return extraModels.getOrDefault(id, missingBlockModel); - } - @Inject(method = "reload", at = @At("HEAD")) private void onHeadReload(ResourceReloader.Synchronizer synchronizer, ResourceManager manager, Executor prepareExecutor, Executor applyExecutor, CallbackInfoReturnable<CompletableFuture<Void>> cir) { eventDispatcherFuture = ModelLoadingPluginManager.preparePlugins(manager, prepareExecutor).thenApplyAsync(ModelLoadingEventDispatcher::new); @@ -89,13 +65,18 @@ abstract class BakedModelManagerMixin implements FabricBakedModelManager { }); } - @ModifyExpressionValue(method = "reload", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/BlockStatesLoader.load(Lnet/minecraft/client/render/model/UnbakedModel;Lnet/minecraft/resource/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) - private CompletableFuture<BlockStatesLoader.BlockStateDefinition> hookBlockStateModels(CompletableFuture<BlockStatesLoader.BlockStateDefinition> modelsFuture) { + @ModifyExpressionValue(method = "reload", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/BakedModelManager.reloadModels(Lnet/minecraft/resource/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture<Map<Identifier, UnbakedModel>> hookModels(CompletableFuture<Map<Identifier, UnbakedModel>> modelsFuture) { + return modelsFuture.thenCombine(eventDispatcherFuture, (models, eventDispatcher) -> eventDispatcher.modifyModelsOnLoad(models)); + } + + @ModifyExpressionValue(method = "reload", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/BlockStatesLoader.load(Lnet/minecraft/resource/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture<BlockStatesLoader.LoadedModels> hookBlockStateModels(CompletableFuture<BlockStatesLoader.LoadedModels> modelsFuture) { return modelsFuture.thenCombine(eventDispatcherFuture, (models, eventDispatcher) -> eventDispatcher.modifyBlockModelsOnLoad(models)); } - @ModifyArg(method = "reload", at = @At(value = "INVOKE", target = "java/util/concurrent/CompletableFuture.thenApplyAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 1), index = 0) - private Function<Void, ReferencedModelsCollector> hookModelDiscovery(Function<Void, ReferencedModelsCollector> function) { + @ModifyArg(method = "reload", at = @At(value = "INVOKE", target = "java/util/concurrent/CompletableFuture.thenComposeAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0) + private Function<Void, CompletableFuture<?>> hookModelBaking(Function<Void, CompletableFuture<?>> function) { return v -> { CompletableFuture<ModelLoadingEventDispatcher> future = eventDispatcherFuture; @@ -104,25 +85,9 @@ abstract class BakedModelManagerMixin implements FabricBakedModelManager { } ModelLoadingEventDispatcher.CURRENT.set(future.join()); - ReferencedModelsCollector referencedModelsCollector = function.apply(v); + CompletableFuture<?> bakingResultFuture = function.apply(v); ModelLoadingEventDispatcher.CURRENT.remove(); - return referencedModelsCollector; - }; - } - - @ModifyArg(method = "reload", at = @At(value = "INVOKE", target = "java/util/concurrent/CompletableFuture.thenApplyAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 3), index = 0) - private Function<Void, Object> hookModelBaking(Function<Void, Object> function) { - return v -> { - CompletableFuture<ModelLoadingEventDispatcher> future = eventDispatcherFuture; - - if (future == null) { - return function.apply(v); - } - - ModelLoadingEventDispatcher.CURRENT.set(future.join()); - Object bakingResult = function.apply(v); - ModelLoadingEventDispatcher.CURRENT.remove(); - return bakingResult; + return bakingResultFuture; }; } @@ -142,9 +107,4 @@ abstract class BakedModelManagerMixin implements FabricBakedModelManager { private static Object actuallyDeserializeModel(Object originalModel, @Local Reader reader) { return UnbakedModelDeserializer.deserialize(reader); } - - @Inject(method = "upload", at = @At(value = "INVOKE_STRING", target = "net/minecraft/util/profiler/Profiler.swap(Ljava/lang/String;)V", args = "ldc=cache")) - private void onUpload(CallbackInfo ci, @Local ModelBaker.BakedModels bakedModels) { - extraModels = ((BakedModelsHooks) (Object) bakedModels).fabric_getExtraModels(); - } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakedModelsMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakedModelsMixin.java deleted file mode 100644 index 9cbc3b6cb..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakedModelsMixin.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.client.model.loading; - -import java.util.Map; - -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBaker; -import net.minecraft.util.Identifier; - -import net.fabricmc.fabric.impl.client.model.loading.BakedModelsHooks; - -@Mixin(ModelBaker.BakedModels.class) -abstract class ModelBakerBakedModelsMixin implements BakedModelsHooks { - @Unique - @Nullable - private Map<Identifier, BakedModel> extraModels; - - @Override - @Nullable - public Map<Identifier, BakedModel> fabric_getExtraModels() { - return extraModels; - } - - @Override - public void fabric_setExtraModels(@Nullable Map<Identifier, BakedModel> extraModels) { - this.extraModels = extraModels; - } -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakerImplMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakerImplMixin.java deleted file mode 100644 index fb3b6629f..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakerImplMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.client.model.loading; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Coerce; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelBaker; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.util.Identifier; - -import net.fabricmc.fabric.impl.client.model.loading.ModelBakerHooks; -import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingEventDispatcher; - -@Mixin(ModelBaker.BakerImpl.class) -abstract class ModelBakerBakerImplMixin { - @Shadow - @Final - private ModelBaker field_40571; - - @WrapOperation(method = "bake(Lnet/minecraft/util/Identifier;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/UnbakedModel.bake(Lnet/minecraft/client/render/model/UnbakedModel;Lnet/minecraft/client/render/model/Baker;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;")) - private BakedModel wrapModelBake(UnbakedModel unbakedModel, @Coerce Baker baker, ModelBakeSettings settings, Operation<BakedModel> operation, Identifier id) { - ModelLoadingEventDispatcher dispatcher = ((ModelBakerHooks) this.field_40571).fabric_getDispatcher(); - - if (dispatcher == null) { - return operation.call(unbakedModel, baker, settings); - } - - unbakedModel = dispatcher.modifyModelBeforeBake(unbakedModel, id, settings, baker); - BakedModel model = operation.call(unbakedModel, baker, settings); - return dispatcher.modifyModelAfterBake(model, id, unbakedModel, settings, baker); - } -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerMixin.java index cd0e04a49..6666e8ebd 100644 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerMixin.java +++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerMixin.java @@ -16,11 +16,12 @@ package net.fabricmc.fabric.mixin.client.model.loading; -import java.util.HashMap; import java.util.Map; +import java.util.function.BiFunction; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; @@ -29,27 +30,29 @@ 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.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.client.render.model.BakedModel; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.item.model.ItemModel; +import net.minecraft.client.render.model.BakedSimpleModel; import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.GroupableModel; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.client.render.model.ModelBaker; -import net.minecraft.client.render.model.ModelRotation; -import net.minecraft.client.util.ModelIdentifier; import net.minecraft.util.Identifier; -import net.fabricmc.fabric.impl.client.model.loading.BakedModelsHooks; -import net.fabricmc.fabric.impl.client.model.loading.ModelBakerHooks; import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingEventDispatcher; @Mixin(ModelBaker.class) -abstract class ModelBakerMixin implements ModelBakerHooks { +abstract class ModelBakerMixin { @Shadow @Final static Logger LOGGER; + @Shadow + @Final + Map<Identifier, BakedSimpleModel> simpleModels; + @Unique @Nullable private ModelLoadingEventDispatcher fabric_eventDispatcher; @@ -59,39 +62,37 @@ abstract class ModelBakerMixin implements ModelBakerHooks { fabric_eventDispatcher = ModelLoadingEventDispatcher.CURRENT.get(); } - @WrapOperation(method = "method_65737", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/GroupableModel.bake(Lnet/minecraft/client/render/model/Baker;)Lnet/minecraft/client/render/model/BakedModel;")) - private BakedModel wrapBlockModelBake(GroupableModel unbakedModel, Baker baker, Operation<BakedModel> operation, ModelBaker.ErrorCollectingSpriteGetter spriteGetter, Map<ModelIdentifier, BakedModel> map, ModelIdentifier id) { + @ModifyArg(method = "bake", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/FutureModel;newTask(Ljava/util/Map;Ljava/util/function/BiFunction;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 1) + private BiFunction<BlockState, BlockStateModel.UnbakedGrouped, BlockStateModel> hookBlockModelBake(BiFunction<BlockState, BlockStateModel.UnbakedGrouped, BlockStateModel> bifunction) { if (fabric_eventDispatcher == null) { - return operation.call(unbakedModel, baker); + return bifunction; } - unbakedModel = fabric_eventDispatcher.modifyBlockModelBeforeBake(unbakedModel, id, baker); - BakedModel model = operation.call(unbakedModel, baker); - return fabric_eventDispatcher.modifyBlockModelAfterBake(model, id, unbakedModel, baker); + return (state, unbakedModel) -> { + ModelLoadingEventDispatcher.CURRENT.set(fabric_eventDispatcher); + BlockStateModel model = bifunction.apply(state, unbakedModel); + ModelLoadingEventDispatcher.CURRENT.remove(); + return model; + }; } - @Inject(method = "bake", at = @At("RETURN")) - private void onReturnBake(ModelBaker.ErrorCollectingSpriteGetter spriteGetter, CallbackInfoReturnable<ModelBaker.BakedModels> cir) { - if (fabric_eventDispatcher == null) { - return; + @WrapOperation(method = "method_68018", at = @At(value = "INVOKE", target = "net/minecraft/client/render/model/BlockStateModel$UnbakedGrouped.getModel(Lnet/minecraft/block/BlockState;Lnet/minecraft/client/render/model/Baker;)Lnet/minecraft/client/render/model/BlockStateModel;")) + private static BlockStateModel wrapBlockModelBake(BlockStateModel.UnbakedGrouped unbakedModel, BlockState state, Baker baker, Operation<BlockStateModel> operation) { + ModelLoadingEventDispatcher eventDispatcher = ModelLoadingEventDispatcher.CURRENT.get(); + + if (eventDispatcher == null) { + return operation.call(unbakedModel, state, baker); } - ModelBaker.BakedModels models = cir.getReturnValue(); - Map<Identifier, BakedModel> extraModels = new HashMap<>(); - fabric_eventDispatcher.forEachExtraModel(id -> { - try { - BakedModel model = ((ModelBaker) (Object) this).new BakerImpl(spriteGetter, id::toString).bake(id, ModelRotation.X0_Y0); - extraModels.put(id, model); - } catch (Exception e) { - LOGGER.warn("Unable to bake extra model: '{}': {}", id, e); - } - }); - ((BakedModelsHooks) (Object) models).fabric_setExtraModels(extraModels); + return eventDispatcher.modifyBlockModel(unbakedModel, state, baker, operation); } - @Override - @Nullable - public ModelLoadingEventDispatcher fabric_getDispatcher() { - return fabric_eventDispatcher; + @WrapOperation(method = "method_68019", at = @At(value = "INVOKE", target = "net/minecraft/client/render/item/model/ItemModel$Unbaked.bake(Lnet/minecraft/client/render/item/model/ItemModel$BakeContext;)Lnet/minecraft/client/render/item/model/ItemModel;")) + private ItemModel wrapItemModelBake(ItemModel.Unbaked unbakedModel, ItemModel.BakeContext bakeContext, Operation<ItemModel> operation, @Local Identifier itemId) { + if (fabric_eventDispatcher == null) { + return operation.call(unbakedModel, bakeContext); + } + + return fabric_eventDispatcher.modifyItemModel(unbakedModel, itemId, bakeContext, operation); } } diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ReferencedModelsCollectorMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ReferencedModelsCollectorMixin.java deleted file mode 100644 index 900eadfee..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ReferencedModelsCollectorMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.client.model.loading; - -import org.jetbrains.annotations.Nullable; -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.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.minecraft.client.render.model.ReferencedModelsCollector; -import net.minecraft.client.render.model.ResolvableModel; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.util.Identifier; - -import net.fabricmc.fabric.impl.client.model.loading.ModelLoadingEventDispatcher; - -@Mixin(ReferencedModelsCollector.class) -abstract class ReferencedModelsCollectorMixin { - @Unique - @Nullable - private ModelLoadingEventDispatcher fabric_eventDispatcher; - - @Shadow - public abstract void add(ResolvableModel model); - - @Shadow - abstract UnbakedModel computeResolvedModel(Identifier id); - - @Inject(method = "<init>", at = @At("RETURN")) - private void onReturnInit(CallbackInfo ci) { - fabric_eventDispatcher = ModelLoadingEventDispatcher.CURRENT.get(); - - if (fabric_eventDispatcher != null) { - fabric_eventDispatcher.forEachExtraModel(id -> add(computeResolvedModel(id))); - } - } - - @ModifyVariable(method = "getModel", at = @At(value = "STORE", ordinal = 0), ordinal = 0) - @Nullable - private UnbakedModel onLoadModel(@Nullable UnbakedModel model, Identifier id) { - if (fabric_eventDispatcher == null) { - return model; - } - - return fabric_eventDispatcher.modifyModelOnLoad(model, id); - } -} diff --git a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/WrapperBakedModelMixin.java b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/WrapperBakedModelMixin.java deleted file mode 100644 index 6fd7417a1..000000000 --- a/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/WrapperBakedModelMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.mixin.client.model.loading; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.WrapperBakedModel; - -import net.fabricmc.fabric.api.client.model.loading.v1.UnwrappableBakedModel; - -@Mixin(WrapperBakedModel.class) -abstract class WrapperBakedModelMixin implements UnwrappableBakedModel { - @Shadow - @Final - protected BakedModel wrapped; - - @Override - public BakedModel getWrappedModel() { - return wrapped; - } -} diff --git a/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.accesswidener b/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.accesswidener deleted file mode 100644 index 12de3c5c2..000000000 --- a/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.accesswidener +++ /dev/null @@ -1,3 +0,0 @@ -accessWidener v2 named -accessible class net/minecraft/client/render/model/ModelBaker$BakerImpl -accessible method net/minecraft/client/render/model/ModelBaker$BakerImpl <init> (Lnet/minecraft/client/render/model/ModelBaker;Lnet/minecraft/client/render/model/ModelBaker$ErrorCollectingSpriteGetter;Lnet/minecraft/client/model/ModelNameSupplier;)V diff --git a/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.mixins.json b/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.mixins.json index d689224f6..0f5410879 100644 --- a/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.mixins.json +++ b/fabric-model-loading-api-v1/src/client/resources/fabric-model-loading-api-v1.mixins.json @@ -6,11 +6,7 @@ "BakedModelManagerMixin", "JsonUnbakedModelAccessor", "JsonUnbakedModelMixin", - "ModelBakerBakedModelsMixin", - "ModelBakerBakerImplMixin", - "ModelBakerMixin", - "ReferencedModelsCollectorMixin", - "WrapperBakedModelMixin" + "ModelBakerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/fabric-model-loading-api-v1/src/client/resources/fabric.mod.json b/fabric-model-loading-api-v1/src/client/resources/fabric.mod.json index 7f8660e30..aaef40d68 100644 --- a/fabric-model-loading-api-v1/src/client/resources/fabric.mod.json +++ b/fabric-model-loading-api-v1/src/client/resources/fabric.mod.json @@ -25,13 +25,5 @@ "environment": "client", "config": "fabric-model-loading-api-v1.mixins.json" } - ], - "accessWidener": "fabric-model-loading-api-v1.accesswidener", - "custom": { - "fabric-api:module-lifecycle": "stable", - "loom:injected_interfaces": { - "net/minecraft/class_1092": [ "net/fabricmc/fabric/api/client/model/loading/v1/FabricBakedModelManager" ], - "net/minecraft/class_10200": [ "net/fabricmc/fabric/api/client/model/loading/v1/UnwrappableBakedModel" ] - } - } + ] } diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java index aaa3e5d7b..9bb7d1bb1 100644 --- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java +++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/BakedModelFeatureRenderer.java @@ -30,28 +30,28 @@ import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.model.EntityModel; import net.minecraft.client.render.entity.state.LivingEntityRenderState; -import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.MathHelper; public class BakedModelFeatureRenderer<S extends LivingEntityRenderState, M extends EntityModel<S>> extends FeatureRenderer<S, M> { - private final Supplier<BakedModel> modelSupplier; + private final Supplier<BlockStateModel> modelSupplier; - public BakedModelFeatureRenderer(FeatureRendererContext<S, M> context, Supplier<BakedModel> modelSupplier) { + public BakedModelFeatureRenderer(FeatureRendererContext<S, M> context, Supplier<BlockStateModel> modelSupplier) { super(context); this.modelSupplier = modelSupplier; } @Override public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, S state, float limbAngle, float limbDistance) { - BakedModel model = modelSupplier.get(); + BlockStateModel model = modelSupplier.get(); VertexConsumer vertices = vertexConsumers.getBuffer(TexturedRenderLayers.getEntityCutout()); matrices.push(); matrices.multiply(new Quaternionf(new AxisAngle4f(state.age * 0.07F - state.bodyYaw * MathHelper.RADIANS_PER_DEGREE, 0, 1, 0))); matrices.scale(-0.75F, -0.75F, 0.75F); float aboveHead = (float) (Math.sin(state.age * 0.08F)) * 0.5F + 0.5F; matrices.translate(-0.5F, 0.75F + aboveHead, -0.5F); - MinecraftClient.getInstance().getBlockRenderManager().getModelRenderer().render(matrices.peek(), vertices, null, model, 1, 1, 1, light, OverlayTexture.DEFAULT_UV); + MinecraftClient.getInstance().getBlockRenderManager().getModelRenderer().render(matrices.peek(), vertices, model, 1, 1, 1, light, OverlayTexture.DEFAULT_UV); matrices.pop(); } } diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/ModelTestModClient.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/ModelTestModClient.java index e18336e12..17d5efaad 100644 --- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/ModelTestModClient.java +++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/ModelTestModClient.java @@ -16,42 +16,22 @@ package net.fabricmc.fabric.test.model.loading; -import java.util.List; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.CropBlock; import net.minecraft.block.HorizontalConnectingBlock; import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.GroupableModel; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.client.render.model.MissingModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelTextures; -import net.minecraft.client.render.model.WrapperBakedModel; -import net.minecraft.client.render.model.json.ModelTransformation; +import net.minecraft.client.render.model.SimpleBlockStateModel; import net.minecraft.client.render.model.json.ModelVariant; -import net.minecraft.client.render.model.json.WeightedUnbakedModel; import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.random.Random; -import net.minecraft.world.BlockRenderView; import net.fabricmc.api.ClientModInitializer; 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.WrapperUnbakedModel; import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback; -import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; -import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; public class ModelTestModClient implements ClientModInitializer { @@ -64,7 +44,7 @@ public class ModelTestModClient implements ClientModInitializer { @Override public void onInitializeClient() { ModelLoadingPlugin.register(pluginContext -> { - pluginContext.addModels(HALF_RED_SAND_MODEL_ID); + //pluginContext.addModels(HALF_RED_SAND_MODEL_ID); // Make wheat stages 1->6 use the same model as stage 0. This can be done with resource packs, this is just a test. pluginContext.registerBlockStateResolver(Blocks.WHEAT, context -> { @@ -72,8 +52,8 @@ public class ModelTestModClient implements ClientModInitializer { Identifier wheatStage0Id = Identifier.ofVanilla("block/wheat_stage0"); Identifier wheatStage7Id = Identifier.ofVanilla("block/wheat_stage7"); - GroupableModel wheatStage0Model = simpleGroupableModel(wheatStage0Id); - GroupableModel wheatStage7Model = simpleGroupableModel(wheatStage7Id); + BlockStateModel.UnbakedGrouped wheatStage0Model = simpleUnbakedGroupedBlockStateModel(wheatStage0Id); + BlockStateModel.UnbakedGrouped wheatStage7Model = simpleUnbakedGroupedBlockStateModel(wheatStage7Id); for (int age = 0; age <= 6; age++) { context.setModel(state.with(CropBlock.AGE, age), wheatStage0Model); @@ -82,52 +62,54 @@ public class ModelTestModClient implements ClientModInitializer { context.setModel(state.with(CropBlock.AGE, 7), wheatStage7Model); }); + // FIXME // Replace the brown glazed terracotta model with a missing model without affecting child models. // Since 1.21.4, the item model is not a child model, so it is also affected. - pluginContext.modifyModelOnLoad().register(ModelModifier.WRAP_PHASE, (model, context) -> { - if (context.id().equals(BROWN_GLAZED_TERRACOTTA_MODEL_ID)) { - return new WrapperUnbakedModel(model) { - @Override - public void resolve(Resolver resolver) { - super.resolve(resolver); - resolver.resolve(MissingModel.ID); - } - - @Override - public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) { - return baker.bake(MissingModel.ID, settings); - } - }; - } - - return model; - }); + //pluginContext.modifyModelOnLoad().register(ModelModifier.WRAP_PHASE, (model, context) -> { + // if (context.id().equals(BROWN_GLAZED_TERRACOTTA_MODEL_ID)) { + // return new WrapperUnbakedModel(model) { + // @Override + // public void resolve(Resolver resolver) { + // super.resolve(resolver); + // resolver.resolve(MissingModel.ID); + // } + // + // @Override + // public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) { + // return baker.bake(MissingModel.ID, settings); + // } + // }; + // } + // + // return model; + //}); // Make oak fences with west: true and everything else false appear to be a missing model visually. BlockState westOakFence = Blocks.OAK_FENCE.getDefaultState().with(HorizontalConnectingBlock.WEST, true); pluginContext.modifyBlockModelOnLoad().register(ModelModifier.OVERRIDE_PHASE, (model, context) -> { if (context.state() == westOakFence) { - return simpleGroupableModel(MissingModel.ID); + return simpleUnbakedGroupedBlockStateModel(MissingModel.ID); } return model; }); + // FIXME // Remove bottom face of gold blocks - pluginContext.modifyModelAfterBake().register(ModelModifier.WRAP_PHASE, (model, context) -> { - if (context.id().equals(GOLD_BLOCK_MODEL_ID)) { - return new DownQuadRemovingModel(model); - } - - return model; - }); + //pluginContext.modifyModelAfterBake().register(ModelModifier.WRAP_PHASE, (model, context) -> { + // if (context.id().equals(GOLD_BLOCK_MODEL_ID)) { + // return new DownQuadRemovingModel(model); + // } + // + // return model; + //}); }); ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(SpecificModelReloadListener.INSTANCE); LivingEntityFeatureRendererRegistrationCallback.EVENT.register((entityType, entityRenderer, registrationHelper, context) -> { if (entityRenderer instanceof PlayerEntityRenderer playerRenderer) { - registrationHelper.register(new BakedModelFeatureRenderer<>(playerRenderer, SpecificModelReloadListener.INSTANCE::getSpecificModel)); + //registrationHelper.register(new BakedModelFeatureRenderer<>(playerRenderer, SpecificModelReloadListener.INSTANCE::getSpecificModel)); } }); } @@ -136,20 +118,20 @@ public class ModelTestModClient implements ClientModInitializer { return Identifier.of(ID, path); } - private static GroupableModel simpleGroupableModel(Identifier model) { - return new WeightedUnbakedModel(List.of(new ModelVariant(model, AffineTransformation.identity(), false, 1))); + private static BlockStateModel.UnbakedGrouped simpleUnbakedGroupedBlockStateModel(Identifier model) { + return new SimpleBlockStateModel.Unbaked(new ModelVariant(model)).cached(); } - private static class DownQuadRemovingModel extends WrapperBakedModel implements FabricBakedModel { - DownQuadRemovingModel(BakedModel model) { - super(model); - } - - @Override - public void emitBlockQuads(QuadEmitter emitter, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, Predicate<@Nullable Direction> cullTest) { - emitter.pushTransform(q -> q.cullFace() != Direction.DOWN); - ((FabricBakedModel) wrapped).emitBlockQuads(emitter, blockView, state, pos, randomSupplier, cullTest); - emitter.popTransform(); - } - } + //private static class DownQuadRemovingModel extends WrapperBakedModel implements FabricBakedModel { + // DownQuadRemovingModel(BakedModel model) { + // super(model); + // } + // + // @Override + // public void emitBlockQuads(QuadEmitter emitter, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, Predicate<@Nullable Direction> cullTest) { + // emitter.pushTransform(q -> q.cullFace() != Direction.DOWN); + // ((FabricBakedModel) wrapped).emitBlockQuads(emitter, blockView, state, pos, randomSupplier, cullTest); + // emitter.popTransform(); + // } + //} } diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/SpecificModelReloadListener.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/SpecificModelReloadListener.java index 0e2d19afe..77b0b631b 100644 --- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/SpecificModelReloadListener.java +++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/SpecificModelReloadListener.java @@ -19,27 +19,27 @@ package net.fabricmc.fabric.test.model.loading; import java.util.Collection; import java.util.List; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BlockStateModel; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys; import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener; +// FIXME public class SpecificModelReloadListener implements SimpleSynchronousResourceReloadListener { public static final SpecificModelReloadListener INSTANCE = new SpecificModelReloadListener(); public static final Identifier ID = Identifier.of(ModelTestModClient.ID, "specific_model"); - private BakedModel specificModel; + private BlockStateModel specificModel; - public BakedModel getSpecificModel() { + public BlockStateModel getSpecificModel() { return specificModel; } @Override public void reload(ResourceManager manager) { - specificModel = MinecraftClient.getInstance().getBakedModelManager().getModel(ModelTestModClient.HALF_RED_SAND_MODEL_ID); + //specificModel = MinecraftClient.getInstance().getBakedModelManager().getModel(ModelTestModClient.HALF_RED_SAND_MODEL_ID); } @Override diff --git a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/UnbakedModelDeserializerTest.java b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/UnbakedModelDeserializerTest.java index 6451758d5..9c4dde25b 100644 --- a/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/UnbakedModelDeserializerTest.java +++ b/fabric-model-loading-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/model/loading/UnbakedModelDeserializerTest.java @@ -16,100 +16,82 @@ package net.fabricmc.fabric.test.model.loading; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; -import com.mojang.serialization.JsonOps; -import org.jetbrains.annotations.Nullable; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelTextures; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.render.model.json.ModelTransformation; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.math.AffineTransformation; - import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.model.loading.v1.UnbakedModelDeserializer; +// FIXME public class UnbakedModelDeserializerTest implements ClientModInitializer { @Override public void onInitializeClient() { - UnbakedModelDeserializer.register(ModelTestModClient.id("transformed"), TransformedModelDeserializer.INSTANCE); + //UnbakedModelDeserializer.register(ModelTestModClient.id("transformed"), TransformedModelDeserializer.INSTANCE); } - private static class TransformedModelDeserializer implements UnbakedModelDeserializer { - public static final TransformedModelDeserializer INSTANCE = new TransformedModelDeserializer(); - - @Override - public UnbakedModel deserialize(JsonObject jsonObject, JsonDeserializationContext context) throws JsonParseException { - JsonElement transformationElement = JsonHelper.getElement(jsonObject, "transformation"); - AffineTransformation transformation = AffineTransformation.ANY_CODEC.parse(JsonOps.INSTANCE, transformationElement).getOrThrow(); - - JsonElement parentElement = JsonHelper.getElement(jsonObject, "parent"); - - if (JsonHelper.isString(parentElement)) { - Identifier parentId = Identifier.of(parentElement.getAsString()); - return new TransformedUnbakedModel(transformation, parentId); - } else if (parentElement.isJsonObject()) { - UnbakedModel parent = context.deserialize(parentElement, UnbakedModel.class); - return new TransformedUnbakedModel(transformation, parent); - } else { - throw new JsonSyntaxException("parent must be string or object"); - } - } - } - - private static class TransformedUnbakedModel implements UnbakedModel { - private final AffineTransformation transformation; - @Nullable - private final Identifier parentId; - private UnbakedModel parent; - - private TransformedUnbakedModel(AffineTransformation transformation, Identifier parentId) { - this.transformation = transformation; - this.parentId = parentId; - } - - private TransformedUnbakedModel(AffineTransformation transformation, UnbakedModel parent) { - this.transformation = transformation; - parentId = null; - this.parent = parent; - } - - @Override - public void resolve(Resolver resolver) { - if (parentId != null) { - parent = resolver.resolve(parentId); - } - } - - @Override - public UnbakedModel getParent() { - return parent; - } - - @Override - public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) { - settings = new SimpleModelBakeSettings(settings.getRotation().multiply(this.transformation), settings.isUvLocked()); - return parent.bake(textures, baker, settings, ambientOcclusion, isSideLit, transformation); - } - } - - private record SimpleModelBakeSettings(AffineTransformation transformation, boolean uvLocked) implements ModelBakeSettings { - @Override - public AffineTransformation getRotation() { - return transformation; - } - - @Override - public boolean isUvLocked() { - return uvLocked; - } - } + //private static class TransformedModelDeserializer implements UnbakedModelDeserializer { + // public static final TransformedModelDeserializer INSTANCE = new TransformedModelDeserializer(); + // + // @Override + // public UnbakedModel deserialize(JsonObject jsonObject, JsonDeserializationContext context) throws JsonParseException { + // JsonElement transformationElement = JsonHelper.getElement(jsonObject, "transformation"); + // AffineTransformation transformation = AffineTransformation.ANY_CODEC.parse(JsonOps.INSTANCE, transformationElement).getOrThrow(); + // + // JsonElement parentElement = JsonHelper.getElement(jsonObject, "parent"); + // + // if (JsonHelper.isString(parentElement)) { + // Identifier parentId = Identifier.of(parentElement.getAsString()); + // return new TransformedUnbakedModel(transformation, parentId); + // } else if (parentElement.isJsonObject()) { + // UnbakedModel parent = context.deserialize(parentElement, UnbakedModel.class); + // return new TransformedUnbakedModel(transformation, parent); + // } else { + // throw new JsonSyntaxException("parent must be string or object"); + // } + // } + //} + // + //private static class TransformedUnbakedModel implements UnbakedModel { + // private final AffineTransformation transformation; + // @Nullable + // private final Identifier parentId; + // private UnbakedModel parent; + // + // private TransformedUnbakedModel(AffineTransformation transformation, Identifier parentId) { + // this.transformation = transformation; + // this.parentId = parentId; + // } + // + // private TransformedUnbakedModel(AffineTransformation transformation, UnbakedModel parent) { + // this.transformation = transformation; + // parentId = null; + // this.parent = parent; + // } + // + // @Override + // public void resolve(Resolver resolver) { + // if (parentId != null) { + // parent = resolver.resolve(parentId); + // } + // } + // + // @Override + // public UnbakedModel getParent() { + // return parent; + // } + // + // @Override + // public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) { + // settings = new SimpleModelBakeSettings(settings.getRotation().multiply(this.transformation), settings.isUvLocked()); + // return parent.bake(textures, baker, settings, ambientOcclusion, isSideLit, transformation); + // } + //} + // + //private record SimpleModelBakeSettings(AffineTransformation transformation, boolean uvLocked) implements ModelBakeSettings { + // @Override + // public AffineTransformation getRotation() { + // return transformation; + // } + // + // @Override + // public boolean isUvLocked() { + // return uvLocked; + // } + //} } diff --git a/settings.gradle b/settings.gradle index df08bdf09..8fce68333 100644 --- a/settings.gradle +++ b/settings.gradle @@ -49,7 +49,7 @@ include 'fabric-key-binding-api-v1' include 'fabric-lifecycle-events-v1' include 'fabric-loot-api-v3' include 'fabric-message-api-v1' -//include 'fabric-model-loading-api-v1' +include 'fabric-model-loading-api-v1' include 'fabric-networking-api-v1' include 'fabric-object-builder-api-v1' include 'fabric-particles-v1'