/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.util.item; import java.lang.ref.WeakReference; import java.util.WeakHashMap; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import appeng.api.AEApi; import appeng.api.features.IItemComparison; import appeng.api.storage.data.IAETagCompound; import appeng.util.Platform; /* * this is used for the shared NBT Cache. */ public class AESharedNBT extends NBTTagCompound implements IAETagCompound { /* * Shared Tag Compound Cache. */ private static final WeakHashMap> SHARED_TAG_COMPOUND = new WeakHashMap>(); private final Item item; private final int meta; private SharedSearchObject sso; private int hash; private IItemComparison comp; private AESharedNBT( final Item itemID, final int damageValue ) { this.item = itemID; this.meta = damageValue; } public AESharedNBT( final int fakeValue ) { this.item = null; this.meta = 0; this.hash = fakeValue; } /* * Debug purposes. */ public static int sharedTagLoad() { return SHARED_TAG_COMPOUND.size(); } /* * Returns an NBT Compound that is used for accelerating comparisons. */ static synchronized NBTTagCompound getSharedTagCompound( final NBTTagCompound tagCompound, final ItemStack s ) { if( tagCompound.hasNoTags() ) { return null; } final Item item = s.getItem(); int meta = -1; if( s.getItem() != null && s.isItemStackDamageable() && s.getHasSubtypes() ) { meta = s.getItemDamage(); } if( isShared( tagCompound ) ) { return tagCompound; } final SharedSearchObject sso = new SharedSearchObject( item, meta, tagCompound ); final WeakReference c = SHARED_TAG_COMPOUND.get( sso ); if( c != null ) { final SharedSearchObject cg = c.get(); if( cg != null ) { return cg.getShared(); // I don't think I really need to check this } // as its already certain to exist.. } final AESharedNBT clone = AESharedNBT.createFromCompound( item, meta, tagCompound ); sso.setCompound( (NBTTagCompound) sso.getCompound().copy() ); // prevent // modification // of data based // on original // item. sso.setShared( clone ); clone.sso = sso; SHARED_TAG_COMPOUND.put( sso, new WeakReference( sso ) ); return clone; } /* * returns true if the compound is part of the shared compound system ( and can thus be compared directly ). */ public static boolean isShared( final NBTTagCompound ta ) { return ta instanceof AESharedNBT; } private static AESharedNBT createFromCompound( final Item itemID, final int damageValue, final NBTTagCompound c ) { final AESharedNBT x = new AESharedNBT( itemID, damageValue ); // c.getTags() for( final Object o : c.getKeySet() ) { final String name = (String) o; x.setTag( name, c.getTag( name ).copy() ); } x.hash = Platform.itemComparisons().createUnorderedNbtHash( c ); final ItemStack isc = new ItemStack( itemID, 1, damageValue ); isc.setTagCompound( c ); x.comp = AEApi.instance().registries().specialComparison().getSpecialComparison( isc ); return x; } int getHash() { return this.hash; } @Override public NBTTagCompound getNBTTagCompoundCopy() { return (NBTTagCompound) this.copy(); } @Override public IItemComparison getSpecialComparison() { return this.comp; } @Override public boolean equals( final Object par1Obj ) { if( par1Obj instanceof AESharedNBT ) { return this == par1Obj; } return super.equals( par1Obj ); } public boolean matches( final Item item, final int meta, final int orderlessHash ) { return item == this.item && this.meta == meta && this.hash == orderlessHash; } public boolean comparePreciseWithRegistry( final AESharedNBT tagCompound ) { if( this == tagCompound ) { return true; } if( this.comp != null && tagCompound.comp != null ) { return this.comp.sameAsPrecise( tagCompound.comp ); } return false; } public boolean compareFuzzyWithRegistry( final AESharedNBT tagCompound ) { if( this == tagCompound ) { return true; } if( tagCompound == null ) { return false; } if( this.comp == tagCompound.comp ) { return true; } if( this.comp != null ) { return this.comp.sameAsFuzzy( tagCompound.comp ); } return false; } }