Implemented Recipe Groups.

Added ISubItemResolvers.
ItemSeeds now use Constants instead of raw integers.
This commit is contained in:
AlgorithmX2 2014-02-24 23:33:31 -06:00
parent 8d44d01fc0
commit 9575c8872c
8 changed files with 287 additions and 74 deletions

View file

@ -113,6 +113,7 @@ import appeng.me.cache.SecurityCache;
import appeng.me.cache.SpatialPylonCache;
import appeng.me.cache.TickManagerCache;
import appeng.me.storage.AEExternalHandler;
import appeng.recipes.AEItemResolver;
import appeng.recipes.RecipeHandler;
import appeng.recipes.Recipes.ShapedRecipe;
import appeng.recipes.Recipes.ShapelessRecipe;
@ -153,6 +154,7 @@ public class Registration
public void PreInit(FMLPreInitializationEvent event)
{
IRecipeHandlerRegistry recipeRegistery = AEApi.instance().registries().recipes();
recipeRegistery.addNewSubItemResolver( new AEItemResolver() );
recipeRegistery.addNewCraftHandler( "grind", Grind.class );
recipeRegistery.addNewCraftHandler( "pulverizer", Pulverizer.class );
@ -338,7 +340,6 @@ public class Registration
addFeature( ToolReplicatorCard.class );
addFeature( BlockItemGen.class );
addFeature( BlockChunkloader.class );
}
private AEItemDefinition addFeature(Class c, Object... Args)

View file

@ -1,39 +1,71 @@
package appeng.core.features.registries;
import java.util.HashMap;
import java.util.LinkedList;
import appeng.api.features.IRecipeHandlerRegistry;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IRecipeHandler;
import appeng.api.recipes.ISubItemResolver;
import appeng.api.recipes.ResolveResult;
import appeng.core.AELog;
import appeng.recipes.RecipeHandler;
public class RecipeHandlerRegistry implements IRecipeHandlerRegistry{
HashMap<String,Class<? extends ICraftHandler>> handlers = new HashMap<String, Class<? extends ICraftHandler >>();
public class RecipeHandlerRegistry implements IRecipeHandlerRegistry
{
HashMap<String, Class<? extends ICraftHandler>> handlers = new HashMap<String, Class<? extends ICraftHandler>>();
LinkedList<ISubItemResolver> resolvers = new LinkedList<ISubItemResolver>();
@Override
public void addNewCraftHandler(String name, Class<? extends ICraftHandler> handler) {
handlers.put(name.toLowerCase(), handler);
public void addNewCraftHandler(String name, Class<? extends ICraftHandler> handler)
{
handlers.put( name.toLowerCase(), handler );
}
@Override
public ICraftHandler getCraftHandlerFor(String name) {
Class<? extends ICraftHandler> clz= handlers.get(name);
if ( clz == null ) return null;
try {
public ICraftHandler getCraftHandlerFor(String name)
{
Class<? extends ICraftHandler> clz = handlers.get( name );
if ( clz == null )
return null;
try
{
return clz.newInstance();
} catch (Throwable e) {
AELog.severe("Error Caused when trying to construct "+clz.getName());
AELog.error(e);
handlers.put(name, null); // clear it..
}
catch (Throwable e)
{
AELog.severe( "Error Caused when trying to construct " + clz.getName() );
AELog.error( e );
handlers.put( name, null ); // clear it..
return null;
}
}
@Override
public IRecipeHandler createNewRecipehandler() {
public IRecipeHandler createNewRecipehandler()
{
return new RecipeHandler();
}
@Override
public void addNewSubItemResolver(ISubItemResolver sir)
{
resolvers.add( sir );
}
@Override
public ResolveResult resolveItem(String nameSpace, String itemName)
{
for (ISubItemResolver sir : resolvers)
{
ResolveResult rr = sir.resolveItemByName( nameSpace, itemName );
if ( rr != null )
return rr;
}
return null;
}
}

View file

@ -26,6 +26,14 @@ import cpw.mods.fml.common.registry.EntityRegistry;
public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal
{
public static final int LEVEL_OFFSET = 200;
public static final int SINGLE_OFFSET = LEVEL_OFFSET * 3;
public static final int Certus = 0;
public static final int Nether = SINGLE_OFFSET;
public static final int Fluix = SINGLE_OFFSET * 2;
public static final int END = SINGLE_OFFSET * 3;
IIcon certus[] = new IIcon[3];
IIcon fluix[] = new IIcon[3];
IIcon nether[] = new IIcon[3];
@ -45,13 +53,13 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal
{
int damage = is.getItemDamage();
if ( damage < 600 )
if ( damage < Certus + SINGLE_OFFSET )
return getUnlocalizedName() + ".Certus";
if ( damage < 1200 )
if ( damage < Nether + SINGLE_OFFSET )
return getUnlocalizedName() + ".Nether";
if ( damage < 1800 )
if ( damage < Fluix + SINGLE_OFFSET )
return getUnlocalizedName() + ".Fluix";
return getUnlocalizedName();
@ -62,13 +70,13 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal
{
int newDamage = is.getItemDamage() + 1;
if ( newDamage == 600 )
if ( newDamage == Certus + SINGLE_OFFSET )
return AEApi.instance().materials().materialPureifiedCertusQuartzCrystal.stack( is.stackSize );
if ( newDamage == 1200 )
if ( newDamage == Nether + SINGLE_OFFSET )
return AEApi.instance().materials().materialPureifiedNetherQuartzCrystal.stack( is.stackSize );
if ( newDamage == 1800 )
if ( newDamage == Fluix + SINGLE_OFFSET )
return AEApi.instance().materials().materialPureifiedFluixCrystal.stack( is.stackSize );
if ( newDamage > 1800 )
if ( newDamage > END )
return null;
is.setItemDamage( newDamage );
@ -106,27 +114,27 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal
{
IIcon list[] = null;
if ( damage < 600 )
if ( damage < Certus + SINGLE_OFFSET )
list = certus;
else if ( damage < 1200 )
else if ( damage < Nether + SINGLE_OFFSET )
{
damage -= 600;
damage -= Nether;
list = nether;
}
else if ( damage < 1800 )
else if ( damage < Fluix + SINGLE_OFFSET )
{
damage -= 1200;
damage -= Fluix;
list = fluix;
}
if ( list == null )
return Items.diamond.getIconFromDamage( 0 );
if ( damage < 200 )
if ( damage < LEVEL_OFFSET )
return list[0];
else if ( damage < 400 )
else if ( damage < LEVEL_OFFSET * 2 )
return list[1];
else
return list[2];
@ -181,19 +189,19 @@ public class ItemCrystalSeed extends AEBaseItem implements IGrowableCrystal
public void getSubItems(Item i, CreativeTabs t, List l)
{
// lvl 0
l.add( new ItemStack( this, 1, 0 ) );
l.add( new ItemStack( this, 1, 600 ) );
l.add( new ItemStack( this, 1, 1200 ) );
l.add( new ItemStack( this, 1, Certus ) );
l.add( new ItemStack( this, 1, Nether ) );
l.add( new ItemStack( this, 1, Fluix ) );
// lvl 1
l.add( new ItemStack( this, 1, 200 + 0 ) );
l.add( new ItemStack( this, 1, 200 + 600 ) );
l.add( new ItemStack( this, 1, 200 + 1200 ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET + Certus ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET + Nether ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET + Fluix ) );
// lvl 2
l.add( new ItemStack( this, 1, 400 + 0 ) );
l.add( new ItemStack( this, 1, 400 + 600 ) );
l.add( new ItemStack( this, 1, 400 + 1200 ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Certus ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Nether ) );
l.add( new ItemStack( this, 1, LEVEL_OFFSET * 2 + Fluix ) );
}
}

View file

@ -0,0 +1,50 @@
package appeng.recipes;
import appeng.api.recipes.ISubItemResolver;
import appeng.api.recipes.ResolveResult;
import appeng.core.AppEng;
import appeng.items.materials.MaterialType;
import appeng.items.misc.ItemCrystalSeed;
import appeng.items.parts.ItemPart;
import appeng.items.parts.PartType;
public class AEItemResolver implements ISubItemResolver
{
@Override
public ResolveResult resolveItemByName(String nameSpace, String itemName)
{
if ( nameSpace.equals( AppEng.modid ) )
{
if ( itemName.startsWith( "ItemCrystalSeed." ) )
{
if ( itemName.equalsIgnoreCase( "ItemCrystalSeed.Certus" ) )
return new ResolveResult( "ItemCrystalSeed", ItemCrystalSeed.Certus );
if ( itemName.equalsIgnoreCase( "ItemCrystalSeed.Nether" ) )
return new ResolveResult( "ItemCrystalSeed", ItemCrystalSeed.Nether );
if ( itemName.equalsIgnoreCase( "ItemCrystalSeed.Fluix" ) )
return new ResolveResult( "ItemCrystalSeed", ItemCrystalSeed.Fluix );
}
if ( itemName.startsWith( "ItemMaterial." ) )
{
String materialName = itemName.substring( itemName.indexOf( "." ) + 1 );
MaterialType mt = MaterialType.valueOf( materialName );
itemName = itemName.substring( 0, itemName.indexOf( "." ) );
return new ResolveResult( itemName, mt.damageValue );
}
if ( itemName.startsWith( "ItemPart." ) )
{
String partName = itemName.substring( itemName.indexOf( "." ) + 1 );
PartType pt = PartType.valueOf( partName );
itemName = itemName.substring( 0, itemName.indexOf( "." ) );
return new ResolveResult( itemName, ItemPart.instance.getDamageByType( pt ) );
}
}
return null;
}
}

View file

@ -0,0 +1,101 @@
package appeng.recipes;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientError;
import appeng.api.exceptions.RecipeError;
import appeng.api.exceptions.RegistrationError;
import appeng.api.recipes.IIngredient;
public class GroupIngredient implements IIngredient
{
int qty = 0;
final String name;
final List<IIngredient> ingredients;
boolean isInside = false;
public GroupIngredient(String myName, List<IIngredient> ingredients) throws RecipeError {
name = myName;
for (IIngredient I : ingredients)
if ( I.isAir() )
throw new RecipeError( "Cannot include air in a group." );
this.ingredients = ingredients;
}
public IIngredient copy(int qty) throws RecipeError
{
GroupIngredient gi = new GroupIngredient( name, ingredients );
gi.qty = qty;
return gi;
}
public int getDamageValue()
{
return OreDictionary.WILDCARD_VALUE;
}
@Override
public String getItemName()
{
return name;
}
@Override
public ItemStack getItemStack() throws RegistrationError, MissingIngredientError
{
throw new RegistrationError( "Cannot pass group of items to a recipe which desires a single recipe item." );
}
@Override
public ItemStack[] getItemStackSet() throws RegistrationError, MissingIngredientError
{
if ( isInside )
return new ItemStack[0];
List<ItemStack> out = new LinkedList();
isInside = true;
try
{
for (IIngredient i : ingredients)
out.addAll( Arrays.asList( i.getItemStackSet() ) );
}
finally
{
isInside = false;
}
if ( out.size() == 0 )
throw new MissingIngredientError( toString() + " - group could not be resolved to any items." );
for (ItemStack is : out)
is.stackSize = qty;
return out.toArray( new ItemStack[out.size()] );
}
public String getNameSpace()
{
return "";
}
@Override
public int getQty()
{
return 0;
}
@Override
public boolean isAir()
{
return false;
}
}

View file

@ -6,14 +6,12 @@ import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingIngredientError;
import appeng.api.exceptions.RecipeError;
import appeng.api.exceptions.RegistrationError;
import appeng.api.recipes.IIngredient;
import appeng.core.AppEng;
import appeng.items.materials.MaterialType;
import appeng.items.parts.ItemPart;
import appeng.items.parts.PartType;
import appeng.api.recipes.ResolveResult;
import cpw.mods.fml.common.registry.GameRegistry;
public class Ingredient implements IIngredient
@ -58,24 +56,15 @@ public class Ingredient implements IIngredient
throw new RecipeError( "Cannot specify meta when using ore dictionary." );
sel = OreDictionary.WILDCARD_VALUE;
}
else if ( nameSpace.equals( AppEng.modid ) )
else
{
try
{
if ( tmpName.startsWith( "ItemMaterial." ) )
ResolveResult rr = AEApi.instance().registries().recipes().resolveItem( nameSpace, tmpName );
if ( rr != null )
{
String materialName = tmpName.substring( tmpName.indexOf( "." ) + 1 );
MaterialType mt = MaterialType.valueOf( materialName );
tmpName = tmpName.substring( 0, tmpName.indexOf( "." ) );
sel = mt.damageValue;
}
if ( tmpName.startsWith( "ItemPart." ) )
{
String partName = tmpName.substring( tmpName.indexOf( "." ) + 1 );
PartType pt = PartType.valueOf( partName );
tmpName = tmpName.substring( 0, tmpName.indexOf( "." ) );
sel = ItemPart.instance.getDamageByType( pt );
tmpName = rr.itemName;
sel = rr.damageValue;
}
}
catch (IllegalArgumentException e)
@ -171,6 +160,9 @@ public class Ingredient implements IIngredient
set[x] = is;
}
if ( set.length == 0 )
throw new MissingIngredientError( toString() + " - ore dictionary could not be resolved to any items." );
return set;
}
@ -178,27 +170,32 @@ public class Ingredient implements IIngredient
}
@Override
public String getNameSpace() {
public String getNameSpace()
{
return nameSpace;
}
@Override
public String getItemName() {
public String getItemName()
{
return itemName;
}
@Override
public int getDamageValue() {
public int getDamageValue()
{
return meta;
}
@Override
public int getQty() {
public int getQty()
{
return qty;
}
@Override
public boolean isAir() {
public boolean isAir()
{
return isAir;
}

View file

@ -10,9 +10,12 @@ public class RecipeData
{
final public HashMap<String, String> aliases = new HashMap<String, String>();
final public HashMap<String, GroupIngredient> groups = new HashMap<String, GroupIngredient>();
final public List<ICraftHandler> Handlers = new LinkedList<ICraftHandler>();
public boolean crash = true;
public boolean exceptions = true;
public boolean erroronmissing = true;
}

View file

@ -58,8 +58,9 @@ public class RecipeHandler implements IRecipeHandler
}
catch (RegistrationError e)
{
AELog.warning( "Unable to regsiter a recipe." );
AELog.error( e );
AELog.warning( "Unable to regsiter a recipe: " + e.getMessage() );
if ( data.exceptions )
AELog.error( e );
if ( data.crash )
throw e;
}
@ -67,8 +68,9 @@ public class RecipeHandler implements IRecipeHandler
{
if ( data.erroronmissing )
{
AELog.warning( "Unable to regsiter a recipe." );
AELog.error( e );
AELog.warning( "Unable to regsiter a recipe:" + e.getMessage() );
if ( data.exceptions )
AELog.error( e );
if ( data.crash )
throw e;
}
@ -77,7 +79,8 @@ public class RecipeHandler implements IRecipeHandler
}
catch (Throwable e)
{
AELog.error( e );
if ( data.exceptions )
AELog.error( e );
if ( data.crash )
throw new RuntimeException( e );
}
@ -231,9 +234,9 @@ public class RecipeHandler implements IRecipeHandler
List<List<IIngredient>> inputs = parseLines( pre );
if ( inputs.size() >= 1 && post.size() == 1 )
if ( inputs.size() == 1 && inputs.get( 0 ).size() > 0 && post.size() == 1 )
{
data.groups.put( post.get( 0 ), new GroupIngredient( post.get( 0 ), inputs.get( 0 ) ) );
}
else
throw new RecipeError( "Group must have exactly 1 output, and 1 or more inputs." );
@ -276,7 +279,16 @@ public class RecipeHandler implements IRecipeHandler
{
String operation = tokens.remove( 0 ).toLowerCase();
if ( operation.equals( "crash" ) && (tokens.get( 0 ).equals( "true" ) || tokens.get( 0 ).equals( "false" )) )
if ( operation.equals( "exceptions" ) && (tokens.get( 0 ).equals( "true" ) || tokens.get( 0 ).equals( "false" )) )
{
if ( tokens.size() == 1 )
{
data.exceptions = tokens.get( 0 ).equals( "true" );
}
else
throw new RecipeError( "exceptions must be true or false explicitly." );
}
else if ( operation.equals( "crash" ) && (tokens.get( 0 ).equals( "true" ) || tokens.get( 0 ).equals( "false" )) )
{
if ( tokens.size() == 1 )
{
@ -309,7 +321,8 @@ public class RecipeHandler implements IRecipeHandler
catch (RecipeError e)
{
AELog.warning( "Recipe Error near line:" + line + " in " + file + " with: " + tokens.toString() );
AELog.error( e );
if ( data.exceptions )
AELog.error( e );
if ( data.crash )
throw e;
}
@ -348,11 +361,11 @@ public class RecipeHandler implements IRecipeHandler
{
if ( hasQty )
{
cList.add( new Ingredient( this, v, qty ) );
cList.add( findIngrident( v, qty ) );
hasQty = false;
}
else
cList.add( new Ingredient( this, v, 1 ) );
cList.add( findIngrident( v, 1 ) );
}
}
}
@ -363,6 +376,14 @@ public class RecipeHandler implements IRecipeHandler
return out;
}
private IIngredient findIngrident(String v, int qty) throws RecipeError
{
GroupIngredient gi = data.groups.get( v );
if ( gi != null )
return gi.copy( qty );
return new Ingredient( this, v, qty );
}
private boolean isNumber(String v)
{
if ( v.length() <= 0 )