Wrap NBTTagCompound#setTag in static helper with safeguards against circular references, fixes #299
This commit is contained in:
@@ -8,7 +8,10 @@ import net.minecraft.entity.monster.*;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EntityDamageSource;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// A note on the use of the vanilla damagesources:
|
||||
// When using indirect damage sources, the SECOND argument is the original entity (i.e. the caster), and the
|
||||
|
||||
@@ -51,8 +51,8 @@ public final class NBTExtras {
|
||||
|
||||
for(Map.Entry<K, V> entry : map.entrySet()){
|
||||
NBTTagCompound mapping = new NBTTagCompound();
|
||||
mapping.setTag(keyTagName, keyFunction.apply(entry.getKey()));
|
||||
mapping.setTag(valueTagName, valueFunction.apply(entry.getValue()));
|
||||
NBTExtras.storeTagSafely(mapping, keyTagName, keyFunction.apply(entry.getKey()));
|
||||
NBTExtras.storeTagSafely(mapping, valueTagName, valueFunction.apply(entry.getValue()));
|
||||
tagList.appendTag(mapping);
|
||||
}
|
||||
|
||||
@@ -205,6 +205,51 @@ public final class NBTExtras {
|
||||
tag.removeTag(key + "Least");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given NBT tag inside the given NBT tag compound using the given key. Under normal circumstances, this
|
||||
* is equivalent to {@link NBTTagCompound#setTag(String, NBTBase)}, but this method performs safety checks to
|
||||
* prevent circular references. If storing the given tag would cause a circular reference, the tag is not stored
|
||||
* and an error is printed to the console.
|
||||
* @param compound The {@link NBTTagCompound} in which to store the tag.
|
||||
* @param key The key to store the tag under.
|
||||
* @param tag The tag to store.
|
||||
*/
|
||||
// This is a catch-all fix for issue #299.
|
||||
public static void storeTagSafely(NBTTagCompound compound, String key, NBTBase tag){
|
||||
|
||||
if(compound == tag || deepContains(tag, compound)){
|
||||
Wizardry.logger.error("Cannot store tag of type {} under key '{}' as it would result in a circular reference!",
|
||||
NBTBase.getTypeName(tag.getId()), key);
|
||||
}else{
|
||||
compound.setTag(key, tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively searches within the first NBT tag for the second NBT tag. This handles both compound and list tags.
|
||||
* @param toSearch The NBT tag to search inside. If this is not a compound or list tag, this method will always
|
||||
* return false.
|
||||
* @param searchFor The NBT tag to search for.
|
||||
* @return True if the second tag appears anywhere within the NBT tree contained within the first tag, false if not.
|
||||
*/
|
||||
public static boolean deepContains(NBTBase toSearch, NBTBase searchFor){
|
||||
|
||||
if(toSearch instanceof NBTTagCompound){
|
||||
|
||||
for(String subKey : ((NBTTagCompound)toSearch).getKeySet()){
|
||||
NBTBase subTag = ((NBTTagCompound)toSearch).getTag(subKey);
|
||||
if(subTag == searchFor || deepContains(subTag, searchFor)) return true;
|
||||
}
|
||||
|
||||
}else if(toSearch instanceof NBTTagList){
|
||||
for(NBTBase subTag : (NBTTagList)toSearch){
|
||||
if(subTag == searchFor || deepContains(subTag, searchFor)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an NBTTagCompound which contains only the given UUID, stored using
|
||||
* {@link NBTTagCompound#setUniqueId(String, UUID)}. Allows for neater storage to NBTTagLists.
|
||||
|
||||
@@ -398,7 +398,7 @@ public final class WandHelper {
|
||||
if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound()));
|
||||
|
||||
if(!wand.getTagCompound().hasKey(UPGRADES_KEY))
|
||||
wand.getTagCompound().setTag(UPGRADES_KEY, new NBTTagCompound());
|
||||
NBTExtras.storeTagSafely(wand.getTagCompound(), UPGRADES_KEY, new NBTTagCompound());
|
||||
|
||||
NBTTagCompound upgrades = wand.getTagCompound().getCompoundTag(UPGRADES_KEY);
|
||||
|
||||
@@ -406,7 +406,7 @@ public final class WandHelper {
|
||||
|
||||
if(key != null) upgrades.setInteger(key, upgrades.getInteger(key) + 1);
|
||||
|
||||
wand.getTagCompound().setTag(UPGRADES_KEY, upgrades);
|
||||
NBTExtras.storeTagSafely(wand.getTagCompound(), UPGRADES_KEY, upgrades);
|
||||
}
|
||||
|
||||
/** Returns true if the given item is a valid special wand upgrade. */
|
||||
|
||||
Reference in New Issue
Block a user