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
This commit is contained in:
thatsIch
2015-04-27 09:51:40 +02:00
parent bbde2443e1
commit e85acf2bee
2 changed files with 134 additions and 139 deletions
@@ -3,8 +3,6 @@ package appeng.core.api.definitions;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import com.google.common.base.Optional;
import appeng.api.definitions.IBlockDefinition; import appeng.api.definitions.IBlockDefinition;
import appeng.api.definitions.IItemDefinition; import appeng.api.definitions.IItemDefinition;
import appeng.api.definitions.ITileDefinition; import appeng.api.definitions.ITileDefinition;
@@ -91,13 +89,9 @@ public class DefinitionConstructor
for( AEColor color : AEColor.values() ) for( AEColor color : AEColor.values() )
{ {
ItemStackSrc multiPartSource = target.createPart( type, color ); final ItemStackSrc multiPartSource = target.createPart( type, color );
final Optional<ItemStackSrc> maybeSource = Optional.fromNullable( multiPartSource );
if( maybeSource.isPresent() ) definition.add( color, multiPartSource );
{
definition.add( color, multiPartSource );
}
} }
return definition; return definition;
@@ -19,6 +19,7 @@
package appeng.items.parts; package appeng.items.parts;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@@ -28,6 +29,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.client.renderer.texture.IIconRegister; 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.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
import com.google.common.base.Preconditions;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.implementations.items.IItemGroup; import appeng.api.implementations.items.IItemGroup;
import appeng.api.parts.IPart; import appeng.api.parts.IPart;
@@ -48,7 +52,6 @@ import appeng.api.parts.IPartHelper;
import appeng.api.parts.IPartItem; import appeng.api.parts.IPartItem;
import appeng.api.util.AEColor; import appeng.api.util.AEColor;
import appeng.core.AEConfig; import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.features.AEFeature; import appeng.core.features.AEFeature;
import appeng.core.features.ItemStackSrc; import appeng.core.features.ItemStackSrc;
import appeng.core.features.NameResolver; import appeng.core.features.NameResolver;
@@ -58,27 +61,55 @@ import appeng.integration.IntegrationType;
import appeng.items.AEBaseItem; 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; public static ItemMultiPart instance;
private final NameResolver nameResolver; private final NameResolver nameResolver;
private final Map<Integer, PartTypeIst> dmgToPart = new HashMap<Integer, PartTypeIst>(); private final Map<Integer, PartTypeWithVariant> registered;
private final Map<Integer, PartTypeWithVariant> unregistered;
public ItemMultiPart( IPartHelper partHelper ) public ItemMultiPart( IPartHelper partHelper )
{ {
Preconditions.checkNotNull( partHelper );
this.registered = new HashMap<Integer, PartTypeWithVariant>();
this.unregistered = new HashMap<Integer, PartTypeWithVariant>();
this.nameResolver = new NameResolver( this.getClass() ); this.nameResolver = new NameResolver( this.getClass() );
this.setFeature( EnumSet.of( AEFeature.Core ) ); this.setFeature( EnumSet.of( AEFeature.Core ) );
partHelper.setItemBusRenderer( this ); partHelper.setItemBusRenderer( this );
this.setHasSubtypes( true ); this.setHasSubtypes( true );
instance = this; instance = this;
} }
@Nonnull
public final ItemStackSrc createPart( PartType mat ) 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 // verify
for( PartTypeIst p : this.dmgToPart.values() ) for( PartTypeWithVariant p : this.registered.values() )
{ {
if( p.part == mat && p.variant == varID ) if( p.part == mat && p.variant == varID )
throw new IllegalStateException( "Cannot create the same material twice..." ); 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() ) for( IntegrationType integrationType : mat.getIntegrations() )
enabled &= IntegrationRegistry.INSTANCE.isEnabled( integrationType ); enabled &= IntegrationRegistry.INSTANCE.isEnabled( integrationType );
int newPartNum = mat.baseDamage + varID; final int partDamage = mat.baseDamage + varID;
ItemStackSrc output = new ItemStackSrc( this, newPartNum ); final ItemStackSrc output = new ItemStackSrc( this, partDamage );
if( enabled ) final PartTypeWithVariant pti = new PartTypeWithVariant( mat, varID );
{
PartTypeIst pti = new PartTypeIst();
pti.part = mat;
pti.variant = varID;
if( this.dmgToPart.get( newPartNum ) == null ) this.processMetaOverlap( enabled, partDamage, mat, pti );
{
this.dmgToPart.put( newPartNum, pti );
return output;
}
else
{
throw new IllegalStateException( "Meta Overlap detected." );
}
}
return output; return output;
} }
public ItemStackSrc createPart( PartType mat, Enum variant ) private void processMetaOverlap( boolean enabled, int partDamage, PartType mat, PartTypeWithVariant pti )
{ {
try assert partDamage >= 0;
{ assert mat != null;
// I think this still works? assert pti != null;
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..
}
int varID = variant == null ? 0 : variant.ordinal(); final Map<Integer, PartTypeWithVariant> 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 reference.put( partDamage, pti );
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;
} }
public int getDamageByType( PartType t ) public int getDamageByType( PartType t )
{ {
for( Entry<Integer, PartTypeIst> pt : this.dmgToPart.entrySet() ) Preconditions.checkNotNull( t );
for( Entry<Integer, PartTypeWithVariant> pt : this.registered.entrySet() )
{ {
if( pt.getValue().part == t ) if( pt.getValue().part == t )
return pt.getKey(); return pt.getKey();
@@ -183,7 +167,7 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
@Override @Override
public IIcon getIconFromDamage( int dmg ) public IIcon getIconFromDamage( int dmg )
{ {
return this.dmgToPart.get( dmg ).ico; return this.registered.get( dmg ).ico;
} }
@Override @Override
@@ -198,36 +182,16 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
return "item.appliedenergistics2." + this.getName( is ); 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 @Override
public String getItemStackDisplayName( ItemStack is ) public String getItemStackDisplayName( ItemStack is )
{ {
PartType pt = this.getTypeByStack( is ); final PartType pt = this.getTypeByStack( is );
if( pt == null )
return "Unnamed";
if( pt.isCable() ) if( pt.isCable() )
{ {
final AEColor[] variants = AEColor.values(); 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 ) if( pt.getExtraName() != null )
@@ -239,60 +203,96 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
@Override @Override
public void getSubItems( Item number, CreativeTabs tab, List cList ) public void getSubItems( Item number, CreativeTabs tab, List cList )
{ {
List<Entry<Integer, PartTypeIst>> types = new ArrayList<Entry<Integer, PartTypeIst>>( this.dmgToPart.entrySet() ); List<Entry<Integer, PartTypeWithVariant>> types = new ArrayList<Entry<Integer, PartTypeWithVariant>>( this.registered.entrySet() );
Collections.sort( types, new Comparator<Entry<Integer, PartTypeIst>>() Collections.sort( types, new Comparator<Entry<Integer, PartTypeWithVariant>>()
{ {
@Override @Override
public int compare( Entry<Integer, PartTypeIst> o1, Entry<Integer, PartTypeIst> o2 ) public int compare( Entry<Integer, PartTypeWithVariant> o1, Entry<Integer, PartTypeWithVariant> o2 )
{ {
return o1.getValue().part.name().compareTo( o2.getValue().part.name() ); return o1.getValue().part.name().compareTo( o2.getValue().part.name() );
} }
} ); } );
for( Entry<Integer, PartTypeIst> part : types ) for( Entry<Integer, PartTypeWithVariant> part : types )
cList.add( new ItemStack( this, 1, part.getKey() ) ); cList.add( new ItemStack( this, 1, part.getKey() ) );
} }
@Override @Override
public void registerIcons( IIconRegister par1IconRegister ) public void registerIcons( IIconRegister par1IconRegister )
{ {
for( Entry<Integer, PartTypeIst> part : this.dmgToPart.entrySet() ) for( Entry<Integer, PartTypeWithVariant> part : this.registered.entrySet() )
{ {
String tex = "appliedenergistics2:" + this.getName( new ItemStack( this, 1, part.getKey() ) ); String tex = "appliedenergistics2:" + this.getName( new ItemStack( this, 1, part.getKey() ) );
part.getValue().ico = par1IconRegister.registerIcon( tex ); 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 @Override
public IPart createPartFromItemStack( ItemStack is ) public IPart createPartFromItemStack( ItemStack is )
{ {
final PartType type = this.getTypeByStack( is );
final Class<? extends IPart> part = type.getPart();
try try
{ {
PartType t = this.getTypeByStack( is ); if( type.constructor == null )
if( t != null ) type.constructor = part.getConstructor( ItemStack.class );
{
if( t.constructor == null )
t.constructor = t.getPart().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 ) public int variantOf( int itemDamage )
{ {
if( this.dmgToPart.containsKey( itemDamage ) ) if( this.registered.containsKey( itemDamage ) )
return this.dmgToPart.get( itemDamage ).variant; return this.registered.get( itemDamage ).variant;
return 0; return 0;
} }
@Nullable
@Override @Override
public String getUnlocalizedGroupName( Set<ItemStack> others, ItemStack is ) public String getUnlocalizedGroupName( Set<ItemStack> others, ItemStack is )
{ {
@@ -307,22 +307,19 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
if( stack.getItem() == this ) if( stack.getItem() == this )
{ {
PartType pt = this.getTypeByStack( stack ); PartType pt = this.getTypeByStack( stack );
if ( pt != null ) switch( pt )
{ {
switch( pt ) case ImportBus:
{ importBus = true;
case ImportBus: if( u == pt )
importBus = true; group = true;
if( u == pt ) break;
group = true; case ExportBus:
break; exportBus = true;
case ExportBus: if( u == pt )
exportBus = true; group = true;
if( u == pt ) break;
group = true; default:
break;
default:
}
} }
} }
} }
@@ -333,17 +330,21 @@ public class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
return null; return null;
} }
public ItemStack getStackFromTypeAndVariant( PartType mt, int variant ) private static final class PartTypeWithVariant
{ {
return new ItemStack( this, 1, mt.baseDamage + variant ); private final PartType part;
} private final int variant;
private static class PartTypeIst
{
private PartType part;
private int variant;
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
private IIcon ico; private IIcon ico;
private PartTypeWithVariant( PartType part, int variant )
{
assert part != null;
assert variant >= 0;
this.part = part;
this.variant = variant;
}
} }
} }