Add type checking to dynamic maps to avoid ClassCastException from badly behaved mods

This commit is contained in:
embeddedt 2024-08-19 18:17:25 -04:00
parent 489136d048
commit 2abc4fa56b
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
6 changed files with 12 additions and 7 deletions

View File

@ -47,7 +47,7 @@ public final class ModelHelpers {
* @return a fake map of the top-level models * @return a fake map of the top-level models
*/ */
public static Map<ResourceLocation, BakedModel> createFakeTopLevelMap(BiFunction<ResourceLocation, ModelState, BakedModel> modelGetter) { public static Map<ResourceLocation, BakedModel> createFakeTopLevelMap(BiFunction<ResourceLocation, ModelState, BakedModel> modelGetter) {
return new DynamicMap<>(location -> modelGetter.apply(location, BlockModelRotation.X0_Y0)); return new DynamicMap<>(ResourceLocation.class, location -> modelGetter.apply(location, BlockModelRotation.X0_Y0));
} }
/** /**

View File

@ -29,7 +29,7 @@ public class BlockModelShaperMixin {
@Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN")) @Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN"))
private void replaceModelMap(CallbackInfo ci) { private void replaceModelMap(CallbackInfo ci) {
// replace the backing map for mods which will access it // replace the backing map for mods which will access it
this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state))); this.modelByStateCache = new DynamicOverridableMap<>(BlockState.class, state -> modelManager.getModel(ModelLocationCache.get(state)));
// Clear the cached models on blockstate objects // Clear the cached models on blockstate objects
for(Block block : BuiltInRegistries.BLOCK) { for(Block block : BuiltInRegistries.BLOCK) {
for(BlockState state : block.getStateDefinition().getPossibleStates()) { for(BlockState state : block.getStateDefinition().getPossibleStates()) {

View File

@ -76,7 +76,7 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
@Shadow @Final public static ModelResourceLocation MISSING_MODEL_VARIANT; @Shadow @Final public static ModelResourceLocation MISSING_MODEL_VARIANT;
private final Map<ModelResourceLocation, BakedModel> mfix$emulatedBakedRegistry = new DynamicOverridableMap<>(this::loadBakedModelDynamic); private final Map<ModelResourceLocation, BakedModel> mfix$emulatedBakedRegistry = new DynamicOverridableMap<>(ModelResourceLocation.class, this::loadBakedModelDynamic);
@Override @Override
public UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location) { public UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location) {

View File

@ -13,7 +13,7 @@ import java.util.function.Function;
public class DynamicInt2ObjectMap<V> extends DynamicMap<Integer, V> implements Int2ObjectMap<V> { public class DynamicInt2ObjectMap<V> extends DynamicMap<Integer, V> implements Int2ObjectMap<V> {
public DynamicInt2ObjectMap(Function<Integer, V> function) { public DynamicInt2ObjectMap(Function<Integer, V> function) {
super(function); super(Integer.class, function);
} }
@Override @Override

View File

@ -11,8 +11,10 @@ import java.util.function.Function;
public class DynamicMap<K, V> implements Map<K, V> { public class DynamicMap<K, V> implements Map<K, V> {
protected final Function<K, V> function; protected final Function<K, V> function;
private final Class<K> keyClass;
public DynamicMap(Function<K, V> function) { public DynamicMap(Class<K> keyClass, Function<K, V> function) {
this.keyClass = keyClass;
this.function = function; this.function = function;
} }
@ -38,6 +40,9 @@ public class DynamicMap<K, V> implements Map<K, V> {
@Override @Override
public V get(Object o) { public V get(Object o) {
if(!keyClass.isInstance(o)) {
return null;
}
return function.apply((K)o); return function.apply((K)o);
} }

View File

@ -10,8 +10,8 @@ import java.util.function.Function;
public class DynamicOverridableMap<K, V> extends DynamicMap<K, V> { public class DynamicOverridableMap<K, V> extends DynamicMap<K, V> {
private final Map<K, V> overrideMap; private final Map<K, V> overrideMap;
public DynamicOverridableMap(Function<K, V> function) { public DynamicOverridableMap(Class<K> keyClass, Function<K, V> function) {
super(function); super(keyClass, function);
overrideMap = new Object2ObjectOpenHashMap<>(); overrideMap = new Object2ObjectOpenHashMap<>();
} }