Compare commits

...

8 Commits

Author SHA1 Message Date
yueh 56435199b7 Merge pull request #1891 from yueh/feature-1156
Added an option to toggle oredict substitutions for patterns.
2015-10-10 22:28:40 +02:00
yueh d615fa2dcd Merge pull request #1940 from yueh/fix-1938
Fixes #1938: UnsortedList not respecting meaningful entries.
2015-10-10 18:31:21 +02:00
yueh 614da977f9 Fixes #1938: UnsortedList not respecting meaningful entries. 2015-10-09 12:27:00 +02:00
yueh 24224a450b Added an option to toggle oredict subsitutions for patterns.
It adds a backward compatibility to convert current patterns to use
oredict by default, which should be removed with rv4 stable.

Closes #1156
2015-10-06 11:33:27 +02:00
thatsIch c14bc82a01 Merge pull request #1900 from thatsIch/export-names-to-csv
Closes #1899, Fixed #1898: Adds an easy way to export item names
2015-10-06 09:00:53 +02:00
yueh 64e4dc08d9 Merge pull request #1908 from yueh/feature-1906
Closes #1906: Using a constant time collection for cells
2015-10-05 20:38:50 +02:00
yueh 2e00a483a0 Closes #1906: Using a constant time collection for cells
Cells are only ever using precise for storing their items, thus there is
no need for a sorted collection with in general logarithmic time.
Storing them inside a HashMap for constant time is a way better solution.

Also adds an UnsortedItemList without fuzzy handling.
If anyone tries to use it, it will currently throw an
UnsupportedOperationException, Should the need arise guava Collections2
could provide a filter for it, but it is no alternative with heavy usage
of fuzzy access.

Also some code cleanup, reducing the visibility when not needed as
protected/default as well as removing actually unused methods.
2015-10-03 15:22:12 +02:00
thatsIch 37ae2131fe Closes #1899, Fixed #1898: Adds an easy way to export interesting information into CSV format
Mostly used for the recipe system, but can also be used for debugging purposes. Debug options needs to be ticked to use the full information gain. Recipes only require the normal localization and the specific name plus metadata.

Shifted the recipes into a recipes folder where the CSV will also reside. This will also elevate the copying of the readme to the user directory since it can reside in the recipes folder.

Fixed a bug where the copier would copy the would also copy empty folders
2015-09-26 23:15:25 +02:00
54 changed files with 1963 additions and 352 deletions
-4
View File
@@ -45,10 +45,6 @@ buildscript {
}
}
configurations.all {
resolutionStrategy.cacheDynamicVersionsFor 7200, 'hours'
}
sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
+1 -1
View File
@@ -31,7 +31,7 @@ invtweaks_version=1.58
#########################################################
fmp_version=1.2.0.345
code_chicken_lib_version=1.1.3.138
code_chicken_core_version=1.0.7.46
code_chicken_core_version=1.0.7.47
nei_version=1.0.5.111
bc_version=7.0.9
opencomputers_version=1.5.12.26
+1 -1
View File
@@ -135,5 +135,5 @@ dependencies {
compile(group: 'api', name: 'railcraft', version: "${api_railcraft_version}")
compile(group: 'api', name: 'rf', version: "${api_rf_version}")
testCompile "junit:junit:4.11"
testCompile "junit:junit:4.12"
}
+1 -1
View File
@@ -1,4 +1,4 @@
#Mon Aug 31 16:41:19 CEST 2015
#Tue Sep 01 22:00:39 CEST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
@@ -0,0 +1,30 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 AlgorithmX2
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package appeng.api.config;
public enum ItemSubstitution
{
ENABLED, DISABLED;
}
@@ -50,6 +50,6 @@ public class ItemCraftingStorage extends AEBaseItemBlock
@Override
public boolean hasContainerItem( final ItemStack stack )
{
return AEConfig.instance.isFeatureEnabled( AEFeature.enableDisassemblyCrafting );
return AEConfig.instance.isFeatureEnabled( AEFeature.EnableDisassemblyCrafting );
}
}
@@ -27,6 +27,7 @@ import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import appeng.api.config.ActionItems;
import appeng.api.config.ItemSubstitution;
import appeng.api.config.Settings;
import appeng.api.storage.ITerminalHost;
import appeng.client.gui.widgets.GuiImgButton;
@@ -41,13 +42,20 @@ import appeng.core.sync.packets.PacketValueConfig;
public class GuiPatternTerm extends GuiMEMonitorable
{
final ContainerPatternTerm container;
private static final String SUBSITUTION_DISABLE = "0";
private static final String SUBSITUTION_ENABLE = "1";
GuiTabButton tabCraftButton;
GuiTabButton tabProcessButton;
// GuiImgButton substitutionsBtn;
GuiImgButton encodeBtn;
GuiImgButton clearBtn;
private static final String CRAFTMODE_CRFTING = "1";
private static final String CRAFTMODE_PROCESSING = "0";
private final ContainerPatternTerm container;
private GuiTabButton tabCraftButton;
private GuiTabButton tabProcessButton;
private GuiImgButton substitutionsEnabledBtn;
private GuiImgButton substitutionsDisabledBtn;
private GuiImgButton encodeBtn;
private GuiImgButton clearBtn;
public GuiPatternTerm( final InventoryPlayer inventoryPlayer, final ITerminalHost te )
{
@@ -66,7 +74,7 @@ public class GuiPatternTerm extends GuiMEMonitorable
if( this.tabCraftButton == btn || this.tabProcessButton == btn )
{
NetworkHandler.instance.sendToServer( new PacketValueConfig( "PatternTerminal.CraftMode", this.tabProcessButton == btn ? "1" : "0" ) );
NetworkHandler.instance.sendToServer( new PacketValueConfig( "PatternTerminal.CraftMode", this.tabProcessButton == btn ? CRAFTMODE_CRFTING : CRAFTMODE_PROCESSING ) );
}
if( this.encodeBtn == btn )
@@ -78,34 +86,43 @@ public class GuiPatternTerm extends GuiMEMonitorable
{
NetworkHandler.instance.sendToServer( new PacketValueConfig( "PatternTerminal.Clear", "1" ) );
}
if( this.substitutionsEnabledBtn == btn || this.substitutionsDisabledBtn == btn )
{
NetworkHandler.instance.sendToServer( new PacketValueConfig( "PatternTerminal.Substitute", this.substitutionsEnabledBtn == btn ? SUBSITUTION_DISABLE : SUBSITUTION_ENABLE ) );
}
}
catch( final IOException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// if ( substitutionsBtn == btn )
// {
// }
}
@Override
public void initGui()
{
super.initGui();
this.buttonList.add( this.tabCraftButton = new GuiTabButton( this.guiLeft + 173, this.guiTop + this.ySize - 177, new ItemStack( Blocks.crafting_table ), GuiText.CraftingPattern.getLocal(), itemRender ) );
this.buttonList.add( this.tabProcessButton = new GuiTabButton( this.guiLeft + 173, this.guiTop + this.ySize - 177, new ItemStack( Blocks.furnace ), GuiText.ProcessingPattern.getLocal(), itemRender ) );
this.tabCraftButton = new GuiTabButton( this.guiLeft + 173, this.guiTop + this.ySize - 177, new ItemStack( Blocks.crafting_table ), GuiText.CraftingPattern.getLocal(), itemRender );
this.buttonList.add( this.tabCraftButton );
// buttonList.add( substitutionsBtn = new GuiImgButton( this.guiLeft + 84, this.guiTop + this.ySize - 163,
// Settings.ACTIONS, ActionItems.SUBSTITUTION ) );
// substitutionsBtn.halfSize = true;
this.tabProcessButton = new GuiTabButton( this.guiLeft + 173, this.guiTop + this.ySize - 177, new ItemStack( Blocks.furnace ), GuiText.ProcessingPattern.getLocal(), itemRender );
this.buttonList.add( this.tabProcessButton );
this.buttonList.add( this.clearBtn = new GuiImgButton( this.guiLeft + 74, this.guiTop + this.ySize - 163, Settings.ACTIONS, ActionItems.CLOSE ) );
this.substitutionsEnabledBtn = new GuiImgButton( this.guiLeft + 84, this.guiTop + this.ySize - 163, Settings.ACTIONS, ItemSubstitution.ENABLED );
this.substitutionsEnabledBtn.halfSize = true;
this.buttonList.add( this.substitutionsEnabledBtn );
this.substitutionsDisabledBtn = new GuiImgButton( this.guiLeft + 84, this.guiTop + this.ySize - 163, Settings.ACTIONS, ItemSubstitution.DISABLED );
this.substitutionsDisabledBtn.halfSize = true;
this.buttonList.add( this.substitutionsDisabledBtn );
this.clearBtn = new GuiImgButton( this.guiLeft + 74, this.guiTop + this.ySize - 163, Settings.ACTIONS, ActionItems.CLOSE );
this.clearBtn.halfSize = true;
this.buttonList.add( this.clearBtn );
this.buttonList.add( this.encodeBtn = new GuiImgButton( this.guiLeft + 147, this.guiTop + this.ySize - 142, Settings.ACTIONS, ActionItems.ENCODE ) );
this.encodeBtn = new GuiImgButton( this.guiLeft + 147, this.guiTop + this.ySize - 142, Settings.ACTIONS, ActionItems.ENCODE );
this.buttonList.add( this.encodeBtn );
}
@Override
@@ -122,6 +139,17 @@ public class GuiPatternTerm extends GuiMEMonitorable
this.tabProcessButton.visible = false;
}
if( this.container.substitute )
{
this.substitutionsEnabledBtn.visible = true;
this.substitutionsDisabledBtn.visible = false;
}
else
{
this.substitutionsEnabledBtn.visible = false;
this.substitutionsDisabledBtn.visible = true;
}
super.drawFG( offsetX, offsetY, mouseX, mouseY );
this.fontRendererObj.drawString( GuiText.PatternTerminal.getLocal(), 8, this.ySize - 96 + 2 - this.reservedSpace, 4210752 );
}
@@ -34,6 +34,7 @@ import appeng.api.config.ActionItems;
import appeng.api.config.CondenserOutput;
import appeng.api.config.FullnessMode;
import appeng.api.config.FuzzyMode;
import appeng.api.config.ItemSubstitution;
import appeng.api.config.LevelType;
import appeng.api.config.OperationMode;
import appeng.api.config.PowerUnits;
@@ -129,7 +130,8 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 6, Settings.ACTIONS, ActionItems.STASH, ButtonToolTips.Stash, ButtonToolTips.StashDesc );
this.registerApp( 8, Settings.ACTIONS, ActionItems.ENCODE, ButtonToolTips.Encode, ButtonToolTips.EncodeDescription );
this.registerApp( 4 + 3 * 16, Settings.ACTIONS, ActionItems.SUBSTITUTION, ButtonToolTips.Substitutions, ButtonToolTips.SubstitutionsDesc );
this.registerApp( 4 + 3 * 16, Settings.ACTIONS, ItemSubstitution.ENABLED, ButtonToolTips.Substitutions, ButtonToolTips.SubstitutionsDescEnabled );
this.registerApp( 7 + 3 * 16, Settings.ACTIONS, ItemSubstitution.DISABLED, ButtonToolTips.Substitutions, ButtonToolTips.SubstitutionsDescDisabled );
this.registerApp( 16, Settings.VIEW_MODE, ViewItems.STORED, ButtonToolTips.View, ButtonToolTips.StoredItems );
this.registerApp( 18, Settings.VIEW_MODE, ViewItems.ALL, ButtonToolTips.View, ButtonToolTips.StoredCraftable );
@@ -71,15 +71,17 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
{
public final PartPatternTerminal ct;
final AppEngInternalInventory cOut = new AppEngInternalInventory( null, 1 );
final IInventory crafting;
final SlotFakeCraftingMatrix[] craftingSlots = new SlotFakeCraftingMatrix[9];
final OptionalSlotFake[] outputSlots = new OptionalSlotFake[3];
final SlotPatternTerm craftSlot;
final SlotRestrictedInput patternSlotIN;
final SlotRestrictedInput patternSlotOUT;
private final AppEngInternalInventory cOut = new AppEngInternalInventory( null, 1 );
private final IInventory crafting;
private final SlotFakeCraftingMatrix[] craftingSlots = new SlotFakeCraftingMatrix[9];
private final OptionalSlotFake[] outputSlots = new OptionalSlotFake[3];
private final SlotPatternTerm craftSlot;
private final SlotRestrictedInput patternSlotIN;
private final SlotRestrictedInput patternSlotOUT;
@GuiSync( 97 )
public boolean craftingMode = true;
@GuiSync( 96 )
public boolean substitute = false;
public ContainerPatternTerm( final InventoryPlayer ip, final ITerminalHost monitorable )
{
@@ -88,6 +90,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
final IInventory patternInv = this.ct.getInventoryByName( "pattern" );
final IInventory output = this.ct.getInventoryByName( "output" );
this.crafting = this.ct.getInventoryByName( "crafting" );
for( int y = 0; y < 3; y++ )
@@ -156,6 +159,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
public ItemStack getAndUpdateOutput()
{
final InventoryCrafting ic = new InventoryCrafting( this, 3, 3 );
for( int x = 0; x < ic.getSizeInventory(); x++ )
{
ic.setInventorySlotContents( x, this.crafting.getStackInSlot( x ) );
@@ -238,6 +242,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
encodedValue.setTag( "in", tagIn );
encodedValue.setTag( "out", tagOut );
encodedValue.setBoolean( "crafting", this.craftingMode );
encodedValue.setBoolean( "substitute", this.substitute );
output.setTagCompound( encodedValue );
}
@@ -269,6 +274,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
if( this.craftingMode )
{
final ItemStack out = this.getAndUpdateOutput();
if( out != null && out.stackSize > 0 )
{
return new ItemStack[] { out };
@@ -282,6 +288,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
for( final OptionalSlotFake outputSlot : this.outputSlots )
{
final ItemStack out = outputSlot.getStack();
if( out != null && out.stackSize > 0 )
{
list.add( out );
@@ -347,9 +354,9 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
if( packetPatternSlot.slotItem != null && this.cellInv != null )
{
final IAEItemStack out = packetPatternSlot.slotItem.copy();
InventoryAdaptor inv = new AdaptorPlayerHand( this.getPlayerInv().player );
final InventoryAdaptor playerInv = InventoryAdaptor.getAdaptor( this.getPlayerInv().player, ForgeDirection.UNKNOWN );
if( packetPatternSlot.shift )
{
inv = playerInv;
@@ -376,6 +383,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 );
final InventoryCrafting real = new InventoryCrafting( new ContainerNull(), 3, 3 );
for( int x = 0; x < 9; x++ )
{
ic.setInventorySlotContents( x, packetPatternSlot.pattern[x] == null ? null : packetPatternSlot.pattern[x].getItemStack() );
@@ -412,6 +420,7 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
for( int x = 0; x < real.getSizeInventory(); x++ )
{
final ItemStack failed = playerInv.addItems( real.getStackInSlot( x ) );
if( failed != null )
{
p.dropPlayerItemWithRandomChoice( failed, false );
@@ -450,6 +459,8 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
this.craftingMode = this.ct.isCraftingRecipe();
this.updateOrderOfOutputSlots();
}
this.substitute = this.ct.isSubstitution();
}
}
@@ -519,4 +530,12 @@ public class ContainerPatternTerm extends ContainerMEMonitorable implements IAEA
{
return false;
}
public void toggleSubstitute()
{
this.substitute = !this.substitute;
this.detectAndSendChanges();
this.getAndUpdateOutput();
}
}
+1 -1
View File
@@ -171,7 +171,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject
for( final AEFeature feature : AEFeature.values() )
{
if( feature.isVisible )
if( feature.isVisible() )
{
if( this.get( "Features." + feature.category, feature.name(), feature.defaultValue ).getBoolean( feature.defaultValue ) )
{
+8
View File
@@ -100,4 +100,12 @@ public final class AELog
log( Level.INFO, format, data );
}
}
public static void debug( String format, Object... data )
{
if( AEConfig.instance.isFeatureEnabled( AEFeature.DebugLogging ) )
{
log( Level.DEBUG, format, data );
}
}
}
+50 -15
View File
@@ -21,11 +21,12 @@ package appeng.core;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import com.google.common.base.Stopwatch;
import net.minecraftforge.common.config.Configuration;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
@@ -48,8 +49,13 @@ import appeng.core.sync.network.NetworkHandler;
import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler;
import appeng.integration.IntegrationRegistry;
import appeng.recipes.CustomRecipeConfig;
import appeng.recipes.CustomRecipeForgeConfiguration;
import appeng.server.AECommand;
import appeng.services.VersionChecker;
import appeng.services.export.ExportConfig;
import appeng.services.export.ExportProcess;
import appeng.services.export.ForgeExportConfig;
import appeng.services.version.VersionCheckerConfig;
import appeng.util.Platform;
@@ -74,15 +80,28 @@ public final class AppEng
@Nonnull
private static final AppEng INSTANCE = new AppEng();
private final IMCHandler imcHandler;
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
*/
private ExportConfig exportConfig;
AppEng()
{
this.imcHandler = new IMCHandler();
FMLCommonHandler.instance().registerCrashCallable( new ModCrashEnhancement( CrashInfo.MOD_VERSION ) );
this.registration = new Registration();
}
@Nonnull
@@ -92,9 +111,10 @@ public final class AppEng
return INSTANCE;
}
public final File getConfigDirectory()
@Nonnull
public final Registration getRegistration()
{
return this.configDirectory;
return this.registration;
}
@EventHandler
@@ -107,14 +127,19 @@ public final class AppEng
final Stopwatch watch = Stopwatch.createStarted();
this.configDirectory = new File( event.getModConfigurationDirectory().getPath(), "AppliedEnergistics2" );
this.recipeDirectory = new File( this.configDirectory, "recipes" );
final File configFile = new File( this.configDirectory, "AppliedEnergistics2.cfg" );
final File facadeFile = new File( this.configDirectory, "Facades.cfg" );
final File versionFile = new File( this.configDirectory, "VersionChecker.cfg" );
final File recipeFile = new File( this.configDirectory, "CustomRecipes.cfg" );
final Configuration recipeConfiguration = new Configuration( recipeFile );
AEConfig.instance = new AEConfig( configFile );
FacadeConfig.instance = new FacadeConfig( facadeFile );
final VersionCheckerConfig versionCheckerConfig = new VersionCheckerConfig( versionFile );
this.customRecipeConfig = new CustomRecipeForgeConfiguration( recipeConfiguration );
this.exportConfig = new ForgeExportConfig( recipeConfiguration );
AELog.info( "Pre Initialization ( started )" );
@@ -129,9 +154,9 @@ public final class AppEng
CommonHelper.proxy.init();
}
Registration.INSTANCE.preInitialize( event );
this.registration.preInitialize( event );
if( versionCheckerConfig.isEnabled() )
if( versionCheckerConfig.isVersionCheckingEnabled() )
{
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
final Thread versionCheckerThread = new Thread( versionChecker );
@@ -154,22 +179,30 @@ public final class AppEng
@EventHandler
private void init( final FMLInitializationEvent event )
{
final Stopwatch star = Stopwatch.createStarted();
final Stopwatch start = Stopwatch.createStarted();
AELog.info( "Initialization ( started )" );
Registration.INSTANCE.initialize( event );
if( exportConfig.isExportingItemNamesEnabled() )
{
final ExportProcess process = new ExportProcess( this.recipeDirectory, exportConfig );
final Thread exportProcessThread = new Thread( process );
this.startService( "AE2 CSV Export", exportProcessThread );
}
this.registration.initialize( event, this.recipeDirectory, this.customRecipeConfig );
IntegrationRegistry.INSTANCE.init();
AELog.info( "Initialization ( ended after " + star.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
AELog.info( "Initialization ( ended after " + start.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
}
@EventHandler
private void postInit( final FMLPostInitializationEvent event )
{
final Stopwatch star = Stopwatch.createStarted();
final Stopwatch start = Stopwatch.createStarted();
AELog.info( "Post Initialization ( started )" );
Registration.INSTANCE.postInit( event );
this.registration.postInit( event );
IntegrationRegistry.INSTANCE.postInit();
FMLCommonHandler.instance().registerCrashCallable( new IntegrationCrashEnhancement() );
@@ -179,13 +212,15 @@ public final class AppEng
NetworkRegistry.INSTANCE.registerGuiHandler( this, GuiBridge.GUI_Handler );
NetworkHandler.instance = new NetworkHandler( "AE2" );
AELog.info( "Post Initialization ( ended after " + star.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
AELog.info( "Post Initialization ( ended after " + start.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
}
@EventHandler
private void handleIMCEvent( final FMLInterModComms.IMCEvent event )
{
this.imcHandler.handleIMCEvent( event );
final IMCHandler imcHandler = new IMCHandler();
imcHandler.handleIMCEvent( event );
}
@EventHandler
+52 -35
View File
@@ -22,7 +22,6 @@ 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;
@@ -30,6 +29,7 @@ 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;
@@ -44,57 +44,74 @@ import appeng.recipes.loader.RecipeResourceCopier;
*/
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 IRecipeHandler handler )
public RecipeLoader( @Nonnull final File recipeDirectory, @Nonnull final CustomRecipeConfig config, @Nonnull final IRecipeHandler handler )
{
Preconditions.checkNotNull( handler );
this.handler = handler;
this.recipeDirectory = Preconditions.checkNotNull( recipeDirectory );
Preconditions.checkArgument( !recipeDirectory.isFile() );
this.config = Preconditions.checkNotNull( config );
this.handler = Preconditions.checkNotNull( handler );
}
@Override
public void run()
public final void run()
{
// setup copying
final RecipeResourceCopier copier = new RecipeResourceCopier( "assets/appliedenergistics2/recipes/" );
final File configDirectory = AppEng.instance().getConfigDirectory();
final File generatedRecipesDir = new File( configDirectory, "generated-recipes" );
final File userRecipesDir = new File( configDirectory, "user-recipes" );
final File readmeGenDest = new File( generatedRecipesDir, "README.html" );
final File readmeUserDest = new File( userRecipesDir, "README.html" );
// 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
if( this.config.isEnabled() )
{
FileUtils.forceMkdir( generatedRecipesDir );
FileUtils.forceMkdir( userRecipesDir );
FileUtils.cleanDirectory( generatedRecipesDir );
// setup copying
final RecipeResourceCopier copier = new RecipeResourceCopier( "assets/appliedenergistics2/recipes/" );
copier.copyTo( generatedRecipesDir );
FileUtils.copyFile( readmeGenDest, readmeUserDest );
final File generatedRecipesDir = new File( this.recipeDirectory, "generated" );
final File userRecipesDir = new File( this.recipeDirectory, "user" );
// parse recipes prioritising the user scripts by using the generated as template
this.handler.parseRecipes( new ConfigLoader( generatedRecipesDir, userRecipesDir ), "index.recipe" );
// 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", 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.error( e );
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
catch( final URISyntaxException e )
{
AELog.error( e );
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
}
// on failure use jar parsing
catch( final IOException e )
else
{
AELog.error( e );
this.handler.parseRecipes( new JarLoader( "/assets/appliedenergistics2/recipes/" ), "index.recipe" );
}
catch( final URISyntaxException e )
{
AELog.error( e );
this.handler.parseRecipes( new JarLoader( "/assets/appliedenergistics2/recipes/" ), "index.recipe" );
this.handler.parseRecipes( new JarLoader( ASSETS_RECIPE_PATH ), "index.recipe" );
}
}
}
+22 -8
View File
@@ -19,6 +19,11 @@
package appeng.core;
import java.io.File;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -88,6 +93,7 @@ import appeng.me.cache.TickManagerCache;
import appeng.me.storage.AEExternalHandler;
import appeng.parts.PartPlacement;
import appeng.recipes.AEItemResolver;
import appeng.recipes.CustomRecipeConfig;
import appeng.recipes.RecipeHandler;
import appeng.recipes.game.DisassembleRecipe;
import appeng.recipes.game.FacadeRecipe;
@@ -117,18 +123,21 @@ import appeng.worldgen.QuartzWorldGen;
public final class Registration
{
public static final Registration INSTANCE = new Registration();
private final RecipeHandler recipeHandler;
private final DefinitionConverter converter;
public BiomeGenBase storageBiome;
private BiomeGenBase storageBiome;
private Registration()
Registration()
{
this.converter = new DefinitionConverter();
this.recipeHandler = new RecipeHandler();
}
public BiomeGenBase getStorageBiome()
{
return this.storageBiome;
}
public void preInitialize( final FMLPreInitializationEvent event )
{
this.registerSpatial( false );
@@ -503,8 +512,13 @@ public final class Registration
target.itemLumenPaintBall = source.coloredLumenPaintBall();
}
public void initialize( final FMLInitializationEvent event )
public void initialize( @Nonnull final FMLInitializationEvent event, @Nonnull final File recipeDirectory, @Nonnull final CustomRecipeConfig customRecipeConfig )
{
Preconditions.checkNotNull( event );
Preconditions.checkNotNull( recipeDirectory );
Preconditions.checkArgument( !recipeDirectory.isFile() );
Preconditions.checkNotNull( customRecipeConfig );
final IAppEngApi api = AEApi.instance();
final IPartHelper partHelper = api.partHelper();
final IRegistryContainer registries = api.registries();
@@ -512,7 +526,7 @@ public final class Registration
// Perform ore camouflage!
ItemMultiMaterial.instance.makeUnique();
final Runnable recipeLoader = new RecipeLoader( this.recipeHandler );
final Runnable recipeLoader = new RecipeLoader( recipeDirectory, customRecipeConfig, this.recipeHandler );
recipeLoader.run();
partHelper.registerNewLayer( "appeng.parts.layers.LayerISidedInventory", "net.minecraft.inventory.ISidedInventory" );
@@ -554,13 +568,13 @@ public final class Registration
registration.registerAchievementHandlers();
registration.registerAchievements();
if( AEConfig.instance.isFeatureEnabled( AEFeature.enableDisassemblyCrafting ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.EnableDisassemblyCrafting ) )
{
GameRegistry.addRecipe( new DisassembleRecipe() );
RecipeSorter.register( "appliedenergistics2:disassemble", DisassembleRecipe.class, Category.SHAPELESS, "after:minecraft:shapeless" );
}
if( AEConfig.instance.isFeatureEnabled( AEFeature.enableFacadeCrafting ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.EnableFacadeCrafting ) )
{
GameRegistry.addRecipe( new FacadeRecipe() );
RecipeSorter.register( "appliedenergistics2:facade", FacadeRecipe.class, Category.SHAPED, "after:minecraft:shaped" );
+130 -34
View File
@@ -21,60 +21,124 @@ package appeng.core.features;
public enum AEFeature
{
Core( null ), // stuff that has no reason for ever being turned off, or that
// stuff that has no reason for ever being turned off, or that
// is just flat out required by tons of
// important stuff.
Core( null )
{
@Override
public boolean isVisible()
{
return false;
}
},
CertusQuartzWorldGen( "World" ), MeteoriteWorldGen( "World" ),
CertusQuartzWorldGen( Constants.CATEGORY_WORLD ),
MeteoriteWorldGen( Constants.CATEGORY_WORLD ),
DecorativeLights( Constants.CATEGORY_WORLD ),
DecorativeQuartzBlocks( Constants.CATEGORY_WORLD ),
SkyStoneChests( Constants.CATEGORY_WORLD ),
SpawnPressesInMeteorites( Constants.CATEGORY_WORLD ),
GrindStone( Constants.CATEGORY_WORLD ),
Flour( Constants.CATEGORY_WORLD ),
Inscriber( Constants.CATEGORY_WORLD ),
ChestLoot( Constants.CATEGORY_WORLD ),
VillagerTrading( Constants.CATEGORY_WORLD ),
TinyTNT( Constants.CATEGORY_WORLD ),
DecorativeLights( "World" ), DecorativeQuartzBlocks( "World" ), SkyStoneChests( "World" ), SpawnPressesInMeteorites( "World" ),
PoweredTools( Constants.CATEGORY_TOOLS_CLASSIFICATIONS ),
CertusQuartzTools( Constants.CATEGORY_TOOLS_CLASSIFICATIONS ),
NetherQuartzTools( Constants.CATEGORY_TOOLS_CLASSIFICATIONS ),
GrindStone( "World" ), Flour( "World" ), Inscriber( "World" ),
QuartzHoe( Constants.CATEGORY_TOOLS ),
QuartzSpade( Constants.CATEGORY_TOOLS ),
QuartzSword( Constants.CATEGORY_TOOLS ),
QuartzPickaxe( Constants.CATEGORY_TOOLS ),
QuartzAxe( Constants.CATEGORY_TOOLS ),
QuartzKnife( Constants.CATEGORY_TOOLS ),
QuartzWrench( Constants.CATEGORY_TOOLS ),
ChargedStaff( Constants.CATEGORY_TOOLS ),
EntropyManipulator( Constants.CATEGORY_TOOLS ),
MatterCannon( Constants.CATEGORY_TOOLS ),
WirelessAccessTerminal( Constants.CATEGORY_TOOLS ),
ColorApplicator( Constants.CATEGORY_TOOLS ),
MeteoriteCompass( Constants.CATEGORY_TOOLS ),
ChestLoot( "World" ), VillagerTrading( "World" ),
PowerGen( Constants.CATEGORY_NETWORK_FEATURES ),
Security( Constants.CATEGORY_NETWORK_FEATURES ),
SpatialIO( Constants.CATEGORY_NETWORK_FEATURES ),
QuantumNetworkBridge( Constants.CATEGORY_NETWORK_FEATURES ),
Channels( Constants.CATEGORY_NETWORK_FEATURES ),
TinyTNT( "World" ),
LevelEmitter( Constants.CATEGORY_NETWORK_BUSES ),
CraftingTerminal( Constants.CATEGORY_NETWORK_BUSES ),
StorageMonitor( Constants.CATEGORY_NETWORK_BUSES ),
P2PTunnel( Constants.CATEGORY_NETWORK_BUSES ),
FormationPlane( Constants.CATEGORY_NETWORK_BUSES ),
AnnihilationPlane( Constants.CATEGORY_NETWORK_BUSES ),
IdentityAnnihilationPlane( Constants.CATEGORY_NETWORK_BUSES ),
ImportBus( Constants.CATEGORY_NETWORK_BUSES ),
ExportBus( Constants.CATEGORY_NETWORK_BUSES ),
StorageBus( Constants.CATEGORY_NETWORK_BUSES ),
PartConversionMonitor( Constants.CATEGORY_NETWORK_BUSES ),
PoweredTools( "ToolsClassifications" ),
PortableCell( Constants.CATEGORY_PORTABLE_CELL ),
CertusQuartzTools( "ToolsClassifications" ),
StorageCells( Constants.CATEGORY_STORAGE ),
MEChest( Constants.CATEGORY_STORAGE ),
MEDrive( Constants.CATEGORY_STORAGE ),
IOPort( Constants.CATEGORY_STORAGE ),
NetherQuartzTools( "ToolsClassifications" ),
NetworkTool( Constants.CATEGORY_NETWORK_TOOL ),
QuartzHoe( "Tools" ), QuartzSpade( "Tools" ), QuartzSword( "Tools" ), QuartzPickaxe( "Tools" ), QuartzAxe( "Tools" ), QuartzKnife( "Tools" ), QuartzWrench( "Tools" ),
DenseEnergyCells( Constants.CATEGORY_HIGHER_CAPACITY ),
DenseCables( Constants.CATEGORY_HIGHER_CAPACITY ),
ChargedStaff( "Tools" ), EntropyManipulator( "Tools" ), MatterCannon( "Tools" ), WirelessAccessTerminal( "Tools" ), ColorApplicator( "Tools" ),
P2PTunnelRF( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelME( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelItems( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelRedstone( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelEU( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelLiquids( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelLight( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelOpenComputers( Constants.CATEGORY_P2P_TUNNELS ),
P2PTunnelPressure( Constants.CATEGORY_P2P_TUNNELS ),
CraftingCPU( "CraftingFeatures" ), PowerGen( "NetworkFeatures" ), Security( "NetworkFeatures" ),
MassCannonBlockDamage( Constants.CATEGORY_BLOCK_FEATURES ),
TinyTNTBlockDamage( Constants.CATEGORY_BLOCK_FEATURES ),
SpatialIO( "NetworkFeatures" ), QuantumNetworkBridge( "NetworkFeatures" ), Channels( "NetworkFeatures" ),
Facades( Constants.CATEGORY_FACADES ),
LevelEmitter( "NetworkBuses" ), CraftingTerminal( "NetworkBuses" ), StorageMonitor( "NetworkBuses" ), P2PTunnel( "NetworkBuses" ), FormationPlane( "NetworkBuses" ), AnnihilationPlane( "NetworkBuses" ), IdentityAnnihilationPlane( "NetworkBuses" ), ImportBus( "NetworkBuses" ), ExportBus( "NetworkBuses" ), StorageBus( "NetworkBuses" ), PartConversionMonitor( "NetworkBuses" ),
UnsupportedDeveloperTools( Constants.CATEGORY_MISC, false ),
Creative( Constants.CATEGORY_MISC ),
GrinderLogging( Constants.CATEGORY_MISC, false ),
Logging( Constants.CATEGORY_MISC ),
IntegrationLogging( Constants.CATEGORY_MISC, false ),
WebsiteRecipes( Constants.CATEGORY_MISC, false ),
LogSecurityAudits( Constants.CATEGORY_MISC, false ),
Achievements( Constants.CATEGORY_MISC ),
UpdateLogging( Constants.CATEGORY_MISC, false ),
PacketLogging( Constants.CATEGORY_MISC, false ),
CraftingLog( Constants.CATEGORY_MISC, false ),
LightDetector( Constants.CATEGORY_MISC ),
DebugLogging( Constants.CATEGORY_MISC, false ),
StorageCells( "Storage" ), PortableCell( "PortableCell" ), MEChest( "Storage" ), MEDrive( "Storage" ), IOPort( "Storage" ),
EnableFacadeCrafting( Constants.CATEGORY_CRAFTING ),
InWorldSingularity( Constants.CATEGORY_CRAFTING ),
InWorldFluix( Constants.CATEGORY_CRAFTING ),
InWorldPurification( Constants.CATEGORY_CRAFTING ),
InterfaceTerminal( Constants.CATEGORY_CRAFTING ),
EnableDisassemblyCrafting( Constants.CATEGORY_CRAFTING ),
NetworkTool( "NetworkTool" ),
AlphaPass( Constants.CATEGORY_RENDERING ), PaintBalls( Constants.CATEGORY_TOOLS ),
DenseEnergyCells( "HigherCapacity" ), DenseCables( "HigherCapacity" ),
MolecularAssembler( Constants.CATEGORY_CRAFTING_FEATURES ),
Patterns( Constants.CATEGORY_CRAFTING_FEATURES ),
CraftingCPU( Constants.CATEGORY_CRAFTING_FEATURES ),
P2PTunnelRF( "P2PTunnels" ), P2PTunnelME( "P2PTunnels" ), P2PTunnelItems( "P2PTunnels" ), P2PTunnelRedstone( "P2PTunnels" ), P2PTunnelEU( "P2PTunnels" ), P2PTunnelLiquids( "P2PTunnels" ), P2PTunnelLight( "P2PTunnels" ), P2PTunnelOpenComputers( "P2PTunnels" ), P2PTunnelPressure( "P2PTunnels" ),
MassCannonBlockDamage( "BlockFeatures" ), TinyTNTBlockDamage( "BlockFeatures" ), Facades( "Facades" ),
UnsupportedDeveloperTools( "Misc", false ), Creative( "Misc" ),
GrinderLogging( "Misc", false ), Logging( "Misc" ), IntegrationLogging( "Misc", false ), WebsiteRecipes( "Misc", false ),
enableFacadeCrafting( "Crafting" ), inWorldSingularity( "Crafting" ), inWorldFluix( "Crafting" ), inWorldPurification( "Crafting" ), UpdateLogging( "Misc", false ),
AlphaPass( "Rendering" ), PaintBalls( "Tools" ), PacketLogging( "Misc", false ), CraftingLog( "Misc", false ), InterfaceTerminal( "Crafting" ), LightDetector( "Misc" ),
enableDisassemblyCrafting( "Crafting" ), MolecularAssembler( "CraftingFeatures" ), MeteoriteCompass( "Tools" ), Patterns( "CraftingFeatures" ),
ChunkLoggerTrace( "Commands", false ), LogSecurityAudits( "Misc", false ), Achievements( "Misc" );
ChunkLoggerTrace( Constants.CATEGORY_COMMANDS, false );
public final String category;
public final boolean isVisible;
public final boolean defaultValue;
AEFeature( final String cat )
@@ -85,7 +149,39 @@ public enum AEFeature
AEFeature( final String cat, final boolean defaultValue )
{
this.category = cat;
this.isVisible = !this.name().equals( "Core" );
this.defaultValue = defaultValue;
}
/**
* override to set visibility
*
* @return default true
*/
public boolean isVisible()
{
return true;
}
private enum Constants
{
;
private static final String CATEGORY_MISC = "Misc";
private static final String CATEGORY_CRAFTING = "Crafting";
private static final String CATEGORY_WORLD = "World";
private static final String CATEGORY_TOOLS = "Tools";
private static final String CATEGORY_TOOLS_CLASSIFICATIONS = "ToolsClassifications";
private static final String CATEGORY_NETWORK_BUSES = "NetworkBuses";
private static final String CATEGORY_P2P_TUNNELS = "P2PTunnels";
private static final String CATEGORY_BLOCK_FEATURES = "BlockFeatures";
private static final String CATEGORY_CRAFTING_FEATURES = "CraftingFeatures";
private static final String CATEGORY_STORAGE = "Storage";
private static final String CATEGORY_HIGHER_CAPACITY = "HigherCapacity";
private static final String CATEGORY_NETWORK_FEATURES = "NetworkFeatures";
private static final String CATEGORY_COMMANDS = "Commands";
private static final String CATEGORY_RENDERING = "Rendering";
private static final String CATEGORY_FACADES = "Facades";
private static final String CATEGORY_NETWORK_TOOL = "NetworkTool";
private static final String CATEGORY_PORTABLE_CELL = "PortableCell";
}
}
@@ -54,7 +54,7 @@ public enum ButtonToolTips
LevelType, LevelType_Energy, LevelType_Item, InventoryTweaks, TerminalStyle, TerminalStyle_Full, TerminalStyle_Tall, TerminalStyle_Small,
Stash, StashDesc, Encode, EncodeDescription, Substitutions, SubstitutionsOn, SubstitutionsOff, SubstitutionsDesc, CraftOnly, CraftEither,
Stash, StashDesc, Encode, EncodeDescription, Substitutions, SubstitutionsOn, SubstitutionsOff, SubstitutionsDescEnabled, SubstitutionsDescDisabled, CraftOnly, CraftEither,
Craft, Mod, DoesntDespawn, EmitterMode, CraftViaRedstone, EmitWhenCrafting, ReportInaccessibleItems, ReportInaccessibleItemsYes, ReportInaccessibleItemsNo,
@@ -47,9 +47,20 @@ public enum GuiText
// tunnel names
METunnel, ItemTunnel, RedstoneTunnel, EUTunnel, FluidTunnel, OCTunnel, LightTunnel, RFTunnel, PressureTunnel,
StoredSize, CopyMode, CopyModeDesc, PatternTerminal, CraftingPattern,
StoredSize, CopyMode, CopyModeDesc, PatternTerminal,
ProcessingPattern, Crafts, Creates, And, With, MolecularAssembler,
// Pattern tooltips
CraftingPattern,
ProcessingPattern,
Crafts,
Creates,
And,
With,
Substitute,
Yes,
No,
MolecularAssembler,
StoredPower, MaxPower, RequiredPower, Efficiency, InWorldCrafting,
@@ -59,8 +59,8 @@ import appeng.helpers.IMouseWheelItem;
public class PacketValueConfig extends AppEngPacket
{
public final String Name;
public final String Value;
private final String Name;
private final String Value;
// automatic.
public PacketValueConfig( final ByteBuf stream ) throws IOException
@@ -158,6 +158,10 @@ public class PacketValueConfig extends AppEngPacket
{
cpt.clear();
}
else if( this.Name.equals( "PatternTerminal.Substitute" ) )
{
cpt.ct.setSubstitution( this.Value.equals( "1" ) );
}
}
else if( this.Name.startsWith( "StorageBus." ) && c instanceof ContainerStorageBus )
{
@@ -20,9 +20,12 @@ package appeng.crafting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import com.google.common.collect.Lists;
import net.minecraft.world.World;
import appeng.api.AEApi;
@@ -41,8 +44,8 @@ public class CraftingTreeNode
// what slot!
final int slot;
final CraftingJob job;
final IItemList<IAEItemStack> used = AEApi.instance().storage().createItemList();
private final CraftingJob job;
private final IItemList<IAEItemStack> used = AEApi.instance().storage().createItemList();
// parent node.
private final CraftingTreeProcess parent;
private final World world;
@@ -50,14 +53,13 @@ public class CraftingTreeNode
private final IAEItemStack what;
// what are the crafting patterns for this?
private final ArrayList<CraftingTreeProcess> nodes = new ArrayList<CraftingTreeProcess>();
int bytes = 0;
boolean canEmit = false;
boolean cannotUse = false;
long missing = 0;
long howManyEmitted = 0;
boolean exhausted = false;
boolean sim;
private int bytes = 0;
private boolean canEmit = false;
private boolean cannotUse = false;
private long missing = 0;
private long howManyEmitted = 0;
private boolean exhausted = false;
private boolean sim;
public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, final CraftingTreeProcess par, final int slot, final int depth )
{
@@ -69,6 +71,7 @@ public class CraftingTreeNode
this.sim = false;
this.canEmit = cc.canEmitFor( this.what );
if( this.canEmit )
{
return; // if you can emit for something, you can't make it with patterns.
@@ -87,6 +90,7 @@ public class CraftingTreeNode
boolean notRecursive( final ICraftingPatternDetails details )
{
IAEItemStack[] o = details.getCondensedOutputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
@@ -96,6 +100,7 @@ public class CraftingTreeNode
}
o = details.getCondensedInputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
@@ -121,12 +126,32 @@ public class CraftingTreeNode
this.what.setStackSize( l );
if( this.slot >= 0 && this.parent != null && this.parent.details.isCraftable() )
{
for( IAEItemStack fuzz : inv.getItemList().findFuzzy( this.what, FuzzyMode.IGNORE_ALL ) )
final Collection<IAEItemStack> itemList;
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
if( this.parent.details.canSubstitute() )
{
itemList = inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL );
}
else
{
itemList = Lists.newArrayList();
final IAEItemStack item = inventoryList.findPrecise( this.what );
if( item != null )
{
itemList.add( item );
}
}
for( IAEItemStack fuzz : itemList )
{
if( this.parent.details.isValidItemForSlot( this.slot, fuzz.getItemStack(), this.world ) )
{
fuzz = fuzz.copy();
fuzz.setStackSize( l );
final IAEItemStack available = inv.extractItems( fuzz, Actionable.MODULATE, src );
if( available != null )
@@ -134,6 +159,7 @@ public class CraftingTreeNode
if( !this.exhausted )
{
final IAEItemStack is = this.job.checkUse( available );
if( is != null )
{
thingsUsed.add( is.copy() );
@@ -161,6 +187,7 @@ public class CraftingTreeNode
if( !this.exhausted )
{
final IAEItemStack is = this.job.checkUse( available );
if( is != null )
{
thingsUsed.add( is.copy() );
@@ -202,6 +229,7 @@ public class CraftingTreeNode
pro.request( inv, pro.getTimes( l, madeWhat.getStackSize() ), src );
madeWhat.setStackSize( l );
final IAEItemStack available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
if( available != null )
@@ -62,7 +62,7 @@ public final class EntityChargedQuartz extends AEBaseEntityItem
{
super.onUpdate();
if( !AEConfig.instance.isFeatureEnabled( AEFeature.inWorldFluix ) )
if( !AEConfig.instance.isFeatureEnabled( AEFeature.InWorldFluix ) )
{
return;
}
@@ -57,7 +57,7 @@ public final class EntityGrowingCrystal extends EntityItem
{
super.onUpdate();
if( !AEConfig.instance.isFeatureEnabled( AEFeature.inWorldPurification ) )
if( !AEConfig.instance.isFeatureEnabled( AEFeature.InWorldPurification ) )
{
return;
}
@@ -74,7 +74,7 @@ public final class EntitySingularity extends AEBaseEntityItem
return;
}
if( !AEConfig.instance.isFeatureEnabled( AEFeature.inWorldSingularity ) )
if( !AEConfig.instance.isFeatureEnabled( AEFeature.InWorldSingularity ) )
{
return;
}
+57 -40
View File
@@ -23,6 +23,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
@@ -45,20 +47,21 @@ import appeng.util.item.AEItemStack;
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper>
{
final ItemStack patternItem;
final InventoryCrafting crafting = new InventoryCrafting( new ContainerNull(), 3, 3 );
final InventoryCrafting testFrame = new InventoryCrafting( new ContainerNull(), 3, 3 );
final ItemStack correctOutput;
final IRecipe standardRecipe;
final IAEItemStack[] condensedInputs;
final IAEItemStack[] condensedOutputs;
final IAEItemStack[] inputs;
final IAEItemStack[] outputs;
final boolean isCrafting;
final HashSet<TestLookup> failCache = new HashSet<TestLookup>();
final HashSet<TestLookup> passCache = new HashSet<TestLookup>();
private final ItemStack patternItem;
private final InventoryCrafting crafting = new InventoryCrafting( new ContainerNull(), 3, 3 );
private final InventoryCrafting testFrame = new InventoryCrafting( new ContainerNull(), 3, 3 );
private final ItemStack correctOutput;
private final IRecipe standardRecipe;
private final IAEItemStack[] condensedInputs;
private final IAEItemStack[] condensedOutputs;
private final IAEItemStack[] inputs;
private final IAEItemStack[] outputs;
private final boolean isCrafting;
private final boolean canSubstitute;
private final Set<TestLookup> failCache = new HashSet<TestLookup>();
private final Set<TestLookup> passCache = new HashSet<TestLookup>();
private final IAEItemStack pattern;
public int priority = 0;
private int priority = 0;
public PatternHelper( final ItemStack is, final World w )
{
@@ -72,6 +75,8 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
final NBTTagList inTag = encodedValue.getTagList( "in", 10 );
final NBTTagList outTag = encodedValue.getTagList( "out", 10 );
this.isCrafting = encodedValue.getBoolean( "crafting" );
this.canSubstitute = encodedValue.getBoolean( "substitute" );
this.patternItem = is;
this.pattern = AEItemStack.create( is );
@@ -81,6 +86,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
for( int x = 0; x < inTag.tagCount(); x++ )
{
final ItemStack gs = ItemStack.loadItemStackFromNBT( inTag.getCompoundTagAt( x ) );
this.crafting.setInventorySlotContents( x, gs );
if( gs != null && ( !this.isCrafting || !gs.hasTagCompound() ) )
@@ -95,6 +101,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
if( this.isCrafting )
{
this.standardRecipe = Platform.findMatchingRecipe( this.crafting, w );
if( this.standardRecipe != null )
{
this.correctOutput = this.standardRecipe.getCraftingResult( this.crafting );
@@ -113,6 +120,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
for( int x = 0; x < outTag.tagCount(); x++ )
{
final ItemStack gs = ItemStack.loadItemStackFromNBT( outTag.getCompoundTagAt( x ) );
if( gs != null )
{
out.add( AEApi.instance().storage().createItemStack( gs ) );
@@ -123,7 +131,8 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
this.outputs = out.toArray( new IAEItemStack[out.size()] );
this.inputs = in.toArray( new IAEItemStack[in.size()] );
final HashMap<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<IAEItemStack, IAEItemStack>();
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<IAEItemStack, IAEItemStack>();
for( final IAEItemStack io : this.outputs )
{
if( io == null )
@@ -132,6 +141,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
}
final IAEItemStack g = tmpOutputs.get( io );
if( g == null )
{
tmpOutputs.put( io, io.copy() );
@@ -142,7 +152,8 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
}
}
final HashMap<IAEItemStack, IAEItemStack> tmpInputs = new HashMap<IAEItemStack, IAEItemStack>();
final Map<IAEItemStack, IAEItemStack> tmpInputs = new HashMap<IAEItemStack, IAEItemStack>();
for( final IAEItemStack io : this.inputs )
{
if( io == null )
@@ -151,6 +162,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
}
final IAEItemStack g = tmpInputs.get( io );
if( g == null )
{
tmpInputs.put( io, io.copy() );
@@ -168,6 +180,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
this.condensedInputs = new IAEItemStack[tmpInputs.size()];
int offset = 0;
for( final IAEItemStack io : tmpInputs.values() )
{
this.condensedInputs[offset] = io;
@@ -176,6 +189,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
offset = 0;
this.condensedOutputs = new IAEItemStack[tmpOutputs.size()];
for( final IAEItemStack io : tmpOutputs.values() )
{
this.condensedOutputs[offset] = io;
@@ -287,7 +301,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
@Override
public boolean canSubstitute()
{
return false;
return this.canSubstitute;
}
@Override
@@ -368,17 +382,38 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
return this.pattern.hashCode();
}
enum TestStatus
@Override
public boolean equals( final Object obj )
{
if( obj == null )
{
return false;
}
if( this.getClass() != obj.getClass() )
{
return false;
}
final PatternHelper other = (PatternHelper) obj;
if( this.pattern != null && other.pattern != null )
{
return this.pattern.equals( other.pattern );
}
return false;
}
private enum TestStatus
{
ACCEPT, DECLINE, TEST
}
static class TestLookup
private static final class TestLookup
{
final int slot;
final int ref;
final int hash;
private final int slot;
private final int ref;
private final int hash;
public TestLookup( final int slot, final ItemStack i )
{
@@ -407,6 +442,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
if( obj instanceof TestLookup )
{
final TestLookup b = (TestLookup) obj;
equality = b.slot == this.slot && b.ref == this.ref;
}
else
@@ -417,23 +453,4 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
return equality;
}
}
@Override
public boolean equals( final Object obj )
{
if( obj == null )
{
return false;
}
if( this.getClass() != obj.getClass() )
{
return false;
}
final PatternHelper other = (PatternHelper) obj;
if( this.pattern != null && other.pattern != null )
{
return this.pattern.equals( other.pattern );
}
return false;
}
}
@@ -90,7 +90,7 @@ public class NEI implements INEI, IContainerTooltipHandler, IIntegrationModule
this.registerRecipeHandler( new NEIWorldCraftingHandler() );
this.registerRecipeHandler( new NEIGrinderRecipeHandler() );
if( AEConfig.instance.isFeatureEnabled( AEFeature.Facades ) && AEConfig.instance.isFeatureEnabled( AEFeature.enableFacadeCrafting ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.Facades ) && AEConfig.instance.isFeatureEnabled( AEFeature.EnableFacadeCrafting ) )
{
this.registerRecipeHandler( new NEIFacadeRecipeHandler() );
}
@@ -221,17 +221,17 @@ public class NEIWorldCraftingHandler implements ICraftingHandler, IUsageHandler
this.addRecipe( materials.engProcessorPress(), GuiText.inWorldCraftingPresses.getLocal() );
}
if( AEConfig.instance.isFeatureEnabled( AEFeature.inWorldFluix ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.InWorldFluix ) )
{
this.addRecipe( materials.fluixCrystal(), GuiText.inWorldFluix.getLocal() );
}
if( AEConfig.instance.isFeatureEnabled( AEFeature.inWorldSingularity ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.InWorldSingularity ) )
{
this.addRecipe( materials.qESingularity(), GuiText.inWorldSingularity.getLocal() );
}
if( AEConfig.instance.isFeatureEnabled( AEFeature.inWorldPurification ) )
if( AEConfig.instance.isFeatureEnabled( AEFeature.InWorldPurification ) )
{
this.addRecipe( materials.purifiedCertusQuartzCrystal(), GuiText.inWorldPurificationCertus.getLocal() );
this.addRecipe( materials.purifiedNetherQuartzCrystal(), GuiText.inWorldPurificationNether.getLocal() );
@@ -42,47 +42,80 @@ public enum MaterialType
{
InvalidType( -1, AEFeature.Core ),
CertusQuartzCrystal( 0, AEFeature.Core, "crystalCertusQuartz" ), CertusQuartzCrystalCharged( 1, AEFeature.Core, EntityChargedQuartz.class ),
CertusQuartzCrystal( 0, AEFeature.Core, "crystalCertusQuartz" ),
CertusQuartzCrystalCharged( 1, AEFeature.Core, EntityChargedQuartz.class ),
CertusQuartzDust( 2, AEFeature.Core, "dustCertusQuartz" ), NetherQuartzDust( 3, AEFeature.Core, "dustNetherQuartz" ), Flour( 4, AEFeature.Flour, "dustWheat" ), GoldDust( 51, AEFeature.Core, "dustGold" ), IronDust( 49, AEFeature.Core, "dustIron" ), IronNugget( 50, AEFeature.Core, "nuggetIron" ),
CertusQuartzDust( 2, AEFeature.Core, "dustCertusQuartz" ),
NetherQuartzDust( 3, AEFeature.Core, "dustNetherQuartz" ),
Flour( 4, AEFeature.Flour, "dustWheat" ),
GoldDust( 51, AEFeature.Core, "dustGold" ),
IronDust( 49, AEFeature.Core, "dustIron" ),
IronNugget( 50, AEFeature.Core, "nuggetIron" ),
Silicon( 5, AEFeature.Core, "itemSilicon" ), MatterBall( 6 ),
Silicon( 5, AEFeature.Core, "itemSilicon" ),
MatterBall( 6 ),
FluixCrystal( 7, AEFeature.Core, "crystalFluix" ), FluixDust( 8, AEFeature.Core, "dustFluix" ), FluixPearl( 9, AEFeature.Core, "pearlFluix" ),
FluixCrystal( 7, AEFeature.Core, "crystalFluix" ),
FluixDust( 8, AEFeature.Core, "dustFluix" ),
FluixPearl( 9, AEFeature.Core, "pearlFluix" ),
PurifiedCertusQuartzCrystal( 10 ), PurifiedNetherQuartzCrystal( 11 ), PurifiedFluixCrystal( 12 ),
PurifiedCertusQuartzCrystal( 10 ),
PurifiedNetherQuartzCrystal( 11 ),
PurifiedFluixCrystal( 12 ),
CalcProcessorPress( 13 ), EngProcessorPress( 14 ), LogicProcessorPress( 15 ),
CalcProcessorPress( 13 ),
EngProcessorPress( 14 ),
LogicProcessorPress( 15 ),
CalcProcessorPrint( 16 ), EngProcessorPrint( 17 ), LogicProcessorPrint( 18 ),
CalcProcessorPrint( 16 ),
EngProcessorPrint( 17 ),
LogicProcessorPrint( 18 ),
SiliconPress( 19 ), SiliconPrint( 20 ),
SiliconPress( 19 ),
SiliconPrint( 20 ),
NamePress( 21 ),
LogicProcessor( 22 ), CalcProcessor( 23 ), EngProcessor( 24 ),
LogicProcessor( 22 ),
CalcProcessor( 23 ),
EngProcessor( 24 ),
// Basic Cards
BasicCard( 25 ), CardRedstone( 26 ), CardCapacity( 27 ),
BasicCard( 25 ),
CardRedstone( 26 ),
CardCapacity( 27 ),
// Adv Cards
AdvCard( 28 ), CardFuzzy( 29 ), CardSpeed( 30 ), CardInverter( 31 ),
AdvCard( 28 ),
CardFuzzy( 29 ), CardSpeed( 30 ),
CardInverter( 31 ),
Cell2SpatialPart( 32, AEFeature.SpatialIO ), Cell16SpatialPart( 33, AEFeature.SpatialIO ), Cell128SpatialPart( 34, AEFeature.SpatialIO ),
Cell2SpatialPart( 32, AEFeature.SpatialIO ),
Cell16SpatialPart( 33, AEFeature.SpatialIO ),
Cell128SpatialPart( 34, AEFeature.SpatialIO ),
Cell1kPart( 35, AEFeature.StorageCells ), Cell4kPart( 36, AEFeature.StorageCells ), Cell16kPart( 37, AEFeature.StorageCells ), Cell64kPart( 38, AEFeature.StorageCells ), EmptyStorageCell( 39, AEFeature.StorageCells ),
Cell1kPart( 35, AEFeature.StorageCells ),
Cell4kPart( 36, AEFeature.StorageCells ),
Cell16kPart( 37, AEFeature.StorageCells ),
Cell64kPart( 38, AEFeature.StorageCells ),
EmptyStorageCell( 39, AEFeature.StorageCells ),
WoodenGear( 40, AEFeature.GrindStone, "gearWood" ),
Wireless( 41, AEFeature.WirelessAccessTerminal ), WirelessBooster( 42, AEFeature.WirelessAccessTerminal ),
Wireless( 41, AEFeature.WirelessAccessTerminal ),
WirelessBooster( 42, AEFeature.WirelessAccessTerminal ),
FormationCore( 43 ), AnnihilationCore( 44 ),
FormationCore( 43 ),
AnnihilationCore( 44 ),
SkyDust( 45, AEFeature.Core ),
EnderDust( 46, AEFeature.QuantumNetworkBridge, "dustEnder,dustEnderPearl", EntitySingularity.class ), Singularity( 47, AEFeature.QuantumNetworkBridge, EntitySingularity.class ), QESingularity( 48, AEFeature.QuantumNetworkBridge, EntitySingularity.class ),
EnderDust( 46, AEFeature.QuantumNetworkBridge, "dustEnder,dustEnderPearl", EntitySingularity.class ),
Singularity( 47, AEFeature.QuantumNetworkBridge, EntitySingularity.class ),
QESingularity( 48, AEFeature.QuantumNetworkBridge, EntitySingularity.class ),
BlankPattern( 52 ), CardCrafting( 53 );
BlankPattern( 52 ),
CardCrafting( 53 );
private final EnumSet<AEFeature> features;
// IIcon for the material.
@@ -113,6 +113,7 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
}
final boolean isCrafting = details.isCraftable();
final boolean substitute = details.canSubstitute();
final IAEItemStack[] in = details.getCondensedInputs();
final IAEItemStack[] out = details.getCondensedOutputs();
@@ -144,6 +145,11 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
lines.add( ( first ? with : and ) + anIn.getStackSize() + ' ' + Platform.getItemDisplayName( anIn ) );
first = false;
}
final String substitutionLabel = GuiText.Substitute.getLocal() + " ";
final String canSubstitute = substitute ? GuiText.Yes.getLocal() : GuiText.No.getLocal();
lines.add( substitutionLabel + canSubstitute );
}
@Override
@@ -308,6 +308,6 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
@Override
public boolean hasContainerItem( final ItemStack stack )
{
return AEConfig.instance.isFeatureEnabled( AEFeature.enableDisassemblyCrafting );
return AEConfig.instance.isFeatureEnabled( AEFeature.EnableDisassemblyCrafting );
}
}
@@ -20,6 +20,7 @@ package appeng.me.storage;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
@@ -28,7 +29,6 @@ import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.exceptions.AppEngException;
@@ -43,38 +43,29 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import appeng.util.item.UnsortedItemList;
public class CellInventory implements ICellInventory
{
static final String ITEM_TYPE_TAG = "it";
static final String ITEM_COUNT_TAG = "ic";
static final String ITEM_SLOT = "#";
static final String ITEM_SLOT_COUNT = "@";
static final String ITEM_PRE_FORMATTED_COUNT = "PF";
static final String ITEM_PRE_FORMATTED_SLOT = "PF#";
static final String ITEM_PRE_FORMATTED_NAME = "PN";
static final String ITEM_PRE_FORMATTED_FUZZY = "FP";
private static final HashSet<Integer> BLACK_LIST = new HashSet<Integer>();
protected static String[] itemSlots;
protected static String[] itemSlotCount;
protected final NBTTagCompound tagCompound;
protected final ISaveProvider container;
protected int maxItemTypes = 63;
protected short storedItems = 0;
protected int storedItemCount = 0;
protected IItemList<IAEItemStack> cellItems;
protected ItemStack i;
protected IStorageCell CellType;
private static final String ITEM_TYPE_TAG = "it";
private static final String ITEM_COUNT_TAG = "ic";
private static final String ITEM_SLOT = "#";
private static final String ITEM_SLOT_COUNT = "@";
private static final Set<Integer> BLACK_LIST = new HashSet<Integer>();
private static String[] itemSlots;
private static String[] itemSlotCount;
private final NBTTagCompound tagCompound;
private final ISaveProvider container;
private int maxItemTypes = 63;
private short storedItems = 0;
private int storedItemCount = 0;
private IItemList<IAEItemStack> cellItems;
private ItemStack cellItem;
private IStorageCell cellType;
protected CellInventory( final NBTTagCompound data, final ISaveProvider container )
{
this.tagCompound = data;
this.container = container;
}
protected CellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException
private CellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException
{
if( itemSlots == null )
{
@@ -93,22 +84,23 @@ public class CellInventory implements ICellInventory
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
}
this.CellType = null;
this.i = o;
this.cellType = null;
this.cellItem = o;
final Item type = this.cellItem.getItem();
final Item type = this.i.getItem();
if( type instanceof IStorageCell )
{
this.CellType = (IStorageCell) this.i.getItem();
this.maxItemTypes = this.CellType.getTotalTypes( this.i );
this.cellType = (IStorageCell) this.cellItem.getItem();
this.maxItemTypes = this.cellType.getTotalTypes( this.cellItem );
}
if( this.CellType == null )
if( this.cellType == null )
{
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
}
if( !this.CellType.isStorageCell( this.i ) )
if( !this.cellType.isStorageCell( this.cellItem ) )
{
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
}
@@ -129,7 +121,7 @@ public class CellInventory implements ICellInventory
this.cellItems = null;
}
public static IMEInventoryHandler getCell( final ItemStack o, final ISaveProvider container2 )
public static IMEInventoryHandler<IAEItemStack> getCell( final ItemStack o, final ISaveProvider container2 )
{
try
{
@@ -141,16 +133,17 @@ public class CellInventory implements ICellInventory
}
}
private static boolean isStorageCell( final ItemStack i )
private static boolean isStorageCell( final ItemStack itemStack )
{
if( i == null )
if( itemStack == null )
{
return false;
}
try
{
final Item type = i.getItem();
final Item type = itemStack.getItem();
if( type instanceof IStorageCell )
{
return !( (IStorageCell) type ).storableInStorageCell();
@@ -164,17 +157,18 @@ public class CellInventory implements ICellInventory
return false;
}
public static boolean isCell( final ItemStack i )
public static boolean isCell( final ItemStack itemStack )
{
if( i == null )
if( itemStack == null )
{
return false;
}
final Item type = i.getItem();
final Item type = itemStack.getItem();
if( type instanceof IStorageCell )
{
return ( (IStorageCell) type ).isStorageCell( i );
return ( (IStorageCell) type ).isStorageCell( itemStack );
}
return false;
@@ -191,12 +185,13 @@ public class CellInventory implements ICellInventory
{
return true;
}
return BLACK_LIST.contains( ( input.getItemDamage() << Platform.DEF_OFFSET ) | Item.getIdFromItem( input.getItem() ) );
}
private boolean isEmpty( final IMEInventory meInventory )
private boolean isEmpty( final IMEInventory<IAEItemStack> meInventory )
{
return meInventory.getAvailableItems( AEApi.instance().storage().createItemList() ).isEmpty();
return meInventory.getAvailableItems( new UnsortedItemList() ).isEmpty();
}
@Override
@@ -206,12 +201,13 @@ public class CellInventory implements ICellInventory
{
return null;
}
if( input.getStackSize() == 0 )
{
return null;
}
if( isBlackListed( input ) || this.CellType.isBlackListed( this.i, input ) )
if( isBlackListed( input ) || this.cellType.isBlackListed( this.cellItem, input ) )
{
return input;
}
@@ -220,7 +216,8 @@ public class CellInventory implements ICellInventory
if( CellInventory.isStorageCell( sharedItemStack ) )
{
final IMEInventory meInventory = getCell( sharedItemStack, null );
final IMEInventory<IAEItemStack> meInventory = getCell( sharedItemStack, null );
if( meInventory != null && !this.isEmpty( meInventory ) )
{
return input;
@@ -228,9 +225,11 @@ public class CellInventory implements ICellInventory
}
final IAEItemStack l = this.getCellItems().findPrecise( input );
if( l != null )
{
final long remainingItemSlots = this.getRemainingItemCount();
if( remainingItemSlots < 0 )
{
return input;
@@ -240,12 +239,14 @@ public class CellInventory implements ICellInventory
{
final IAEItemStack r = input.copy();
r.setStackSize( r.getStackSize() - remainingItemSlots );
if( mode == Actionable.MODULATE )
{
l.setStackSize( l.getStackSize() + remainingItemSlots );
this.updateItemCount( remainingItemSlots );
this.saveChanges();
}
return r;
}
else
@@ -256,6 +257,7 @@ public class CellInventory implements ICellInventory
this.updateItemCount( input.getStackSize() );
this.saveChanges();
}
return null;
}
}
@@ -263,12 +265,14 @@ public class CellInventory implements ICellInventory
if( this.canHoldNewItem() ) // room for new type, and for at least one item!
{
final int remainingItemCount = (int) this.getRemainingItemCount() - this.getBytesPerType() * 8;
if( remainingItemCount > 0 )
{
if( input.getStackSize() > remainingItemCount )
{
final ItemStack toReturn = Platform.cloneItemStack( sharedItemStack );
toReturn.stackSize = sharedItemStack.stackSize - remainingItemCount;
if( mode == Actionable.MODULATE )
{
final ItemStack toWrite = Platform.cloneItemStack( sharedItemStack );
@@ -279,6 +283,7 @@ public class CellInventory implements ICellInventory
this.saveChanges();
}
return AEItemStack.create( toReturn );
}
@@ -306,16 +311,18 @@ public class CellInventory implements ICellInventory
final long size = Math.min( Integer.MAX_VALUE, request.getStackSize() );
IAEItemStack Results = null;
IAEItemStack results = null;
final IAEItemStack l = this.getCellItems().findPrecise( request );
if( l != null )
{
Results = l.copy();
results = l.copy();
if( l.getStackSize() <= size )
{
Results.setStackSize( l.getStackSize() );
results.setStackSize( l.getStackSize() );
if( mode == Actionable.MODULATE )
{
this.updateItemCount( -l.getStackSize() );
@@ -325,7 +332,8 @@ public class CellInventory implements ICellInventory
}
else
{
Results.setStackSize( size );
results.setStackSize( size );
if( mode == Actionable.MODULATE )
{
l.setStackSize( l.getStackSize() - size );
@@ -335,14 +343,13 @@ public class CellInventory implements ICellInventory
}
}
return Results;
return results;
}
IItemList<IAEItemStack> getCellItems()
private IItemList<IAEItemStack> getCellItems()
{
if( this.cellItems == null )
{
this.cellItems = AEApi.instance().storage().createItemList();
this.loadCellItems();
}
@@ -355,18 +362,20 @@ public class CellInventory implements ICellInventory
this.tagCompound.setInteger( ITEM_COUNT_TAG, this.storedItemCount );
}
void saveChanges()
private void saveChanges()
{
// cellItems.clean();
int itemCount = 0;
// add new pretty stuff...
int x = 0;
for( final IAEItemStack v : this.cellItems )
{
itemCount += v.getStackSize();
final NBTBase c = this.tagCompound.getTag( itemSlots[x] );
if( c instanceof NBTTagCompound )
{
v.writeToNBT( (NBTTagCompound) c );
@@ -396,6 +405,7 @@ public class CellInventory implements ICellInventory
* else
*/
this.storedItems = (short) this.cellItems.size();
if( this.cellItems.isEmpty() )
{
this.tagCompound.removeTag( ITEM_TYPE_TAG );
@@ -409,6 +419,7 @@ public class CellInventory implements ICellInventory
* if ( tagCount instanceof NBTTagInt ) ((NBTTagInt) tagCount).data = storedItemCount = itemCount; else
*/
this.storedItemCount = itemCount;
if( itemCount == 0 )
{
this.tagCompound.removeTag( ITEM_COUNT_TAG );
@@ -431,11 +442,11 @@ public class CellInventory implements ICellInventory
}
}
protected void loadCellItems()
private void loadCellItems()
{
if( this.cellItems == null )
{
this.cellItems = AEApi.instance().storage().createItemList();
this.cellItems = new UnsortedItemList();
}
this.cellItems.resetStatus(); // clears totals and stuff.
@@ -445,6 +456,7 @@ public class CellInventory implements ICellInventory
for( int x = 0; x < types; x++ )
{
final ItemStack t = ItemStack.loadItemStackFromNBT( this.tagCompound.getCompoundTag( itemSlots[x] ) );
if( t != null )
{
t.stackSize = this.tagCompound.getInteger( itemSlotCount[x] );
@@ -460,7 +472,7 @@ public class CellInventory implements ICellInventory
}
@Override
public IItemList getAvailableItems( final IItemList out )
public IItemList<IAEItemStack> getAvailableItems( final IItemList<IAEItemStack> out )
{
for( final IAEItemStack i : this.getCellItems() )
{
@@ -479,50 +491,51 @@ public class CellInventory implements ICellInventory
@Override
public ItemStack getItemStack()
{
return this.i;
return this.cellItem;
}
@Override
public double getIdleDrain()
{
return this.CellType.getIdleDrain();
return this.cellType.getIdleDrain();
}
@Override
public FuzzyMode getFuzzyMode()
{
return this.CellType.getFuzzyMode( this.i );
return this.cellType.getFuzzyMode( this.cellItem );
}
@Override
public IInventory getConfigInventory()
{
return this.CellType.getConfigInventory( this.i );
return this.cellType.getConfigInventory( this.cellItem );
}
@Override
public IInventory getUpgradesInventory()
{
return this.CellType.getUpgradesInventory( this.i );
return this.cellType.getUpgradesInventory( this.cellItem );
}
@Override
public int getBytesPerType()
{
return this.CellType.BytePerType( this.i );
return this.cellType.getBytesPerType( this.cellItem );
}
@Override
public boolean canHoldNewItem()
{
final long bytesFree = this.getFreeBytes();
return ( bytesFree > this.getBytesPerType() || ( bytesFree == this.getBytesPerType() && this.getUnusedItemCount() > 0 ) ) && this.getRemainingItemTypes() > 0;
}
@Override
public long getTotalBytes()
{
return this.CellType.getBytes( this.i );
return this.cellType.getBytes( this.cellItem );
}
@Override
@@ -535,6 +548,7 @@ public class CellInventory implements ICellInventory
public long getUsedBytes()
{
final long bytesForItemCount = ( this.getStoredItemCount() + this.getUnusedItemCount() ) / 8;
return this.getStoredItemTypes() * this.getBytesPerType() + bytesForItemCount;
}
@@ -561,6 +575,7 @@ public class CellInventory implements ICellInventory
{
final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType();
final long baseOnTotal = this.getTotalItemTypes() - this.getStoredItemTypes();
return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage;
}
@@ -568,6 +583,7 @@ public class CellInventory implements ICellInventory
public long getRemainingItemCount()
{
final long remaining = this.getFreeBytes() * 8 + this.getUnusedItemCount();
return remaining > 0 ? remaining : 0;
}
@@ -21,7 +21,6 @@ package appeng.me.storage;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import appeng.api.AEApi;
import appeng.api.config.FuzzyMode;
@@ -34,7 +33,6 @@ import appeng.api.storage.IMEInventory;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import appeng.util.prioitylist.FuzzyPriorityList;
import appeng.util.prioitylist.PrecisePriorityList;
@@ -43,11 +41,12 @@ import appeng.util.prioitylist.PrecisePriorityList;
public class CellInventoryHandler extends MEInventoryHandler<IAEItemStack> implements ICellInventoryHandler
{
CellInventoryHandler( final IMEInventory c )
CellInventoryHandler( final IMEInventory<IAEItemStack> c )
{
super( c, StorageChannel.ITEMS );
final ICellInventory ci = this.getCellInv();
if( ci != null )
{
final IItemList<IAEItemStack> priorityList = AEApi.instance().storage().createItemList();
@@ -137,11 +136,6 @@ public class CellInventoryHandler extends MEInventoryHandler<IAEItemStack> imple
return this.getWhitelist();
}
NBTTagCompound openNbtData()
{
return Platform.openNbtData( this.getCellInv().getItemStack() );
}
public int getStatusForCell()
{
int val = this.getCellInv().getStatusForCell();
@@ -47,6 +47,7 @@ public class PartPatternTerminal extends AbstractPartTerminal
private final AppEngInternalInventory pattern = new AppEngInternalInventory( this, 2 );
private boolean craftingMode = true;
private boolean substitute = false;
@Reflected
public PartPatternTerminal( final ItemStack is )
@@ -71,6 +72,7 @@ public class PartPatternTerminal extends AbstractPartTerminal
{
super.readFromNBT( data );
this.setCraftingRecipe( data.getBoolean( "craftingMode" ) );
this.setSubstitution( data.getBoolean( "substitute" ) );
this.pattern.readFromNBT( data, "pattern" );
this.output.readFromNBT( data, "outputList" );
this.crafting.readFromNBT( data, "craftingGrid" );
@@ -81,6 +83,7 @@ public class PartPatternTerminal extends AbstractPartTerminal
{
super.writeToNBT( data );
data.setBoolean( "craftingMode", this.craftingMode );
data.setBoolean( "substitute", this.substitute );
this.pattern.writeToNBT( data, "pattern" );
this.output.writeToNBT( data, "outputList" );
this.crafting.writeToNBT( data, "craftingGrid" );
@@ -119,6 +122,7 @@ public class PartPatternTerminal extends AbstractPartTerminal
if( details != null )
{
this.setCraftingRecipe( details.isCraftable() );
this.setSubstitution( details.canSubstitute() );
for( int x = 0; x < this.crafting.getSizeInventory() && x < details.getInputs().length; x++ )
{
@@ -168,6 +172,16 @@ public class PartPatternTerminal extends AbstractPartTerminal
this.fixCraftingRecipes();
}
public boolean isSubstitution()
{
return this.substitute;
}
public void setSubstitution( boolean canSubstitute )
{
this.substitute = canSubstitute;
}
@Override
public IInventory getInventoryByName( final String name )
{
@@ -0,0 +1,30 @@
/*
* 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();
}
@@ -0,0 +1,50 @@
/*
* 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;
}
}
@@ -23,7 +23,6 @@ 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;
@@ -31,6 +30,9 @@ 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;
@@ -22,6 +22,7 @@ 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.net.URLDecoder;
@@ -30,8 +31,8 @@ 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;
@@ -40,9 +41,7 @@ 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
* 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
@@ -55,6 +54,10 @@ public class RecipeResourceCopier
*/
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";
private static final String UTF_8_ENCODING = "UTF-8";
/**
* copy source in the jar
@@ -76,47 +79,52 @@ public class RecipeResourceCopier
/**
* 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 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 File destination ) throws URISyntaxException, IOException
public void copyTo( @Nonnull final String identifier, @Nonnull final File destination ) throws URISyntaxException, IOException
{
Preconditions.checkNotNull( destination );
Preconditions.checkArgument( destination.isDirectory() );
this.copyTo( destination, this.root );
this.copyTo( identifier, destination, this.root );
}
/**
* @see {RecipeResourceCopier#copyTo(File)}
*
* @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
* @throws IOException {@see #getResourceListing} and if copying the detected resource to file is not possible
* @see {RecipeResourceCopier#copyTo(File)}
*/
private void copyTo( final File destination, final String directory ) throws URISyntaxException, IOException
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 String[] listing = this.getResourceListing( this.getClass(), directory );
final Class<? extends RecipeResourceCopier> copierClass = this.getClass();
final String[] listing = this.getResourceListing( copierClass, directory );
for( final String list : listing )
{
if( list.endsWith( ".recipe" ) || list.endsWith( ".html" ) )
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 );
FileUtils.forceMkdir( subDirectory );
this.copyTo( subDirectory, directory + list + "/" );
this.copyTo( identifier, subDirectory, directory + list + "/" );
}
}
}
@@ -126,16 +134,18 @@ public class RecipeResourceCopier
*
* @param destination folder to which the file is copied to
* @param directory the directory containing the file
* @param fileName the fily to copy
* @param fileName the file to copy
*
* @throws IOException if copying the file is not possible
*/
private void copyFile( final File destination, final String directory, final String fileName ) throws IOException
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 InputStream inStream = this.getClass().getResourceAsStream( '/' + directory + fileName );
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 )
@@ -146,30 +156,50 @@ public class RecipeResourceCopier
}
/**
* List directory contents for a resource folder. Not recursive.
* This is basically a brute-force implementation.
* Works for regular files and also JARs.
* 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 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( final Class<?> clazz, final String path ) throws URISyntaxException, IOException
private String[] getResourceListing( @Nonnull final Class<?> clazz, @Nonnull final String path ) throws URISyntaxException, IOException
{
assert clazz != null;
assert path != null;
URL dirURL = clazz.getClassLoader().getResource( path );
if( dirURL != null && dirURL.getProtocol().equals( "file" ) )
final ClassLoader classLoader = clazz.getClassLoader();
if( classLoader == null )
{
// A file path: easy enough
return new File( dirURL.toURI() ).list();
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 )
@@ -178,43 +208,52 @@ public class RecipeResourceCopier
* In case of a jar file, we can't actually find a directory.
* Have to assume the same jar as clazz.
*/
final String me = DOT_COMPILE_PATTERN.matcher( clazz.getName() ).replaceAll( "/" ) + ".class";
dirURL = clazz.getClassLoader().getResource( me );
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 && dirURL.getProtocol().equals( "jar" ) )
if( dirURL != null )
{
/* A JAR path */
final String jarPath = dirURL.getPath().substring( 5, dirURL.getPath().indexOf( '!' ) ); // strip out only
// the JAR file
final JarFile jar = new JarFile( URLDecoder.decode( jarPath, "UTF-8" ) );
try
final String protocol = dirURL.getProtocol();
if( protocol.equals( JAR_PROTOCOL ) )
{
final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar
final Collection<String> result = new HashSet<String>( INITIAL_RESOURCE_CAPACITY ); // avoid duplicates
// in case it is a
// subdirectory
while( entries.hasMoreElements() )
/* A JAR path */
final String dirPath = dirURL.getPath();
final String jarPath = dirPath.substring( 5, dirPath.indexOf( '!' ) ); // strip out only
// the JAR file
final JarFile jar = new JarFile( URLDecoder.decode( jarPath, UTF_8_ENCODING ) );
try
{
final String name = entries.nextElement().getName();
if( name.startsWith( path ) )
{ // filter according to the path
String entry = name.substring( path.length() );
final int checkSubDir = entry.indexOf( '/' );
if( checkSubDir >= 0 )
{
// if it is a subdirectory, we just return the directory name
entry = entry.substring( 0, checkSubDir );
}
result.add( entry );
}
}
final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar
final Collection<String> result = new HashSet<String>( INITIAL_RESOURCE_CAPACITY ); // avoid duplicates
return result.toArray( new String[result.size()] );
}
finally
{
jar.close();
// 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();
}
}
}
+2 -1
View File
@@ -25,7 +25,8 @@ import appeng.server.subcommands.Supporters;
public enum Commands
{
Chunklogger( 4, new ChunkLogger() ), supporters( 0, new Supporters() );
Chunklogger( 4, new ChunkLogger() ),
Supporters( 0, new Supporters() );
public final int level;
public final ISubCommand command;
@@ -76,7 +76,13 @@ public final class VersionChecker implements Runnable
{
Thread.yield();
// persist the config
this.config.save();
// retrieve data
final String rawLastCheck = this.config.lastCheck();
// process data
final long lastCheck = Long.parseLong( rawLastCheck );
final Date now = new Date();
final long nowInMs = now.getTime();
@@ -0,0 +1,41 @@
/*
* 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.services.export;
/**
* Defines a concrete result type when using the {@link Checker#isEqual(Object)} from the {@link Checker} class.
*
* @author thatsIch
* @version rv3 - 25.09.2015
* @see Checker
* @since rv3 - 25.09.2015
*/
enum CheckType
{
/**
* If checking resulted in both objects being <b>equal</b>
*/
EQUAL,
/**
* If checking resulted in both objects being <b>unequal</b>
*/
UNEQUAL
}
@@ -0,0 +1,45 @@
/*
* 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.services.export;
import javax.annotation.Nonnull;
/**
* Checks against a specific type with its own check type for clear outcome.
*
* The constructor will generally have a value which the checker will check against
*
* @author thatsIch
* @version rv3 - 01.09.2015
* @since rv3 - 01.09.2015
*/
interface Checker<T>
{
/**
* @param checkedAgainst the object it is checked against
*
* @return non null being either equal or unequal
*
* @since rv3 - 01.09.2015
*/
@Nonnull
CheckType isEqual( @Nonnull final T checkedAgainst );
}
@@ -0,0 +1,82 @@
/*
* 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.services.export;
import javax.annotation.Nonnull;
/**
* @author thatsIch
* @version rv3 - 14.08.2015
* @since rv3 14.08.2015
*/
public interface ExportConfig
{
/**
* config switch to disable the exporting.
* if the recipes system is not used
* there is no reason to export them.
* Still can be useful for debugging purpose,
* thus not tying it to the recipe system directly.
*
* @return true if exporting is enabled
*/
boolean isExportingItemNamesEnabled();
/**
* config switch for using the digest cache.
*
* @return true if cache is enabled
*/
boolean isCacheEnabled();
/**
* config switch to always refresh the CSV. Might be useful to activate on debugging.
*
* @return true if force refresh is enabled
*/
boolean isForceRefreshEnabled();
/**
* config switch to export more information mostly used for debugging
*
* @return true if additional information are enabled
*/
boolean isAdditionalInformationEnabled();
/**
* Will get the cache from last session. Can be used to reduce I/O operations though containing itself calculation.
*
* @return a digest from the last calculation
*/
String getCache();
/**
* sets the cache for the next session to reduce calculation overhead
*
* @param digest new digest for the cache
*/
void setCache( @Nonnull String digest );
/**
* Will delegate the saving
*/
void save();
}
@@ -0,0 +1,42 @@
/*
* 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.services.export;
/**
* Defines the different modes which need to be distinguished upon exporting.
*
* using a different mode will result in a different export outcome.
*
* @author thatsIch
* @version rv3 - 23.09.2015
* @since rv3 - 23.09.2015
*/
enum ExportMode
{
/**
* Will provide general users with information required for recipe making
*/
MINIMAL,
/**
* Will provide advanced users with information with debugging functionality
*/
VERBOSE
}
@@ -0,0 +1,130 @@
/*
* 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.services.export;
import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import net.minecraft.item.Item;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry;
import cpw.mods.fml.common.registry.GameData;
import appeng.core.AELog;
/**
* Main entry point for exporting the CSV file
*
* makes everything threadable
*
* @author thatsIch
* @version rv3 - 14.08.2015
* @since rv3 14.08.2015
*/
public class ExportProcess implements Runnable
{
private static final String FORCE_REFRESH_MESSAGE = "Force Refresh enabled. Will ignore cache and export CSV content.";
private static final String CACHE_ENABLED_MESSAGE = "Cache is enabled. Checking for new mod configurations.";
private static final String EQUAL_CONTENT_MESSAGE = "Same mod configuration was found. Not updating CSV content.";
private static final String UNEQUAL_CONTENT_MESSAGE = "New mod configuration was found. Commencing exporting.";
private static final String CACHE_DISABLED_MESSAGE = "Cache is disabled. Commencing exporting.";
private static final String EXPORT_START_MESSAGE = "Item Exporting ( started )";
private static final String EXPORT_END_MESSAGE = "Item Exporting ( ended after %s ms)";
@Nonnull
private final File exportDirectory;
@Nonnull
private final Checker<List<ModContainer>> modChecker;
@Nonnull
private final ExportConfig config;
/**
* @param exportDirectory directory where the final CSV file will be exported to
* @param config configuration to manipulate the export process
*/
public ExportProcess( @Nonnull final File exportDirectory, @Nonnull final ExportConfig config )
{
this.exportDirectory = Preconditions.checkNotNull( exportDirectory );
this.config = Preconditions.checkNotNull( config );
this.modChecker = new ModListChecker( config );
}
/**
* Will check and export if various config settings will lead to exporting the CSV file.
*/
@Override
public void run()
{
// no priority to this thread
Thread.yield();
// logic when to cancel the export process
if( this.config.isForceRefreshEnabled() )
{
AELog.info( FORCE_REFRESH_MESSAGE );
}
else
{
if( this.config.isCacheEnabled() )
{
AELog.info( CACHE_ENABLED_MESSAGE );
final Loader loader = Loader.instance();
final List<ModContainer> mods = loader.getActiveModList();
if( this.modChecker.isEqual( mods ) == CheckType.EQUAL )
{
AELog.info( EQUAL_CONTENT_MESSAGE );
return;
}
else
{
AELog.info( UNEQUAL_CONTENT_MESSAGE );
}
}
else
{
AELog.info( CACHE_DISABLED_MESSAGE );
}
}
AELog.info( EXPORT_START_MESSAGE );
final Stopwatch watch = Stopwatch.createStarted();
final FMLControlledNamespacedRegistry<Item> itemRegistry = GameData.getItemRegistry();
final ExportMode mode = this.config.isAdditionalInformationEnabled() ? ExportMode.VERBOSE : ExportMode.MINIMAL;
final Exporter exporter = new MinecraftItemCSVExporter( this.exportDirectory, itemRegistry, mode );
exporter.export();
AELog.info( EXPORT_END_MESSAGE, watch.elapsed( TimeUnit.MILLISECONDS ) );
}
}
@@ -0,0 +1,35 @@
/*
* 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.services.export;
/**
* General purpose interface to define an export operation with side effects
*
* @author thatsIch
* @version rv3 - 19.08.2015
* @since rv3 19.08.2015
*/
interface Exporter
{
/**
* Will export something defined by the Exporter with side effects
*/
void export();
}
@@ -0,0 +1,129 @@
/*
* 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.services.export;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
/**
* Offers configuration switches for the user to change the export process
*
* @author thatsIch
* @version rv3 - 14.08.2015
* @since rv3 14.08.2015
*/
public final class ForgeExportConfig implements ExportConfig
{
private static final String GENERAL_CATEGORY = "general";
private static final String CACHE_CATEGORY = "cache";
private static final String EXPORT_ITEM_NAMES_KEY = "exportItemNames";
private static final boolean EXPORT_ITEM_NAMES_DEFAULT = true;
private static final String EXPORT_ITEM_NAMES_DESCRIPTION = "If true, all registered items will be exported containing the internal minecraft name and the localized name to actually find the item you are using. This also contains the item representation of the blocks, but are missing items, which are too much to display e.g. FMP.";
private static final String ENABLE_FORCE_REFRESH_KEY = "enableForceRefresh";
private static final boolean ENABLE_FORCE_REFRESH_DEFAULT = false;
private static final String ENABLE_FORCE_REFRESH_DESCRIPTION = "If true, the CSV exporting will always happen. This will not use the cache to reduce the computation.";
private static final String ENABLE_CACHE_KEY = "enableCache";
private static final boolean ENABLE_CACHE_DEFAULT = true;
private static final String ENABLE_CACHE_DESCRIPTION = "Caching can save processing time, if there are a lot of items.";
private static final String ENABLE_ADDITIONAL_INFO_KEY = "enableAdditionalInfo";
private static final boolean ENABLE_ADDITIONAL_INFO_DEFAULT = false;
private static final String ENABLE_ADDITIONAL_INFO_DESCRIPTION = "Will output more detailed information into the CSV like corresponding items";
private static final String DIGEST_KEY = "digest";
private static final String DIGEST_DEFAULT = "";
private static final String DIGEST_DESCRIPTION = "Digest of all the mods and versions to check if a re-export of the item names is required.";
private final boolean exportItemNamesEnabled;
private final boolean cacheEnabled;
private final boolean forceRefreshEnabled;
private final boolean additionalInformationEnabled;
private final String cache;
private final Configuration config;
/**
* Constructor using the configuration. Apparently there are some race conditions if constructing configurations on multiple file accesses
*
* @param config to be wrapped configuration.
*/
public ForgeExportConfig( @Nonnull final Configuration config )
{
this.config = Preconditions.checkNotNull( config );
this.exportItemNamesEnabled = this.config.getBoolean( EXPORT_ITEM_NAMES_KEY, GENERAL_CATEGORY, EXPORT_ITEM_NAMES_DEFAULT, EXPORT_ITEM_NAMES_DESCRIPTION );
this.cacheEnabled = this.config.getBoolean( ENABLE_CACHE_KEY, CACHE_CATEGORY, ENABLE_CACHE_DEFAULT, ENABLE_CACHE_DESCRIPTION );
this.additionalInformationEnabled = this.config.getBoolean( ENABLE_ADDITIONAL_INFO_KEY, GENERAL_CATEGORY, ENABLE_ADDITIONAL_INFO_DEFAULT, ENABLE_ADDITIONAL_INFO_DESCRIPTION );
this.cache = this.config.getString( DIGEST_KEY, CACHE_CATEGORY, DIGEST_DEFAULT, DIGEST_DESCRIPTION );
this.forceRefreshEnabled = this.config.getBoolean( ENABLE_FORCE_REFRESH_KEY, GENERAL_CATEGORY, ENABLE_FORCE_REFRESH_DEFAULT, ENABLE_FORCE_REFRESH_DESCRIPTION );
}
@Override
public boolean isExportingItemNamesEnabled()
{
return this.exportItemNamesEnabled;
}
@Override
public boolean isCacheEnabled()
{
return this.cacheEnabled;
}
@Override
public boolean isForceRefreshEnabled()
{
return this.forceRefreshEnabled;
}
@Override
public boolean isAdditionalInformationEnabled()
{
return this.additionalInformationEnabled;
}
@Override
public String getCache()
{
return this.cache;
}
@Override
public void setCache( @Nonnull final String digest )
{
final Property digestProperty = this.config.get( CACHE_CATEGORY, DIGEST_KEY, DIGEST_DEFAULT );
digestProperty.set( digest );
this.config.save();
}
@Override
public void save()
{
this.config.save();
}
}
@@ -0,0 +1,290 @@
/*
* 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.services.export;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.StatCollector;
import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry;
import appeng.core.AELog;
/**
* handles the exporting including processing, transformation and persisting the information
*
* @author thatsIch
* @version rv3 - 14.08.2015
* @since rv3 14.08.2015
*/
final class MinecraftItemCSVExporter implements Exporter
{
private static final String ITEM_CSV_FILE_NAME = "items.csv";
private static final String MINIMAL_HEADER = "Mod:Item:MetaData, Localized Name";
private static final String VERBOSE_HEADER = MINIMAL_HEADER + ", Unlocalized Name, Is Air?, Class Name";
private static final String EXPORT_SUCCESSFUL_MESSAGE = "Exported successfully %d items into %s";
private static final String EXPORT_UNSUCCESSFUL_MESSAGE = "Exporting was unsuccessful.";
@Nonnull
private final File exportDirectory;
@Nonnull
private final FMLControlledNamespacedRegistry<Item> itemRegistry;
@Nonnull
private final ExportMode mode;
/**
* @param exportDirectory directory of the resulting export file. Non-null required.
* @param itemRegistry the registry with minecraft items. Needs to be populated at that time, thus the exporting can only happen in init (pre-init is the
* phase when all items are determined)
* @param mode mode in which the export should be operated. Resulting CSV will change depending on this.
*/
MinecraftItemCSVExporter( @Nonnull final File exportDirectory, @Nonnull final FMLControlledNamespacedRegistry<Item> itemRegistry, @Nonnull final ExportMode mode )
{
this.exportDirectory = Preconditions.checkNotNull( exportDirectory );
Preconditions.checkArgument( !exportDirectory.isFile() );
this.itemRegistry = Preconditions.checkNotNull( itemRegistry );
this.mode = Preconditions.checkNotNull( mode );
}
@Override
public void export()
{
final Iterable<Item> items = this.itemRegistry.typeSafeIterable();
final List<Item> itemList = Lists.newArrayList( items );
final List<String> lines = Lists.transform( itemList, new ItemRowExtractFunction( this.itemRegistry, this.mode ) );
final Joiner newLineJoiner = Joiner.on( '\n' );
final Joiner newLineJoinerIgnoringNull = newLineJoiner.skipNulls();
final String joined = newLineJoinerIgnoringNull.join( lines );
final File file = new File( this.exportDirectory, ITEM_CSV_FILE_NAME );
try
{
FileUtils.forceMkdir( this.exportDirectory );
final Writer writer = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file ), Charset.forName("UTF-8") ) );
final String header = this.mode == ExportMode.MINIMAL ? MINIMAL_HEADER : VERBOSE_HEADER;
writer.write( header );
writer.write( "\n" );
writer.write( joined );
writer.flush();
writer.close();
AELog.info( EXPORT_SUCCESSFUL_MESSAGE, lines.size(), ITEM_CSV_FILE_NAME );
}
catch( final IOException e )
{
AELog.warning( EXPORT_UNSUCCESSFUL_MESSAGE );
AELog.error( e );
}
}
/**
* Extracts item name with meta and the display name
*/
private static final class TypeExtractFunction implements Function<ItemStack, String>
{
private static final String EXTRACTING_NULL_MESSAGE = "extracting type null";
private static final String EXTRACTING_ITEM_MESSAGE = "extracting type %s:%d";
@Nonnull
private final String itemName;
@Nonnull
private final ExportMode mode;
private TypeExtractFunction( @Nonnull final String itemName, @Nonnull final ExportMode mode )
{
this.itemName = Preconditions.checkNotNull( itemName );
Preconditions.checkArgument( !itemName.isEmpty() );
this.mode = Preconditions.checkNotNull( mode );
}
@Nullable
@Override
public String apply( @Nullable final ItemStack input )
{
if( input == null )
{
AELog.debug( EXTRACTING_NULL_MESSAGE );
return null;
}
else
{
AELog.debug( EXTRACTING_ITEM_MESSAGE, input.getDisplayName(), input.getItemDamage() );
}
final List<String> joinedBlockAttributes = Lists.newArrayListWithCapacity( 5 );
final int meta = input.getItemDamage();
final String metaName = this.itemName + ':' + meta;
final String localization = input.getDisplayName();
joinedBlockAttributes.add( metaName );
joinedBlockAttributes.add( localization );
if( this.mode == ExportMode.VERBOSE )
{
final Item item = input.getItem();
final String unlocalizedItem = input.getUnlocalizedName();
final Block block = Block.getBlockFromItem( item );
final boolean isBlock = !block.equals( Blocks.air );
final Class<? extends ItemStack> stackClass = input.getClass();
final String stackClassName = stackClass.getName();
joinedBlockAttributes.add( unlocalizedItem );
joinedBlockAttributes.add( Boolean.toString( isBlock ) );
joinedBlockAttributes.add( stackClassName );
}
final Joiner csvJoiner = Joiner.on( ", " );
final Joiner csvJoinerIgnoringNulls = csvJoiner.skipNulls();
return csvJoinerIgnoringNulls.join( joinedBlockAttributes );
}
}
/**
* transforms an item into a row representation of the CSV file
*/
private static final class ItemRowExtractFunction implements Function<Item, String>
{
/**
* this extension is required to apply the {@link StatCollector}
*/
private static final String LOCALIZATION_NAME_EXTENSION = ".name";
private static final String EXPORTING_NOTHING_MESSAGE = "Exporting nothing";
private static final String EXPORTING_SUBTYPES_MESSAGE = "Exporting input %s with subtypes: %b";
@Nonnull
private final FMLControlledNamespacedRegistry<Item> itemRegistry;
@Nonnull
private final ExportMode mode;
/**
* @param itemRegistry used to retrieve the name of the item
* @param mode extracts more or less information from item depending on mode
*/
ItemRowExtractFunction( @Nonnull final FMLControlledNamespacedRegistry<Item> itemRegistry, @Nonnull final ExportMode mode )
{
this.itemRegistry = Preconditions.checkNotNull( itemRegistry );
this.mode = Preconditions.checkNotNull( mode );
}
@Nullable
@Override
public String apply( @Nullable final Item input )
{
if( input == null )
{
AELog.debug( EXPORTING_NOTHING_MESSAGE );
return null;
}
else
{
AELog.debug( EXPORTING_SUBTYPES_MESSAGE, input.getUnlocalizedName(), input.getHasSubtypes() );
}
final String itemName = this.itemRegistry.getNameForObject( input );
final boolean hasSubtypes = input.getHasSubtypes();
if( hasSubtypes )
{
final CreativeTabs creativeTab = input.getCreativeTab();
final List<ItemStack> stacks = Lists.newArrayList();
// modifies the stacks list and adds the different sub types to it
try
{
input.getSubItems( input, creativeTab, stacks );
}
catch( final Exception ignored )
{
AELog.error( ignored );
// ignore if mods do bullshit in their code
return null;
}
// list can be empty, no clue why
if( stacks.isEmpty() )
{
return null;
}
final Joiner newLineJoiner = Joiner.on( '\n' );
final Joiner typeJoiner = newLineJoiner.skipNulls();
final List<String> transformedTypes = Lists.transform( stacks, new TypeExtractFunction( itemName, this.mode ) );
return typeJoiner.join( transformedTypes );
}
final List<String> joinedBlockAttributes = Lists.newArrayListWithCapacity( 5 );
final String unlocalizedItem = input.getUnlocalizedName();
final String localization = StatCollector.translateToLocal( unlocalizedItem + LOCALIZATION_NAME_EXTENSION );
joinedBlockAttributes.add( itemName );
joinedBlockAttributes.add( localization );
if( this.mode == ExportMode.VERBOSE )
{
final Block block = Block.getBlockFromItem( input );
final boolean isBlock = !block.equals( Blocks.air );
final Class<? extends Item> itemClass = input.getClass();
final String itemClassName = itemClass.getName();
joinedBlockAttributes.add( unlocalizedItem );
joinedBlockAttributes.add( Boolean.toString( isBlock ) );
joinedBlockAttributes.add( itemClassName );
}
final Joiner csvJoiner = Joiner.on( ", " );
final Joiner csvJoinerIgnoringNulls = csvJoiner.skipNulls();
return csvJoinerIgnoringNulls.join( joinedBlockAttributes );
}
}
}
@@ -0,0 +1,92 @@
/*
* 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.services.export;
import java.util.List;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import org.apache.commons.codec.digest.DigestUtils;
import cpw.mods.fml.common.ModContainer;
/**
* Checks the cached digest against the current mods including their versions.
* Use the config to manipulate the process
*
* @author thatsIch
* @version rv3 - 01.09.2015
* @since rv3 - 01.09.2015
*/
final class ModListChecker implements Checker<List<ModContainer>>
{
private final String configHashValue;
@Nonnull
private final ExportConfig config;
/**
* @param config uses the config to retrieve the old hash of the mod list
*/
ModListChecker( @Nonnull final ExportConfig config )
{
this.config = Preconditions.checkNotNull( config );
this.configHashValue = Preconditions.checkNotNull( config.getCache() );
}
/**
* Compiles a list of all mods and their versions to a digest which is updated, if it differs from the config. This is used to elevate the need to export
* the csv once again, if no change was detected.
*
* @param modContainers all mods and their versions to check if a difference exists between the current instance and the previous instance
*
* @return CheckType.EQUAL if no change was detected
*/
@Nonnull
@Override
public CheckType isEqual( @Nonnull final List<ModContainer> modContainers )
{
Preconditions.checkNotNull( modContainers );
final StringBuilder builder = new StringBuilder();
for( final ModContainer container : modContainers )
{
builder.append( container.getModId() );
builder.append( container.getVersion() );
}
final String allModsAndVersions = builder.toString();
final String hex = DigestUtils.md5Hex( allModsAndVersions );
if( hex.equals( this.configHashValue ) )
{
return CheckType.EQUAL;
}
else
{
this.config.setCache( hex );
return CheckType.UNEQUAL;
}
}
}
@@ -0,0 +1,33 @@
/*
* 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>.
*/
/**
* the export package is to export all the required information for recipes into a convenient CSV file
* often names are difficult to acquire without access to the internal names.
*
* To save from rescanning every start-up it can save a list of mods and their version
* and if only something changed, it requires to update the CSV.
*
* There is no explicit check if it was manually tempered
*
* @author thatsIch
* @version rv3 - 14.08.2015
* @since rv3 14.08.2015
*/
package appeng.services.export;
@@ -65,7 +65,7 @@ public final class VersionCheckerConfig
this.shouldPostChangelog = this.config.getBoolean( "changelog", "client", true, "If true, the player is getting a notification including changelog. Only happens if notification are enabled." );
}
public boolean isEnabled()
public boolean isVersionCheckingEnabled()
{
return this.isEnabled;
}
@@ -76,8 +76,7 @@ public final class VersionCheckerConfig
}
/**
* Stores the current date in milli seconds into the "lastCheck" field of the config
* and makes it persistent.
* Stores the current date in milli seconds into the "lastCheck" field of the config and makes it persistent.
*/
public void updateLastCheck()
{
@@ -109,4 +108,12 @@ public final class VersionCheckerConfig
{
return this.shouldPostChangelog;
}
public void save()
{
if( this.config.hasChanged() )
{
this.config.save();
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
* 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
@@ -23,6 +23,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Vec3;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.WorldChunkManagerHell;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
@@ -32,6 +33,7 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import appeng.client.render.SpatialSkyRender;
import appeng.core.AppEng;
import appeng.core.Registration;
@@ -46,7 +48,11 @@ public class StorageWorldProvider extends WorldProvider
@Override
protected void registerWorldChunkManager()
{
super.worldChunkMgr = new WorldChunkManagerHell( Registration.INSTANCE.storageBiome, 0.0F );
final AppEng ae2internal = AppEng.instance();
final Registration ae2registration = ae2internal.getRegistration();
final BiomeGenBase storageBiome = ae2registration.getStorageBiome();
super.worldChunkMgr = new WorldChunkManagerHell( storageBiome, 0.0F );
}
@Override
@@ -0,0 +1,179 @@
/*
* 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.util.item;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.Nonnull;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
/**
* An unsorted {@link IItemList} providing constant access time instead of logarithmic time.
*
* As tradeoff it will no longer support fuzzy operations.
* Also no advanced features like storing craftable or requestable items is supported.
*
*/
public final class UnsortedItemList implements IItemList<IAEItemStack>
{
/**
* {@link Predicate} to filter all meaningful entries with {@link Iterators}
*/
private static final Predicate<IAEItemStack> MEANINGFUL_PREDICATE = new Predicate<IAEItemStack>()
{
@Override
public boolean apply( @Nonnull IAEItemStack input )
{
return input.isMeaningful();
}
};
private final Map<IAEItemStack, IAEItemStack> records = new HashMap<IAEItemStack, IAEItemStack>();
@Override
public void add( IAEItemStack option )
{
if( option == null )
{
return;
}
final IAEItemStack st = this.records.get( option );
if( st != null )
{
st.add( option );
return;
}
final IAEItemStack opt = option.copy();
this.records.put( opt, opt );
}
@Override
public IAEItemStack findPrecise( IAEItemStack itemStack )
{
if( itemStack == null )
{
return null;
}
return this.records.get( itemStack );
}
@Override
public boolean isEmpty()
{
return !this.iterator().hasNext();
}
@Override
public int size()
{
return this.records.size();
}
@Override
public Iterator<IAEItemStack> iterator()
{
return Iterators.filter( this.records.values().iterator(), MEANINGFUL_PREDICATE );
}
@Override
public IAEItemStack getFirstItem()
{
for( final IAEItemStack stackType : this )
{
return stackType;
}
return null;
}
@Override
public void resetStatus()
{
for( final IAEItemStack i : this )
{
i.reset();
}
}
/**
* Unsupported due to being a unsorted collection and thus only solvable in linear or worse time.
*
* @deprecated to indicate this method is unsupported.
*/
@Override
@Deprecated
public Collection<IAEItemStack> findFuzzy( IAEItemStack filter, FuzzyMode fuzzy )
{
throw new UnsupportedOperationException( "Unsupported on an unsorted collection" );
}
/**
* Unsupported to avoid being used as anything but a plain collection to store real item stacks.
*
* @deprecated to indicate this method is unsupported.
*/
@Override
@Deprecated
public void addStorage( IAEItemStack option )
{
throw new UnsupportedOperationException( "Purely designed for item storage" );
}
/**
* Unsupported to avoid being used as anything but a plain collection to store real item stacks.
*
* @deprecated to indicate this method is unsupported.
*/
@Override
@Deprecated
public void addCrafting( IAEItemStack option )
{
throw new UnsupportedOperationException( "Purely designed for item storage" );
}
/**
* Unsupported to avoid being used as anything but a plain collection to store real item stacks.
*
* @deprecated to indicate this method is unsupported.
*/
@Override
@Deprecated
public void addRequestable( IAEItemStack option )
{
throw new UnsupportedOperationException( "Purely designed for item storage" );
}
}
@@ -177,6 +177,9 @@ gui.appliedenergistics2.Crafts=Crafts
gui.appliedenergistics2.And=and
gui.appliedenergistics2.Creates=Creates
gui.appliedenergistics2.With=with
gui.appliedenergistics2.Substitute=Using Substitutions:
gui.appliedenergistics2.Yes=Yes
gui.appliedenergistics2.No=No
gui.appliedenergistics2.InWorldCrafting=AE2 In World Crafting
gui.appliedenergistics2.inWorldFluix=Drop 1 Charged Certus Quartz + 1 Nether Quartz + Redstone Dust into a puddle next to one another and wait a moment to receive 2 Fluix Crystals.
gui.appliedenergistics2.inWorldPurificationCertus=Drop a Certus Quartz Seed made from Certus Quartz Dust and Sand into a puddle of water; to make the process faster add Crystal Growth Accelerators.
@@ -234,7 +237,8 @@ gui.appliedenergistics2.Nothing=Nothing
gui.tooltips.appliedenergistics2.Stash=Store Items
gui.tooltips.appliedenergistics2.StashDesc=Return items on the crafting grid to network storage.
gui.tooltips.appliedenergistics2.Substitutions=Ore-Dict Substitutions
gui.tooltips.appliedenergistics2.SubstitutionsDesc=Edit substitution options for input components.
gui.tooltips.appliedenergistics2.SubstitutionsDescEnabled=Allow substitutions of input components.
gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=Prevent substitutions of input components.
gui.tooltips.appliedenergistics2.SubstitutionsOn=Substitutions Enabled
gui.tooltips.appliedenergistics2.SubstitutionsOff=Substitutions Disabled
gui.tooltips.appliedenergistics2.Encode=Encode Pattern
@@ -1,6 +1,6 @@
import=processing/factorization.recipe
import=processing/grind.recipe
import=processing/hydralicraft.recipe
import=processing/hydraulicraft.recipe
import=processing/ic2.recipe
import=processing/mekanism.recipe
import=processing/rotarycraft.recipe
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB