/* * 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 . */ package appeng.items.materials; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.oredict.OreDictionary; import appeng.api.config.Upgrades; import appeng.api.implementations.IUpgradeableHost; import appeng.api.implementations.items.IItemGroup; import appeng.api.implementations.items.IStorageComponent; import appeng.api.implementations.items.IUpgradeModule; import appeng.api.implementations.tiles.ISegmentedInventory; import appeng.api.parts.IPartHost; import appeng.api.parts.SelectedPart; import appeng.client.texture.MissingIcon; import appeng.core.AEConfig; import appeng.core.features.AEFeature; import appeng.core.features.IStackSrc; import appeng.core.features.MaterialStackSrc; import appeng.core.features.NameResolver; import appeng.items.AEBaseItem; import appeng.util.InventoryAdaptor; import appeng.util.Platform; public final class ItemMultiMaterial extends AEBaseItem implements IStorageComponent, IUpgradeModule { public static final int KILO_SCALAR = 1024; public static ItemMultiMaterial instance; private final Map dmgToMaterial = new HashMap(); private final NameResolver nameResolver; public ItemMultiMaterial() { this.nameResolver = new NameResolver( this.getClass() ); this.setFeature( EnumSet.of( AEFeature.Core ) ); this.setHasSubtypes( true ); instance = this; } @Override public void addCheckedInformation( ItemStack stack, EntityPlayer player, List lines, boolean displayMoreInfo ) { super.addCheckedInformation( stack, player, lines, displayMoreInfo ); MaterialType mt = this.getTypeByStack( stack ); if( mt == null ) { return; } if( mt == MaterialType.NamePress ) { NBTTagCompound c = Platform.openNbtData( stack ); lines.add( c.getString( "InscribeName" ) ); } Upgrades u = this.getType( stack ); if( u != null ) { List textList = new LinkedList(); for( Entry j : u.getSupported().entrySet() ) { String name = null; int limit = j.getValue(); if( j.getKey().getItem() instanceof IItemGroup ) { IItemGroup ig = (IItemGroup) j.getKey().getItem(); String str = ig.getUnlocalizedGroupName( u.getSupported().keySet(), j.getKey() ); if( str != null ) { name = Platform.gui_localize( str ) + ( limit > 1 ? " (" + limit + ')' : "" ); } } if( name == null ) { name = j.getKey().getDisplayName() + ( limit > 1 ? " (" + limit + ')' : "" ); } if( !textList.contains( name ) ) { textList.add( name ); } } Pattern p = Pattern.compile( "(\\d+)[^\\d]" ); SlightlyBetterSort s = new SlightlyBetterSort( p ); Collections.sort( textList, s ); lines.addAll( textList ); } } public MaterialType getTypeByStack( ItemStack is ) { if( this.dmgToMaterial.containsKey( is.getItemDamage() ) ) { return this.dmgToMaterial.get( is.getItemDamage() ); } return MaterialType.InvalidType; } @Override public Upgrades getType( ItemStack itemstack ) { switch( this.getTypeByStack( itemstack ) ) { case CardCapacity: return Upgrades.CAPACITY; case CardFuzzy: return Upgrades.FUZZY; case CardRedstone: return Upgrades.REDSTONE; case CardSpeed: return Upgrades.SPEED; case CardInverter: return Upgrades.INVERTER; case CardCrafting: return Upgrades.CRAFTING; default: return null; } } public IStackSrc createMaterial( MaterialType mat ) { Preconditions.checkState( !mat.isRegistered(), "Cannot create the same material twice." ); boolean enabled = true; for( AEFeature f : mat.getFeature() ) { enabled = enabled && AEConfig.instance.isFeatureEnabled( f ); } mat.stackSrc = new MaterialStackSrc( mat ); if( enabled ) { mat.itemInstance = this; mat.markReady(); int newMaterialNum = mat.damageValue; if( this.dmgToMaterial.get( newMaterialNum ) == null ) { this.dmgToMaterial.put( newMaterialNum, mat ); } else { throw new IllegalStateException( "Meta Overlap detected." ); } } return mat.stackSrc; } public void makeUnique() { for( MaterialType mt : ImmutableSet.copyOf( this.dmgToMaterial.values() ) ) { if( mt.getOreName() != null ) { ItemStack replacement = null; String[] names = mt.getOreName().split( "," ); for( String name : names ) { if( replacement != null ) { break; } List options = OreDictionary.getOres( name ); if( options != null && options.size() > 0 ) { for( ItemStack is : options ) { if( is != null && is.getItem() != null ) { replacement = is.copy(); break; } } } } if( replacement == null || AEConfig.instance.useAEVersion( mt ) ) { // continue using the AE2 item. for( String name : names ) { OreDictionary.registerOre( name, mt.stack( 1 ) ); } } else { if( mt.itemInstance == this ) { this.dmgToMaterial.remove( mt.damageValue ); } mt.itemInstance = replacement.getItem(); mt.damageValue = replacement.getItemDamage(); } } } } @Override public IIcon getIconFromDamage( int dmg ) { if( this.dmgToMaterial.containsKey( dmg ) ) { return this.dmgToMaterial.get( dmg ).IIcon; } return new MissingIcon( this ); } @Override public String getUnlocalizedName( ItemStack is ) { return "item.appliedenergistics2." + this.nameOf( is ); } private String nameOf( ItemStack is ) { if( is == null ) { return "null"; } MaterialType mt = this.getTypeByStack( is ); if( mt == null ) { return "null"; } return this.nameResolver.getName( mt.name() ); } @Override protected void getCheckedSubItems( Item sameItem, CreativeTabs creativeTab, List itemStacks ) { List types = Arrays.asList( MaterialType.values() ); Collections.sort( types, new Comparator() { @Override public int compare( MaterialType o1, MaterialType o2 ) { return o1.name().compareTo( o2.name() ); } } ); for( MaterialType mat : types ) { if( mat.damageValue >= 0 && mat.isRegistered() && mat.itemInstance == this ) { itemStacks.add( new ItemStack( this, 1, mat.damageValue ) ); } } } @Override public void registerIcons( IIconRegister icoRegister ) { for( MaterialType mat : MaterialType.values() ) { if( mat.damageValue != -1 ) { ItemStack what = new ItemStack( this, 1, mat.damageValue ); if( this.getTypeByStack( what ) != MaterialType.InvalidType ) { String tex = "appliedenergistics2:" + this.nameOf( what ); mat.IIcon = icoRegister.registerIcon( tex ); } } } } @Override public boolean onItemUseFirst( ItemStack is, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ ) { if( player.isSneaking() ) { TileEntity te = world.getTileEntity( x, y, z ); IInventory upgrades = null; if( te instanceof IPartHost ) { SelectedPart sp = ( (IPartHost) te ).selectPart( Vec3.createVectorHelper( hitX, hitY, hitZ ) ); if( sp.part instanceof IUpgradeableHost ) { upgrades = ( (ISegmentedInventory) sp.part ).getInventoryByName( "upgrades" ); } } else if( te instanceof IUpgradeableHost ) { upgrades = ( (ISegmentedInventory) te ).getInventoryByName( "upgrades" ); } if( upgrades != null && is != null && is.getItem() instanceof IUpgradeModule ) { IUpgradeModule um = (IUpgradeModule) is.getItem(); Upgrades u = um.getType( is ); if( u != null ) { InventoryAdaptor ad = InventoryAdaptor.getAdaptor( upgrades, ForgeDirection.UNKNOWN ); if( ad != null ) { if( player.worldObj.isRemote ) { return false; } player.inventory.setInventorySlotContents( player.inventory.currentItem, ad.addItems( is ) ); return true; } } } } return super.onItemUseFirst( is, player, world, x, y, z, side, hitX, hitY, hitZ ); } @Override public boolean hasCustomEntity( ItemStack is ) { return this.getTypeByStack( is ).hasCustomEntity(); } @Override public Entity createEntity( World w, Entity location, ItemStack itemstack ) { Class droppedEntity = this.getTypeByStack( itemstack ).getCustomEntityClass(); Entity eqi; try { eqi = droppedEntity.getConstructor( World.class, double.class, double.class, double.class, ItemStack.class ).newInstance( w, location.posX, location.posY, location.posZ, itemstack ); } catch( Throwable t ) { throw new IllegalStateException( t ); } eqi.motionX = location.motionX; eqi.motionY = location.motionY; eqi.motionZ = location.motionZ; if( location instanceof EntityItem && eqi instanceof EntityItem ) { ( (EntityItem) eqi ).delayBeforeCanPickup = ( (EntityItem) location ).delayBeforeCanPickup; } return eqi; } @Override public int getBytes( ItemStack is ) { switch( this.getTypeByStack( is ) ) { case Cell1kPart: return KILO_SCALAR; case Cell4kPart: return KILO_SCALAR * 4; case Cell16kPart: return KILO_SCALAR * 16; case Cell64kPart: return KILO_SCALAR * 64; default: } return 0; } @Override public boolean isStorageComponent( ItemStack is ) { switch( this.getTypeByStack( is ) ) { case Cell1kPart: case Cell4kPart: case Cell16kPart: case Cell64kPart: return true; default: } return false; } private static class SlightlyBetterSort implements Comparator { private final Pattern pattern; public SlightlyBetterSort( Pattern pattern ) { this.pattern = pattern; } @Override public int compare( String o1, String o2 ) { try { Matcher a = this.pattern.matcher( o1 ); Matcher b = this.pattern.matcher( o2 ); if( a.find() && b.find() ) { int ia = Integer.parseInt( a.group( 1 ) ); int ib = Integer.parseInt( b.group( 1 ) ); return Integer.compare( ia, ib ); } } catch( Throwable t ) { // ek! } return o1.compareTo( o2 ); } } }