Revert "Use copy-on-write map for permanent overrides"
This solution is also not good enough. It causes catastrophic time complexity with mods that call get and put in rapid succession (i.e. every Forge mod using ModelBakeEvent)
This commit is contained in:
parent
621ecf6b3e
commit
ced7f866d8
|
|
@ -2,7 +2,6 @@ package org.embeddedt.modernfix.dynamicresources;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.mojang.math.Transformation;
|
import com.mojang.math.Transformation;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||||
|
|
@ -39,8 +38,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
public static DynamicBakedModelProvider currentInstance = null;
|
public static DynamicBakedModelProvider currentInstance = null;
|
||||||
private final ModelBakery bakery;
|
private final ModelBakery bakery;
|
||||||
private final Map<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> bakedCache;
|
private final Map<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> bakedCache;
|
||||||
private volatile Map<ResourceLocation, BakedModel> permanentOverridesView = null;
|
private final Map<ResourceLocation, BakedModel> permanentOverrides;
|
||||||
private final Map<ResourceLocation, BakedModel> permanentOverridesMutable;
|
|
||||||
private BakedModel missingModel;
|
private BakedModel missingModel;
|
||||||
private static final BakedModel SENTINEL = new BakedModel() {
|
private static final BakedModel SENTINEL = new BakedModel() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -87,7 +85,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
public DynamicBakedModelProvider(ModelBakery bakery, Map<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> cache) {
|
public DynamicBakedModelProvider(ModelBakery bakery, Map<Triple<ResourceLocation, Transformation, Boolean>, BakedModel> cache) {
|
||||||
this.bakery = bakery;
|
this.bakery = bakery;
|
||||||
this.bakedCache = cache;
|
this.bakedCache = cache;
|
||||||
this.permanentOverridesMutable = new Object2ObjectOpenHashMap<>();
|
this.permanentOverrides = Collections.synchronizedMap(new Object2ObjectOpenHashMap<>());
|
||||||
if(currentInstance == null)
|
if(currentInstance == null)
|
||||||
currentInstance = this;
|
currentInstance = this;
|
||||||
}
|
}
|
||||||
|
|
@ -109,27 +107,14 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
return bakedCache.isEmpty();
|
return bakedCache.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<ResourceLocation, BakedModel> getPermanentOverrides() {
|
|
||||||
Map<ResourceLocation, BakedModel> map = permanentOverridesView;
|
|
||||||
if(map == null) {
|
|
||||||
synchronized (this) {
|
|
||||||
map = permanentOverridesView;
|
|
||||||
if(map == null) {
|
|
||||||
permanentOverridesView = map = Object2ObjectMaps.unmodifiable(new Object2ObjectOpenHashMap<>(permanentOverridesMutable));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsKey(Object o) {
|
public boolean containsKey(Object o) {
|
||||||
return getPermanentOverrides().getOrDefault(o, SENTINEL) != null;
|
return permanentOverrides.getOrDefault(o, SENTINEL) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsValue(Object o) {
|
public boolean containsValue(Object o) {
|
||||||
return getPermanentOverrides().containsValue(o) || bakedCache.containsValue(o);
|
return permanentOverrides.containsValue(o) || bakedCache.containsValue(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isVanillaTopLevelModel(ResourceLocation location) {
|
private static boolean isVanillaTopLevelModel(ResourceLocation location) {
|
||||||
|
|
@ -155,7 +140,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BakedModel get(Object o) {
|
public BakedModel get(Object o) {
|
||||||
BakedModel model = getPermanentOverrides().getOrDefault(o, SENTINEL);
|
BakedModel model = permanentOverrides.getOrDefault(o, SENTINEL);
|
||||||
if(model != SENTINEL)
|
if(model != SENTINEL)
|
||||||
return model;
|
return model;
|
||||||
else {
|
else {
|
||||||
|
|
@ -171,7 +156,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
if(model == missingModel) {
|
if(model == missingModel) {
|
||||||
// to correctly emulate the original map, we return null for missing models, unless they are top-level
|
// to correctly emulate the original map, we return null for missing models, unless they are top-level
|
||||||
model = isVanillaTopLevelModel((ResourceLocation)o) ? model : null;
|
model = isVanillaTopLevelModel((ResourceLocation)o) ? model : null;
|
||||||
this.put((ResourceLocation) o, model);
|
permanentOverrides.put((ResourceLocation) o, model);
|
||||||
}
|
}
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
@ -179,11 +164,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) {
|
public BakedModel put(ResourceLocation resourceLocation, BakedModel bakedModel) {
|
||||||
BakedModel m;
|
BakedModel m = permanentOverrides.put(resourceLocation, bakedModel);
|
||||||
synchronized (this) {
|
|
||||||
m = permanentOverridesMutable.put(resourceLocation, bakedModel);
|
|
||||||
permanentOverridesView = null;
|
|
||||||
}
|
|
||||||
if(m != null)
|
if(m != null)
|
||||||
return m;
|
return m;
|
||||||
else
|
else
|
||||||
|
|
@ -192,11 +173,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BakedModel remove(Object o) {
|
public BakedModel remove(Object o) {
|
||||||
BakedModel m;
|
BakedModel m = permanentOverrides.remove(o);
|
||||||
synchronized (this) {
|
|
||||||
m = permanentOverridesMutable.remove(o);
|
|
||||||
permanentOverridesView = null;
|
|
||||||
}
|
|
||||||
if(m != null)
|
if(m != null)
|
||||||
return m;
|
return m;
|
||||||
return bakedCache.remove(vanillaKey(o));
|
return bakedCache.remove(vanillaKey(o));
|
||||||
|
|
@ -204,10 +181,7 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putAll(@NotNull Map<? extends ResourceLocation, ? extends BakedModel> map) {
|
public void putAll(@NotNull Map<? extends ResourceLocation, ? extends BakedModel> map) {
|
||||||
synchronized (this) {
|
permanentOverrides.putAll(map);
|
||||||
permanentOverridesMutable.putAll(map);
|
|
||||||
permanentOverridesView = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -236,27 +210,23 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BakedModel replace(ResourceLocation key, BakedModel value) {
|
public BakedModel replace(ResourceLocation key, BakedModel value) {
|
||||||
synchronized (this) {
|
BakedModel existingOverride = permanentOverrides.get(key);
|
||||||
BakedModel existingOverride = permanentOverridesMutable.get(key);
|
// as long as no valid override was put in (null can mean unable to load model, so we treat as invalid), replace
|
||||||
// as long as no valid override was put in (null can mean unable to load model, so we treat as invalid), replace
|
// the model
|
||||||
// the model
|
if(existingOverride == null)
|
||||||
if(existingOverride == null)
|
return this.put(key, value);
|
||||||
return this.put(key, value);
|
else
|
||||||
else
|
return existingOverride;
|
||||||
return existingOverride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replaceAll(BiFunction<? super ResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
|
public void replaceAll(BiFunction<? super ResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
|
||||||
synchronized (this) {
|
Set<ResourceLocation> overridenLocations = permanentOverrides.keySet();
|
||||||
permanentOverridesMutable.replaceAll(function);
|
permanentOverrides.replaceAll(function);
|
||||||
permanentOverridesView = null;
|
|
||||||
}
|
|
||||||
boolean uvLock = BlockModelRotation.X0_Y0.isUvLocked();
|
boolean uvLock = BlockModelRotation.X0_Y0.isUvLocked();
|
||||||
Transformation rotation = BlockModelRotation.X0_Y0.getRotation();
|
Transformation rotation = BlockModelRotation.X0_Y0.getRotation();
|
||||||
bakedCache.replaceAll((loc, oldModel) -> {
|
bakedCache.replaceAll((loc, oldModel) -> {
|
||||||
if(loc.getMiddle() != rotation || loc.getRight() != uvLock || getPermanentOverrides().containsKey(loc.getLeft()))
|
if(loc.getMiddle() != rotation || loc.getRight() != uvLock || overridenLocations.contains(loc.getLeft()))
|
||||||
return oldModel;
|
return oldModel;
|
||||||
else
|
else
|
||||||
return function.apply(loc.getLeft(), oldModel);
|
return function.apply(loc.getLeft(), oldModel);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user