From dc7a41d7197231eea336e1030f780c7a09a9a5ab Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 31 Jul 2014 17:48:20 +0100 Subject: [PATCH] Filter attribute modifiers which cause the attribute to go out of its range diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java index 2429eef..dbdd47d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -49,6 +49,8 @@ import org.apache.commons.codec.binary.Base64; // Spigot start import static org.spigotmc.ValidateUtils.*; +import net.minecraft.server.GenericAttributes; +import net.minecraft.server.IAttribute; // Spigot end /** @@ -279,6 +281,123 @@ class CraftMetaItem implements ItemMeta, Repairable { NBTTagList save = null; NBTTagList nbttaglist = tag.getList(ATTRIBUTES.NBT, 10); + // Spigot start + gnu.trove.map.hash.TObjectDoubleHashMap attributeTracker = new gnu.trove.map.hash.TObjectDoubleHashMap(); + gnu.trove.map.hash.TObjectDoubleHashMap attributeTrackerX = new gnu.trove.map.hash.TObjectDoubleHashMap(); + Map attributesByName = new HashMap(); + attributeTracker.put( "generic.maxHealth", 20.0 ); + attributesByName.put( "generic.maxHealth", GenericAttributes.maxHealth ); + attributeTracker.put( "generic.followRange", 32.0 ); + attributesByName.put( "generic.followRange", GenericAttributes.b ); + attributeTracker.put( "generic.knockbackResistance", 0.0 ); + attributesByName.put( "generic.knockbackResistance", GenericAttributes.c ); + attributeTracker.put( "generic.movementSpeed", 0.7 ); + attributesByName.put( "generic.movementSpeed", GenericAttributes.d ); + attributeTracker.put( "generic.attackDamage", 1.0 ); + attributesByName.put( "generic.attackDamage", GenericAttributes.e ); + NBTTagList oldList = nbttaglist; + nbttaglist = new NBTTagList(); + + List op0 = new ArrayList(); + List op1 = new ArrayList(); + List op2 = new ArrayList(); + + for ( int i = 0; i < oldList.size(); ++i ) + { + NBTTagCompound nbttagcompound = oldList.get( i ); + if ( nbttagcompound == null ) continue; + + if ( !nbttagcompound.hasKeyOfType(ATTRIBUTES_UUID_HIGH.NBT, 99) ) + { + continue; + } + if ( !nbttagcompound.hasKeyOfType(ATTRIBUTES_UUID_LOW.NBT, 99) ) + { + continue; + } + if ( !( nbttagcompound.get( ATTRIBUTES_IDENTIFIER.NBT ) instanceof NBTTagString ) || !CraftItemFactory.KNOWN_NBT_ATTRIBUTE_NAMES.contains( nbttagcompound.getString( ATTRIBUTES_IDENTIFIER.NBT ) ) ) + { + continue; + } + if ( !( nbttagcompound.get( ATTRIBUTES_NAME.NBT ) instanceof NBTTagString ) || nbttagcompound.getString( ATTRIBUTES_NAME.NBT ).isEmpty() ) + { + continue; + } + if ( !nbttagcompound.hasKeyOfType(ATTRIBUTES_VALUE.NBT, 99) ) + { + continue; + } + if ( !nbttagcompound.hasKeyOfType(ATTRIBUTES_TYPE.NBT, 99) || nbttagcompound.getInt( ATTRIBUTES_TYPE.NBT ) < 0 || nbttagcompound.getInt( ATTRIBUTES_TYPE.NBT ) > 2 ) + { + continue; + } + + switch ( nbttagcompound.getInt( ATTRIBUTES_TYPE.NBT ) ) + { + case 0: + op0.add( nbttagcompound ); + break; + case 1: + op1.add( nbttagcompound ); + break; + case 2: + op2.add( nbttagcompound ); + break; + } + } + for ( NBTTagCompound nbtTagCompound : op0 ) + { + String name = nbtTagCompound.getString( ATTRIBUTES_IDENTIFIER.NBT ); + if ( attributeTracker.containsKey( name ) ) + { + double val = attributeTracker.get( name ); + val += nbtTagCompound.getDouble( ATTRIBUTES_VALUE.NBT ); + if ( val != attributesByName.get( name ).a( val ) ) + { + continue; + } + attributeTracker.put( name, val ); + } + nbttaglist.add( nbtTagCompound ); + } + for ( String name : attributeTracker.keySet() ) + { + attributeTrackerX.put( name, attributeTracker.get( name ) ); + } + for ( NBTTagCompound nbtTagCompound : op1 ) + { + String name = nbtTagCompound.getString( ATTRIBUTES_IDENTIFIER.NBT ); + if ( attributeTracker.containsKey( name ) ) + { + double val = attributeTracker.get( name ); + double valX = attributeTrackerX.get( name ); + val += valX * nbtTagCompound.getDouble( ATTRIBUTES_VALUE.NBT ); + if ( val != attributesByName.get( name ).a( val ) ) + { + continue; + } + attributeTracker.put( name, val ); + } + nbttaglist.add( nbtTagCompound ); + } + for ( NBTTagCompound nbtTagCompound : op2 ) + { + String name = nbtTagCompound.getString( ATTRIBUTES_IDENTIFIER.NBT ); + if ( attributeTracker.containsKey( name ) ) + { + double val = attributeTracker.get( name ); + val += val * nbtTagCompound.getDouble( ATTRIBUTES_VALUE.NBT ); + if ( val != attributesByName.get( name ).a( val ) ) + { + continue; + } + attributeTracker.put( name, val ); + } + nbttaglist.add( nbtTagCompound ); + } + + // Spigot end + for (int i = 0; i < nbttaglist.size(); ++i) { if (!(nbttaglist.get(i) instanceof NBTTagCompound)) { continue; -- 2.1.0