Fabric
This commit is contained in:
parent
ea25f2e854
commit
efb9f4ca2d
|
|
@ -0,0 +1,67 @@
|
|||
package org.embeddedt.modernfix.fabric.mixin.perf.dynamic_resources;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
|
||||
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@Mixin(ModelBakery.ModelBakerImpl.class)
|
||||
public abstract class ModelBakerImplMixin {
|
||||
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
|
||||
@Shadow @Final private ModelBakery field_40571;
|
||||
|
||||
@Shadow public abstract UnbakedModel getModel(ResourceLocation arg);
|
||||
|
||||
@Shadow @Final private Function<Material, TextureAtlasSprite> modelTextureGetter;
|
||||
|
||||
@Inject(method = "bake", at = @At("HEAD"), cancellable = true, remap = false)
|
||||
public void getOrLoadBakedModelDynamic(ResourceLocation arg, ModelState arg2, CallbackInfoReturnable<BakedModel> cir) {
|
||||
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);
|
||||
} 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(this.modelTextureGetter, blockmodel).bake((ModelBaker)this, blockmodel, this.modelTextureGetter, arg2, arg, false);
|
||||
}
|
||||
}
|
||||
if(ibakedmodel == null) {
|
||||
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());
|
||||
}
|
||||
ibakedmodel = extendedBakery.getBakedMissingModel();
|
||||
} else
|
||||
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, this.modelTextureGetter, arg2, arg);
|
||||
}
|
||||
this.field_40571.bakedCache.put(key, ibakedmodel);
|
||||
cir.setReturnValue(ibakedmodel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,34 +4,21 @@ import com.google.common.cache.Cache;
|
|||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.RemovalNotification;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
|
||||
import net.minecraft.client.renderer.texture.AtlasSet;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.resources.ClientPackSource;
|
||||
import net.minecraft.client.resources.model.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.FilePackResources;
|
||||
import net.minecraft.server.packs.FolderPackResources;
|
||||
import net.minecraft.server.packs.PackResources;
|
||||
import net.minecraft.server.packs.VanillaPackResources;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
|
||||
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
|
||||
import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
@ -44,10 +31,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/* high priority so that our injectors are added before other mods' */
|
||||
@Mixin(value = ModelBakery.class, priority = 600)
|
||||
|
|
@ -62,34 +52,27 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
@Shadow protected abstract BlockModel loadBlockModel(ResourceLocation location) throws IOException;
|
||||
|
||||
@Shadow @Final protected ResourceManager resourceManager;
|
||||
@Shadow private AtlasSet atlasSet;
|
||||
@Shadow @Final private Set<ResourceLocation> loadingStack;
|
||||
|
||||
@Shadow protected abstract void loadModel(ResourceLocation blockstateLocation) throws Exception;
|
||||
|
||||
@Shadow @Final private static Logger LOGGER;
|
||||
|
||||
@Shadow @Final @Mutable
|
||||
private Map<ResourceLocation, BakedModel> bakedTopLevelModels;
|
||||
|
||||
@Shadow @Final @Mutable private Map<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> bakedCache;
|
||||
@Shadow @Final @Mutable private Map<ModelBakery.BakedCacheKey, BakedModel> bakedCache;
|
||||
|
||||
@Shadow @Final public static BlockModel GENERATION_MARKER;
|
||||
@Shadow @Final @Mutable private BlockColors blockColors;
|
||||
@Shadow @Final private static Logger LOGGER;
|
||||
private Cache<ModelBakery.BakedCacheKey, BakedModel> loadedBakedModels;
|
||||
|
||||
@Shadow @Final private static ItemModelGenerator ITEM_MODEL_GENERATOR;
|
||||
|
||||
@Shadow public abstract UnbakedModel getModel(ResourceLocation modelLocation);
|
||||
|
||||
@Shadow @Nullable public abstract BakedModel bake(ResourceLocation location, ModelState transform);
|
||||
|
||||
private Cache<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> loadedBakedModels;
|
||||
private Cache<ResourceLocation, UnbakedModel> loadedModels;
|
||||
|
||||
private HashMap<ResourceLocation, UnbakedModel> smallLoadingCache = new HashMap<>();
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;push(Ljava/lang/String;)V", ordinal = 0))
|
||||
private void replaceTopLevelBakedModels(ProfilerFiller filler, String s) {
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/resources/model/ModelBakery;blockColors:Lnet/minecraft/client/color/block/BlockColors;"))
|
||||
private void replaceTopLevelBakedModels(ModelBakery bakery, BlockColors val) {
|
||||
this.blockColors = val;
|
||||
this.loadedBakedModels = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(3, TimeUnit.MINUTES)
|
||||
.maximumSize(1000)
|
||||
|
|
@ -107,7 +90,6 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
this.bakedCache = loadedBakedModels.asMap();
|
||||
this.unbakedCache = loadedModels.asMap();
|
||||
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);
|
||||
filler.push(s);
|
||||
}
|
||||
|
||||
private <K, V> void onModelRemoved(RemovalNotification<K, V> notification) {
|
||||
|
|
@ -121,7 +103,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
if(k instanceof ResourceLocation) {
|
||||
rl = (ResourceLocation)k;
|
||||
} else {
|
||||
rl = ((Triple<ResourceLocation, Transformation, Boolean>)k).getLeft();
|
||||
rl = ((ModelBakery.BakedCacheKey)k).id();
|
||||
baked = true;
|
||||
}
|
||||
ModernFix.LOGGER.warn("Evicted {} model {}", baked ? "baked" : "unbaked", rl);
|
||||
|
|
@ -142,61 +124,30 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason don't actually load the model. instead, keep track of if we need to load a blockstate or a model,
|
||||
* and save the info into the two lists
|
||||
* @reason don't actually load the model.
|
||||
*/
|
||||
@Inject(method = "loadTopLevel", at = @At("HEAD"), cancellable = true)
|
||||
private void addTopLevelFile(ModelResourceLocation location, CallbackInfo ci) {
|
||||
ci.cancel();
|
||||
if(Objects.equals(location.getVariant(), "inventory")) {
|
||||
modelFiles.add(new ResourceLocation(location.getNamespace(), "item/" + location.getPath()));
|
||||
} else {
|
||||
blockStateFiles.add(new ResourceLocation(location.getNamespace(), location.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Set;addAll(Ljava/util/Collection;)Z", ordinal = 0))
|
||||
private boolean gatherModelTextures(Set<Material> materialSet, Collection<Material> collection) {
|
||||
materialSet.addAll(collection);
|
||||
gatherModelMaterials(materialSet);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 0))
|
||||
private void fetchStaticDefinitions(Map<ResourceLocation, StateDefinition<Block, BlockState>> map, BiConsumer<ResourceLocation, StateDefinition<Block, BlockState>> func) {
|
||||
map.forEach((loc, def) -> blockStateFiles.add(loc));
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;", ordinal = 0))
|
||||
private ImmutableList<BlockState> fetchBlocks(StateDefinition<Block, BlockState> def) {
|
||||
blockStateFiles.add(Registry.BLOCK.getKey(def.any().getBlock()));
|
||||
/* no-op */
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private boolean trustedResourcePack(PackResources pack) {
|
||||
return pack instanceof VanillaPackResources ||
|
||||
pack instanceof ClientPackSource ||
|
||||
pack instanceof FolderPackResources ||
|
||||
pack instanceof FilePackResources;
|
||||
}
|
||||
private BiFunction<ResourceLocation, Material, TextureAtlasSprite> textureGetter;
|
||||
|
||||
/**
|
||||
* Load all blockstate JSONs and model files, collect textures.
|
||||
*/
|
||||
private void gatherModelMaterials(Set<Material> materialSet) {
|
||||
Function<JsonElement, BlockModel> modelDeserializer = model -> BlockModel.GSON.fromJson(model, BlockModel.class);
|
||||
ModelBakeryHelpers.gatherModelMaterials(this.resourceManager, this::trustedResourcePack, materialSet, blockStateFiles,
|
||||
modelFiles, missingModel, modelDeserializer, this::getModel);
|
||||
loadedModels.invalidateAll();
|
||||
loadedModels.put(MISSING_MODEL_LOCATION, missingModel);
|
||||
}
|
||||
|
||||
@Inject(method = "uploadTextures", at = @At(value = "FIELD", target = "Lnet/minecraft/client/resources/model/ModelBakery;topLevelModels:Ljava/util/Map;", ordinal = 0), cancellable = true)
|
||||
private void skipBake(TextureManager resourceManager, ProfilerFiller profiler, CallbackInfoReturnable<AtlasSet> cir) {
|
||||
profiler.pop();
|
||||
// ensure missing model is a permanent override
|
||||
this.bakedTopLevelModels.put(MISSING_MODEL_LOCATION, this.bake(MISSING_MODEL_LOCATION, BlockModelRotation.X0_Y0));
|
||||
cir.setReturnValue(atlasSet);
|
||||
@Inject(method = "bakeModels", at = @At("HEAD"), cancellable = true)
|
||||
private void skipBake(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
|
||||
textureGetter = getter;
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -277,7 +228,14 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
}
|
||||
@Redirect(method = "loadModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;"))
|
||||
private ImmutableList<BlockState> loadOnlyRelevantBlockState(StateDefinition<Block, BlockState> stateDefinition, ResourceLocation location) {
|
||||
return ModelBakeryHelpers.getBlockStatesForMRL(stateDefinition, (ModelResourceLocation)location);
|
||||
return ModelBakeryHelpers.getBlockStatesForMRL(stateDefinition, (ModelResourceLocation)location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bakeDefault(ResourceLocation modelLocation) {
|
||||
ModelBakery self = (ModelBakery) (Object) this;
|
||||
ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation);
|
||||
return theBaker.bake(modelLocation, BlockModelRotation.X0_Y0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -287,45 +245,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
|||
|
||||
private BakedModel bakedMissingModel = null;
|
||||
|
||||
@Inject(method = "bake", at = @At("HEAD"), cancellable = true)
|
||||
public void getOrLoadBakedModelDynamic(ResourceLocation arg, ModelState arg2, CallbackInfoReturnable<BakedModel> cir) {
|
||||
Function<Material, TextureAtlasSprite> textureGetter = mat -> this.atlasSet.getSprite(mat);
|
||||
Triple<ResourceLocation, Transformation, Boolean> triple = Triple.of(arg, arg2.getRotation(), arg2.isUvLocked());
|
||||
BakedModel existing = this.bakedCache.get(triple);
|
||||
if (existing != null) {
|
||||
cir.setReturnValue(existing);
|
||||
} else if (this.atlasSet == null) {
|
||||
throw new IllegalStateException("bake called too early");
|
||||
} else {
|
||||
synchronized (this) {
|
||||
if(debugDynamicModelLoading)
|
||||
LOGGER.info("Baking {}", arg);
|
||||
UnbakedModel iunbakedmodel = this.getModel(arg);
|
||||
iunbakedmodel.getMaterials(this::getModel, new HashSet<>());
|
||||
if(iunbakedmodel == missingModel && debugDynamicModelLoading)
|
||||
LOGGER.warn("Model {} not present", arg);
|
||||
BakedModel ibakedmodel = null;
|
||||
if (iunbakedmodel instanceof BlockModel) {
|
||||
BlockModel blockmodel = (BlockModel)iunbakedmodel;
|
||||
if (blockmodel.getRootModel() == GENERATION_MARKER) {
|
||||
ibakedmodel = ITEM_MODEL_GENERATOR.generateBlockModel(textureGetter, blockmodel).bake((ModelBakery)(Object)this, blockmodel, this.atlasSet::getSprite, arg2, arg, false);
|
||||
}
|
||||
}
|
||||
if(ibakedmodel == null) {
|
||||
if(iunbakedmodel == missingModel) {
|
||||
// use a shared baked missing model
|
||||
if(bakedMissingModel == null) {
|
||||
bakedMissingModel = iunbakedmodel.bake((ModelBakery) (Object) this, textureGetter, arg2, arg);
|
||||
((DynamicBakedModelProvider)this.bakedTopLevelModels).setMissingModel(bakedMissingModel);
|
||||
}
|
||||
ibakedmodel = bakedMissingModel;
|
||||
} else
|
||||
ibakedmodel = iunbakedmodel.bake((ModelBakery) (Object) this, textureGetter, arg2, arg);
|
||||
}
|
||||
// TODO event
|
||||
this.bakedCache.put(triple, ibakedmodel);
|
||||
cir.setReturnValue(ibakedmodel);
|
||||
}
|
||||
}
|
||||
public void setBakedMissingModel(BakedModel m) {
|
||||
bakedMissingModel = m;
|
||||
}
|
||||
|
||||
public BakedModel getBakedMissingModel() {
|
||||
return bakedMissingModel;
|
||||
}
|
||||
|
||||
public UnbakedModel mfix$getUnbakedMissingModel() {
|
||||
return missingModel;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package org.embeddedt.modernfix.fabric.mixin.perf.dynamic_resources;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.util.LambdaMap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(ModelManager.class)
|
||||
public class ModelManagerMixin {
|
||||
@Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockModels(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
|
||||
private CompletableFuture<Map<ResourceLocation, BlockModel>> deferBlockModelLoad(ResourceManager manager, Executor executor) {
|
||||
return CompletableFuture.completedFuture(new LambdaMap<>(location -> loadSingleBlockModel(manager, location)));
|
||||
}
|
||||
|
||||
@Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockStates(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
|
||||
private CompletableFuture<Map<ResourceLocation, List<ModelBakery.LoadedJson>>> deferBlockStateLoad(ResourceManager manager, Executor executor) {
|
||||
return CompletableFuture.completedFuture(new LambdaMap<>(location -> loadSingleBlockState(manager, location)));
|
||||
}
|
||||
|
||||
@Redirect(method = "loadModels", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;"))
|
||||
private ImmutableList<BlockState> skipCollection(StateDefinition<Block, BlockState> definition) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private BlockModel loadSingleBlockModel(ResourceManager manager, ResourceLocation location) {
|
||||
return manager.getResource(location).map(resource -> {
|
||||
try {
|
||||
return BlockModel.fromStream(resource.openAsReader());
|
||||
} catch(IOException e) {
|
||||
ModernFix.LOGGER.error("Couldn't load model", e);
|
||||
return null;
|
||||
}
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
private List<ModelBakery.LoadedJson> loadSingleBlockState(ResourceManager manager, ResourceLocation location) {
|
||||
return manager.getResourceStack(location).stream().map(resource -> {
|
||||
try {
|
||||
return new ModelBakery.LoadedJson(resource.sourcePackId(), GsonHelper.parse(resource.openAsReader()));
|
||||
} catch(IOException e) {
|
||||
ModernFix.LOGGER.error("Couldn't load blockstate", e);
|
||||
return null;
|
||||
}
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
@ -51,15 +51,6 @@ public class ModernFixPlatformHooksImpl {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static TextureAtlasSprite loadTextureAtlasSprite(TextureAtlas atlasTexture,
|
||||
ResourceManager resourceManager, TextureAtlasSprite.Info textureInfo,
|
||||
Resource resource,
|
||||
int atlasWidth, int atlasHeight,
|
||||
int spriteX, int spriteY, int mipmapLevel,
|
||||
NativeImage image) {
|
||||
return new TextureAtlasSprite(atlasTexture, textureInfo, mipmapLevel, atlasWidth, atlasHeight, spriteX, spriteY, image);
|
||||
}
|
||||
|
||||
public static Path getGameDirectory() {
|
||||
return FabricLoader.getInstance().getGameDir();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user