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 factories = new HashMap<>(); private final ModContainer mod; private final JsonContext ctx; public AERecipeLoader() { this.mod = Loader.instance().getIndexedModList().get( AppEng.MOD_ID ); this.ctx = new JsonContext( AppEng.MOD_ID ); this.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; } this.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 = this.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() ); } }