From e85acf2beeac99bf6ca58a2018aa8b490fa177a1 Mon Sep 17 00:00:00 2001 From: thatsIch Date: Mon, 27 Apr 2015 09:51:40 +0200 Subject: [PATCH] Fixes #1339: Was not able to retrieve the name of an unregistered part Added an additional map to store all parts and be able to access them if needed. Added public preconditions Added private asserts Excluded public overridden methods, since behaviour can be unexpected --- .../definitions/DefinitionConstructor.java | 10 +- .../appeng/items/parts/ItemMultiPart.java | 263 +++++++++--------- 2 files changed, 134 insertions(+), 139 deletions(-) diff --git a/src/main/java/appeng/core/api/definitions/DefinitionConstructor.java b/src/main/java/appeng/core/api/definitions/DefinitionConstructor.java index 9addd1eb6..4b3be3c7c 100644 --- a/src/main/java/appeng/core/api/definitions/DefinitionConstructor.java +++ b/src/main/java/appeng/core/api/definitions/DefinitionConstructor.java @@ -3,8 +3,6 @@ package appeng.core.api.definitions; import net.minecraft.item.Item; -import com.google.common.base.Optional; - import appeng.api.definitions.IBlockDefinition; import appeng.api.definitions.IItemDefinition; import appeng.api.definitions.ITileDefinition; @@ -91,13 +89,9 @@ public class DefinitionConstructor for( AEColor color : AEColor.values() ) { - ItemStackSrc multiPartSource = target.createPart( type, color ); - final Optional maybeSource = Optional.fromNullable( multiPartSource ); + final ItemStackSrc multiPartSource = target.createPart( type, color ); - if( maybeSource.isPresent() ) - { - definition.add( color, multiPartSource ); - } + definition.add( color, multiPartSource ); } return definition; diff --git a/src/main/java/appeng/items/parts/ItemMultiPart.java b/src/main/java/appeng/items/parts/ItemMultiPart.java index 222978b5e..cbd62863a 100644 --- a/src/main/java/appeng/items/parts/ItemMultiPart.java +++ b/src/main/java/appeng/items/parts/ItemMultiPart.java @@ -19,6 +19,7 @@ package appeng.items.parts; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -28,6 +29,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.client.renderer.texture.IIconRegister; @@ -41,6 +43,8 @@ import net.minecraft.world.World; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import com.google.common.base.Preconditions; + import appeng.api.AEApi; import appeng.api.implementations.items.IItemGroup; import appeng.api.parts.IPart; @@ -48,7 +52,6 @@ import appeng.api.parts.IPartHelper; import appeng.api.parts.IPartItem; import appeng.api.util.AEColor; import appeng.core.AEConfig; -import appeng.core.AELog; import appeng.core.features.AEFeature; import appeng.core.features.ItemStackSrc; import appeng.core.features.NameResolver; @@ -58,27 +61,55 @@ import appeng.integration.IntegrationType; import appeng.items.AEBaseItem; -public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup +public final class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup { public static ItemMultiPart instance; private final NameResolver nameResolver; - private final Map dmgToPart = new HashMap(); + private final Map registered; + private final Map unregistered; public ItemMultiPart( IPartHelper partHelper ) { + Preconditions.checkNotNull( partHelper ); + + this.registered = new HashMap(); + this.unregistered = new HashMap(); + this.nameResolver = new NameResolver( this.getClass() ); this.setFeature( EnumSet.of( AEFeature.Core ) ); partHelper.setItemBusRenderer( this ); this.setHasSubtypes( true ); + instance = this; } + @Nonnull public final ItemStackSrc createPart( PartType mat ) { - int varID = 0; + Preconditions.checkNotNull( mat ); + + return this.createPart( mat, 0 ); + } + + @Nonnull + public ItemStackSrc createPart( PartType mat, AEColor color ) + { + Preconditions.checkNotNull( mat ); + Preconditions.checkNotNull( color ); + + final int varID = color.ordinal(); + + return this.createPart( mat, varID ); + } + + @Nonnull + private ItemStackSrc createPart( PartType mat, int varID ) + { + assert mat != null; + assert varID >= 0; // verify - for( PartTypeIst p : this.dmgToPart.values() ) + for( PartTypeWithVariant p : this.registered.values() ) { if( p.part == mat && p.variant == varID ) throw new IllegalStateException( "Cannot create the same material twice..." ); @@ -91,81 +122,34 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup for( IntegrationType integrationType : mat.getIntegrations() ) enabled &= IntegrationRegistry.INSTANCE.isEnabled( integrationType ); - int newPartNum = mat.baseDamage + varID; - ItemStackSrc output = new ItemStackSrc( this, newPartNum ); + final int partDamage = mat.baseDamage + varID; + final ItemStackSrc output = new ItemStackSrc( this, partDamage ); - if( enabled ) - { - PartTypeIst pti = new PartTypeIst(); - pti.part = mat; - pti.variant = varID; + final PartTypeWithVariant pti = new PartTypeWithVariant( mat, varID ); - if( this.dmgToPart.get( newPartNum ) == null ) - { - this.dmgToPart.put( newPartNum, pti ); - return output; - } - else - { - throw new IllegalStateException( "Meta Overlap detected." ); - } - } + this.processMetaOverlap( enabled, partDamage, mat, pti ); return output; } - public ItemStackSrc createPart( PartType mat, Enum variant ) + private void processMetaOverlap( boolean enabled, int partDamage, PartType mat, PartTypeWithVariant pti ) { - try - { - // I think this still works? - ItemStack is = new ItemStack( this ); - mat.getPart().getConstructor( ItemStack.class ).newInstance( is ); - } - catch( Throwable e ) - { - AELog.integration( e ); - e.printStackTrace(); - return null; // part not supported.. - } + assert partDamage >= 0; + assert mat != null; + assert pti != null; - int varID = variant == null ? 0 : variant.ordinal(); + final Map reference = ( enabled ) ? this.registered : this.unregistered; + if( reference.containsKey( partDamage ) ) + throw new IllegalStateException( "Meta Overlap detected with type " + mat + " and damage " + partDamage + ". Found " + reference.get( partDamage ) + " there already." ); - // verify - for( PartTypeIst p : this.dmgToPart.values() ) - { - if( p.part == mat && p.variant == varID ) - throw new IllegalStateException( "Cannot create the same material twice..." ); - } - - boolean enabled = true; - for( AEFeature f : mat.getFeature() ) - enabled = enabled && AEConfig.instance.isFeatureEnabled( f ); - - if( enabled ) - { - int newPartNum = mat.baseDamage + varID; - ItemStackSrc output = new ItemStackSrc( this, newPartNum ); - - PartTypeIst pti = new PartTypeIst(); - pti.part = mat; - pti.variant = varID; - - if( this.dmgToPart.get( newPartNum ) == null ) - { - this.dmgToPart.put( newPartNum, pti ); - return output; - } - else - throw new IllegalStateException( "Meta Overlap detected." ); - } - - return null; + reference.put( partDamage, pti ); } public int getDamageByType( PartType t ) { - for( Entry pt : this.dmgToPart.entrySet() ) + Preconditions.checkNotNull( t ); + + for( Entry pt : this.registered.entrySet() ) { if( pt.getValue().part == t ) return pt.getKey(); @@ -183,7 +167,7 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup @Override public IIcon getIconFromDamage( int dmg ) { - return this.dmgToPart.get( dmg ).ico; + return this.registered.get( dmg ).ico; } @Override @@ -198,36 +182,16 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup return "item.appliedenergistics2." + this.getName( is ); } - public String getName( ItemStack is ) - { - return this.nameResolver.getName( this.getTypeByStack( is ).name() ); - } - - @Nullable - public PartType getTypeByStack( ItemStack is ) - { - if( is == null ) - return null; - - PartTypeIst pt = this.dmgToPart.get( is.getItemDamage() ); - if( pt != null ) - return pt.part; - - return null; - } - @Override public String getItemStackDisplayName( ItemStack is ) { - PartType pt = this.getTypeByStack( is ); - if( pt == null ) - return "Unnamed"; + final PartType pt = this.getTypeByStack( is ); if( pt.isCable() ) { final AEColor[] variants = AEColor.values(); - return super.getItemStackDisplayName( is ) + " - " + variants[this.dmgToPart.get( is.getItemDamage() ).variant].toString(); + return super.getItemStackDisplayName( is ) + " - " + variants[this.registered.get( is.getItemDamage() ).variant].toString(); } if( pt.getExtraName() != null ) @@ -239,60 +203,96 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup @Override public void getSubItems( Item number, CreativeTabs tab, List cList ) { - List> types = new ArrayList>( this.dmgToPart.entrySet() ); - Collections.sort( types, new Comparator>() + List> types = new ArrayList>( this.registered.entrySet() ); + Collections.sort( types, new Comparator>() { @Override - public int compare( Entry o1, Entry o2 ) + public int compare( Entry o1, Entry o2 ) { return o1.getValue().part.name().compareTo( o2.getValue().part.name() ); } } ); - for( Entry part : types ) + for( Entry part : types ) cList.add( new ItemStack( this, 1, part.getKey() ) ); } @Override public void registerIcons( IIconRegister par1IconRegister ) { - for( Entry part : this.dmgToPart.entrySet() ) + for( Entry part : this.registered.entrySet() ) { String tex = "appliedenergistics2:" + this.getName( new ItemStack( this, 1, part.getKey() ) ); part.getValue().ico = par1IconRegister.registerIcon( tex ); } } + public String getName( ItemStack is ) + { + Preconditions.checkNotNull( is ); + + final PartType stackType = this.getTypeByStack( is ); + final String typeName = stackType.name(); + + return this.nameResolver.getName( typeName ); + } + + @Nonnull + public PartType getTypeByStack( ItemStack is ) + { + Preconditions.checkNotNull( is ); + + final PartTypeWithVariant pt = this.registered.get( is.getItemDamage() ); + if( pt != null ) + return pt.part; + final PartTypeWithVariant unregisteredPartType = this.unregistered.get( is.getItemDamage() ); + if( unregisteredPartType != null ) + return unregisteredPartType.part; + + throw new IllegalStateException( "ItemStack " + is + " has to be either registered or unregistered, but was not found in either." ); + } + + @Nonnull @Override public IPart createPartFromItemStack( ItemStack is ) { + final PartType type = this.getTypeByStack( is ); + final Class part = type.getPart(); + try { - PartType t = this.getTypeByStack( is ); - if( t != null ) - { - if( t.constructor == null ) - t.constructor = t.getPart().getConstructor( ItemStack.class ); + if( type.constructor == null ) + type.constructor = part.getConstructor( ItemStack.class ); - return t.constructor.newInstance( is ); - } + return type.constructor.newInstance( is ); } - catch( Throwable e ) + catch( InstantiationException e ) { - throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + this.getTypeByStack( is ).getPart().getName() + " ; Possibly didn't have correct constructor( ItemStack )", e ); + throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e ); + } + catch( IllegalAccessException e ) + { + throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e ); + } + catch( InvocationTargetException e ) + { + throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e ); + } + catch( NoSuchMethodException e ) + { + throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e ); } - - return null; } public int variantOf( int itemDamage ) { - if( this.dmgToPart.containsKey( itemDamage ) ) - return this.dmgToPart.get( itemDamage ).variant; + if( this.registered.containsKey( itemDamage ) ) + return this.registered.get( itemDamage ).variant; return 0; } + @Nullable @Override public String getUnlocalizedGroupName( Set others, ItemStack is ) { @@ -307,22 +307,19 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup if( stack.getItem() == this ) { PartType pt = this.getTypeByStack( stack ); - if ( pt != null ) + switch( pt ) { - switch( pt ) - { - case ImportBus: - importBus = true; - if( u == pt ) - group = true; - break; - case ExportBus: - exportBus = true; - if( u == pt ) - group = true; - break; - default: - } + case ImportBus: + importBus = true; + if( u == pt ) + group = true; + break; + case ExportBus: + exportBus = true; + if( u == pt ) + group = true; + break; + default: } } } @@ -333,17 +330,21 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup return null; } - public ItemStack getStackFromTypeAndVariant( PartType mt, int variant ) + private static final class PartTypeWithVariant { - return new ItemStack( this, 1, mt.baseDamage + variant ); - } - - private static class PartTypeIst - { - private PartType part; - private int variant; + private final PartType part; + private final int variant; @SideOnly( Side.CLIENT ) private IIcon ico; + + private PartTypeWithVariant( PartType part, int variant ) + { + assert part != null; + assert variant >= 0; + + this.part = part; + this.variant = variant; + } } }