PaperMC/CraftBukkit-Patches/0139-Filter-attribute-modifiers-which-cause-the-attribute.patch

147 lines
6.7 KiB
Diff

From bebc5998602c0facf0282204a3f2ff4060618c25 Mon Sep 17 00:00:00 2001
From: Thinkofdeath <thinkofdeath@spigotmc.org>
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 07ea6f6..2dac846 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<String> attributeTracker = new gnu.trove.map.hash.TObjectDoubleHashMap<String>();
+ gnu.trove.map.hash.TObjectDoubleHashMap<String> attributeTrackerX = new gnu.trove.map.hash.TObjectDoubleHashMap<String>();
+ Map<String, IAttribute> attributesByName = new HashMap<String, IAttribute>();
+ attributeTracker.put( "generic.maxHealth", 20.0 );
+ attributesByName.put( "generic.maxHealth", GenericAttributes.maxHealth );
+ attributeTracker.put( "generic.followRange", 32.0 );
+ attributesByName.put( "generic.followRange", GenericAttributes.FOLLOW_RANGE );
+ attributeTracker.put( "generic.knockbackResistance", 0.0 );
+ attributesByName.put( "generic.knockbackResistance", GenericAttributes.c );
+ attributeTracker.put( "generic.movementSpeed", 0.7 );
+ attributesByName.put( "generic.movementSpeed", GenericAttributes.MOVEMENT_SPEED );
+ attributeTracker.put( "generic.attackDamage", 1.0 );
+ attributesByName.put( "generic.attackDamage", GenericAttributes.ATTACK_DAMAGE );
+ NBTTagList oldList = nbttaglist;
+ nbttaglist = new NBTTagList();
+
+ List<NBTTagCompound> op0 = new ArrayList<NBTTagCompound>();
+ List<NBTTagCompound> op1 = new ArrayList<NBTTagCompound>();
+ List<NBTTagCompound> op2 = new ArrayList<NBTTagCompound>();
+
+ 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.4