Skip to content

Commit 9efe912

Browse files
committed
Merge 1.20 into 1.20.2
2 parents 95f2dc9 + bd55e16 commit 9efe912

File tree

5 files changed

+162
-67
lines changed

5 files changed

+162
-67
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.cache_profile_texture_url;
2+
3+
import com.google.common.cache.Cache;
4+
import com.google.common.cache.CacheBuilder;
5+
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
6+
import net.minecraft.client.resources.SkinManager;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.Unique;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Redirect;
11+
12+
import java.util.concurrent.ExecutionException;
13+
import java.util.concurrent.TimeUnit;
14+
15+
@Mixin(SkinManager.class)
16+
public class SkinManagerMixin {
17+
@Unique
18+
private final Cache<MinecraftProfileTexture, String> mfix$hashCache = CacheBuilder.newBuilder()
19+
.expireAfterAccess(60, TimeUnit.SECONDS)
20+
.concurrencyLevel(1)
21+
.build();
22+
23+
@Redirect(method = "registerTexture(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/client/resources/SkinManager$SkinTextureCallback;)Lnet/minecraft/resources/ResourceLocation;",
24+
at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;getHash()Ljava/lang/String;", remap = false))
25+
private String useCachedHash(MinecraftProfileTexture texture) {
26+
// avoid lambda allocation for common case
27+
String hash = mfix$hashCache.getIfPresent(texture);
28+
if(hash != null)
29+
return hash;
30+
31+
try {
32+
return mfix$hashCache.get(texture, texture::getHash);
33+
} catch (ExecutionException e) {
34+
throw new RuntimeException(e);
35+
}
36+
}
37+
}

common/src/main/resources/assets/modernfix/lang/en_us.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,6 @@
120120
"modernfix.option.mixin.perf.compact_mojang_registries": "(Fabric) Experimental option that reduces the memory usage of registries by roughly 50%. Not useful in most modpacks unless they contain millions of blocks and items.",
121121
"modernfix.option.mixin.perf.dynamic_block_codecs": "Avoids storing a codec for every block(state) and instead generates and caches it on the fly when needed. Generally not worth enabling unless you have a million blocks/items.",
122122
"modernfix.option.mixin.perf.faster_command_suggestions": "Mitigate lag when there are hundreds of thousands of suggestions while typing a command",
123-
"modernfix.option.mixin.perf.mojang_registry_size": "Fixes an issue causing registration of blocks/items to slow down proportional to the number already registered. This improves startup time."
123+
"modernfix.option.mixin.perf.mojang_registry_size": "Fixes an issue causing registration of blocks/items to slow down proportional to the number already registered. This improves startup time.",
124+
"modernfix.option.mixin.perf.cache_profile_texture_url": "Avoids pointlessly creating a URL object and speeds up skull block rendering."
124125
}

forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828
public class ModelBakeEventHelper {
2929
// TODO: make into config option
30-
private static final Set<String> INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism");
30+
private static final Set<String> INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism", "embers");
3131
private final Map<ResourceLocation, BakedModel> modelRegistry;
3232
private final Set<ResourceLocation> topLevelModelLocations;
3333
private final MutableGraph<String> dependencyGraph;
Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources;
22

3-
import net.minecraft.client.renderer.block.model.BlockModel;
3+
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
44
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
55
import net.minecraft.client.resources.model.*;
6+
import net.minecraft.core.registries.BuiltInRegistries;
67
import net.minecraft.resources.ResourceLocation;
8+
import net.minecraft.world.level.block.Block;
9+
import net.minecraft.world.level.block.state.BlockState;
10+
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
711
import org.embeddedt.modernfix.ModernFix;
812
import org.embeddedt.modernfix.ModernFixClient;
913
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
1014
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
11-
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
1215
import org.embeddedt.modernfix.forge.dynresources.IModelBakerImpl;
1316
import org.spongepowered.asm.mixin.Final;
1417
import org.spongepowered.asm.mixin.Mixin;
@@ -17,71 +20,104 @@
1720
import org.spongepowered.asm.mixin.injection.Inject;
1821
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1922

23+
import java.lang.invoke.MethodHandle;
24+
import java.lang.invoke.MethodHandles;
25+
import java.util.Objects;
26+
import java.util.Optional;
2027
import java.util.function.Function;
2128

22-
@Mixin(ModelBakery.ModelBakerImpl.class)
29+
@Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600)
2330
public abstract class ModelBakerImplMixin implements IModelBakerImpl {
2431
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
2532
@Shadow @Final private ModelBakery field_40571;
2633

27-
@Shadow public abstract UnbakedModel getModel(ResourceLocation arg);
28-
2934
private boolean mfix$ignoreCache = false;
3035

36+
@Shadow @Final private Function<Material, TextureAtlasSprite> modelTextureGetter;
37+
38+
private static final MethodHandle blockStateLoaderHandle;
39+
static {
40+
try {
41+
blockStateLoaderHandle = MethodHandles.lookup().unreflect(
42+
ObfuscationReflectionHelper.findMethod(ModelBakery.class, "m_119263_", BlockState.class)
43+
);
44+
} catch(ReflectiveOperationException e) {
45+
throw new RuntimeException(e);
46+
}
47+
}
48+
3149
@Override
3250
public void mfix$ignoreCache() {
3351
mfix$ignoreCache = true;
3452
}
3553

36-
@Inject(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At("HEAD"), cancellable = true, remap = false)
37-
public void getOrLoadBakedModelDynamic(ResourceLocation arg, ModelState arg2, Function<Material, TextureAtlasSprite> textureGetter, CallbackInfoReturnable<BakedModel> cir) {
38-
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(arg, arg2.getRotation(), arg2.isUvLocked());
39-
BakedModel existing = mfix$ignoreCache ? null : this.field_40571.bakedCache.get(key);
40-
if (existing != null) {
41-
cir.setReturnValue(existing);
42-
} else {
43-
synchronized (this) {
44-
if(debugDynamicModelLoading)
45-
ModernFix.LOGGER.info("Baking {}", arg);
46-
UnbakedModel iunbakedmodel = this.getModel(arg);
47-
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
48-
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel() && debugDynamicModelLoading)
49-
ModernFix.LOGGER.warn("Model {} not present", arg);
50-
// TODO: make sure parent resolution doesn't re-run many times
51-
iunbakedmodel.resolveParents(this::getModel);
52-
BakedModel ibakedmodel = null;
53-
if (iunbakedmodel instanceof BlockModel) {
54-
BlockModel blockmodel = (BlockModel)iunbakedmodel;
55-
if (blockmodel.getRootModel() == ModelBakery.GENERATION_MARKER) {
56-
ibakedmodel = ModelBakery.ITEM_MODEL_GENERATOR.generateBlockModel(textureGetter, blockmodel).bake((ModelBaker)this, blockmodel, textureGetter, arg2, arg, false);
57-
}
58-
}
59-
if(iunbakedmodel != extendedBakery.mfix$getUnbakedMissingModel()) {
60-
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
54+
private ResourceLocation capturedLocation;
55+
private UnbakedModel capturedModel;
56+
private ModelState capturedState;
57+
58+
@Inject(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At("HEAD"), remap = false)
59+
private void captureState(ResourceLocation arg, ModelState state, Function<Material, TextureAtlasSprite> sprites, CallbackInfoReturnable<BakedModel> cir) {
60+
capturedState = state;
61+
}
62+
63+
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
64+
private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) {
65+
capturedLocation = arg;
66+
if(debugDynamicModelLoading)
67+
ModernFix.LOGGER.info("Baking {}", arg);
68+
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
69+
if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) {
70+
// synchronized because we use topLevelModels
71+
synchronized (this.field_40571) {
72+
/* to emulate vanilla model loading, treat as top-level */
73+
Optional<Block> blockOpt = Objects.equals(((ModelResourceLocation)arg).getVariant(), "inventory") ? Optional.empty() : BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(arg.getNamespace(), arg.getPath()));
74+
if(blockOpt.isPresent()) {
75+
/* load via lambda for mods that expect blockstate to get loaded */
76+
for(BlockState state : extendedBakery.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), (ModelResourceLocation)arg)) {
6177
try {
62-
iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, this.field_40571);
63-
} catch(RuntimeException e) {
64-
ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e);
78+
blockStateLoaderHandle.invokeExact(this.field_40571, state);
79+
} catch(Throwable e) {
80+
ModernFix.LOGGER.error("Error loading model", e);
6581
}
6682
}
83+
} else {
84+
this.field_40571.loadTopLevel((ModelResourceLocation)arg);
6785
}
68-
if(ibakedmodel == null) {
69-
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel()) {
70-
// use a shared baked missing model
71-
if(extendedBakery.getBakedMissingModel() == null) {
72-
extendedBakery.setBakedMissingModel(iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, arg));
73-
((DynamicBakedModelProvider)this.field_40571.getBakedTopLevelModels()).setMissingModel(extendedBakery.getBakedMissingModel());
74-
}
75-
ibakedmodel = extendedBakery.getBakedMissingModel();
76-
} else
77-
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, arg);
78-
}
79-
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
80-
ibakedmodel = integration.onBakedModelLoad(arg, iunbakedmodel, ibakedmodel, arg2, this.field_40571);
86+
cir.setReturnValue(this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel()));
87+
// avoid leaks
88+
this.field_40571.topLevelModels.clear();
89+
}
90+
} else
91+
cir.setReturnValue(this.field_40571.getModel(arg));
92+
UnbakedModel toReplace = cir.getReturnValue();
93+
if(true) {
94+
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
95+
try {
96+
toReplace = integration.onUnbakedModelPreBake(arg, toReplace, this.field_40571);
97+
} catch(RuntimeException e) {
98+
ModernFix.LOGGER.error("Exception firing model pre-bake event for {}", arg, e);
8199
}
82-
this.field_40571.bakedCache.put(key, ibakedmodel);
83-
cir.setReturnValue(ibakedmodel);
84100
}
85101
}
102+
cir.setReturnValue(toReplace);
103+
cir.getReturnValue().resolveParents(this.field_40571::getModel);
104+
capturedModel = cir.getReturnValue();
105+
if(cir.getReturnValue() == extendedBakery.mfix$getUnbakedMissingModel()) {
106+
if(arg != ModelBakery.MISSING_MODEL_LOCATION && debugDynamicModelLoading)
107+
ModernFix.LOGGER.warn("Model {} not present", arg);
108+
}
109+
}
110+
111+
@ModifyExpressionValue(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0), remap = false)
112+
private Object ignoreCacheIfRequested(Object o) {
113+
return mfix$ignoreCache ? null : o;
114+
}
115+
116+
@ModifyExpressionValue(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At(value = "INVOKE", 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;"))
117+
private BakedModel unifyMissingBakedModel(BakedModel model) {
118+
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
119+
model = integration.onBakedModelLoad(capturedLocation, capturedModel, model, capturedState, this.field_40571);
120+
}
121+
return model;
86122
}
87123
}

0 commit comments

Comments
 (0)