Rework custom recipe system (#3232)

This commit is contained in:
fscan
2018-06-24 17:20:29 +02:00
committed by GitHub
parent e72b5b369c
commit 841bc6e356
165 changed files with 680 additions and 6300 deletions
@@ -146,7 +146,7 @@ public class CubeBuilder
builder.setQuadOrientation( face );
builder.setQuadTint( -1 );
builder.setApplyDiffuseLighting( true );
UvVector uv = new UvVector();
// The user might have set specific UV coordinates for this face
+2 -16
View File
@@ -58,8 +58,6 @@ import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.recipes.CustomRecipeConfig;
import appeng.recipes.CustomRecipeForgeConfiguration;
import appeng.server.AECommand;
import appeng.services.VersionChecker;
import appeng.services.export.ExportConfig;
@@ -98,14 +96,6 @@ public final class AppEng
private final Registration registration;
private File configDirectory;
private CustomRecipeConfig customRecipeConfig;
/**
* Folder for recipes
*
* used for CSV item names and the recipes
*/
private File recipeDirectory;
/**
* determined in pre-init but used in init
@@ -152,7 +142,6 @@ public final class AppEng
{
final Stopwatch watch = Stopwatch.createStarted();
this.configDirectory = new File( event.getModConfigurationDirectory().getPath(), "AppliedEnergistics2" );
this.recipeDirectory = new File( this.configDirectory, "aerecipes" );
final File configFile = new File( this.configDirectory, "AppliedEnergistics2.cfg" );
final File facadeFile = new File( this.configDirectory, "Facades.cfg" );
@@ -164,11 +153,8 @@ public final class AppEng
FacadeConfig.init( facadeFile );
final VersionCheckerConfig versionCheckerConfig = new VersionCheckerConfig( versionFile );
this.customRecipeConfig = new CustomRecipeForgeConfiguration( recipeConfiguration );
this.exportConfig = new ForgeExportConfig( recipeConfiguration );
this.registration.setRecipeInformation( this.recipeDirectory, this.customRecipeConfig );
AELog.info( "Pre Initialization ( started )" );
CreativeTab.init();
@@ -226,7 +212,7 @@ public final class AppEng
{
if( FMLCommonHandler.instance().getSide().isClient() )
{
final ExportProcess process = new ExportProcess( this.recipeDirectory, this.exportConfig );
final ExportProcess process = new ExportProcess( this.configDirectory, this.exportConfig );
final Thread exportProcessThread = new Thread( process );
this.startService( "AE2 CSV Export", exportProcessThread );
@@ -237,7 +223,7 @@ public final class AppEng
}
}
this.registration.initialize( event, this.recipeDirectory, this.customRecipeConfig );
this.registration.initialize( event, this.configDirectory );
IntegrationRegistry.INSTANCE.init();
AELog.info( "Initialization ( ended after " + start.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
-118
View File
@@ -1,118 +0,0 @@
/*
* 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.core;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import org.apache.commons.io.FileUtils;
import appeng.api.recipes.IRecipeHandler;
import appeng.recipes.CustomRecipeConfig;
import appeng.recipes.loader.ConfigLoader;
import appeng.recipes.loader.JarLoader;
import appeng.recipes.loader.RecipeResourceCopier;
/**
* handles the decision if recipes should be loaded from jar, loaded from file system or force copied from jar
*
* @author thatsIch
* @version rv3 - 12.05.2015
* @since rv3 12.05.2015
*/
public class RecipeLoader implements Runnable
{
/**
* recipe path in the jar
*/
private static final String ASSETS_RECIPE_PATH = "/assets/appliedenergistics2/recipes/";
@Nonnull
private final IRecipeHandler handler;
@Nonnull
private final CustomRecipeConfig config;
@Nonnull
private final File recipeDirectory;
/**
* @param config configuration for the knowledge how to handle the loading process
* @param handler handler to load the recipes
*
* @throws NullPointerException if handler is <tt>null</tt>
*/
public RecipeLoader( @Nonnull final File recipeDirectory, @Nonnull final CustomRecipeConfig config, @Nonnull final IRecipeHandler handler )
{
this.recipeDirectory = Preconditions.checkNotNull( recipeDirectory );
Preconditions.checkArgument( !recipeDirectory.isFile() );
this.config = Preconditions.checkNotNull( config );
this.handler = Preconditions.checkNotNull( handler );
}
@Override
public final void run()
{
if( this.config.isEnabled() )
{
// setup copying
final RecipeResourceCopier copier = new RecipeResourceCopier( "assets/appliedenergistics2/aerecipes/" );
final File generatedRecipesDir = new File( this.recipeDirectory, "generated" );
final File userRecipesDir = new File( this.recipeDirectory, "user" );
// generates generated and user recipes dir
// will clean the generated every time to keep it up to date
// copies over the recipes in the jar over to the generated folder
// copies over the readmes
try
{
FileUtils.forceMkdir( generatedRecipesDir );
FileUtils.forceMkdir( userRecipesDir );
FileUtils.cleanDirectory( generatedRecipesDir );
copier.copyTo( ".recipe", generatedRecipesDir );
copier.copyTo( ".html", this.recipeDirectory );
// parse recipes prioritising the user scripts by using the generated as template
this.handler.parseRecipes( new ConfigLoader( generatedRecipesDir, userRecipesDir ), "index.recipe" );
}
// on failure use jar parsing
catch( final IOException e )
{
AELog.debug( e );
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
catch( final URISyntaxException e )
{
AELog.debug( e );
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
}
else
{
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
}
}
+6 -67
View File
@@ -77,7 +77,6 @@ import appeng.api.networking.spatial.ISpatialCache;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.ticking.ITickManager;
import appeng.api.parts.IPartHelper;
import appeng.api.recipes.IRecipeHandler;
import appeng.bootstrap.ICriterionTriggerRegistry;
import appeng.bootstrap.IModelRegistry;
import appeng.bootstrap.components.IBlockRegistrationComponent;
@@ -103,6 +102,7 @@ import appeng.fluids.registries.BasicFluidCellHandler;
import appeng.hooks.TickHandler;
import appeng.items.materials.ItemMaterial;
import appeng.items.parts.ItemFacade;
import appeng.items.parts.ItemPart;
import appeng.loot.ChestLoot;
import appeng.me.cache.CraftingGridCache;
import appeng.me.cache.EnergyGridCache;
@@ -114,20 +114,9 @@ import appeng.me.cache.SpatialPylonCache;
import appeng.me.cache.TickManagerCache;
import appeng.parts.PartPlacement;
import appeng.recipes.AEItemResolver;
import appeng.recipes.CustomRecipeConfig;
import appeng.recipes.RecipeHandler;
import appeng.recipes.AERecipeLoader;
import appeng.recipes.game.DisassembleRecipe;
import appeng.recipes.game.FacadeRecipe;
import appeng.recipes.handlers.Crusher;
import appeng.recipes.handlers.Grind;
import appeng.recipes.handlers.HCCrusher;
import appeng.recipes.handlers.Inscribe;
import appeng.recipes.handlers.Macerator;
import appeng.recipes.handlers.MekCrusher;
import appeng.recipes.handlers.MekEnrichment;
import appeng.recipes.handlers.Press;
import appeng.recipes.handlers.Pulverizer;
import appeng.recipes.handlers.Smelt;
import appeng.recipes.ores.OreDictionaryHandler;
import appeng.spatial.BiomeGenStorage;
import appeng.spatial.StorageWorldProvider;
@@ -143,15 +132,6 @@ final class Registration
Biome storageBiome;
AdvancementTriggers advancementTriggers;
private File recipeDirectory;
private CustomRecipeConfig customRecipeConfig;
public void setRecipeInformation( File f, CustomRecipeConfig f2 )
{
this.recipeDirectory = f;
this.customRecipeConfig = f2;
}
void preInitialize( final FMLPreInitializationEvent event )
{
Capabilities.register();
@@ -160,10 +140,6 @@ final class Registration
final IRecipeHandlerRegistry recipeRegistry = api.registries().recipes();
this.registerCraftHandlers( recipeRegistry );
// RecipeSorter.register( "AE2-Facade", FacadeRecipe.class, Category.SHAPED, "" );
// RecipeSorter.register( "AE2-Shaped", ShapedRecipe.class, Category.SHAPED, "" );
// RecipeSorter.register( "AE2-Shapeless", ShapelessRecipe.class, Category.SHAPELESS, "" );
MinecraftForge.EVENT_BUS.register( OreDictionaryHandler.INSTANCE );
ApiDefinitions definitions = api.definitions();
@@ -226,26 +202,13 @@ final class Registration
private void registerCraftHandlers( final IRecipeHandlerRegistry registry )
{
registry.addNewSubItemResolver( new AEItemResolver() );
registry.addNewCraftHandler( "hccrusher", HCCrusher.class );
registry.addNewCraftHandler( "mekcrusher", MekCrusher.class );
registry.addNewCraftHandler( "mekechamber", MekEnrichment.class );
registry.addNewCraftHandler( "grind", Grind.class );
registry.addNewCraftHandler( "crusher", Crusher.class );
registry.addNewCraftHandler( "pulverizer", Pulverizer.class );
registry.addNewCraftHandler( "macerator", Macerator.class );
registry.addNewCraftHandler( "smelt", Smelt.class );
registry.addNewCraftHandler( "inscribe", Inscribe.class );
registry.addNewCraftHandler( "press", Press.class );
}
public void initialize( @Nonnull final FMLInitializationEvent event, @Nonnull final File recipeDirectory, @Nonnull final CustomRecipeConfig customRecipeConfig )
public void initialize( @Nonnull final FMLInitializationEvent event, @Nonnull final File recipeDirectory )
{
Preconditions.checkNotNull( event );
Preconditions.checkNotNull( recipeDirectory );
Preconditions.checkArgument( !recipeDirectory.isFile() );
Preconditions.checkNotNull( customRecipeConfig );
final Api api = Api.INSTANCE;
final IPartHelper partHelper = api.partHelper();
@@ -255,19 +218,6 @@ final class Registration
definitions.getRegistry().getBootstrapComponents( IOreDictComponent.class ).forEachRemaining( b -> b.oreRegistration( event.getSide() ) );
definitions.getRegistry().getBootstrapComponents( IInitComponent.class ).forEachRemaining( b -> b.initialize( event.getSide() ) );
//
// // Perform ore camouflage!
// ItemMaterial.instance.makeUnique();
// final Runnable recipeLoader = new RecipeLoader( recipeDirectory, customRecipeConfig, this.recipeHandler );
// recipeLoader.run();
// if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.OpenComputers ) )
// {
// partHelper.registerNewLayer( "appeng.parts.layers.LayerSidedEnvironment",
// "li.cil.oc.api.network.SidedEnvironment" );
// }
MinecraftForge.EVENT_BUS.register( TickHandler.INSTANCE );
MinecraftForge.EVENT_BUS.register( new PartPlacement() );
@@ -349,13 +299,12 @@ final class Registration
// Perform ore camouflage!
ItemMaterial.instance.makeUnique();
ItemPart.instance.registerOreDicts();
if( AEConfig.instance().isFeatureEnabled( AEFeature.ENABLE_DISASSEMBLY_CRAFTING ) )
{
DisassembleRecipe r = new DisassembleRecipe();
registry.register( r.setRegistryName( AppEng.MOD_ID.toLowerCase(), "disassemble" ) );
// RecipeSorter.register( "appliedenergistics2:disassemble", DisassembleRecipe.class, Category.SHAPELESS,
// "after:minecraft:shapeless" );
}
if( AEConfig.instance().isFeatureEnabled( AEFeature.ENABLE_FACADE_CRAFTING ) )
@@ -364,18 +313,13 @@ final class Registration
{
FacadeRecipe f = new FacadeRecipe( (ItemFacade) facadeItem );
registry.register( f.setRegistryName( AppEng.MOD_ID.toLowerCase(), "facade" ) );
// RecipeSorter.register( "appliedenergistics2:facade", FacadeRecipe.class, Category.SHAPED,
// "after:minecraft:shaped" );
} );
}
definitions.getRegistry().getBootstrapComponents( IRecipeRegistrationComponent.class ).forEachRemaining( b -> b.recipeRegistration( side, registry ) );
// load machine recipes
final IRecipeHandler recipeHandler = new RecipeHandler();
final Runnable recipeLoader = new RecipeLoader( this.recipeDirectory, this.customRecipeConfig, recipeHandler );
recipeLoader.run();
recipeHandler.injectRecipes();
final AERecipeLoader ldr = new AERecipeLoader();
ldr.loadProcessingRecipes();
}
@SubscribeEvent
@@ -572,11 +516,6 @@ final class Registration
{
registries.worldgen().enableWorldGenForDimension( WorldGenType.METEORITES, dimension );
}
/*
* initial recipe bake, if ore dictionary changes after this it re-bakes.
*/
OreDictionaryHandler.INSTANCE.bakeRecipes();
}
private static class ModelLoaderWrapper implements IModelRegistry
@@ -250,7 +250,11 @@ public final class ApiBlocks implements IBlocks
this.quartzOreCharged = registry.block( "charged_quartz_ore", BlockChargedQuartzOre::new )
.features( AEFeature.CERTUS_ORE, AEFeature.CHARGED_CERTUS_ORE )
.useCustomItemModel()
.bootstrap( ( block, item ) -> (IOreDictComponent) side -> OreDictionary.registerOre( "oreCertusQuartz", new ItemStack( block ) ) )
.bootstrap( ( block, item ) -> (IOreDictComponent) side ->
{
OreDictionary.registerOre( "oreCertusQuartz", new ItemStack( block ) );
OreDictionary.registerOre( "oreChargedCertusQuartz", new ItemStack( block ) );
} )
.build();
this.matrixFrame = registry.block( "matrix_frame", BlockMatrixFrame::new ).features( AEFeature.SPATIAL_IO ).build();
@@ -49,8 +49,6 @@ import appeng.core.features.AEFeature;
import appeng.core.localization.GuiText;
import appeng.integration.Integrations;
import appeng.items.parts.ItemFacade;
import appeng.recipes.game.ShapedRecipe;
import appeng.recipes.game.ShapelessRecipe;
@mezz.jei.api.JEIPlugin
@@ -68,9 +66,6 @@ public class JEIPlugin implements IModPlugin
@Override
public void register( IModRegistry registry )
{
registry.handleRecipes( ShapedRecipe.class, new ShapedRecipeHandler(), VanillaRecipeCategoryUid.CRAFTING );
registry.handleRecipes( ShapelessRecipe.class, new ShapelessRecipeHandler(), VanillaRecipeCategoryUid.CRAFTING );
IDefinitions definitions = AEApi.instance().definitions();
this.registerFacadeRecipe( definitions, registry );
@@ -1,35 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.integration.modules.jei;
import mezz.jei.api.recipe.IRecipeWrapper;
import mezz.jei.api.recipe.IRecipeWrapperFactory;
import appeng.recipes.game.ShapedRecipe;
class ShapedRecipeHandler implements IRecipeWrapperFactory<ShapedRecipe>
{
@Override
public IRecipeWrapper getRecipeWrapper( ShapedRecipe recipe )
{
return new ShapedRecipeWrapper( recipe );
}
}
@@ -1,102 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.integration.modules.jei;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.minecraft.item.ItemStack;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.wrapper.IShapedCraftingRecipeWrapper;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
import appeng.core.AEConfig;
import appeng.recipes.game.ShapedRecipe;
import appeng.util.Platform;
class ShapedRecipeWrapper implements IShapedCraftingRecipeWrapper
{
private final ShapedRecipe recipe;
public ShapedRecipeWrapper( ShapedRecipe recipe )
{
this.recipe = recipe;
}
@Override
public void getIngredients( IIngredients ingredients )
{
final boolean useSingleItems = AEConfig.instance().disableColoredCableRecipesInJEI();
Object[] items = this.recipe.getIIngredients();
int width = this.recipe.getWidth();
int height = this.recipe.getHeight();
List<List<ItemStack>> in = new ArrayList<>( width * height );
for( int x = 0; x < width; x++ )
{
for( int y = 0; y < height; y++ )
{
if( items[( x * height + y )] != null )
{
final IIngredient ing = (IIngredient) items[( x * height + y )];
List<ItemStack> slotList = Collections.emptyList();
try
{
ItemStack[] is = ing.getItemStackSet();
slotList = useSingleItems ? Platform.findPreferred( is ) : Arrays.asList( is );
}
catch( final RegistrationException | MissingIngredientException ignored )
{
}
in.add( slotList );
}
else
{
in.add( Collections.emptyList() );
}
}
}
ingredients.setInputLists( ItemStack.class, in );
ingredients.setOutput( ItemStack.class, this.recipe.getRecipeOutput() );
}
@Override
public int getWidth()
{
return this.recipe.getWidth();
}
@Override
public int getHeight()
{
return this.recipe.getHeight();
}
}
@@ -1,35 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.integration.modules.jei;
import mezz.jei.api.recipe.IRecipeWrapper;
import mezz.jei.api.recipe.IRecipeWrapperFactory;
import appeng.recipes.game.ShapelessRecipe;
class ShapelessRecipeHandler implements IRecipeWrapperFactory<ShapelessRecipe>
{
@Override
public IRecipeWrapper getRecipeWrapper( ShapelessRecipe recipe )
{
return new ShapelessRecipeWrapper( recipe );
}
}
@@ -1,73 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.integration.modules.jei;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import net.minecraft.item.ItemStack;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.IRecipeWrapper;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
import appeng.recipes.game.ShapelessRecipe;
class ShapelessRecipeWrapper implements IRecipeWrapper
{
private final ShapelessRecipe recipe;
public ShapelessRecipeWrapper( ShapelessRecipe recipe )
{
this.recipe = recipe;
}
@Override
public void getIngredients( IIngredients ingredients )
{
List<Object> recipeInput = this.recipe.getInput();
List<List<ItemStack>> inputs = new ArrayList<>( recipeInput.size() );
for( Object inputObj : recipeInput )
{
if( inputObj instanceof IIngredient )
{
IIngredient ingredient = (IIngredient) inputObj;
try
{
inputs.add( Lists.newArrayList( ingredient.getItemStackSet() ) );
}
catch( RegistrationException | MissingIngredientException registrationError )
{
throw new RuntimeException( "Unable to register recipe with JEI" );
}
}
}
ingredients.setInputLists( ItemStack.class, inputs );
ingredients.setOutput( ItemStack.class, this.recipe.getRecipeOutput() );
}
}
@@ -45,7 +45,7 @@ public enum MaterialType
CERTUS_QUARTZ_CRYSTAL_CHARGED( 1, "material_certus_quartz_crystal_charged", EnumSet.of( AEFeature.CERTUS ), EntityChargedQuartz.class ),
CERTUS_QUARTZ_DUST( 2, "material_certus_quartz_dust", EnumSet.of( AEFeature.DUSTS, AEFeature.CERTUS ), "dustCertusQuartz" ),
NETHER_QUARTZ_DUST( 3, "material_nether_quartz_dust", EnumSet.of( AEFeature.DUSTS ), "dustNetherQuartz" ),
NETHER_QUARTZ_DUST( 3, "material_nether_quartz_dust", EnumSet.of( AEFeature.DUSTS ), "dustNetherQuartz,dustQuartz" ),
FLOUR( 4, "material_flour", EnumSet.of( AEFeature.FLOUR ), "dustWheat" ),
GOLD_DUST( 51, "material_gold_dust", EnumSet.of( AEFeature.DUSTS ), "dustGold" ),
IRON_DUST( 49, "material_iron_dust", EnumSet.of( AEFeature.DUSTS ), "dustIron" ),
@@ -57,9 +57,10 @@ public enum MaterialType
FLUIX_DUST( 8, "material_fluix_dust", EnumSet.of( AEFeature.FLUIX, AEFeature.DUSTS ), "dustFluix" ),
FLUIX_PEARL( 9, "material_fluix_pearl", EnumSet.of( AEFeature.FLUIX ), "pearlFluix" ),
PURIFIED_CERTUS_QUARTZ_CRYSTAL( 10, "material_purified_certus_quartz_crystal", EnumSet.of( AEFeature.CERTUS, AEFeature.PURE_CRYSTALS ) ),
PURIFIED_NETHER_QUARTZ_CRYSTAL( 11, "material_purified_nether_quartz_crystal", EnumSet.of( AEFeature.PURE_CRYSTALS ) ),
PURIFIED_FLUIX_CRYSTAL( 12, "material_purified_fluix_crystal", EnumSet.of( AEFeature.FLUIX, AEFeature.PURE_CRYSTALS ) ),
PURIFIED_CERTUS_QUARTZ_CRYSTAL( 10, "material_purified_certus_quartz_crystal", EnumSet.of( AEFeature.CERTUS,
AEFeature.PURE_CRYSTALS ), "crystalPureCertusQuartz" ),
PURIFIED_NETHER_QUARTZ_CRYSTAL( 11, "material_purified_nether_quartz_crystal", EnumSet.of( AEFeature.PURE_CRYSTALS ), "crystalPureNetherQuartz" ),
PURIFIED_FLUIX_CRYSTAL( 12, "material_purified_fluix_crystal", EnumSet.of( AEFeature.FLUIX, AEFeature.PURE_CRYSTALS ), "crystalPureFluix" ),
CALCULATION_PROCESSOR_PRESS( 13, "material_calculation_processor_press", EnumSet.of( AEFeature.PRESSES ) ),
ENGINEERING_PROCESSOR_PRESS( 14, "material_engineering_processor_press", EnumSet.of( AEFeature.PRESSES ) ),
@@ -33,6 +33,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
@@ -43,6 +44,7 @@ import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi;
import appeng.api.implementations.items.IItemGroup;
@@ -376,4 +378,20 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup
}
}
public void registerOreDicts()
{
for( final PartTypeWithVariant mt : ImmutableSet.copyOf( this.registered.values() ) )
{
if( mt.part.getOreName() != null )
{
final String[] names = mt.part.getOreName().split( "," );
for( final String name : names )
{
OreDictionary.registerOre( name, new ItemStack( this, 1, mt.part.getBaseDamage() + mt.variant ) );
}
}
}
}
}
+22 -4
View File
@@ -187,11 +187,12 @@ public enum PartType
QUARTZ_FIBER( 140, "quartz_fiber", EnumSet.of( AEFeature.QUARTZ_FIBER ), EnumSet.noneOf( IntegrationType.class ), PartQuartzFiber.class ),
MONITOR( 160, "monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartPanel.class ),
MONITOR( 160, "monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartPanel.class, "itemIlluminatedPanel" ),
SEMI_DARK_MONITOR( 180, "semi_dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartSemiDarkPanel.class ),
SEMI_DARK_MONITOR( 180, "semi_dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet
.noneOf( IntegrationType.class ), PartSemiDarkPanel.class, "itemIlluminatedPanel" ),
DARK_MONITOR( 200, "dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartDarkPanel.class ),
DARK_MONITOR( 200, "dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartDarkPanel.class, "itemIlluminatedPanel" ),
STORAGE_BUS( 220, "storage_bus", EnumSet.of( AEFeature.STORAGE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartStorageBus.class ),
FLUID_STORAGE_BUS( 221, "fluid_storage_bus", EnumSet.of( AEFeature.FLUID_STORAGE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartFluidStorageBus.class ),
@@ -316,19 +317,31 @@ public enum PartType
private final Set<ResourceLocation> models;
private final boolean enabled;
private Constructor<? extends IPart> constructor;
private final String oreName;
PartType( final int baseMetaValue, final String itemModel, final Set<AEFeature> features, final Set<IntegrationType> integrations, final Class<? extends IPart> c )
{
this( baseMetaValue, itemModel, features, integrations, c, null );
this( baseMetaValue, itemModel, features, integrations, c, null, null );
}
PartType( final int baseMetaValue, final String itemModel, final Set<AEFeature> features, final Set<IntegrationType> integrations, final Class<? extends IPart> c, final String oreDict )
{
this( baseMetaValue, itemModel, features, integrations, c, null, oreDict );
}
PartType( final int baseMetaValue, final String itemModel, final Set<AEFeature> features, final Set<IntegrationType> integrations, final Class<? extends IPart> c, final GuiText en )
{
this( baseMetaValue, itemModel, features, integrations, c, en, null );
}
PartType( final int baseMetaValue, final String itemModel, final Set<AEFeature> features, final Set<IntegrationType> integrations, final Class<? extends IPart> c, final GuiText en, final String oreDict )
{
this.baseDamage = baseMetaValue;
this.features = Collections.unmodifiableSet( features );
this.integrations = Collections.unmodifiableSet( integrations );
this.myPart = c;
this.extraName = en;
this.oreName = oreDict;
// The part is enabled if all features + integrations it needs are enabled
this.enabled = features.stream().allMatch( AEConfig.instance()::isFeatureEnabled ) && integrations.stream()
@@ -423,6 +436,11 @@ public enum PartType
this.constructor = constructor;
}
public String getOreName()
{
return this.oreName;
}
@SideOnly( Side.CLIENT )
public List<ModelResourceLocation> getItemModels()
{
@@ -0,0 +1,121 @@
package appeng.recipes;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import appeng.core.AppEng;
import appeng.recipes.handlers.GrinderHandler;
import appeng.recipes.handlers.InscriberHandler;
import appeng.recipes.handlers.SmeltingHandler;
public class AERecipeLoader
{
private static final String AERECIPE_BASE = "/aerecipes";
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private final Map<ResourceLocation, IAERecipeFactory> factories = new HashMap<>();
private final ModContainer mod;
private final JsonContext ctx;
public AERecipeLoader()
{
mod = Loader.instance().getIndexedModList().get( AppEng.MOD_ID );
ctx = new JsonContext( AppEng.MOD_ID );
initFactories();
}
public boolean loadProcessingRecipes()
{
return CraftingHelper.findFiles( this.mod, "assets/" + AppEng.MOD_ID + AERECIPE_BASE, this::preprocess, this::process, true, true );
}
private boolean preprocess( final Path root )
{
return true;
}
private boolean process( final Path root, final Path file )
{
String relative = root.relativize( file ).toString();
if( !"json".equals( FilenameUtils.getExtension( file.toString() ) ) || relative.startsWith( "_" ) )
return true;
String name = FilenameUtils.removeExtension( relative ).replaceAll( "\\\\", "/" );
ResourceLocation key = new ResourceLocation( this.ctx.getModId(), name );
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader( file );
JsonObject json = JsonUtils.fromJson( GSON, reader, JsonObject.class );
if( json.has( "conditions" ) && !CraftingHelper.processConditions( JsonUtils.getJsonArray( json, "conditions" ), this.ctx ) )
return true;
register( json );
}
catch( JsonParseException e )
{
FMLLog.log.error( "Parsing error loading recipe {}", key, e );
return false;
}
catch( IOException e )
{
FMLLog.log.error( "Couldn't read recipe {} from {}", key, file, e );
return false;
}
finally
{
IOUtils.closeQuietly( reader );
}
return true;
}
private void register( JsonObject json )
{
if( json == null || json.isJsonNull() )
throw new JsonSyntaxException( "Json cannot be null" );
String type = this.ctx.appendModId( JsonUtils.getString( json, "type" ) );
if( type.isEmpty() )
throw new JsonSyntaxException( "Recipe type can not be an empty string" );
IAERecipeFactory factory = factories.get( new ResourceLocation( type ) );
if( factory == null )
throw new JsonSyntaxException( "Unknown recipe type: " + type );
factory.register( json, this.ctx );
}
private void initFactories()
{
this.factories.put( new ResourceLocation( AppEng.MOD_ID, "inscriber" ), new InscriberHandler() );
this.factories.put( new ResourceLocation( AppEng.MOD_ID, "smelt" ), new SmeltingHandler() );
this.factories.put( new ResourceLocation( AppEng.MOD_ID, "grinder" ), new GrinderHandler() );
}
}
@@ -1,30 +0,0 @@
/*
* 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.recipes;
/**
* @author thatsIch
* @version rv3 - 22.08.2015
* @since rv3 22.08.2015
*/
public interface CustomRecipeConfig
{
boolean isEnabled();
}
@@ -1,50 +0,0 @@
/*
* 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.recipes;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraftforge.common.config.Configuration;
/**
* @author thatsIch
* @version rv3 - 23.08.2015
* @since rv3 23.08.2015
*/
public class CustomRecipeForgeConfiguration implements CustomRecipeConfig
{
private final boolean isEnabled;
public CustomRecipeForgeConfiguration( @Nonnull final Configuration config )
{
Preconditions.checkNotNull( config );
this.isEnabled = config.getBoolean( "enabled", "general", true, "If true, the custom recipes are enabled. Acts as a master switch." );
}
@Override
public final boolean isEnabled()
{
return this.isEnabled;
}
}
@@ -1,162 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
public class GroupIngredient implements IIngredient
{
private final String name;
private final List<IIngredient> ingredients;
private final int qty;
private ItemStack[] baked;
private boolean isInside = false;
public GroupIngredient( final String myName, final List<IIngredient> ingredients, final int qty ) throws RecipeException
{
Preconditions.checkNotNull( myName );
Preconditions.checkNotNull( ingredients );
Preconditions.checkState( !ingredients.isEmpty() );
Preconditions.checkState( qty > 0 );
this.name = myName;
this.qty = qty;
for( final IIngredient ingredient : ingredients )
{
if( ingredient.isAir() )
{
throw new RecipeException( "Cannot include air in a group." );
}
}
this.ingredients = ingredients;
}
IIngredient copy( final int qty ) throws RecipeException
{
Preconditions.checkState( qty > 0 );
return new GroupIngredient( this.name, this.ingredients, qty );
}
@Override
public ItemStack getItemStack() throws RegistrationException, MissingIngredientException
{
throw new RegistrationException( "Cannot pass group of items to a recipe which desires a single recipe item." );
}
@Override
public ItemStack[] getItemStackSet() throws RegistrationException, MissingIngredientException
{
if( this.baked != null )
{
return this.baked;
}
if( this.isInside )
{
return new ItemStack[0];
}
final List<ItemStack> out = new LinkedList<>();
this.isInside = true;
try
{
for( final IIngredient i : this.ingredients )
{
try
{
out.addAll( Arrays.asList( i.getItemStackSet() ) );
}
catch( final MissingIngredientException mir )
{
// oh well this is a group!
}
}
}
finally
{
this.isInside = false;
}
if( out.isEmpty() )
{
throw new MissingIngredientException( this.toString() + " - group could not be resolved to any items." );
}
for( final ItemStack is : out )
{
is.setCount( this.qty );
}
return out.toArray( new ItemStack[out.size()] );
}
@Override
public boolean isAir()
{
return false;
}
@Override
public String getNameSpace()
{
return "";
}
@Override
public String getItemName()
{
return this.name;
}
@Override
public int getDamageValue()
{
return OreDictionary.WILDCARD_VALUE;
}
@Override
public int getQty()
{
return this.qty;
}
@Override
public void bake() throws RegistrationException, MissingIngredientException
{
this.baked = null;
this.baked = this.getItemStackSet();
}
}
@@ -0,0 +1,13 @@
package appeng.recipes;
import com.google.gson.JsonObject;
import net.minecraftforge.common.crafting.JsonContext;
public interface IAERecipeFactory
{
void register( JsonObject json, JsonContext ctx );
}
@@ -1,276 +0,0 @@
/*
* 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.recipes;
import java.util.List;
import com.google.common.base.Preconditions;
import net.minecraft.block.Block;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
import appeng.api.recipes.ResolverResult;
import appeng.api.recipes.ResolverResultSet;
public class Ingredient implements IIngredient
{
private final boolean isAir;
private final String nameSpace;
private final String itemName;
private final int meta;
private final int qty;
private NBTTagCompound nbt = null;
private ItemStack[] baked;
public Ingredient( final RecipeHandler handler, final String input, final int qty ) throws RecipeException, MissedIngredientSet
{
Preconditions.checkNotNull( handler );
Preconditions.checkNotNull( input );
Preconditions.checkState( qty > 0 );
// works no matter wat!
this.qty = qty;
if( input.equals( "_" ) )
{
this.isAir = true;
this.nameSpace = "";
this.itemName = "";
this.meta = OreDictionary.WILDCARD_VALUE;
return;
}
this.isAir = false;
final String[] parts = input.split( ":" );
if( parts.length >= 2 )
{
this.nameSpace = handler.alias( parts[0] );
String tmpName = handler.alias( parts[1] );
if( parts.length != 3 )
{
int sel = 0;
if( this.nameSpace.equalsIgnoreCase( "oreDictionary" ) )
{
if( parts.length == 3 )
{
throw new RecipeException( "Cannot specify meta when using ore dictionary." );
}
sel = OreDictionary.WILDCARD_VALUE;
}
else
{
try
{
final Object ro = AEApi.instance().registries().recipes().resolveItem( this.nameSpace, tmpName );
if( ro instanceof ResolverResult )
{
final ResolverResult rr = (ResolverResult) ro;
tmpName = rr.itemName;
sel = rr.damageValue;
this.nbt = rr.compound;
}
else if( ro instanceof ResolverResultSet )
{
throw new MissedIngredientSet( (ResolverResultSet) ro );
}
}
catch( final IllegalArgumentException e )
{
throw new RecipeException( tmpName + " is not a valid ae2 item definition." );
}
}
this.meta = sel;
}
else
{
if( parts[2].equals( "*" ) )
{
this.meta = OreDictionary.WILDCARD_VALUE;
}
else
{
try
{
this.meta = Integer.parseInt( parts[2] );
}
catch( final NumberFormatException e )
{
throw new RecipeException( "Invalid Metadata." );
}
}
}
this.itemName = tmpName;
}
else
{
throw new RecipeException( input + " : Needs at least Namespace and Name." );
}
handler.getData().knownItem.add( this.toString() );
}
@Override
public String toString()
{
return this.nameSpace + ':' + this.itemName + ':' + this.meta;
}
@Override
public ItemStack getItemStack() throws RegistrationException, MissingIngredientException
{
if( this.isAir )
{
throw new RegistrationException( "Found blank item and expected a real item." );
}
if( this.nameSpace.equalsIgnoreCase( "oreDictionary" ) )
{
throw new RegistrationException( "Recipe format expected a single item, but got a set of items." );
}
Block blk = Block.getBlockFromName( this.nameSpace + ":" + this.itemName );
if( blk == null )
{
blk = Block.getBlockFromName( this.nameSpace + ":" + "tile." + this.itemName );
}
if( blk != null )
{
final Item it = Item.getItemFromBlock( blk );
if( it != Items.AIR )
{
return this.makeItemStack( it, this.qty, this.meta, this.nbt );
}
}
Item it = Item.getByNameOrId( this.nameSpace + ":" + this.itemName );
if( it == null )
{
it = Item.getByNameOrId( this.nameSpace + ":" + "item." + this.itemName );
}
if( it != null )
{
return this.makeItemStack( it, this.qty, this.meta, this.nbt );
}
/*
* Object o = Item.itemRegistry.getObject( nameSpace + ":" + itemName ); if ( o instanceof Item ) return new
* ItemStack( (Item) o, qty, meta );
* if ( o instanceof Block ) return new ItemStack( (Block) o, qty, meta );
* o = Item.itemRegistry.getObject( nameSpace + ":item." + itemName ); if ( o instanceof Item ) return new
* ItemStack( (Item) o, qty, meta );
* o = Block.blockRegistry.getObject( nameSpace + ":tile." + itemName ); if ( o instanceof Block && (!(o
* instanceof BlockAir)) ) return new ItemStack( (Block) o, qty, meta );
*/
throw new MissingIngredientException( "Unable to find item: " + this.toString() );
}
private ItemStack makeItemStack( final Item it, final int quantity, final int damageValue, final NBTTagCompound compound )
{
final ItemStack is = new ItemStack( it, quantity, damageValue );
is.setTagCompound( compound );
return is;
}
@Override
public ItemStack[] getItemStackSet() throws RegistrationException, MissingIngredientException
{
if( this.baked != null )
{
return this.baked;
}
if( this.nameSpace.equalsIgnoreCase( "oreDictionary" ) )
{
final List<ItemStack> ores = OreDictionary.getOres( this.itemName );
final ItemStack[] set = ores.toArray( new ItemStack[ores.size()] );
// clone and set qty.
for( int x = 0; x < set.length; x++ )
{
final ItemStack is = set[x].copy();
is.setCount( this.qty );
set[x] = is;
}
if( set.length == 0 )
{
throw new MissingIngredientException( this.itemName + " - ore dictionary could not be resolved to any items." );
}
return set;
}
return new ItemStack[] { this.getItemStack() };
}
@Override
public String getNameSpace()
{
return this.nameSpace;
}
@Override
public String getItemName()
{
return this.itemName;
}
@Override
public int getDamageValue()
{
return this.meta;
}
@Override
public int getQty()
{
return this.qty;
}
@Override
public boolean isAir()
{
return this.isAir;
}
@Override
public void bake() throws RegistrationException, MissingIngredientException
{
this.baked = null;
this.baked = this.getItemStackSet();
}
}
@@ -1,128 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes;
import java.util.LinkedList;
import java.util.List;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
import appeng.api.recipes.ResolverResultSet;
public class IngredientSet implements IIngredient
{
private final int qty;
private final String name;
private final List<ItemStack> items;
private final boolean isInside = false;
private ItemStack[] baked;
public IngredientSet( final ResolverResultSet rr, final int qty )
{
Preconditions.checkNotNull( rr );
Preconditions.checkNotNull( rr.name );
Preconditions.checkNotNull( rr.results );
Preconditions.checkState( qty > 0 );
this.name = rr.name;
this.items = rr.results;
this.qty = qty;
}
@Override
public ItemStack getItemStack() throws RegistrationException, MissingIngredientException
{
throw new RegistrationException( "Cannot pass group of items to a recipe which desires a single recipe item." );
}
@Override
public ItemStack[] getItemStackSet() throws RegistrationException, MissingIngredientException
{
if( this.baked != null )
{
return this.baked;
}
if( this.isInside )
{
return new ItemStack[0];
}
final List<ItemStack> out = new LinkedList<>();
out.addAll( this.items );
if( out.isEmpty() )
{
throw new MissingIngredientException( this.toString() + " - group could not be resolved to any items." );
}
for( final ItemStack is : out )
{
is.setCount( this.qty );
}
return out.toArray( new ItemStack[out.size()] );
}
@Override
public boolean isAir()
{
return false;
}
@Override
public String getNameSpace()
{
return "";
}
@Override
public String getItemName()
{
return this.name;
}
@Override
public int getDamageValue()
{
return OreDictionary.WILDCARD_VALUE;
}
@Override
public int getQty()
{
return this.qty;
}
@Override
public void bake() throws RegistrationException, MissingIngredientException
{
this.baked = null;
this.baked = this.getItemStackSet();
}
}
@@ -1,40 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes;
import appeng.api.recipes.ResolverResultSet;
public class MissedIngredientSet extends Throwable
{
private static final long serialVersionUID = 2672951714376345807L;
private final ResolverResultSet resolverResultSet;
public MissedIngredientSet( final ResolverResultSet ro )
{
this.resolverResultSet = ro;
}
ResolverResultSet getResolverResultSet()
{
return this.resolverResultSet;
}
}
@@ -1,43 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import appeng.api.recipes.ICraftHandler;
public class RecipeData
{
final Map<String, String> aliases = new HashMap<>();
final Map<String, GroupIngredient> groups = new HashMap<>();
final List<ICraftHandler> handlers = new LinkedList<>();
final Set<String> knownItem = new HashSet<>();
boolean crash = true;
boolean exceptions = true;
boolean errorOnMissing = true;
}
+2 -726
View File
@@ -19,51 +19,8 @@
package appeng.recipes;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.LoaderState;
import appeng.api.AEApi;
import appeng.api.definitions.IBlocks;
import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IItems;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.features.IRecipeHandlerRegistry;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.api.recipes.IRecipeHandler;
import appeng.api.recipes.IRecipeLoader;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.features.AEFeature;
import appeng.items.materials.ItemMaterial;
import appeng.items.misc.ItemCrystalSeed;
import appeng.items.parts.ItemPart;
import appeng.recipes.handlers.IWebsiteSerializer;
import appeng.recipes.handlers.OreRegistration;
/**
@@ -74,696 +31,15 @@ import appeng.recipes.handlers.OreRegistration;
*/
public class RecipeHandler implements IRecipeHandler
{
private final RecipeData data;
private final List<String> tokens = new LinkedList<>();
public RecipeHandler()
{
this.data = new RecipeData();
}
RecipeHandler( final RecipeHandler parent )
{
Preconditions.checkNotNull( parent );
this.data = parent.data;
}
private void addCrafting( final ICraftHandler ch )
{
this.data.handlers.add( ch );
}
public String getName( @Nonnull final IIngredient i )
{
try
{
for( final ItemStack is : i.getItemStackSet() )
{
return this.getName( is );
}
}
catch( final RecipeException ignored )
{
}
catch( final Throwable t )
{
t.printStackTrace();
// :P
}
return i.getNameSpace() + ':' + i.getItemName();
}
private String getName( final ItemStack is ) throws RecipeException
{
Preconditions.checkNotNull( is );
final ResourceLocation id = Item.REGISTRY.getNameForObject( is.getItem() );
String realName = id.toString();
if( !id.getResourceDomain().equals( AppEng.MOD_ID ) && !id.getResourceDomain().equals( "minecraft" ) )
{
throw new RecipeException( "Not applicable for website" );
}
final IDefinitions definitions = AEApi.instance().definitions();
final IItems items = definitions.items();
final IBlocks blocks = definitions.blocks();
final Optional<Item> maybeCrystalSeedItem = items.crystalSeed().maybeItem();
final Optional<Item> maybeSkyStoneItem = blocks.skyStoneBlock().maybeItem();
final Optional<Item> maybeCStorageItem = blocks.craftingStorage1k().maybeItem();
final Optional<Item> maybeCUnitItem = blocks.craftingUnit().maybeItem();
final Optional<Item> maybeSkyChestItem = blocks.skyStoneChest().maybeItem();
if( maybeCrystalSeedItem.isPresent() && is.getItem() == maybeCrystalSeedItem.get() )
{
final int dmg = is.getItemDamage();
if( dmg < ItemCrystalSeed.NETHER )
{
realName += ".Certus";
}
else if( dmg < ItemCrystalSeed.FLUIX )
{
realName += ".Nether";
}
else if( dmg < ItemCrystalSeed.FINAL_STAGE )
{
realName += ".Fluix";
}
}
else if( maybeSkyStoneItem.isPresent() && is.getItem() == maybeSkyStoneItem.get() )
{
switch( is.getItemDamage() )
{
case 1:
realName += ".Block";
break;
case 2:
realName += ".Brick";
break;
case 3:
realName += ".SmallBrick";
break;
default:
}
}
else if( maybeCStorageItem.isPresent() && is.getItem() == maybeCStorageItem.get() )
{
switch( is.getItemDamage() )
{
case 1:
realName += "4k";
break;
case 2:
realName += "16k";
break;
case 3:
realName += "64k";
break;
default:
}
}
else if( maybeCUnitItem.isPresent() && is.getItem() == maybeCUnitItem.get() )
{
switch( is.getItemDamage() )
{
case 1:
realName = realName.replace( "Unit", "Accelerator" );
break;
default:
}
}
else if( maybeSkyChestItem.isPresent() && is.getItem() == maybeSkyChestItem.get() )
{
switch( is.getItemDamage() )
{
case 1:
realName += ".Block";
break;
default:
}
}
else if( is.getItem() instanceof ItemMaterial )
{
realName = realName.replace( "ItemMultiMaterial", "ItemMaterial" );
realName += '.' + ( (ItemMaterial) is.getItem() ).getTypeByStack( is ).name();
}
else if( is.getItem() instanceof ItemPart )
{
realName = realName.replace( "ItemPart", "ItemPart" );
realName += '.' + ( (ItemPart) is.getItem() ).getTypeByStack( is ).name();
}
else if( is.getItemDamage() > 0 )
{
realName += "." + is.getItemDamage();
}
return realName;
}
String alias( final String in )
{
Preconditions.checkNotNull( in );
final String out = this.data.aliases.get( in );
if( out != null )
{
return out;
}
return in;
}
@Override
public void parseRecipes( final IRecipeLoader loader, final String path )
{
Preconditions.checkNotNull( loader );
Preconditions.checkNotNull( path );
try
{
BufferedReader reader = null;
try
{
reader = loader.getFile( path );
}
catch( final Exception err )
{
AELog.warn( "Error Loading Recipe File:" + path );
if( this.data.exceptions )
{
AELog.debug( err );
}
return;
}
boolean inQuote = false;
boolean inComment = false;
String token = "";
int line = 0;
int val = -1;
while( ( val = reader.read() ) != -1 )
{
final char c = (char) val;
if( c == '\n' )
{
line++;
}
if( inComment )
{
if( c == '\n' || c == '\r' )
{
inComment = false;
}
}
else if( inQuote )
{
switch( c )
{
case '"':
inQuote = !inQuote;
break;
default:
token += c;
}
}
else
{
switch( c )
{
case '"':
inQuote = !inQuote;
break;
case ',':
if( token.length() > 0 )
{
this.tokens.add( token );
this.tokens.add( "," );
}
token = "";
break;
case '=':
this.processTokens( loader, path, line );
if( token.length() > 0 )
{
this.tokens.add( token );
}
token = "";
break;
case '#':
inComment = true;
// then add a token if you can...
case '\n':
case '\t':
case '\r':
case ' ':
if( token.length() > 0 )
{
this.tokens.add( token );
}
token = "";
break;
default:
token += c;
}
}
}
if( token.length() > 0 )
{
this.tokens.add( token );
}
reader.close();
this.processTokens( loader, path, line );
}
catch( final Throwable e )
{
AELog.debug( e );
if( this.data.crash )
{
throw new IllegalStateException( e );
}
}
// dummy
}
@Override
public void injectRecipes()
{
if( net.minecraftforge.fml.common.Loader.instance().hasReachedState( LoaderState.POSTINITIALIZATION ) )
{
throw new IllegalStateException( "Recipes must now be loaded in Init." );
}
final Map<Class, Integer> processed = new HashMap<>();
for( final ICraftHandler ch : this.data.handlers )
{
try
{
ch.register();
final Class clz = ch.getClass();
final Integer i = processed.get( clz );
if( i == null )
{
processed.put( clz, 1 );
}
else
{
processed.put( clz, i + 1 );
}
}
catch( final MissingIngredientException e )
{
if( this.data.errorOnMissing )
{
AELog.warn( "Unable to register a recipe:" + e.getMessage() );
if( this.data.exceptions )
{
AELog.debug( e );
}
if( this.data.crash )
{
throw new IllegalStateException( e );
}
}
}
catch( final RegistrationException e )
{
AELog.warn( "Unable to register a recipe: " + e.getMessage() );
if( this.data.exceptions )
{
AELog.debug( e );
}
if( this.data.crash )
{
throw new IllegalStateException( e );
}
}
}
for( final Entry<Class, Integer> e : processed.entrySet() )
{
AELog.info( "Recipes Loading: " + e.getKey().getSimpleName() + ": " + e.getValue() + " loaded." );
}
if( AEConfig.instance().isFeatureEnabled( AEFeature.WEBSITE_RECIPES ) )
{
try
{
final ZipOutputStream out = new ZipOutputStream( new FileOutputStream( "recipes.zip" ) );
final HashMultimap<String, IWebsiteSerializer> combined = HashMultimap.create();
for( final String s : this.data.knownItem )
{
try
{
final IIngredient i = new Ingredient( this, s, 1 );
for( final ItemStack is : i.getItemStackSet() )
{
final String realName = this.getName( is );
final List<IWebsiteSerializer> recipes = this.findRecipe( is );
if( !recipes.isEmpty() )
{
combined.putAll( realName, recipes );
}
}
}
catch( final RecipeException ignored )
{
}
catch( final MissedIngredientSet ignored )
{
}
catch( final RegistrationException ignored )
{
}
catch( final MissingIngredientException ignored )
{
}
}
for( final String realName : combined.keySet() )
{
int offset = 0;
for( final IWebsiteSerializer ws : combined.get( realName ) )
{
final String rew = ws.getPattern( this );
if( rew != null && rew.length() > 0 )
{
out.putNextEntry( new ZipEntry( realName + '_' + offset + ".txt" ) );
offset++;
out.write( rew.getBytes() );
}
}
}
out.close();
}
catch( final FileNotFoundException e1 )
{
AELog.debug( e1 );
}
catch( final IOException e1 )
{
AELog.debug( e1 );
}
}
// dummy
}
private List<IWebsiteSerializer> findRecipe( final ItemStack output )
{
final List<IWebsiteSerializer> out = new LinkedList<>();
for( final ICraftHandler ch : this.data.handlers )
{
try
{
if( ch instanceof IWebsiteSerializer && ( (IWebsiteSerializer) ch ).canCraft( output ) )
{
out.add( (IWebsiteSerializer) ch );
}
}
catch( final Throwable t )
{
AELog.debug( t );
}
}
return out;
}
RecipeData getData()
{
return this.data;
}
private void processTokens( final IRecipeLoader loader, final String file, final int line ) throws RecipeException
{
try
{
final IRecipeHandlerRegistry cr = AEApi.instance().registries().recipes();
if( this.tokens.isEmpty() )
{
return;
}
final int split = this.tokens.indexOf( "->" );
if( split != -1 )
{
final String operation = this.tokens.remove( 0 ).toLowerCase( Locale.ENGLISH );
if( operation.equals( "alias" ) )
{
if( this.tokens.size() == 3 && this.tokens.indexOf( "->" ) == 1 )
{
this.data.aliases.put( this.tokens.get( 0 ), this.tokens.get( 2 ) );
}
else
{
throw new RecipeException( "Alias must have exactly 1 input and 1 output." );
}
}
else if( operation.equals( "group" ) )
{
final List<String> pre = this.tokens.subList( 0, split - 1 );
final List<String> post = this.tokens.subList( split, this.tokens.size() );
final List<List<IIngredient>> inputs = this.parseLines( pre );
if( inputs.size() == 1 && inputs.get( 0 ).size() > 0 && post.size() == 1 )
{
this.data.groups.put( post.get( 0 ), new GroupIngredient( post.get( 0 ), inputs.get( 0 ), 1 ) );
}
else
{
throw new RecipeException( "Group must have exactly 1 output, and 1 or more inputs." );
}
}
else if( operation.equals( "ore" ) )
{
final List<String> pre = this.tokens.subList( 0, split - 1 );
final List<String> post = this.tokens.subList( split, this.tokens.size() );
final List<List<IIngredient>> inputs = this.parseLines( pre );
if( inputs.size() == 1 && inputs.get( 0 ).size() > 0 && post.size() == 1 )
{
final ICraftHandler ch = new OreRegistration( inputs.get( 0 ), post.get( 0 ) );
this.addCrafting( ch );
}
else
{
throw new RecipeException( "Group must have exactly 1 output, and 1 or more inputs in a single row." );
}
}
else
{
final List<String> pre = this.tokens.subList( 0, split - 1 );
final List<String> post = this.tokens.subList( split, this.tokens.size() );
final List<List<IIngredient>> inputs = this.parseLines( pre );
final List<List<IIngredient>> outputs = this.parseLines( post );
final ICraftHandler ch = cr.getCraftHandlerFor( operation );
if( ch != null )
{
ch.setup( inputs, outputs );
this.addCrafting( ch );
}
else
{
throw new RecipeException( "Invalid crafting type: " + operation );
}
}
}
else
{
final String operation = this.tokens.remove( 0 ).toLowerCase();
if( operation.equals( "exceptions" ) && ( this.tokens.get( 0 ).equals( "true" ) || this.tokens.get( 0 ).equals( "false" ) ) )
{
if( this.tokens.size() == 1 )
{
this.data.exceptions = this.tokens.get( 0 ).equals( "true" );
}
else
{
throw new RecipeException( "exceptions must be true or false explicitly." );
}
}
else if( operation.equals( "crash" ) && ( this.tokens.get( 0 ).equals( "true" ) || this.tokens.get( 0 ).equals( "false" ) ) )
{
if( this.tokens.size() == 1 )
{
this.data.crash = this.tokens.get( 0 ).equals( "true" );
}
else
{
throw new RecipeException( "crash must be true or false explicitly." );
}
}
else if( operation.equals( "erroronmissing" ) )
{
if( this.tokens.size() == 1 && ( this.tokens.get( 0 ).equals( "true" ) || this.tokens.get( 0 ).equals( "false" ) ) )
{
this.data.errorOnMissing = this.tokens.get( 0 ).equals( "true" );
}
else
{
throw new RecipeException( "erroronmissing must be true or false explicitly." );
}
}
else if( operation.equals( "import" ) )
{
if( this.tokens.size() == 1 )
{
( new RecipeHandler( this ) ).parseRecipes( loader, this.tokens.get( 0 ) );
}
else
{
throw new RecipeException( "Import must have exactly 1 input." );
}
}
else
{
throw new RecipeException( operation + ": " + this.tokens.toString() + "; recipe without an output." );
}
}
}
catch( final RecipeException e )
{
AELog.warn( "Recipe Error '" + e.getMessage() + "' near line:" + line + " in " + file + " with: " + this.tokens.toString() );
if( this.data.exceptions )
{
AELog.debug( e );
}
if( this.data.crash )
{
throw e;
}
}
this.tokens.clear();
}
private List<List<IIngredient>> parseLines( final Iterable<String> subList ) throws RecipeException
{
final List<List<IIngredient>> out = new LinkedList<>();
List<IIngredient> cList = new LinkedList<>();
boolean hasQty = false;
int qty = 1;
for( final String v : subList )
{
if( v.equals( "," ) )
{
if( hasQty )
{
throw new RecipeException( "Qty found with no item." );
}
if( !cList.isEmpty() )
{
out.add( cList );
}
cList = new LinkedList<>();
}
else
{
if( this.isNumber( v ) )
{
if( hasQty )
{
throw new RecipeException( "Qty found with no item." );
}
hasQty = true;
qty = Integer.parseInt( v );
}
else
{
if( hasQty )
{
cList.add( this.findIngredient( v, qty ) );
hasQty = false;
}
else
{
cList.add( this.findIngredient( v, 1 ) );
}
}
}
}
if( !cList.isEmpty() )
{
out.add( cList );
}
return out;
}
private IIngredient findIngredient( final String v, final int qty ) throws RecipeException
{
final GroupIngredient gi = this.data.groups.get( v );
if( gi != null )
{
return gi.copy( qty );
}
try
{
return new Ingredient( this, v, qty );
}
catch( final MissedIngredientSet grp )
{
return new IngredientSet( grp.getResolverResultSet(), qty );
}
}
private boolean isNumber( final CharSequence v )
{
if( v.length() <= 0 )
{
return false;
}
final int l = v.length();
for( int x = 0; x < l; x++ )
{
if( !Character.isDigit( v.charAt( x ) ) )
{
return false;
}
}
return true;
}
}
@@ -74,7 +74,12 @@ public class PartRecipeFactory implements IRecipeFactory
public static ItemStack getResult( JsonObject json, JsonContext context )
{
JsonObject resultObject = JsonUtils.getJsonObject( json, "result" );
return getResult( json, context, "result" );
}
public static ItemStack getResult( JsonObject json, JsonContext context, String name )
{
JsonObject resultObject = JsonUtils.getJsonObject( json, name );
if( resultObject.has( "part" ) )
{
@@ -1,28 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.game;
import appeng.api.exceptions.RegistrationException;
public interface IRecipeBakeable
{
void bake() throws RegistrationException;
}
@@ -1,336 +0,0 @@
/*
* 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.recipes.game;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
public class ShapedRecipe extends net.minecraftforge.registries.IForgeRegistryEntry.Impl<IRecipe> implements IRecipe, IRecipeBakeable
{
// Added in for future ease of change, but hard coded for now.
private static final int MAX_CRAFT_GRID_WIDTH = 3;
private static final int MAX_CRAFT_GRID_HEIGHT = 3;
private ItemStack output = ItemStack.EMPTY;
private Object[] input = null;
private int width = 0;
private int height = 0;
private boolean mirrored = true;
private boolean disable = false;
public ShapedRecipe( final ItemStack result, Object... recipe )
{
this.output = result.copy();
final StringBuilder shape = new StringBuilder();
int idx = 0;
if( recipe[idx] instanceof Boolean )
{
this.mirrored = (Boolean) recipe[idx];
if( recipe[idx + 1] instanceof Object[] )
{
recipe = (Object[]) recipe[idx + 1];
}
else
{
idx = 1;
}
}
if( recipe[idx] instanceof String[] )
{
final String[] parts = ( (String[]) recipe[idx] );
idx++;
for( final String s : parts )
{
this.width = s.length();
shape.append( s );
}
this.height = parts.length;
}
else
{
while( recipe[idx] instanceof String )
{
final String s = (String) recipe[idx];
idx++;
shape.append( s );
this.width = s.length();
this.height++;
}
}
if( this.width * this.height != shape.length() )
{
final StringBuilder ret = new StringBuilder( "Invalid shaped ore recipe: " );
for( final Object tmp : recipe )
{
ret.append( tmp ).append( ", " );
}
ret.append( this.output );
throw new IllegalStateException( ret.toString() );
}
final Map<Character, IIngredient> itemMap = new HashMap<>();
for( ; idx < recipe.length; idx += 2 )
{
final Character chr = (Character) recipe[idx];
final Object in = recipe[idx + 1];
if( in instanceof IIngredient )
{
itemMap.put( chr, (IIngredient) in );
}
else
{
final StringBuilder ret = new StringBuilder( "Invalid shaped ore recipe: " );
for( final Object tmp : recipe )
{
ret.append( tmp ).append( ", " );
}
ret.append( this.output );
throw new IllegalStateException( ret.toString() );
}
}
this.input = new Object[this.width * this.height];
int x = 0;
for( final char chr : shape.toString().toCharArray() )
{
this.input[x] = itemMap.get( chr );
x++;
}
}
public boolean isEnabled()
{
return !this.disable;
}
@Override
public boolean matches( final InventoryCrafting inv, final World world )
{
if( this.disable )
{
return false;
}
for( int x = 0; x <= MAX_CRAFT_GRID_WIDTH - this.width; x++ )
{
for( int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - this.height; ++y )
{
if( this.checkMatch( inv, x, y, false ) )
{
return true;
}
if( this.mirrored && this.checkMatch( inv, x, y, true ) )
{
return true;
}
}
}
return false;
}
@Override
public ItemStack getCraftingResult( final InventoryCrafting var1 )
{
return this.output.copy();
}
@Override
public boolean canFit( int i, int i1 )
{
return false;
}
@Override
public ItemStack getRecipeOutput()
{
return this.output;
}
@SuppressWarnings( "unchecked" )
private boolean checkMatch( final InventoryCrafting inv, final int startX, final int startY, final boolean mirror )
{
if( this.disable )
{
return false;
}
for( int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++ )
{
for( int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++ )
{
final int subX = x - startX;
final int subY = y - startY;
Object target = null;
if( subX >= 0 && subY >= 0 && subX < this.width && subY < this.height )
{
if( mirror )
{
target = this.input[this.width - subX - 1 + subY * this.width];
}
else
{
target = this.input[subX + subY * this.width];
}
}
final ItemStack slot = inv.getStackInRowAndColumn( x, y );
if( target instanceof IIngredient )
{
boolean matched = false;
try
{
for( final ItemStack item : ( (IIngredient) target ).getItemStackSet() )
{
matched = matched || this.checkItemEquals( item, slot );
}
}
catch( final RegistrationException e )
{
// :P
}
catch( final MissingIngredientException e )
{
// :P
}
if( !matched )
{
return false;
}
}
else if( target instanceof ArrayList )
{
boolean matched = false;
for( final ItemStack item : (Iterable<ItemStack>) target )
{
matched = matched || this.checkItemEquals( item, slot );
}
if( !matched )
{
return false;
}
}
else if( target == null && !slot.isEmpty() )
{
return false;
}
}
}
return true;
}
private boolean checkItemEquals( final ItemStack target, final ItemStack input )
{
if( input.isEmpty() && !target.isEmpty() || !input.isEmpty() && target.isEmpty() )
{
return false;
}
return( target.getItem() == input
.getItem() && ( target.getItemDamage() == OreDictionary.WILDCARD_VALUE || target.getItemDamage() == input.getItemDamage() ) );
}
public ShapedRecipe setMirrored( final boolean mirror )
{
this.mirrored = mirror;
return this;
}
/**
* Returns the input for this recipe, any mod accessing this value should never manipulate the values in this array
* as it will effect the recipe itself.
*
* @return The recipes input vales.
*/
public Object[] getInput()
{
return this.input;
}
public int getWidth()
{
return this.width;
}
public int getHeight()
{
return this.height;
}
public Object[] getIIngredients()
{
return this.input;
}
@Override
public void bake() throws RegistrationException
{
try
{
this.disable = false;
for( final Object o : this.input )
{
if( o instanceof IIngredient )
{
( (IIngredient) o ).bake();
}
}
}
catch( final MissingIngredientException err )
{
this.disable = true;
}
}
@Override
public NonNullList<ItemStack> getRemainingItems( final InventoryCrafting inv )
{
return ForgeHooks.defaultRecipeGetRemainingItems( inv );
}
}
@@ -1,191 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.game;
import java.util.ArrayList;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.IIngredient;
public class ShapelessRecipe extends net.minecraftforge.registries.IForgeRegistryEntry.Impl<IRecipe> implements IRecipe, IRecipeBakeable
{
private final ArrayList<Object> input = new ArrayList<>();
private ItemStack output = ItemStack.EMPTY;
private boolean disable = false;
public ShapelessRecipe( final ItemStack result, final Object... recipe )
{
this.output = result.copy();
for( final Object in : recipe )
{
if( in instanceof IIngredient )
{
this.input.add( in );
}
else
{
final StringBuilder ret = new StringBuilder( "Invalid shapeless ore recipe: " );
for( final Object tmp : recipe )
{
ret.append( tmp ).append( ", " );
}
ret.append( this.output );
throw new IllegalArgumentException( ret.toString() );
}
}
}
public boolean isEnabled()
{
return !this.disable;
}
@SuppressWarnings( "unchecked" )
@Override
public boolean matches( final InventoryCrafting var1, final World world )
{
if( this.disable )
{
return false;
}
final ArrayList<Object> required = new ArrayList<>( this.input );
for( int x = 0; x < var1.getSizeInventory(); x++ )
{
final ItemStack slot = var1.getStackInSlot( x );
if( !slot.isEmpty() )
{
boolean inRecipe = false;
for( final Object next : required )
{
boolean match = false;
if( next instanceof IIngredient )
{
try
{
for( final ItemStack item : ( (IIngredient) next ).getItemStackSet() )
{
match = match || this.checkItemEquals( item, slot );
}
}
catch( final RegistrationException e )
{
// :P
}
catch( final MissingIngredientException e )
{
// :P
}
}
if( match )
{
inRecipe = true;
required.remove( next );
break;
}
}
if( !inRecipe )
{
return false;
}
}
}
return required.isEmpty();
}
@Override
public ItemStack getCraftingResult( final InventoryCrafting var1 )
{
return this.output.copy();
}
@Override
public boolean canFit( int i, int i1 )
{
return false;
}
@Override
public ItemStack getRecipeOutput()
{
return this.output;
}
private boolean checkItemEquals( final ItemStack target, final ItemStack input )
{
return( target.getItem() == input
.getItem() && ( target.getItemDamage() == OreDictionary.WILDCARD_VALUE || target.getItemDamage() == input.getItemDamage() ) );
}
/**
* Returns the input for this recipe, any mod accessing this value should never manipulate the values in this array
* as it will effect the recipe itself.
*
* @return The recipes input vales.
*/
public ArrayList<Object> getInput()
{
return this.input;
}
@Override
public void bake() throws RegistrationException
{
try
{
this.disable = false;
for( final Object o : this.input )
{
if( o instanceof IIngredient )
{
( (IIngredient) o ).bake();
}
}
}
catch( final MissingIngredientException e )
{
this.disable = true;
}
}
@Override
public NonNullList<ItemStack> getRemainingItems( final InventoryCrafting inv )
{
return ForgeHooks.defaultRecipeGetRemainingItems( inv );
}
}
@@ -1,88 +0,0 @@
/*
* 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.integration.Integrations;
import appeng.integration.abstraction.IRC;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Crusher implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "Crusher must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
final IRC rc = Integrations.rc();
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
try
{
rc.rockCrusher( is, this.pro_output[0].getItemStack() );
}
catch( final java.lang.RuntimeException err )
{
AELog.info( "RC not happy - " + err.getMessage() );
}
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,88 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.features.IGrinderRecipe;
import appeng.api.features.IGrinderRecipeBuilder;
import appeng.api.features.IGrinderRegistry;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Grind implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "Grind must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
final IGrinderRegistry grinderRegistry = AEApi.instance().registries().grinder();
final IGrinderRecipeBuilder builder = grinderRegistry.builder();
final IGrinderRecipe grinderRecipe = builder.withInput( is )
.withOutput( this.pro_output[0].getItemStack() )
.withTurns( 8 )
.build();
grinderRegistry.addRecipe( grinderRecipe );
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return "grind\n" + h.getName( this.pro_input ) + '\n' + h.getName( this.pro_output[0] );
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -0,0 +1,49 @@
package appeng.recipes.handlers;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.util.JsonUtils;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import appeng.api.AEApi;
import appeng.api.features.IGrinderRecipeBuilder;
import appeng.api.features.IGrinderRegistry;
import appeng.recipes.IAERecipeFactory;
import appeng.recipes.factories.recipes.PartRecipeFactory;
public class GrinderHandler implements IAERecipeFactory
{
@Override
public void register( JsonObject json, JsonContext ctx )
{
// TODO only primary for now
JsonObject result = JsonUtils.getJsonObject( json, "result" );
ItemStack primary = PartRecipeFactory.getResult( result, ctx, "primary" );
ItemStack[] input = CraftingHelper.getIngredient( json.get( "input" ), ctx ).getMatchingStacks();
int turns = 5;
if( json.has( "turns" ) )
{
turns = JsonUtils.getInt( json, "turns" );
}
final IGrinderRegistry reg = AEApi.instance().registries().grinder();
for( int i = 0; i < input.length; ++i )
{
final IGrinderRecipeBuilder builder = reg.builder();
builder.withOutput( primary );
builder.withInput( input[i] );
builder.withTurns( turns );
reg.addRecipe( builder.build() );
}
}
}
@@ -1,101 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fml.common.event.FMLInterModComms;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class HCCrusher implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "Crusher must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
for( final ItemStack beginStack : this.pro_input.getItemStackSet() )
{
try
{
final NBTTagCompound toRegister = new NBTTagCompound();
final ItemStack endStack = this.pro_output[0].getItemStack();
final NBTTagCompound itemFrom = new NBTTagCompound();
final NBTTagCompound itemTo = new NBTTagCompound();
beginStack.writeToNBT( itemFrom );
endStack.writeToNBT( itemTo );
toRegister.setTag( "itemFrom", itemFrom );
toRegister.setTag( "itemTo", itemTo );
toRegister.setFloat( "pressureRatio", 1.0F );
FMLInterModComms.sendMessage( "HydCraft", "registerCrushingRecipe", toRegister );
}
catch( final java.lang.RuntimeException err )
{
AELog.info( "Hydraulicraft not happy - " + err.getMessage() );
}
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,79 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.InscriberProcessType;
/**
* recipe translation for inscribe process
*
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public final class Inscribe extends InscriberProcess
{
@Override
public void register() throws RegistrationException, MissingIngredientException
{
if( this.getImprintable() == null )
{
return;
}
if( this.getOutput() == null )
{
return;
}
final IInscriberRecipeBuilder builder = AEApi.instance().registries().inscriber().builder();
final ItemStack[] realInput = this.getImprintable().getItemStackSet();
final List<ItemStack> inputs = new ArrayList<>( realInput.length );
Collections.addAll( inputs, realInput );
final ItemStack output = this.getOutput().getItemStack();
final InscriberProcessType type = InscriberProcessType.INSCRIBE;
builder.withInputs( inputs )
.withOutput( output )
.withProcessType( type );
if( this.getTopOptional() != null && !this.getTopOptional().getItemStack().isEmpty() )
{
builder.withTopOptional( this.getTopOptional().getItemStack() );
}
if( this.getBotOptional() != null && !this.getBotOptional().getItemStack().isEmpty() )
{
builder.withBottomOptional( this.getBotOptional().getItemStack() );
}
AEApi.instance().registries().inscriber().addRecipe( builder.build() );
}
}
@@ -0,0 +1,71 @@
package appeng.recipes.handlers;
import java.util.Arrays;
import java.util.List;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.util.JsonUtils;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import appeng.api.AEApi;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.IInscriberRegistry;
import appeng.api.features.InscriberProcessType;
import appeng.recipes.IAERecipeFactory;
import appeng.recipes.factories.recipes.PartRecipeFactory;
public class InscriberHandler implements IAERecipeFactory
{
@Override
public void register( JsonObject json, JsonContext ctx )
{
ItemStack result = PartRecipeFactory.getResult( json, ctx );
String mode = JsonUtils.getString( json, "mode" );
JsonObject ingredients = JsonUtils.getJsonObject( json, "ingredients" );
List<ItemStack> middle = Arrays.asList( CraftingHelper.getIngredient( ingredients.get( "middle" ), ctx ).getMatchingStacks() );
ItemStack[] top = new ItemStack[] { null };
if( ingredients.has( "top" ) )
{
top = CraftingHelper.getIngredient( JsonUtils.getJsonObject( ingredients, "top" ), ctx ).getMatchingStacks();
}
ItemStack[] bottom = new ItemStack[] { null };
if( ingredients.has( "bottom" ) )
{
bottom = CraftingHelper.getIngredient( JsonUtils.getJsonObject( ingredients, "bottom" ), ctx ).getMatchingStacks();
}
final IInscriberRegistry reg = AEApi.instance().registries().inscriber();
for( int i = 0; i < top.length; ++i )
{
for( int j = 0; j < bottom.length; ++j )
{
final IInscriberRecipeBuilder builder = reg.builder();
builder.withOutput( result );
builder.withProcessType( "press".equals( mode ) ? InscriberProcessType.PRESS : InscriberProcessType.INSCRIBE );
builder.withInputs( middle );
if( top[i] != null )
{
builder.withTopOptional( top[i] );
}
if( bottom[j] != null )
{
builder.withBottomOptional( bottom[j] );
}
reg.addRecipe( builder.build() );
}
}
}
}
@@ -1,146 +0,0 @@
/*
* 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.recipes.handlers;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
/**
* basic inscriber process for recipes
*
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public abstract class InscriberProcess implements ICraftHandler, IWebsiteSerializer
{
@Nullable
private IIngredient imprintable;
@Nullable
private IIngredient topOptional;
@Nullable
private IIngredient botOptional;
@Nullable
private IIngredient output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( output.size() == 1 && output.get( 0 ).size() == 1 )
{
if( input.size() == 1 && input.get( 0 ).size() > 1 )
{
this.imprintable = input.get( 0 ).get( 0 );
this.topOptional = input.get( 0 ).get( 1 );
if( input.get( 0 ).size() > 2 )
{
this.botOptional = input.get( 0 ).get( 2 );
}
this.output = output.get( 0 ).get( 0 );
}
else
{
throw new RecipeException( "Inscriber recipes cannot have rows, and must have more then one input." );
}
}
else
{
throw new RecipeException( "Inscriber recipes must produce a single output." );
}
}
@Override
public boolean canCraft( final ItemStack reqOutput ) throws RegistrationException, MissingIngredientException
{
return this.output != null && Platform.itemComparisons().isSameItem( this.output.getItemStack(), reqOutput );
}
@Override
public String getPattern( final RecipeHandler handler )
{
String pattern = "inscriber ";
if( this.output != null )
{
pattern += this.output.getQty() + '\n';
pattern += handler.getName( this.output ) + '\n';
}
if( this.topOptional != null )
{
pattern += handler.getName( this.topOptional ) + '\n';
}
if( this.imprintable != null )
{
pattern += handler.getName( this.imprintable );
}
if( this.botOptional != null )
{
pattern += '\n' + handler.getName( this.botOptional );
}
return pattern;
}
@Nullable
protected IIngredient getImprintable()
{
return this.imprintable;
}
@Nullable
protected IIngredient getTopOptional()
{
return this.topOptional;
}
@Nullable
protected IIngredient getBotOptional()
{
return this.botOptional;
}
@Nullable
protected IIngredient getOutput()
{
return this.output;
}
}
@@ -1,88 +0,0 @@
/*
* 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.integration.Integrations;
import appeng.integration.abstraction.IIC2;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Macerator implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "Grind must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
IIC2 ic2 = Integrations.ic2();
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
try
{
ic2.maceratorRecipe( is, this.pro_output[0].getItemStack() );
}
catch( final java.lang.RuntimeException err )
{
AELog.info( "IC2 not happy - " + err.getMessage() );
}
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,89 +0,0 @@
/*
* 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.integration.Integrations;
import appeng.integration.abstraction.IMekanism;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class MekCrusher implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "MekCrusher must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
IMekanism mekanism = Integrations.mekanism();
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
try
{
mekanism.addCrusherRecipe( is, this.pro_output[0].getItemStack() );
}
catch( final java.lang.RuntimeException err )
{
AELog.info( "Mekanism not happy - " + err.getMessage() );
}
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,88 +0,0 @@
/*
* 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.integration.Integrations;
import appeng.integration.abstraction.IMekanism;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class MekEnrichment implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "MekCrusher must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
IMekanism mekanism = Integrations.mekanism();
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
try
{
mekanism.addEnrichmentChamberRecipe( is, this.pro_output[0].getItemStack() );
}
catch( final java.lang.RuntimeException err )
{
AELog.info( "Mekanism not happy - " + err.getMessage() );
}
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,63 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
public class OreRegistration implements ICraftHandler
{
private final List<IIngredient> inputs;
private final String name;
public OreRegistration( final List<IIngredient> in, final String out )
{
this.inputs = in;
this.name = out;
}
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
for( final IIngredient i : this.inputs )
{
for( final ItemStack is : i.getItemStackSet() )
{
OreDictionary.registerOre( this.name, is );
}
}
}
}
@@ -1,76 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.features.IInscriberRecipe;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.InscriberProcessType;
/**
* recipe translation for pressing in the inscriber
*
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public final class Press extends InscriberProcess
{
@Override
public void register() throws RegistrationException, MissingIngredientException
{
if( this.getImprintable() == null )
{
return;
}
if( this.getOutput() == null )
{
return;
}
final IInscriberRecipeBuilder builder = AEApi.instance().registries().inscriber().builder();
final ItemStack[] realInput = this.getImprintable().getItemStackSet();
final List<ItemStack> inputs = new ArrayList<>( realInput.length );
Collections.addAll( inputs, realInput );
final ItemStack top = ( this.getTopOptional() == null ) ? ItemStack.EMPTY : this.getTopOptional().getItemStack();
final ItemStack bot = ( this.getBotOptional() == null ) ? ItemStack.EMPTY : this.getBotOptional().getItemStack();
final ItemStack output = this.getOutput().getItemStack();
final InscriberProcessType type = InscriberProcessType.PRESS;
final IInscriberRecipe recipe = builder.withInputs( inputs )
.withOutput( output )
.withTopOptional( top )
.withBottomOptional( bot )
.withProcessType( type )
.build();
AEApi.instance().registries().inscriber().addRecipe( recipe );
}
}
@@ -1,87 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fml.common.event.FMLInterModComms;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Pulverizer implements ICraftHandler, IWebsiteSerializer
{
private IIngredient pro_input;
private IIngredient[] pro_output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final int outs = output.get( 0 ).size();
if( input.get( 0 ).size() == 1 && outs == 1 )
{
this.pro_input = input.get( 0 ).get( 0 );
this.pro_output = output.get( 0 ).toArray( new IIngredient[outs] );
return;
}
}
throw new RecipeException( "Grind must have a single input, and single output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
final NBTTagCompound toSend = new NBTTagCompound();
toSend.setInteger( "energy", 800 );
toSend.setTag( "primaryOutput", new NBTTagCompound() );
this.pro_output[0].getItemStack().writeToNBT( toSend.getCompoundTag( "primaryOutput" ) );
for( final ItemStack is : this.pro_input.getItemStackSet() )
{
toSend.setTag( "input", new NBTTagCompound() );
is.writeToNBT( toSend.getCompoundTag( "input" ) );
FMLInterModComms.sendMessage( "ThermalExpansion", "PulverizerRecipe", toSend );
}
}
@Override
public String getPattern( final RecipeHandler h )
{
return null;
}
@Override
public boolean canCraft( final ItemStack output ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.pro_output[0].getItemStack(), output );
}
}
@@ -1,175 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Shaped implements ICraftHandler, IWebsiteSerializer
{
private List<List<IIngredient>> inputs;
private IIngredient output;
private int rows;
private int cols;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( output.size() == 1 && output.get( 0 ).size() == 1 )
{
this.rows = input.size();
if( this.rows > 0 && input.size() <= 3 )
{
this.cols = input.get( 0 ).size();
if( this.cols <= 3 && this.cols >= 1 )
{
for( final List<IIngredient> anInput : input )
{
if( anInput.size() != this.cols )
{
throw new RecipeException( "all rows in a shaped crafting recipe must contain the same number of ingredients." );
}
}
this.inputs = input;
this.output = output.get( 0 ).get( 0 );
}
else
{
throw new RecipeException( "Crafting recipes must have 1-3 columns." );
}
}
else
{
throw new RecipeException( "shaped crafting recipes must have 1-3 rows." );
}
}
else
{
throw new RecipeException( "Crafting must produce a single output." );
}
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
char first = 'A';
final List<Object> args = new ArrayList<>();
for( int y = 0; y < this.rows; y++ )
{
final StringBuilder row = new StringBuilder();
for( int x = 0; x < this.cols; x++ )
{
if( this.inputs.get( y ).get( x ).isAir() )
{
row.append( ' ' );
}
else
{
row.append( first );
args.add( first );
args.add( this.inputs.get( y ).get( x ) );
first++;
}
}
args.add( y, row.toString() );
}
final ItemStack outIS = this.output.getItemStack();
try
{
// TODO : 1.12 Cleanup/remove the old recipe loader.
// Registration.addRecipeToRegister( new ShapedRecipe( outIS, args.toArray( new Object[args.size()] ) ) );
}
catch( final Throwable e )
{
AELog.debug( e );
throw new RegistrationException( "Error while adding shaped recipe." );
}
}
@Override
public String getPattern( final RecipeHandler h )
{
String o = "shaped " + this.output.getQty() + ' ' + this.cols + 'x' + this.rows + '\n';
o += h.getName( this.output ) + '\n';
for( int y = 0; y < this.rows; y++ )
{
for( int x = 0; x < this.cols; x++ )
{
final IIngredient i = this.inputs.get( y ).get( x );
if( i.isAir() )
{
o += "air" + ( x + 1 == this.cols ? "\n" : " " );
}
else
{
o += h.getName( i ) + ( x + 1 == this.cols ? "\n" : " " );
}
}
}
return o.trim();
}
@Override
public boolean canCraft( final ItemStack reqOutput ) throws RegistrationException, MissingIngredientException
{
for( int y = 0; y < this.rows; y++ )
{
for( int x = 0; x < this.cols; x++ )
{
final IIngredient i = this.inputs.get( y ).get( x );
if( !i.isAir() )
{
for( final ItemStack r : i.getItemStackSet() )
{
if( Platform.itemComparisons().isSameItem( r, reqOutput ) )
{
return false;
}
}
}
}
}
return Platform.itemComparisons().isSameItem( this.output.getItemStack(), reqOutput );
}
}
@@ -1,141 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.core.AELog;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Shapeless implements ICraftHandler, IWebsiteSerializer
{
private List<IIngredient> inputs;
private IIngredient output;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( output.size() == 1 && output.get( 0 ).size() == 1 )
{
if( input.size() == 1 )
{
this.inputs = input.get( 0 );
this.output = output.get( 0 ).get( 0 );
}
else
{
throw new RecipeException( "Shapeless crafting recipes cannot have rows." );
}
}
else
{
throw new RecipeException( "Crafting must produce a single output." );
}
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
final List<Object> args = new ArrayList<>();
for( final IIngredient i : this.inputs )
{
args.add( i );
}
final ItemStack outIS = this.output.getItemStack();
try
{
// TODO : 1.12 Cleanup/remove the old recipe loader.
// Registration.addRecipeToRegister( new ShapelessRecipe( outIS, args.toArray( new Object[args.size()] ) )
// );
}
catch( final Throwable e )
{
AELog.debug( e );
throw new RegistrationException( "Error while adding shapeless recipe." );
}
}
@Override
public String getPattern( final RecipeHandler h )
{
final StringBuilder o = new StringBuilder( "shapeless " + this.output.getQty() + '\n' );
o.append( h.getName( this.output ) ).append( '\n' );
for( int y = 0; y < this.inputs.size(); y++ )
{
final IIngredient i = this.inputs.get( y );
if( i.isAir() )
{
o.append( "air" );
}
else
{
o.append( h.getName( i ) );
}
if( y + 1 == this.inputs.size() )
{
o.append( '\n' );
}
else
{
o.append( ' ' );
}
}
return o.toString().trim();
}
@Override
public boolean canCraft( final ItemStack reqOutput ) throws RegistrationException, MissingIngredientException
{
for( final IIngredient i : this.inputs )
{
if( !i.isAir() )
{
for( final ItemStack r : i.getItemStackSet() )
{
if( Platform.itemComparisons().isSameItem( r, reqOutput ) )
{
return false;
}
}
}
}
return Platform.itemComparisons().isSameItem( this.output.getItemStack(), reqOutput );
}
}
@@ -1,87 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, 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.recipes.handlers;
import java.util.List;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.registry.GameRegistry;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
import appeng.api.recipes.ICraftHandler;
import appeng.api.recipes.IIngredient;
import appeng.recipes.RecipeHandler;
import appeng.util.Platform;
public class Smelt implements ICraftHandler, IWebsiteSerializer
{
private IIngredient in;
private IIngredient out;
@Override
public void setup( final List<List<IIngredient>> input, final List<List<IIngredient>> output ) throws RecipeException
{
if( input.size() == 1 && output.size() == 1 )
{
final List<IIngredient> inputList = input.get( 0 );
final List<IIngredient> outputList = output.get( 0 );
if( inputList.size() == 1 && outputList.size() == 1 )
{
this.in = inputList.get( 0 );
this.out = outputList.get( 0 );
return;
}
}
throw new RecipeException( "Smelting recipe can only have a single input and output." );
}
@Override
public void register() throws RegistrationException, MissingIngredientException
{
if( this.in.getItemStack().getItem() == Items.AIR )
{
throw new RegistrationException( this.in.toString() + ": Smelting Input is not a valid item." );
}
if( this.out.getItemStack().getItem() == Items.AIR )
{
throw new RegistrationException( this.out.toString() + ": Smelting Output is not a valid item." );
}
GameRegistry.addSmelting( this.in.getItemStack(), this.out.getItemStack(), 0 );
}
@Override
public String getPattern( final RecipeHandler h )
{
return "smelt " + this.out.getQty() + '\n' + h.getName( this.out ) + '\n' + h.getName( this.in );
}
@Override
public boolean canCraft( final ItemStack reqOutput ) throws RegistrationException, MissingIngredientException
{
return Platform.itemComparisons().isSameItem( this.out.getItemStack(), reqOutput );
}
}
@@ -0,0 +1,36 @@
package appeng.recipes.handlers;
import com.google.gson.JsonObject;
import net.minecraft.item.ItemStack;
import net.minecraft.util.JsonUtils;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.fml.common.registry.GameRegistry;
import appeng.recipes.IAERecipeFactory;
import appeng.recipes.factories.recipes.PartRecipeFactory;
public class SmeltingHandler implements IAERecipeFactory
{
@Override
public void register( JsonObject json, JsonContext ctx )
{
ItemStack result = PartRecipeFactory.getResult( json, ctx );
ItemStack[] input = CraftingHelper.getIngredient( json.get( "input" ), ctx ).getMatchingStacks();
float xp = 0.0f;
if( json.has( "xp" ) )
{
xp = JsonUtils.getFloat( json, "xp" );
}
for( int i = 0; i < input.length; ++i )
{
GameRegistry.addSmelting( input[i], result, xp );
}
}
}
@@ -1,61 +0,0 @@
/*
* 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.recipes.loader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import appeng.api.recipes.IRecipeLoader;
/**
* Loads the recipes from the config folder
*/
public final class ConfigLoader implements IRecipeLoader
{
private final File generatedRecipesDir;
private final File userRecipesDir;
public ConfigLoader( final File generatedRecipesDir, final File userRecipesDir )
{
this.generatedRecipesDir = generatedRecipesDir;
this.userRecipesDir = userRecipesDir;
}
@Override
public BufferedReader getFile( @Nonnull final String relativeFilePath ) throws Exception
{
Preconditions.checkNotNull( relativeFilePath );
Preconditions.checkArgument( !relativeFilePath.isEmpty(), "Supplying an empty String will result creating a reader of a folder." );
final File generatedFile = new File( this.generatedRecipesDir, relativeFilePath );
final File userFile = new File( this.userRecipesDir, relativeFilePath );
final File toBeLoaded = ( userFile.exists() && userFile.isFile() ) ? userFile : generatedFile;
return new BufferedReader( new InputStreamReader( new FileInputStream( toBeLoaded ), "UTF-8" ) );
}
}
@@ -1,50 +0,0 @@
/*
* 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.recipes.loader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import appeng.api.recipes.IRecipeLoader;
public class JarLoader implements IRecipeLoader
{
private final String rootPath;
public JarLoader( final String s )
{
this.rootPath = s;
}
@Override
public BufferedReader getFile( @Nonnull final String s ) throws Exception
{
Preconditions.checkNotNull( s );
Preconditions.checkArgument( !s.isEmpty() );
return new BufferedReader( new InputStreamReader( this.getClass().getResourceAsStream( this.rootPath + s ), "UTF-8" ) );
}
}
@@ -1,265 +0,0 @@
/*
* 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.recipes.loader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import org.apache.commons.io.FileUtils;
/**
* copies recipes in jars onto file system includes the readme, needs to be modified if other files needs to be handled
*
* @author thatsIch
* @version rv3 - 11.05.2015
* @since rv3 11.05.2015
*/
public class RecipeResourceCopier
{
/**
* Most expected size of recipes found
*/
private static final int INITIAL_RESOURCE_CAPACITY = 20;
private static final Pattern DOT_COMPILE_PATTERN = Pattern.compile( ".", Pattern.LITERAL );
private static final String FILE_PROTOCOL = "file";
private static final String CLASS_EXTENSION = ".class";
private static final String JAR_PROTOCOL = "jar";
/**
* copy source in the jar
*/
private final String root;
/**
* @param root source root folder of the recipes inside the jar.
*
* @throws NullPointerException if root is <tt>null</tt>
*/
public RecipeResourceCopier( @Nonnull final String root )
{
Preconditions.checkNotNull( root );
this.root = root;
}
/**
* copies recipes found in the root to destination.
*
* @param identifier only copy files which end with the identifier
* @param destination destination folder to which the recipes are copied to
*
* @throws URISyntaxException {@see #getResourceListing}
* @throws IOException {@see #getResourceListing} and if copying the detected resource to file is not possible
* @throws NullPointerException if either parameter is <tt>null</tt>
* @throws IllegalArgumentException if destination is not a directory
*/
public void copyTo( @Nonnull final String identifier, @Nonnull final File destination ) throws URISyntaxException, IOException
{
Preconditions.checkNotNull( destination );
Preconditions.checkArgument( destination.isDirectory() );
this.copyTo( identifier, destination, this.root );
}
/**
* @param destination destination folder to which the recipes are copied to
* @param directory the folder to copy.
*
* @throws URISyntaxException {@see #getResourceListing}
* @throws IOException {@see #getResourceListing} and if copying the detected resource to file is not possible
* @see {RecipeResourceCopier#copyTo(File)}
*/
private void copyTo( @Nonnull final String identifier, @Nonnull final File destination, @Nonnull final String directory ) throws URISyntaxException, IOException
{
assert identifier != null;
assert destination != null;
assert directory != null;
final Class<? extends RecipeResourceCopier> copierClass = this.getClass();
final String[] listing = this.getResourceListing( copierClass, directory );
for( final String list : listing )
{
if( list.endsWith( identifier ) )
{
// generate folder before the file is copied so no empty folders will be generated
FileUtils.forceMkdir( destination );
this.copyFile( destination, directory, list );
}
else if( !list.contains( "." ) )
{
final File subDirectory = new File( destination, list );
this.copyTo( identifier, subDirectory, directory + list + "/" );
}
}
}
/**
* Copies a single file inside a folder to the destination.
*
* @param destination folder to which the file is copied to
* @param directory the directory containing the file
* @param fileName the file to copy
*
* @throws IOException if copying the file is not possible
*/
private void copyFile( @Nonnull final File destination, @Nonnull final String directory, @Nonnull final String fileName ) throws IOException
{
assert destination != null;
assert directory != null;
assert fileName != null;
final Class<? extends RecipeResourceCopier> copierClass = this.getClass();
final InputStream inStream = copierClass.getResourceAsStream( '/' + directory + fileName );
final File outFile = new File( destination, fileName );
if( !outFile.exists() && inStream != null )
{
FileUtils.copyInputStreamToFile( inStream, outFile );
inStream.close();
}
}
/**
* List directory contents for a resource folder. Not recursive. This is basically a brute-force implementation.
* Works for regular files and also JARs.
*
* @param clazz Any java class that lives in the same place as the resources you want.
* @param path Should end with "/", but not start with one.
*
* @return Just the name of each member item, not the full paths.
*
* @throws URISyntaxException if it is a file path and the URL can not be converted to URI
* @throws IOException if jar path can not be decoded
* @throws UnsupportedOperationException if it is neither in jar nor in file path
*/
@Nonnull
private String[] getResourceListing( @Nonnull final Class<?> clazz, @Nonnull final String path ) throws URISyntaxException, IOException
{
assert clazz != null;
assert path != null;
final ClassLoader classLoader = clazz.getClassLoader();
if( classLoader == null )
{
throw new IllegalStateException( "ClassLoader was not found. It was probably loaded at a inappropriate time" );
}
URL dirURL = classLoader.getResource( path );
if( dirURL != null )
{
final String protocol = dirURL.getProtocol();
if( protocol.equals( FILE_PROTOCOL ) )
{
// A file path: easy enough
final URI uriOfURL = dirURL.toURI();
final File fileOfURI = new File( uriOfURL );
final String[] filesAndDirectoriesOfURI = fileOfURI.list();
if( filesAndDirectoriesOfURI == null )
{
throw new IllegalStateException( "Files and Directories were illegal. Either an abstract pathname does not denote a directory, or an I/O error occured." );
}
else
{
return filesAndDirectoriesOfURI;
}
}
}
if( dirURL == null )
{
/*
* In case of a jar file, we can't actually find a directory.
* Have to assume the same jar as clazz.
*/
final String className = clazz.getName();
final Matcher matcher = DOT_COMPILE_PATTERN.matcher( className );
final String me = matcher.replaceAll( "/" ) + CLASS_EXTENSION;
dirURL = classLoader.getResource( me );
}
if( dirURL != null )
{
final String protocol = dirURL.getProtocol();
if( protocol.equals( JAR_PROTOCOL ) )
{
/* A JAR path */
final String dirPath = dirURL.getPath();
final String jarPath = dirPath.substring( 0, dirPath.indexOf( '!' ) ); // strip out only
// the JAR file
final JarFile jar = new JarFile( new File( new URI( jarPath ) ) );
try
{
final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar
final Collection<String> result = new HashSet<>( INITIAL_RESOURCE_CAPACITY ); // avoid
// duplicates
// in case it is a
// subdirectory
while( entries.hasMoreElements() )
{
final JarEntry entry = entries.nextElement();
final String entryFullName = entry.getName();
if( entryFullName.startsWith( path ) )
{ // filter according to the path
String entryName = entryFullName.substring( path.length() );
final int checkSubDir = entryName.indexOf( '/' );
if( checkSubDir >= 0 )
{
// if it is a subdirectory, we just return the directory name
entryName = entryName.substring( 0, checkSubDir );
}
result.add( entryName );
}
}
return result.toArray( new String[result.size()] );
}
finally
{
jar.close();
}
}
}
throw new UnsupportedOperationException( "Cannot list files for URL " + dirURL );
}
}
@@ -24,12 +24,8 @@ import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.oredict.OreDictionary;
import appeng.core.AELog;
import appeng.recipes.game.IRecipeBakeable;
public class OreDictionaryHandler
{
@@ -38,8 +34,6 @@ public class OreDictionaryHandler
private final List<IOreListener> oreListeners = new ArrayList<>();
private boolean enableRebaking = false;
@SubscribeEvent
public void onOreDictionaryRegister( final OreDictionary.OreRegisterEvent event )
{
@@ -55,11 +49,6 @@ public class OreDictionaryHandler
v.oreRegistered( event.getName(), event.getOre() );
}
}
if( this.enableRebaking )
{
this.bakeRecipes();
}
}
/**
@@ -74,26 +63,6 @@ public class OreDictionaryHandler
return true;
}
public void bakeRecipes()
{
this.enableRebaking = true;
for( final Object o : ForgeRegistries.RECIPES.getValues() )
{
if( o instanceof IRecipeBakeable )
{
try
{
( (IRecipeBakeable) o ).bake();
}
catch( final Throwable e )
{
AELog.debug( e );
}
}
}
}
/**
* Adds a new IOreListener and immediately notifies it of any previous ores, any ores added latter will be added at
* that point.