Rewrite 1.19.4 Fabric model baker mixin for compatibility purposes

This commit is contained in:
embeddedt 2023-05-03 19:59:48 -04:00
parent d4bfe17a72
commit 545c68f122
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
4 changed files with 106 additions and 45 deletions

View File

@ -41,6 +41,17 @@ allprojects {
includeGroup "curse.maven"
}
}
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
filter {
includeGroup "maven.modrinth"
}
}
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org'

View File

@ -1,7 +1,6 @@
package org.embeddedt.modernfix.fabric.mixin.perf.dynamic_resources;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.core.registries.BuiltInRegistries;
@ -16,14 +15,16 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
@Mixin(ModelBakery.ModelBakerImpl.class)
@Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600)
public abstract class ModelBakerImplMixin {
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
@Shadow @Final private ModelBakery field_40571;
@ -49,41 +50,85 @@ public abstract class ModelBakerImplMixin {
}
}
private void createBakedMissingModelIfNeeded(IExtendedModelBakery extendedBakery, UnbakedModel iunbakedmodel, ModelState arg2, ResourceLocation arg) {
if(extendedBakery.getBakedMissingModel() == null) {
extendedBakery.setBakedMissingModel(iunbakedmodel.bake((ModelBaker)this, this.modelTextureGetter, arg2, arg));
((DynamicBakedModelProvider)this.field_40571.getBakedTopLevelModels()).setMissingModel(extendedBakery.getBakedMissingModel());
}
}
@Inject(method = "bake", at = @At("HEAD"), cancellable = true)
public void getOrLoadBakedModelDynamic(ResourceLocation arg, ModelState arg2, CallbackInfoReturnable<BakedModel> cir) {
private boolean wasMissingModel = false;
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) {
if(debugDynamicModelLoading)
ModernFix.LOGGER.info("Baking {}", arg);
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) {
/* to emulate vanilla model loading, treat as top-level */
Optional<Block> blockOpt = Objects.equals(((ModelResourceLocation)arg).getVariant(), "inventory") ? Optional.empty() : BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(arg.getNamespace(), arg.getPath()));
if(blockOpt.isPresent()) {
/* load via lambda for mods that expect blockstate to get loaded */
for(BlockState state : extendedBakery.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), (ModelResourceLocation)arg)) {
try {
blockStateLoaderHandle.invokeExact(this.field_40571, state);
} catch(Throwable e) {
ModernFix.LOGGER.error("Error loading model", e);
}
}
} else {
this.field_40571.loadTopLevel((ModelResourceLocation)arg);
}
cir.setReturnValue(this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel()));
// avoid leaks
this.field_40571.topLevelModels.clear();
} else
cir.setReturnValue(this.field_40571.getModel(arg));
if(cir.getReturnValue() == extendedBakery.mfix$getUnbakedMissingModel()) {
if(arg != ModelBakery.MISSING_MODEL_LOCATION && debugDynamicModelLoading)
ModernFix.LOGGER.warn("Model {} not present", arg);
wasMissingModel = true;
}
cir.getReturnValue().resolveParents(this.field_40571::getModel);
}
@ModifyVariable(method = "bake", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/resources/model/UnbakedModel;bake(Lnet/minecraft/client/resources/model/ModelBaker;Ljava/util/function/Function;Lnet/minecraft/client/resources/model/ModelState;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/resources/model/BakedModel;"))
private BakedModel unifyMissingBakedModel(BakedModel model) {
if(wasMissingModel) {
// use a shared baked missing model
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
BakedModel missing;
synchronized (this.field_40571) {
if(extendedBakery.getBakedMissingModel() == null) {
extendedBakery.setBakedMissingModel(model);
missing = model;
} else {
missing = extendedBakery.getBakedMissingModel();
}
}
return missing;
}
return model;
}
/**
* @author embeddedt
* @reason emulate old function, to allow injectors to work
*/
/*
@Overwrite
public BakedModel bake(ResourceLocation arg, ModelState arg2) {
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(arg, arg2.getRotation(), arg2.isUvLocked());
BakedModel existing = this.field_40571.bakedCache.get(key);
if (existing != null) {
cir.setReturnValue(existing);
return existing;
} else {
synchronized (this.field_40571) {
if(debugDynamicModelLoading)
ModernFix.LOGGER.info("Baking {}", arg);
UnbakedModel iunbakedmodel;
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) {
/* to emulate vanilla model loading, treat as top-level */
Optional<Block> blockOpt = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(arg.getNamespace(), arg.getPath()));
if(blockOpt.isPresent()) {
/* load via lambda for mods that expect blockstate to get loaded */
for(BlockState state : extendedBakery.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), (ModelResourceLocation)arg)) {
try {
blockStateLoaderHandle.invokeExact(this.field_40571, state);
} catch(Throwable e) {
ModernFix.LOGGER.error("Error loading model", e);
}
}
} else {
this.field_40571.loadTopLevel((ModelResourceLocation)arg);
}
iunbakedmodel = this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel());
// avoid leaks
this.field_40571.topLevelModels.clear();
} else
iunbakedmodel = this.getModel(arg);
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel() && arg != ModelBakery.MISSING_MODEL_LOCATION && debugDynamicModelLoading)
ModernFix.LOGGER.warn("Model {} not present", arg);
UnbakedModel iunbakedmodel = this.getModel(arg);
// TODO: make sure parent resolution doesn't re-run many times
iunbakedmodel.resolveParents(this::getModel);
BakedModel ibakedmodel = null;
@ -94,19 +139,21 @@ public abstract class ModelBakerImplMixin {
}
}
if(ibakedmodel == null) {
// leave the original assignment in the same spot so wrapping injectors work
// this means two bakes might happen for missing models, but not much we can do
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, this.modelTextureGetter, arg2, arg);
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel()) {
// use a shared baked missing model
if(extendedBakery.getBakedMissingModel() == null) {
extendedBakery.setBakedMissingModel(iunbakedmodel.bake((ModelBaker)this, this.modelTextureGetter, arg2, arg));
((DynamicBakedModelProvider)this.field_40571.getBakedTopLevelModels()).setMissingModel(extendedBakery.getBakedMissingModel());
}
createBakedMissingModelIfNeeded(extendedBakery, iunbakedmodel, arg2, arg);
ibakedmodel = extendedBakery.getBakedMissingModel();
} else
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, this.modelTextureGetter, arg2, arg);
}
}
this.field_40571.bakedCache.put(key, ibakedmodel);
cir.setReturnValue(ibakedmodel);
return ibakedmodel;
}
}
}
*/
}

View File

@ -31,17 +31,14 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
/* high priority so that our injectors are added before other mods' */
@Mixin(value = ModelBakery.class, priority = 600)
/* low priority so that our injectors are added after other mods' */
@Mixin(value = ModelBakery.class, priority = 1100)
@ClientOnlyMixin
public abstract class ModelBakeryMixin implements IExtendedModelBakery {
@ -172,10 +169,14 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
private BiFunction<ResourceLocation, Material, TextureAtlasSprite> textureGetter;
@Inject(method = "bakeModels", at = @At("HEAD"), cancellable = true)
private void skipBake(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
@Inject(method = "bakeModels", at = @At("HEAD"))
private void captureGetter(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
textureGetter = getter;
ci.cancel();
}
@Redirect(method = "bakeModels", at = @At(value = "INVOKE", target = "Ljava/util/Map;keySet()Ljava/util/Set;"))
private Set<ResourceLocation> skipBake(Map<ResourceLocation, UnbakedModel> instance) {
return Collections.emptySet();
}
/**

View File

@ -15,3 +15,5 @@ rhino_version=1902.2.2-build.268
fabric_loader_version=0.14.18
fabric_api_version=0.80.0+1.19.4
continuity_version=3.0.0-beta.2+1.19.3