package org.embeddedt.modernfix.dynamicresources; import com.mojang.math.Transformation; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BlockModelRotation; import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.tuple.Triple; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.AbstractMap; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; import java.util.stream.Collectors; public class DynamicBakedModelProvider implements Map { private final ModelBakery bakery; private final Map, BakedModel> bakedCache; private final Map permanentOverrides; public DynamicBakedModelProvider(ModelBakery bakery, Map, BakedModel> cache) { this.bakery = bakery; this.bakedCache = cache; this.permanentOverrides = new Object2ObjectOpenHashMap<>(); } private static Triple vanillaKey(Object o) { return Triple.of((ResourceLocation)o, BlockModelRotation.X0_Y0.getRotation(), false); } @Override public int size() { return bakedCache.size(); } @Override public boolean isEmpty() { return bakedCache.isEmpty(); } @Override public boolean containsKey(Object o) { return true; //permanentOverrides.containsKey(o) || bakedCache.containsKey(vanillaKey(o)); } @Override public boolean containsValue(Object o) { return permanentOverrides.containsValue(o) || bakedCache.containsValue(o); } @Override public BakedModel get(Object o) { BakedModel model = permanentOverrides.get(o); return model != null ? model : bakery.bake((ResourceLocation)o, BlockModelRotation.X0_Y0); } @Nullable @Override public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) { BakedModel m = permanentOverrides.put(resourceLocation, bakedModel); if(m != null) return m; else return bakedCache.get(vanillaKey(resourceLocation)); } @Override public BakedModel remove(Object o) { BakedModel m = permanentOverrides.remove(o); if(m != null) return m; return bakedCache.remove(vanillaKey(o)); } @Override public void putAll(@NotNull Map map) { permanentOverrides.putAll(map); } @Override public void clear() { throw new UnsupportedOperationException(); } @NotNull @Override public Set keySet() { return bakedCache.keySet().stream().map(Triple::getLeft).collect(Collectors.toSet()); } @NotNull @Override public Collection values() { return bakedCache.values(); } @NotNull @Override public Set> entrySet() { return bakedCache.entrySet().stream().map(entry -> new AbstractMap.SimpleImmutableEntry<>(entry.getKey().getLeft(), entry.getValue())).collect(Collectors.toSet()); } @Override public void replaceAll(BiFunction function) { Set overridenLocations = permanentOverrides.keySet(); permanentOverrides.replaceAll(function); boolean uvLock = BlockModelRotation.X0_Y0.isUvLocked(); Transformation rotation = BlockModelRotation.X0_Y0.getRotation(); bakedCache.replaceAll((loc, oldModel) -> { if(loc.getMiddle() != rotation || loc.getRight() != uvLock || overridenLocations.contains(loc.getLeft())) return oldModel; else return function.apply(loc.getLeft(), oldModel); }); } }