Applied-Energistics-2-tiler.../src/main/java/appeng/items/parts/ItemMultiPart.java
2016-09-17 17:05:07 +02:00

369 lines
9.8 KiB
Java

/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, 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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
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 com.google.common.base.Preconditions;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.implementations.items.IItemGroup;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartItem;
import appeng.api.util.AEColor;
import appeng.core.AEConfig;
import appeng.core.features.AEFeature;
import appeng.core.features.ActivityState;
import appeng.core.features.ItemStackSrc;
import appeng.core.localization.GuiText;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.items.AEBaseItem;
public final class ItemMultiPart extends AEBaseItem implements IPartItem, IItemGroup
{
private static final int INITIAL_REGISTERED_CAPACITY = PartType.values().length;
private static final Comparator<Entry<Integer, PartTypeWithVariant>> REGISTERED_COMPARATOR = new RegisteredComparator();
public static ItemMultiPart instance;
private final Map<Integer, PartTypeWithVariant> registered;
public ItemMultiPart()
{
this.registered = new HashMap<>( INITIAL_REGISTERED_CAPACITY );
this.setHasSubtypes( true );
instance = this;
}
@Nonnull
public final ItemStackSrc createPart( final PartType mat )
{
Preconditions.checkNotNull( mat );
return this.createPart( mat, 0 );
}
@Nonnull
public ItemStackSrc createPart( final PartType mat, final AEColor color )
{
Preconditions.checkNotNull( mat );
Preconditions.checkNotNull( color );
final int varID = color.ordinal();
return this.createPart( mat, varID );
}
@Nonnull
private ItemStackSrc createPart( final PartType mat, final int varID )
{
assert mat != null;
assert varID >= 0;
// verify
for( final PartTypeWithVariant p : this.registered.values() )
{
if( p.part == mat && p.variant == varID )
{
throw new IllegalStateException( "Cannot create the same material twice..." );
}
}
boolean enabled = true;
for( final AEFeature f : mat.getFeature() )
{
enabled = enabled && AEConfig.instance.isFeatureEnabled( f );
}
for( final IntegrationType integrationType : mat.getIntegrations() )
{
enabled &= IntegrationRegistry.INSTANCE.isEnabled( integrationType );
}
final int partDamage = mat.getBaseDamage() + varID;
final ActivityState state = ActivityState.from( enabled );
final ItemStackSrc output = new ItemStackSrc( this, partDamage, state );
final PartTypeWithVariant pti = new PartTypeWithVariant( mat, varID );
this.processMetaOverlap( enabled, partDamage, mat, pti );
return output;
}
private void processMetaOverlap( final boolean enabled, final int partDamage, final PartType mat, final PartTypeWithVariant pti )
{
assert partDamage >= 0;
assert mat != null;
assert pti != null;
final PartTypeWithVariant registeredPartType = this.registered.get( partDamage );
if( registeredPartType != null )
{
throw new IllegalStateException( "Meta Overlap detected with type " + mat + " and damage " + partDamage + ". Found " + registeredPartType + " there already." );
}
if( enabled )
{
this.registered.put( partDamage, pti );
}
}
public int getDamageByType( final PartType t )
{
Preconditions.checkNotNull( t );
for( final Entry<Integer, PartTypeWithVariant> pt : this.registered.entrySet() )
{
if( pt.getValue().part == t )
{
return pt.getKey();
}
}
return -1;
}
@Override
public EnumActionResult onItemUse( final ItemStack is, final EntityPlayer player, final World w, final BlockPos pos, final EnumHand hand, final EnumFacing side, final float hitX, final float hitY, final float hitZ )
{
if( this.getTypeByStack( is ) == PartType.InvalidType )
{
return EnumActionResult.FAIL;
}
return AEApi.instance().partHelper().placeBus( is, pos, side, player, hand, w );
}
@Override
public String getUnlocalizedName( final ItemStack is )
{
return "item.appliedenergistics2." + this.getName( is );
}
@Override
public String getItemStackDisplayName( final ItemStack is )
{
final PartType pt = this.getTypeByStack( is );
if( pt.isCable() )
{
final AEColor[] variants = AEColor.values();
final int itemDamage = is.getItemDamage();
final PartTypeWithVariant registeredPartType = this.registered.get( itemDamage );
if( registeredPartType != null )
{
return super.getItemStackDisplayName( is ) + " - " + variants[registeredPartType.variant].toString();
}
}
if( pt.getExtraName() != null )
{
return super.getItemStackDisplayName( is ) + " - " + pt.getExtraName().getLocal();
}
return super.getItemStackDisplayName( is );
}
@Override
protected void getCheckedSubItems( final Item sameItem, final CreativeTabs creativeTab, final List<ItemStack> itemStacks )
{
final List<Entry<Integer, PartTypeWithVariant>> types = new ArrayList<Entry<Integer, PartTypeWithVariant>>( this.registered.entrySet() );
Collections.sort( types, REGISTERED_COMPARATOR );
for( final Entry<Integer, PartTypeWithVariant> part : types )
{
itemStacks.add( new ItemStack( this, 1, part.getKey() ) );
}
}
private String getName( final ItemStack is )
{
Preconditions.checkNotNull( is );
final PartType stackType = this.getTypeByStack( is );
final String typeName = stackType.name();
return typeName;
}
@Nonnull
public PartType getTypeByStack( final ItemStack is )
{
Preconditions.checkNotNull( is );
final PartTypeWithVariant pt = this.registered.get( is.getItemDamage() );
if( pt != null )
{
return pt.part;
}
return PartType.InvalidType;
}
@Nullable
@Override
public IPart createPartFromItemStack( final ItemStack is )
{
final PartType type = this.getTypeByStack( is );
final Class<? extends IPart> part = type.getPart();
if( part == null )
{
return null;
}
try
{
if( type.getConstructor() == null )
{
type.setConstructor( part.getConstructor( ItemStack.class ) );
}
return type.getConstructor().newInstance( is );
}
catch( final InstantiationException e )
{
throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e );
}
catch( final IllegalAccessException e )
{
throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e );
}
catch( final InvocationTargetException e )
{
throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e );
}
catch( final NoSuchMethodException e )
{
throw new IllegalStateException( "Unable to construct IBusPart from IBusItem : " + part.getName() + " ; Possibly didn't have correct constructor( ItemStack )", e );
}
}
public int variantOf( final int itemDamage )
{
final PartTypeWithVariant registeredPartType = this.registered.get( itemDamage );
if( registeredPartType != null )
{
return registeredPartType.variant;
}
return 0;
}
@Nullable
@Override
public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is )
{
boolean importBus = false;
boolean exportBus = false;
boolean group = false;
final PartType u = this.getTypeByStack( is );
for( final ItemStack stack : others )
{
if( stack.getItem() == this )
{
final PartType pt = this.getTypeByStack( stack );
switch( pt )
{
case ImportBus:
importBus = true;
if( u == pt )
{
group = true;
}
break;
case ExportBus:
exportBus = true;
if( u == pt )
{
group = true;
}
break;
default:
}
}
}
if( group && importBus && exportBus )
{
return GuiText.IOBuses.getUnlocalized();
}
return null;
}
private static final class PartTypeWithVariant
{
private final PartType part;
private final int variant;
private PartTypeWithVariant( final PartType part, final int variant )
{
assert part != null;
assert variant >= 0;
this.part = part;
this.variant = variant;
}
@Override
public String toString()
{
return "PartTypeWithVariant{" + "part=" + this.part + ", variant=" + this.variant + '}';
}
}
private static final class RegisteredComparator implements Comparator<Entry<Integer, PartTypeWithVariant>>
{
@Override
public int compare( final Entry<Integer, PartTypeWithVariant> o1, final Entry<Integer, PartTypeWithVariant> o2 )
{
return o1.getValue().part.name().compareTo( o2.getValue().part.name() );
}
}
}