Merge 1.20.2 into 1.20.3
This commit is contained in:
commit
207521f778
|
|
@ -0,0 +1,37 @@
|
|||
package org.embeddedt.modernfix.common.mixin.perf.cache_profile_texture_url;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
import net.minecraft.client.resources.SkinManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Mixin(SkinManager.class)
|
||||
public class SkinManagerMixin {
|
||||
@Unique
|
||||
private final Cache<MinecraftProfileTexture, String> mfix$hashCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(60, TimeUnit.SECONDS)
|
||||
.concurrencyLevel(1)
|
||||
.build();
|
||||
|
||||
@Redirect(method = "registerTexture(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/client/resources/SkinManager$SkinTextureCallback;)Lnet/minecraft/resources/ResourceLocation;",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;getHash()Ljava/lang/String;", remap = false))
|
||||
private String useCachedHash(MinecraftProfileTexture texture) {
|
||||
// avoid lambda allocation for common case
|
||||
String hash = mfix$hashCache.getIfPresent(texture);
|
||||
if(hash != null)
|
||||
return hash;
|
||||
|
||||
try {
|
||||
return mfix$hashCache.get(texture, texture::getHash);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -120,5 +120,6 @@
|
|||
"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.",
|
||||
"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.",
|
||||
"modernfix.option.mixin.perf.faster_command_suggestions": "Mitigate lag when there are hundreds of thousands of suggestions while typing a command",
|
||||
"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."
|
||||
"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.",
|
||||
"modernfix.option.mixin.perf.cache_profile_texture_url": "Avoids pointlessly creating a URL object and speeds up skull block rendering."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import java.util.*;
|
|||
*/
|
||||
public class ModelBakeEventHelper {
|
||||
// TODO: make into config option
|
||||
private static final Set<String> INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism");
|
||||
private static final Set<String> INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism", "embers");
|
||||
private final Map<ResourceLocation, BakedModel> modelRegistry;
|
||||
private final Set<ResourceLocation> topLevelModelLocations;
|
||||
private final MutableGraph<String> dependencyGraph;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.*;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.ModernFixClient;
|
||||
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
|
||||
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
|
||||
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
|
||||
import org.embeddedt.modernfix.forge.dynresources.IModelBakerImpl;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
@ -17,71 +20,104 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
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 implements IModelBakerImpl {
|
||||
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
|
||||
@Shadow @Final private ModelBakery field_40571;
|
||||
|
||||
@Shadow public abstract UnbakedModel getModel(ResourceLocation arg);
|
||||
|
||||
private boolean mfix$ignoreCache = false;
|
||||
|
||||
@Shadow @Final private Function<Material, TextureAtlasSprite> modelTextureGetter;
|
||||
|
||||
private static final MethodHandle blockStateLoaderHandle;
|
||||
static {
|
||||
try {
|
||||
blockStateLoaderHandle = MethodHandles.lookup().unreflect(
|
||||
ObfuscationReflectionHelper.findMethod(ModelBakery.class, "m_119263_", BlockState.class)
|
||||
);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mfix$ignoreCache() {
|
||||
mfix$ignoreCache = true;
|
||||
}
|
||||
|
||||
@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)
|
||||
public void getOrLoadBakedModelDynamic(ResourceLocation arg, ModelState arg2, Function<Material, TextureAtlasSprite> textureGetter, CallbackInfoReturnable<BakedModel> cir) {
|
||||
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(arg, arg2.getRotation(), arg2.isUvLocked());
|
||||
BakedModel existing = mfix$ignoreCache ? null : this.field_40571.bakedCache.get(key);
|
||||
if (existing != null) {
|
||||
cir.setReturnValue(existing);
|
||||
} else {
|
||||
synchronized (this) {
|
||||
if(debugDynamicModelLoading)
|
||||
ModernFix.LOGGER.info("Baking {}", arg);
|
||||
UnbakedModel iunbakedmodel = this.getModel(arg);
|
||||
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
|
||||
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel() && debugDynamicModelLoading)
|
||||
ModernFix.LOGGER.warn("Model {} not present", arg);
|
||||
// TODO: make sure parent resolution doesn't re-run many times
|
||||
iunbakedmodel.resolveParents(this::getModel);
|
||||
BakedModel ibakedmodel = null;
|
||||
if (iunbakedmodel instanceof BlockModel) {
|
||||
BlockModel blockmodel = (BlockModel)iunbakedmodel;
|
||||
if (blockmodel.getRootModel() == ModelBakery.GENERATION_MARKER) {
|
||||
ibakedmodel = ModelBakery.ITEM_MODEL_GENERATOR.generateBlockModel(textureGetter, blockmodel).bake((ModelBaker)this, blockmodel, textureGetter, arg2, arg, false);
|
||||
}
|
||||
}
|
||||
if(iunbakedmodel != extendedBakery.mfix$getUnbakedMissingModel()) {
|
||||
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
|
||||
private ResourceLocation capturedLocation;
|
||||
private UnbakedModel capturedModel;
|
||||
private ModelState capturedState;
|
||||
|
||||
@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)
|
||||
private void captureState(ResourceLocation arg, ModelState state, Function<Material, TextureAtlasSprite> sprites, CallbackInfoReturnable<BakedModel> cir) {
|
||||
capturedState = state;
|
||||
}
|
||||
|
||||
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
|
||||
private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) {
|
||||
capturedLocation = arg;
|
||||
if(debugDynamicModelLoading)
|
||||
ModernFix.LOGGER.info("Baking {}", arg);
|
||||
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
|
||||
if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) {
|
||||
// synchronized because we use topLevelModels
|
||||
synchronized (this.field_40571) {
|
||||
/* 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 {
|
||||
iunbakedmodel = integration.onUnbakedModelPreBake(arg, iunbakedmodel, this.field_40571);
|
||||
} catch(RuntimeException e) {
|
||||
ModernFix.LOGGER.error("Exception encountered firing bake event for {}", arg, e);
|
||||
blockStateLoaderHandle.invokeExact(this.field_40571, state);
|
||||
} catch(Throwable e) {
|
||||
ModernFix.LOGGER.error("Error loading model", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.field_40571.loadTopLevel((ModelResourceLocation)arg);
|
||||
}
|
||||
if(ibakedmodel == null) {
|
||||
if(iunbakedmodel == extendedBakery.mfix$getUnbakedMissingModel()) {
|
||||
// use a shared baked missing model
|
||||
if(extendedBakery.getBakedMissingModel() == null) {
|
||||
extendedBakery.setBakedMissingModel(iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, arg));
|
||||
((DynamicBakedModelProvider)this.field_40571.getBakedTopLevelModels()).setMissingModel(extendedBakery.getBakedMissingModel());
|
||||
}
|
||||
ibakedmodel = extendedBakery.getBakedMissingModel();
|
||||
} else
|
||||
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, 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));
|
||||
UnbakedModel toReplace = cir.getReturnValue();
|
||||
if(true) {
|
||||
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
|
||||
try {
|
||||
toReplace = integration.onUnbakedModelPreBake(arg, toReplace, this.field_40571);
|
||||
} catch(RuntimeException e) {
|
||||
ModernFix.LOGGER.error("Exception firing model pre-bake event for {}", arg, e);
|
||||
}
|
||||
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
|
||||
ibakedmodel = integration.onBakedModelLoad(arg, iunbakedmodel, ibakedmodel, arg2, this.field_40571);
|
||||
}
|
||||
this.field_40571.bakedCache.put(key, ibakedmodel);
|
||||
cir.setReturnValue(ibakedmodel);
|
||||
}
|
||||
}
|
||||
cir.setReturnValue(toReplace);
|
||||
cir.getReturnValue().resolveParents(this.field_40571::getModel);
|
||||
capturedModel = cir.getReturnValue();
|
||||
if(cir.getReturnValue() == extendedBakery.mfix$getUnbakedMissingModel()) {
|
||||
if(arg != ModelBakery.MISSING_MODEL_LOCATION && debugDynamicModelLoading)
|
||||
ModernFix.LOGGER.warn("Model {} not present", arg);
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
private Object ignoreCacheIfRequested(Object o) {
|
||||
return mfix$ignoreCache ? null : o;
|
||||
}
|
||||
|
||||
@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;"))
|
||||
private BakedModel unifyMissingBakedModel(BakedModel model) {
|
||||
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
|
||||
model = integration.onBakedModelLoad(capturedLocation, capturedModel, model, capturedState, this.field_40571);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,7 @@ import org.spongepowered.asm.mixin.Final;
|
|||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
|
|
@ -42,8 +39,8 @@ 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 {
|
||||
|
||||
|
|
@ -68,6 +65,9 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
@Shadow @Final private static Logger LOGGER;
|
||||
|
||||
@Shadow
|
||||
public abstract void loadTopLevel(ModelResourceLocation modelResourceLocation);
|
||||
|
||||
@Shadow public abstract UnbakedModel getModel(ResourceLocation resourceLocation);
|
||||
|
||||
private Cache<ModelBakery.BakedCacheKey, BakedModel> loadedBakedModels;
|
||||
|
|
@ -76,6 +76,8 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
private HashMap<ResourceLocation, UnbakedModel> smallLoadingCache = new HashMap<>();
|
||||
|
||||
private boolean ignoreModelLoad;
|
||||
|
||||
// disable fabric recursion
|
||||
@SuppressWarnings("unused")
|
||||
private boolean fabric_enableGetOrLoadModelGuard;
|
||||
|
|
@ -116,6 +118,12 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);
|
||||
}
|
||||
|
||||
@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", ordinal = 0), index = 0)
|
||||
private String ignoreFutureModelLoads(String name) {
|
||||
this.ignoreModelLoad = true;
|
||||
return name;
|
||||
}
|
||||
|
||||
private <K, V> void onModelRemoved(RemovalNotification<K, V> notification) {
|
||||
if(!debugDynamicModelLoading)
|
||||
return;
|
||||
|
|
@ -130,6 +138,9 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
rl = ((ModelBakery.BakedCacheKey)k).id();
|
||||
baked = true;
|
||||
}
|
||||
/* can fire when a model is replaced */
|
||||
if(!baked && this.loadedModels.getIfPresent(rl) != null)
|
||||
return;
|
||||
ModernFix.LOGGER.warn("Evicted {} model {}", baked ? "baked" : "unbaked", rl);
|
||||
}
|
||||
|
||||
|
|
@ -138,21 +149,23 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
private Set<ResourceLocation> blockStateFiles;
|
||||
private Set<ResourceLocation> modelFiles;
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBakery;loadBlockModel(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/renderer/block/model/BlockModel;", ordinal = 0))
|
||||
private BlockModel captureMissingModel(ModelBakery bakery, ResourceLocation location) throws IOException {
|
||||
this.missingModel = this.loadBlockModel(location);
|
||||
@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0), index = 1)
|
||||
private Object captureMissingModel(Object model) {
|
||||
this.missingModel = (UnbakedModel)model;
|
||||
this.blockStateFiles = new HashSet<>();
|
||||
this.modelFiles = new HashSet<>();
|
||||
return (BlockModel)this.missingModel;
|
||||
return this.missingModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason don't actually load the model.
|
||||
* @reason don't actually load most models
|
||||
*/
|
||||
@Inject(method = "loadTopLevel", at = @At("HEAD"), cancellable = true)
|
||||
private void addTopLevelFile(ModelResourceLocation location, CallbackInfo ci) {
|
||||
ci.cancel();
|
||||
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBakery;loadTopLevel(Lnet/minecraft/client/resources/model/ModelResourceLocation;)V"))
|
||||
private void addTopLevelFile(ModelBakery bakery, ModelResourceLocation location) {
|
||||
if(location == MISSING_MODEL_LOCATION || !this.ignoreModelLoad) {
|
||||
loadTopLevel(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 0))
|
||||
|
|
@ -177,13 +190,14 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
private BiFunction<ResourceLocation, Material, TextureAtlasSprite> textureGetter;
|
||||
|
||||
@Inject(method = "bakeModels", at = @At("HEAD"))
|
||||
private void storeTextureGetter(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
|
||||
private void captureGetter(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
|
||||
this.ignoreModelLoad = false;
|
||||
textureGetter = getter;
|
||||
DynamicBakedModelProvider.currentInstance = (DynamicBakedModelProvider)this.bakedTopLevelModels;
|
||||
}
|
||||
|
||||
@Redirect(method = "bakeModels", at = @At(value = "INVOKE", target = "Ljava/util/Map;keySet()Ljava/util/Set;"))
|
||||
private Set skipBakingModels(Map instance) {
|
||||
private Set<ResourceLocation> skipBake(Map<ResourceLocation, UnbakedModel> instance) {
|
||||
Set<ResourceLocation> modelSet = new HashSet<>(instance.keySet());
|
||||
if(modelSet.size() > 0)
|
||||
ModernFix.LOGGER.info("Early baking {} models", modelSet.size());
|
||||
|
|
@ -295,9 +309,16 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
@Override
|
||||
public BakedModel bakeDefault(ResourceLocation modelLocation, ModelState state) {
|
||||
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(modelLocation, BlockModelRotation.X0_Y0.getRotation(), BlockModelRotation.X0_Y0.isUvLocked());
|
||||
BakedModel m = loadedBakedModels.getIfPresent(key);
|
||||
if(m != null)
|
||||
return m;
|
||||
ModelBakery self = (ModelBakery) (Object) this;
|
||||
ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation);
|
||||
return theBaker.bake(modelLocation, state, theBaker.getModelTextureGetter());
|
||||
synchronized(this) { m = theBaker.bake(modelLocation, state, theBaker.getModelTextureGetter()); }
|
||||
if(m != null)
|
||||
loadedBakedModels.put(key, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user