From 6206975f10b20f3b91611e865b0153625572bf1a Mon Sep 17 00:00:00 2001
From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com>
Date: Sun, 22 Dec 2024 14:44:03 -0800
Subject: [PATCH] Reintroduce BeforeBake and AfterBake model modifiers
---
.../model/loading/v1/ModelLoadingPlugin.java | 26 +++
.../model/loading/v1/ModelModifier.java | 158 +++++++++++++++++-
.../client/model/loading/ModelBakerHooks.java | 24 +++
.../loading/ModelLoadingEventDispatcher.java | 157 ++++++++++++++++-
.../ModelLoadingPluginContextImpl.java | 64 +++++++
.../loading/ModelBakerBakerImplMixin.java | 55 ++++++
.../client/model/loading/ModelBakerMixin.java | 25 ++-
.../fabric-model-loading-api-v1.mixins.json | 1 +
.../model/loading/ModelTestModClient.java | 11 +-
9 files changed, 509 insertions(+), 12 deletions(-)
create mode 100644 fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelBakerHooks.java
create mode 100644 fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakerImplMixin.java
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 30bc4ea274..a9138c92e2 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
@@ -82,12 +82,38 @@ interface Context {
/**
* Event access to monitor unbaked model loads and replace the loaded model.
+ *
+ *
Replacements done by listeners of this callback do affect child models (that is, models whose
+ * parent hierarchy contains the replaced model), unlike {@link #modifyModelBeforeBake}.
*/
Event modifyModelOnLoad();
+ /**
+ * Event access to replace the unbaked model used for baking without replacing the cached model.
+ *
+ * Replacements done by listeners of this callback do not affect child models (that is, models whose
+ * parent hierarchy contains the replaced model), unlike {@link #modifyModelOnLoad}.
+ */
+ Event modifyModelBeforeBake();
+
+ /**
+ * Event access to replace the baked model.
+ */
+ Event modifyModelAfterBake();
+
/**
* Event access to monitor unbaked block model loads and replace the loaded model.
*/
Event modifyBlockModelOnLoad();
+
+ /**
+ * Event access to replace the unbaked block model used for baking.
+ */
+ Event modifyBlockModelBeforeBake();
+
+ /**
+ * Event access to replace the baked block model.
+ */
+ Event modifyBlockModelAfterBake();
}
}
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 fdfc4f018e..95ad0a4645 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
@@ -20,7 +20,10 @@
import org.jetbrains.annotations.Nullable;
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.ModelBakeSettings;
import net.minecraft.client.render.model.ResolvableModel;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
@@ -44,7 +47,7 @@
* 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.
*
- * These callbacks are invoked for every single model that is loaded, so implementations should be
+ *
These callbacks are invoked for every single model that is loaded or baked, so implementations should be
* as efficient as possible.
*/
public final class ModelModifier {
@@ -75,7 +78,11 @@ public interface OnLoad {
*
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.
+ * 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.
+ *
+ *
For further information, see the docs of {@link ModelLoadingPlugin.Context#modifyModelOnLoad()}.
*
* @param model the current unbaked model instance
* @param context context with additional information about the model/loader
@@ -97,6 +104,86 @@ interface Context {
}
}
+ @FunctionalInterface
+ public interface BeforeBake {
+ /**
+ * This handler is invoked to allow modification of the unbaked model instance right before it is baked.
+ *
+ *
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 {
/**
@@ -126,5 +213,72 @@ interface Context {
}
}
+ @FunctionalInterface
+ public interface BeforeBakeBlock {
+ /**
+ * This handler is invoked to allow modification of the unbaked block 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#modifyBlockModelBeforeBake
+ */
+ GroupableModel modifyModelBeforeBake(GroupableModel model, Context context);
+
+ /**
+ * The context for a before bake block model modification event.
+ */
+ @ApiStatus.NonExtendable
+ interface Context {
+ /**
+ * The identifier of the model being baked.
+ */
+ ModelIdentifier id();
+
+ /**
+ * 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 AfterBakeBlock {
+ /**
+ * This handler is invoked to allow modification of the baked block 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#modifyBlockModelAfterBake
+ */
+ BakedModel modifyModelAfterBake(BakedModel model, Context context);
+
+ /**
+ * The context for an after bake block model modification event.
+ */
+ @ApiStatus.NonExtendable
+ interface Context {
+ /**
+ * The identifier of the model being baked.
+ */
+ ModelIdentifier id();
+
+ /**
+ * The unbaked model that is being baked.
+ */
+ GroupableModel 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.
+ */
+ Baker baker();
+ }
+ }
+
private ModelModifier() { }
}
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
new file mode 100644
index 0000000000..c6a245e6eb
--- /dev/null
+++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/impl/client/model/loading/ModelBakerHooks.java
@@ -0,0 +1,24 @@
+/*
+ * 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 f6a75e21dc..ad9be411c4 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
@@ -25,6 +25,7 @@
import java.util.function.Consumer;
import com.google.common.collect.ImmutableList;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import org.jetbrains.annotations.Nullable;
@@ -34,8 +35,11 @@
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.model.Baker;
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;
@@ -55,7 +59,12 @@ public class ModelLoadingEventDispatcher {
private final BlockStateResolverContext blockStateResolverContext = new BlockStateResolverContext();
private final OnLoadModifierContext onLoadModifierContext = new OnLoadModifierContext();
+ private final ObjectArrayList beforeBakeModifierContextStack = new ObjectArrayList<>();
+ private final ObjectArrayList afterBakeModifierContextStack = new ObjectArrayList<>();
+
private final OnLoadBlockModifierContext onLoadBlockModifierContext = new OnLoadBlockModifierContext();
+ private final BeforeBakeBlockModifierContext beforeBakeBlockModifierContext = new BeforeBakeBlockModifierContext();
+ private final AfterBakeBlockModifierContext afterBakeBlockModifierContext = new AfterBakeBlockModifierContext();
public ModelLoadingEventDispatcher(List plugins) {
this.pluginContext = new ModelLoadingPluginContextImpl();
@@ -79,6 +88,34 @@ public UnbakedModel modifyModelOnLoad(@Nullable UnbakedModel model, Identifier i
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 map = models.models();
@@ -162,6 +199,16 @@ private GroupableModel modifyBlockModelOnLoad(GroupableModel model, ModelIdentif
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 BakedModel modifyBlockModelAfterBake(BakedModel model, ModelIdentifier id, GroupableModel sourceModel, Baker baker) {
+ afterBakeBlockModifierContext.prepare(id, sourceModel, baker);
+ return pluginContext.modifyBlockModelAfterBake().invoker().modifyModelAfterBake(model, afterBakeBlockModifierContext);
+ }
+
private static class BlockStateResolverContext implements BlockStateResolver.Context {
private Block block;
private final Reference2ReferenceMap models = new Reference2ReferenceOpenHashMap<>();
@@ -178,7 +225,7 @@ public Block block() {
@Override
public void setModel(BlockState state, GroupableModel model) {
- Objects.requireNonNull(model, "state cannot be null");
+ Objects.requireNonNull(state, "state cannot be null");
Objects.requireNonNull(model, "model cannot be null");
if (!state.isOf(block)) {
@@ -204,6 +251,67 @@ public Identifier id() {
}
}
+ 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;
@@ -223,4 +331,51 @@ public BlockState state() {
return state;
}
}
+
+ private static class BeforeBakeBlockModifierContext implements ModelModifier.BeforeBakeBlock.Context {
+ private ModelIdentifier id;
+ private Baker baker;
+
+ private void prepare(ModelIdentifier id, Baker baker) {
+ this.id = id;
+ this.baker = baker;
+ }
+
+ @Override
+ public ModelIdentifier id() {
+ return id;
+ }
+
+ @Override
+ public Baker baker() {
+ return baker;
+ }
+ }
+
+ private static class AfterBakeBlockModifierContext implements ModelModifier.AfterBakeBlock.Context {
+ private ModelIdentifier id;
+ private GroupableModel sourceModel;
+ private Baker baker;
+
+ private void prepare(ModelIdentifier id, GroupableModel sourceModel, Baker baker) {
+ this.id = id;
+ this.sourceModel = sourceModel;
+ this.baker = baker;
+ }
+
+ @Override
+ public ModelIdentifier id() {
+ return id;
+ }
+
+ @Override
+ public GroupableModel 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 41c2d8ad7a..c0a605f888 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
@@ -57,6 +57,28 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context
return model;
}, MODEL_MODIFIER_PHASES);
+ private final Event beforeBakeModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBake.class, modifiers -> (model, context) -> {
+ for (ModelModifier.BeforeBake modifier : modifiers) {
+ try {
+ model = modifier.modifyModelBeforeBake(model, context);
+ } catch (Exception exception) {
+ LOGGER.error("Failed to modify unbaked model before bake", exception);
+ }
+ }
+
+ return model;
+ }, MODEL_MODIFIER_PHASES);
+ private final Event afterBakeModifiers = EventFactory.createWithPhases(ModelModifier.AfterBake.class, modifiers -> (model, context) -> {
+ for (ModelModifier.AfterBake modifier : modifiers) {
+ try {
+ model = modifier.modifyModelAfterBake(model, context);
+ } catch (Exception exception) {
+ LOGGER.error("Failed to modify baked model after bake", exception);
+ }
+ }
+
+ return model;
+ }, MODEL_MODIFIER_PHASES);
private final Event onLoadBlockModifiers = EventFactory.createWithPhases(ModelModifier.OnLoadBlock.class, modifiers -> (model, context) -> {
for (ModelModifier.OnLoadBlock modifier : modifiers) {
try {
@@ -68,6 +90,28 @@ public class ModelLoadingPluginContextImpl implements ModelLoadingPlugin.Context
return model;
}, MODEL_MODIFIER_PHASES);
+ private final Event beforeBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.BeforeBakeBlock.class, modifiers -> (model, context) -> {
+ for (ModelModifier.BeforeBakeBlock modifier : modifiers) {
+ try {
+ model = modifier.modifyModelBeforeBake(model, context);
+ } catch (Exception exception) {
+ LOGGER.error("Failed to modify unbaked block model before bake", exception);
+ }
+ }
+
+ return model;
+ }, MODEL_MODIFIER_PHASES);
+ private final Event afterBakeBlockModifiers = EventFactory.createWithPhases(ModelModifier.AfterBakeBlock.class, modifiers -> (model, context) -> {
+ for (ModelModifier.AfterBakeBlock modifier : modifiers) {
+ try {
+ model = modifier.modifyModelAfterBake(model, context);
+ } catch (Exception exception) {
+ LOGGER.error("Failed to modify baked block model after bake", exception);
+ }
+ }
+
+ return model;
+ }, MODEL_MODIFIER_PHASES);
@Override
public void addModels(Identifier... ids) {
@@ -102,8 +146,28 @@ public Event modifyModelOnLoad() {
return onLoadModifiers;
}
+ @Override
+ public Event modifyModelBeforeBake() {
+ return beforeBakeModifiers;
+ }
+
+ @Override
+ public Event modifyModelAfterBake() {
+ return afterBakeModifiers;
+ }
+
@Override
public Event modifyBlockModelOnLoad() {
return onLoadBlockModifiers;
}
+
+ @Override
+ public Event modifyBlockModelBeforeBake() {
+ return beforeBakeBlockModifiers;
+ }
+
+ @Override
+ public Event modifyBlockModelAfterBake() {
+ return afterBakeBlockModifiers;
+ }
}
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
new file mode 100644
index 0000000000..fb3b6629f4
--- /dev/null
+++ b/fabric-model-loading-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/model/loading/ModelBakerBakerImplMixin.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.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 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 e89d086d3c..cd0e04a491 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
@@ -19,6 +19,8 @@
import java.util.HashMap;
import java.util.Map;
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Final;
@@ -31,15 +33,19 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
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.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 {
+abstract class ModelBakerMixin implements ModelBakerHooks {
@Shadow
@Final
static Logger LOGGER;
@@ -53,6 +59,17 @@ private void onReturnInit(CallbackInfo ci) {
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 operation, ModelBaker.ErrorCollectingSpriteGetter spriteGetter, Map map, ModelIdentifier id) {
+ if (fabric_eventDispatcher == null) {
+ return operation.call(unbakedModel, baker);
+ }
+
+ unbakedModel = fabric_eventDispatcher.modifyBlockModelBeforeBake(unbakedModel, id, baker);
+ BakedModel model = operation.call(unbakedModel, baker);
+ return fabric_eventDispatcher.modifyBlockModelAfterBake(model, id, unbakedModel, baker);
+ }
+
@Inject(method = "bake", at = @At("RETURN"))
private void onReturnBake(ModelBaker.ErrorCollectingSpriteGetter spriteGetter, CallbackInfoReturnable cir) {
if (fabric_eventDispatcher == null) {
@@ -71,4 +88,10 @@ private void onReturnBake(ModelBaker.ErrorCollectingSpriteGetter spriteGetter, C
});
((BakedModelsHooks) (Object) models).fabric_setExtraModels(extraModels);
}
+
+ @Override
+ @Nullable
+ public ModelLoadingEventDispatcher fabric_getDispatcher() {
+ return fabric_eventDispatcher;
+ }
}
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 f299bdb408..d6e3c40f08 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
@@ -5,6 +5,7 @@
"client": [
"BakedModelManagerMixin",
"ModelBakerBakedModelsMixin",
+ "ModelBakerBakerImplMixin",
"ModelBakerMixin",
"ReferencedModelsCollectorMixin",
"WrapperBakedModelMixin"
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 6456b82f63..e18336e124 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
@@ -58,8 +58,8 @@ public class ModelTestModClient implements ClientModInitializer {
public static final String ID = "fabric-model-loading-api-v1-testmod";
public static final Identifier HALF_RED_SAND_MODEL_ID = id("half_red_sand");
- public static final Identifier GOLD_BLOCK_MODEL_ID = Identifier.ofVanilla("block/gold_block");
public static final Identifier BROWN_GLAZED_TERRACOTTA_MODEL_ID = Identifier.ofVanilla("block/brown_glazed_terracotta");
+ public static final Identifier GOLD_BLOCK_MODEL_ID = Identifier.ofVanilla("block/gold_block");
@Override
public void onInitializeClient() {
@@ -114,14 +114,9 @@ public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings se
});
// Remove bottom face of gold blocks
- pluginContext.modifyModelOnLoad().register(ModelModifier.WRAP_PHASE, (model, context) -> {
+ pluginContext.modifyModelAfterBake().register(ModelModifier.WRAP_PHASE, (model, context) -> {
if (context.id().equals(GOLD_BLOCK_MODEL_ID)) {
- return new WrapperUnbakedModel(model) {
- @Override
- public BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) {
- return new DownQuadRemovingModel(super.bake(textures, baker, settings, ambientOcclusion, isSideLit, transformation));
- }
- };
+ return new DownQuadRemovingModel(model);
}
return model;