diff --git a/src/api/java/appeng/api/features/IInscriberRecipe.java b/src/api/java/appeng/api/features/IInscriberRecipe.java new file mode 100644 index 000000000..04c8161e0 --- /dev/null +++ b/src/api/java/appeng/api/features/IInscriberRecipe.java @@ -0,0 +1,65 @@ +package appeng.api.features; + + +import java.util.List; +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + +import com.google.common.base.Optional; + + +/** + * Registration Records for {@link IInscriberRegistry} + * + * You have to pay attention though, that recipes are not mirrored, + * where the top and bottom slots are switching places. + * + * This is applied on runtime. + * + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public interface IInscriberRecipe +{ + /** + * the current inputs + * + * @return inputs the inscriber will accept + */ + @Nonnull + List getInputs(); + + /** + * gets the current output + * + * @return output that the recipe will produce + */ + @Nonnull + ItemStack getOutput(); + + /** + * gets the top optional + * + * @return item which is used top + */ + @Nonnull + Optional getTopOptional(); + + /** + * gets the bottom optional + * + * @return item which is used bottom + */ + @Nonnull + Optional getBottomOptional(); + + /** + * type of inscriber process + * + * @return type of process the inscriber is doing + */ + @Nonnull + InscriberProcessType getProcessType(); +} diff --git a/src/api/java/appeng/api/features/IInscriberRecipeBuilder.java b/src/api/java/appeng/api/features/IInscriberRecipeBuilder.java new file mode 100644 index 000000000..43c3fa3e4 --- /dev/null +++ b/src/api/java/appeng/api/features/IInscriberRecipeBuilder.java @@ -0,0 +1,88 @@ +package appeng.api.features; + + +import java.util.Collection; +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + + +/** + * Builder for an inscriber recipe + * + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public interface IInscriberRecipeBuilder +{ + /** + * Creates an inscriber recipe with inputs. + * Needs to be invoked. + * + * @param inputs new inputs for the recipe + * + * @return currently used builder + */ + @Nonnull + IInscriberRecipeBuilder withInputs( @Nonnull Collection inputs ); + + /** + * Creates an inscriber recipe with output. + * Needs to be invoked. + * + * @param output new output for the recipe + * + * @return currently used builder + */ + @Nonnull + IInscriberRecipeBuilder withOutput( @Nonnull ItemStack output ); + + /** + * Creates an inscriber recipe with top. + * Either this or bot needs to be invoked. + * + * @param topOptional new top for the recipe + * + * @return currently used builder + */ + @Nonnull + IInscriberRecipeBuilder withTopOptional( @Nonnull ItemStack topOptional ); + + /** + * Creates an inscriber recipe with bot. + * Either this or top needs to be invoked. + * + * @param bottomOptional new bot for the recipe + * + * @return currently used builder + */ + @Nonnull + IInscriberRecipeBuilder withBottomOptional( @Nonnull ItemStack bottomOptional ); + + /** + * Creates an inscriber recipe with type. + * Needs to be invoked. + * + * @param type new type for the recipe + * + * @return currently used builder + */ + @Nonnull + IInscriberRecipeBuilder withProcessType( @Nonnull InscriberProcessType type ); + + /** + * Finalizes the process of making the recipe. + * Needs to be invoked to fetch inscriber recipe. + * + * @return legal inscriber recipe + * + * @throws IllegalStateException when input is not defined + * @throws IllegalStateException when input has no size + * @throws IllegalStateException when output is not defined + * @throws IllegalStateException when both optionals are not defined + * @throws IllegalStateException when process type is not defined + */ + @Nonnull + IInscriberRecipe build(); +} diff --git a/src/api/java/appeng/api/features/IInscriberRegistry.java b/src/api/java/appeng/api/features/IInscriberRegistry.java new file mode 100644 index 000000000..0d535e78f --- /dev/null +++ b/src/api/java/appeng/api/features/IInscriberRegistry.java @@ -0,0 +1,69 @@ +package appeng.api.features; + + +import java.util.List; +import java.util.Set; +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + + +/** + * Lets you manipulate Inscriber Recipes, by adding or editing existing ones. + * + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public interface IInscriberRegistry +{ + /** + * Current list of registered recipes, you can modify this if you want too. + * Will never contain a null recipe + * + * @return currentlyRegisteredRecipes + */ + @Nonnull + List getRecipes(); + + /** + * Optional items which are used in the top or bottom slot + * + * @return set of all optional items + */ + @Nonnull + Set getOptionals(); + + /** + * Get all registered items which are valid inputs + * + * @return set of all input items + */ + @Nonnull + Set getInputs(); + + /** + * Extensible way to create an inscriber recipe + * + * @return builder for inscriber recipes + */ + @Nonnull + IInscriberRecipeBuilder builder(); + + /** + * add a new recipe the easy way, duplicates will not be added. + * Added recipes will be automatically added to the optionals and inputs. + * + * @param recipe new recipe + * + * @throws IllegalArgumentException if null is added + */ + void addRecipe( IInscriberRecipe recipe ); + + /** + * Removes a recipe from the registry + * + * @param toBeRemovedRecipe to be removed recipe, can be null, makes just no sense + */ + void removeRecipe( IInscriberRecipe toBeRemovedRecipe ); +} diff --git a/src/api/java/appeng/api/features/IRegistryContainer.java b/src/api/java/appeng/api/features/IRegistryContainer.java index 19f1607c8..9b3a7e103 100644 --- a/src/api/java/appeng/api/features/IRegistryContainer.java +++ b/src/api/java/appeng/api/features/IRegistryContainer.java @@ -30,6 +30,12 @@ import appeng.api.storage.ICellRegistry; import appeng.api.storage.IExternalStorageRegistry; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public interface IRegistryContainer { @@ -69,6 +75,11 @@ public interface IRegistryContainer */ IGrinderRegistry grinder(); + /** + * Manage inscriber recipes via API + */ + IInscriberRegistry inscriber(); + /** * get access to the locatable registry */ diff --git a/src/api/java/appeng/api/features/InscriberProcessType.java b/src/api/java/appeng/api/features/InscriberProcessType.java new file mode 100644 index 000000000..70aaa9f7a --- /dev/null +++ b/src/api/java/appeng/api/features/InscriberProcessType.java @@ -0,0 +1,15 @@ +package appeng.api.features; + + +public enum InscriberProcessType +{ + /** + * uses the optionals as catalyst + */ + Inscribe, + + /** + * spends the optionals + */ + Press +} diff --git a/src/main/java/appeng/client/render/blocks/RenderBlockInscriber.java b/src/main/java/appeng/client/render/blocks/RenderBlockInscriber.java index 92502d748..1a0ab2e54 100644 --- a/src/main/java/appeng/client/render/blocks/RenderBlockInscriber.java +++ b/src/main/java/appeng/client/render/blocks/RenderBlockInscriber.java @@ -36,18 +36,24 @@ import net.minecraft.world.IBlockAccess; import net.minecraftforge.client.IItemRenderer.ItemRenderType; import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.features.IInscriberRecipe; import appeng.api.util.IOrientable; import appeng.block.AEBaseBlock; import appeng.block.misc.BlockInscriber; import appeng.client.render.BaseBlockRender; import appeng.client.texture.ExtraBlockTextures; import appeng.core.AELog; -import appeng.recipes.handlers.Inscribe.InscriberRecipe; import appeng.tile.AEBaseTile; import appeng.tile.misc.TileInscriber; import appeng.util.Platform; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class RenderBlockInscriber extends BaseBlockRender { @@ -225,9 +231,9 @@ public class RenderBlockInscriber extends BaseBlockRender if( is == null ) { - InscriberRecipe ir = inv.getTask(); + IInscriberRecipe ir = inv.getTask(); if( ir != null ) - is = ir.output.copy(); + is = ir.getOutput().copy(); } this.renderItem( is, 0.0f, block, tile, tess, x, y, z, f, renderer ); diff --git a/src/main/java/appeng/container/implementations/ContainerInscriber.java b/src/main/java/appeng/container/implementations/ContainerInscriber.java index 6870e219c..94832a0ab 100644 --- a/src/main/java/appeng/container/implementations/ContainerInscriber.java +++ b/src/main/java/appeng/container/implementations/ContainerInscriber.java @@ -25,16 +25,21 @@ import net.minecraft.item.ItemStack; import appeng.api.AEApi; import appeng.api.definitions.IItemDefinition; +import appeng.api.features.IInscriberRecipe; import appeng.container.guisync.GuiSync; import appeng.container.interfaces.IProgressProvider; import appeng.container.slot.SlotOutput; import appeng.container.slot.SlotRestrictedInput; -import appeng.recipes.handlers.Inscribe; -import appeng.recipes.handlers.Inscribe.InscriberRecipe; import appeng.tile.misc.TileInscriber; import appeng.util.Platform; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class ContainerInscriber extends ContainerUpgradeable implements IProgressProvider { @@ -105,32 +110,32 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres @Override public boolean isValidForSlot( Slot s, ItemStack is ) { - ItemStack PlateA = this.ti.getStackInSlot( 0 ); - ItemStack PlateB = this.ti.getStackInSlot( 1 ); + ItemStack top = this.ti.getStackInSlot( 0 ); + ItemStack bot = this.ti.getStackInSlot( 1 ); if( s == this.middle ) { - for( ItemStack i : Inscribe.PLATES ) + for( ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() ) { - if( Platform.isSameItemPrecise( i, is ) ) + if( Platform.isSameItemPrecise( optional, is ) ) return false; } boolean matches = false; boolean found = false; - for( InscriberRecipe i : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { - boolean matchA = ( PlateA == null && i.plateA == null ) || ( Platform.isSameItemPrecise( PlateA, i.plateA ) ) && // and... - ( PlateB == null && i.plateB == null ) | ( Platform.isSameItemPrecise( PlateB, i.plateB ) ); + boolean matchA = ( top == null && !recipe.getTopOptional().isPresent() ) || ( Platform.isSameItemPrecise( top, recipe.getTopOptional().orNull() ) ) && // and... + ( bot == null && !recipe.getBottomOptional().isPresent() ) | ( Platform.isSameItemPrecise( bot, recipe.getBottomOptional().orNull() ) ); - boolean matchB = ( PlateB == null && i.plateA == null ) || ( Platform.isSameItemPrecise( PlateB, i.plateA ) ) && // and... - ( PlateA == null && i.plateB == null ) | ( Platform.isSameItemPrecise( PlateA, i.plateB ) ); + boolean matchB = ( bot == null && !recipe.getTopOptional().isPresent() ) || ( Platform.isSameItemPrecise( bot, recipe.getTopOptional().orNull() ) ) && // and... + ( top == null && !recipe.getBottomOptional().isPresent() ) | ( Platform.isSameItemPrecise( top, recipe.getBottomOptional().orNull() ) ); if( matchA || matchB ) { matches = true; - for( ItemStack option : i.imprintable ) + for( ItemStack option : recipe.getInputs() ) { if( Platform.isSameItemPrecise( is, option ) ) found = true; @@ -142,7 +147,7 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres return false; } - if( ( s == this.top && PlateB != null ) || ( s == this.bottom && PlateA != null ) ) + if( ( s == this.top && bot != null ) || ( s == this.bottom && top != null ) ) { boolean isValid = false; ItemStack otherSlot = null; @@ -159,15 +164,15 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres } // everything else - for( InscriberRecipe i : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { - if( Platform.isSameItemPrecise( i.plateA, otherSlot ) ) + if( Platform.isSameItemPrecise( recipe.getTopOptional().orNull(), otherSlot ) ) { - isValid = Platform.isSameItemPrecise( is, i.plateB ); + isValid = Platform.isSameItemPrecise( is, recipe.getBottomOptional().orNull() ); } - else if( Platform.isSameItemPrecise( i.plateB, otherSlot ) ) + else if( Platform.isSameItemPrecise( recipe.getBottomOptional().orNull(), otherSlot ) ) { - isValid = Platform.isSameItemPrecise( is, i.plateA ); + isValid = Platform.isSameItemPrecise( is, recipe.getTopOptional().orNull() ); } if( isValid ) diff --git a/src/main/java/appeng/container/slot/SlotRestrictedInput.java b/src/main/java/appeng/container/slot/SlotRestrictedInput.java index 96a3661d0..8ada89653 100644 --- a/src/main/java/appeng/container/slot/SlotRestrictedInput.java +++ b/src/main/java/appeng/container/slot/SlotRestrictedInput.java @@ -42,10 +42,15 @@ import appeng.api.implementations.items.IUpgradeModule; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.storage.ICellWorkbenchItem; import appeng.items.misc.ItemEncodedPattern; -import appeng.recipes.handlers.Inscribe; import appeng.util.Platform; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class SlotRestrictedInput extends AppEngSlot { @@ -144,8 +149,8 @@ public class SlotRestrictedInput extends AppEngSlot return true; } - for( ItemStack is : Inscribe.PLATES ) - if( Platform.isSameItemPrecise( is, i ) ) + for( ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() ) + if( Platform.isSameItemPrecise( optional, i ) ) return true; return false; diff --git a/src/main/java/appeng/core/features/registries/InscriberRegistry.java b/src/main/java/appeng/core/features/registries/InscriberRegistry.java new file mode 100644 index 000000000..a0ab71254 --- /dev/null +++ b/src/main/java/appeng/core/features/registries/InscriberRegistry.java @@ -0,0 +1,170 @@ +package appeng.core.features.registries; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + +import appeng.api.features.IInscriberRecipe; +import appeng.api.features.IInscriberRecipeBuilder; +import appeng.api.features.IInscriberRegistry; +import appeng.api.features.InscriberProcessType; +import appeng.core.features.registries.entries.InscriberRecipe; + + +/** + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public final class InscriberRegistry implements IInscriberRegistry +{ + private final List recipes; + private final Set optionals; + private final Set inputs; + + public InscriberRegistry() + { + this.inputs = new HashSet(); + this.optionals = new HashSet(); + this.recipes = new ArrayList(); + } + + @Nonnull + @Override + public List getRecipes() + { + return this.recipes; + } + + @Nonnull + @Override + public Set getOptionals() + { + return this.optionals; + } + + @Nonnull + @Override + public Set getInputs() + { + return this.inputs; + } + + @Nonnull + @Override + public IInscriberRecipeBuilder builder() + { + return new Builder(); + } + + @Override + public void addRecipe( IInscriberRecipe recipe ) + { + if( recipe == null ) + throw new IllegalArgumentException( "Tried to add an invalid (null) inscriber recipe to the registry." ); + + this.recipes.add( recipe ); + + this.optionals.addAll( recipe.getTopOptional().asSet() ); + this.optionals.addAll( recipe.getBottomOptional().asSet() ); + + this.inputs.addAll( recipe.getInputs() ); + } + + @Override + public void removeRecipe( IInscriberRecipe toBeRemovedRecipe ) + { + for( final Iterator iterator = this.recipes.iterator(); iterator.hasNext(); ) + { + final IInscriberRecipe recipe = iterator.next(); + if( recipe.equals( toBeRemovedRecipe ) ) + { + iterator.remove(); + } + } + } + + /** + * Internal {@link IInscriberRecipeBuilder} implementation. + * Needs to be adapted to represent a correct {@link IInscriberRecipe} + */ + private static final class Builder implements IInscriberRecipeBuilder + { + private List inputs; + private ItemStack output; + private ItemStack topOptional; + private ItemStack bottomOptional; + private InscriberProcessType type; + + @Nonnull + @Override + public Builder withInputs( @Nonnull Collection inputs ) + { + this.inputs = new ArrayList( inputs.size() ); + this.inputs.addAll( inputs ); + + return this; + } + + @Nonnull + @Override + public Builder withOutput( @Nonnull ItemStack output ) + { + this.output = output; + + return this; + } + + @Nonnull + @Override + public Builder withTopOptional( @Nonnull ItemStack topOptional ) + { + this.topOptional = topOptional; + + return this; + } + + @Nonnull + @Override + public Builder withBottomOptional( @Nonnull ItemStack bottomOptional ) + { + this.bottomOptional = bottomOptional; + + return this; + } + + @Nonnull + @Override + public Builder withProcessType( @Nonnull InscriberProcessType type ) + { + this.type = type; + + return this; + } + + @Nonnull + @Override + public IInscriberRecipe build() + { + if( this.inputs == null ) + throw new IllegalStateException( "Input must be defined." ); + if( this.inputs.size() == 0 ) + throw new IllegalStateException( "Input must have a size." ); + if( this.output == null ) + throw new IllegalStateException( "Output must be defined." ); + if ( this.topOptional == null && this.bottomOptional == null ) + throw new IllegalStateException( "One optional must be defined." ); + if ( this.type == null ) + throw new IllegalStateException( "Process type must be defined." ); + + return new InscriberRecipe( this.inputs, this.output, this.topOptional, this.bottomOptional, this.type ); + } + } +} diff --git a/src/main/java/appeng/core/features/registries/RegistryContainer.java b/src/main/java/appeng/core/features/registries/RegistryContainer.java index 3150ae736..1ec2e6612 100644 --- a/src/main/java/appeng/core/features/registries/RegistryContainer.java +++ b/src/main/java/appeng/core/features/registries/RegistryContainer.java @@ -20,6 +20,7 @@ package appeng.core.features.registries; import appeng.api.features.IGrinderRegistry; +import appeng.api.features.IInscriberRegistry; import appeng.api.features.ILocatableRegistry; import appeng.api.features.IMatterCannonAmmoRegistry; import appeng.api.features.IP2PTunnelRegistry; @@ -35,74 +36,88 @@ import appeng.api.storage.ICellRegistry; import appeng.api.storage.IExternalStorageRegistry; +/** + * represents all registries + * + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class RegistryContainer implements IRegistryContainer { - - private final GrinderRecipeManager GrinderRecipes = new GrinderRecipeManager(); - private final ExternalStorageRegistry ExternalStorageHandlers = new ExternalStorageRegistry(); - private final CellRegistry CellRegistry = new CellRegistry(); - private final LocatableRegistry LocatableRegistry = new LocatableRegistry(); - private final SpecialComparisonRegistry SpecialComparisonRegistry = new SpecialComparisonRegistry(); - private final WirelessRegistry WirelessRegistry = new WirelessRegistry(); - private final GridCacheRegistry GridCacheRegistry = new GridCacheRegistry(); - private final P2PTunnelRegistry P2PRegistry = new P2PTunnelRegistry(); - private final MovableTileRegistry MovableReg = new MovableTileRegistry(); - private final MatterCannonAmmoRegistry matterCannonReg = new MatterCannonAmmoRegistry(); - private final PlayerRegistry playerRegistry = new PlayerRegistry(); + private final IGrinderRegistry grinder = new GrinderRecipeManager(); + private final IInscriberRegistry inscriber = new InscriberRegistry(); + private final IExternalStorageRegistry storage = new ExternalStorageRegistry(); + private final ICellRegistry cell = new CellRegistry(); + private final ILocatableRegistry locatable = new LocatableRegistry(); + private final ISpecialComparisonRegistry comparison = new SpecialComparisonRegistry(); + private final IWirelessTermRegistry wireless = new WirelessRegistry(); + private final IGridCacheRegistry gridCache = new GridCacheRegistry(); + private final IP2PTunnelRegistry p2ptunnel = new P2PTunnelRegistry(); + private final IMovableRegistry movable = new MovableTileRegistry(); + private final IMatterCannonAmmoRegistry matterCannonReg = new MatterCannonAmmoRegistry(); + private final IPlayerRegistry playerRegistry = new PlayerRegistry(); private final IRecipeHandlerRegistry recipeReg = new RecipeHandlerRegistry(); @Override public IMovableRegistry movable() { - return this.MovableReg; + return this.movable; } @Override public IGridCacheRegistry gridCache() { - return this.GridCacheRegistry; + return this.gridCache; } @Override public IExternalStorageRegistry externalStorage() { - return this.ExternalStorageHandlers; + return this.storage; } @Override public ISpecialComparisonRegistry specialComparison() { - return this.SpecialComparisonRegistry; + return this.comparison; } @Override public IWirelessTermRegistry wireless() { - return this.WirelessRegistry; + return this.wireless; } @Override public ICellRegistry cell() { - return this.CellRegistry; + return this.cell; } @Override public IGrinderRegistry grinder() { - return this.GrinderRecipes; + return this.grinder; + } + + @Override + public IInscriberRegistry inscriber() + { + return this.inscriber; } @Override public ILocatableRegistry locatable() { - return this.LocatableRegistry; + return this.locatable; } @Override public IP2PTunnelRegistry p2pTunnel() { - return this.P2PRegistry; + return this.p2ptunnel; } @Override diff --git a/src/main/java/appeng/core/features/registries/entries/InscriberInscribeRecipe.java b/src/main/java/appeng/core/features/registries/entries/InscriberInscribeRecipe.java new file mode 100644 index 000000000..412f8a3c7 --- /dev/null +++ b/src/main/java/appeng/core/features/registries/entries/InscriberInscribeRecipe.java @@ -0,0 +1,26 @@ +package appeng.core.features.registries.entries; + + +import java.util.Collection; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; + +import appeng.api.features.InscriberProcessType; + + +/** + * inscribe recipes do not use up the provided optional upon craft + * + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public class InscriberInscribeRecipe extends InscriberRecipe +{ + public InscriberInscribeRecipe( @Nonnull Collection inputs, @Nonnull ItemStack output, @Nullable ItemStack top, @Nullable ItemStack bot ) + { + super( inputs, output, top, bot, InscriberProcessType.Inscribe ); + } +} diff --git a/src/main/java/appeng/core/features/registries/entries/InscriberRecipe.java b/src/main/java/appeng/core/features/registries/entries/InscriberRecipe.java new file mode 100644 index 000000000..1ffadbde9 --- /dev/null +++ b/src/main/java/appeng/core/features/registries/entries/InscriberRecipe.java @@ -0,0 +1,120 @@ +package appeng.core.features.registries.entries; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; + +import com.google.common.base.Optional; + +import appeng.api.features.IInscriberRecipe; +import appeng.api.features.InscriberProcessType; + + +/** + * Basic inscriber recipe + * + * @author thatsIch + * @version rv2 + * @since rv2 + */ +public class InscriberRecipe implements IInscriberRecipe +{ + @Nonnull + private final List inputs; + + @Nonnull + private final ItemStack output; + + @Nonnull + private final Optional maybeTop; + + @Nonnull + private final Optional maybeBot; + + @Nonnull + private final InscriberProcessType type; + + public InscriberRecipe( @Nonnull Collection inputs, @Nonnull ItemStack output, @Nullable ItemStack top, @Nullable ItemStack bot, @Nonnull InscriberProcessType type ) + { + this.inputs = new ArrayList( inputs.size() ); + this.inputs.addAll( inputs ); + + this.output = output; + this.maybeTop = Optional.fromNullable( top ); + this.maybeBot = Optional.fromNullable( bot ); + + this.type = type; + } + + @Nonnull + @Override + public final List getInputs() + { + return this.inputs; + } + + @Nonnull + @Override + public final ItemStack getOutput() + { + return this.output; + } + + @Nonnull + @Override + public final Optional getTopOptional() + { + return this.maybeTop; + } + + @Nonnull + @Override + public final Optional getBottomOptional() + { + return this.maybeBot; + } + + @Nonnull + @Override + public final InscriberProcessType getProcessType() + { + return this.type; + } + + @Override + public boolean equals( Object o ) + { + if( this == o ) + return true; + if( !(o instanceof IInscriberRecipe) ) + return false; + + IInscriberRecipe that = (IInscriberRecipe) o; + + if( !this.inputs.equals( that.getInputs() ) ) + return false; + if( !this.output.equals( that.getOutput() ) ) + return false; + if( !this.maybeTop.equals( that.getTopOptional() ) ) + return false; + if( !this.maybeBot.equals( that.getBottomOptional()) ) + return false; + return this.type == that.getProcessType(); + } + + @Override + public int hashCode() + { + int result = this.inputs.hashCode(); + result = 31 * result + this.output.hashCode(); + result = 31 * result + this.maybeTop.hashCode(); + result = 31 * result + this.maybeBot.hashCode(); + result = 31 * result + this.type.hashCode(); + return result; + } +} diff --git a/src/main/java/appeng/integration/modules/NEIHelpers/NEIInscriberRecipeHandler.java b/src/main/java/appeng/integration/modules/NEIHelpers/NEIInscriberRecipeHandler.java index e01527f8b..b351ce708 100644 --- a/src/main/java/appeng/integration/modules/NEIHelpers/NEIInscriberRecipeHandler.java +++ b/src/main/java/appeng/integration/modules/NEIHelpers/NEIInscriberRecipeHandler.java @@ -36,15 +36,21 @@ import codechicken.nei.api.IOverlayHandler; import codechicken.nei.api.IRecipeOverlayRenderer; import codechicken.nei.recipe.TemplateRecipeHandler; +import appeng.api.AEApi; +import appeng.api.features.IInscriberRecipe; import appeng.client.gui.implementations.GuiInscriber; import appeng.core.localization.GuiText; -import appeng.recipes.handlers.Inscribe; -import appeng.recipes.handlers.Inscribe.InscriberRecipe; import static codechicken.lib.gui.GuiDraw.changeTexture; import static codechicken.lib.gui.GuiDraw.drawTexturedModalRect; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class NEIInscriberRecipeHandler extends TemplateRecipeHandler { @@ -59,7 +65,7 @@ public class NEIInscriberRecipeHandler extends TemplateRecipeHandler { if( ( outputId.equals( "inscriber" ) ) && ( this.getClass() == NEIInscriberRecipeHandler.class ) ) { - for( InscriberRecipe recipe : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { CachedInscriberRecipe cachedRecipe = new CachedInscriberRecipe( recipe ); cachedRecipe.computeVisuals(); @@ -75,9 +81,9 @@ public class NEIInscriberRecipeHandler extends TemplateRecipeHandler @Override public void loadCraftingRecipes( ItemStack result ) { - for( InscriberRecipe recipe : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { - if( NEIServerUtils.areStacksSameTypeCrafting( recipe.output, result ) ) + if( NEIServerUtils.areStacksSameTypeCrafting( recipe.getOutput(), result ) ) { CachedInscriberRecipe cachedRecipe = new CachedInscriberRecipe( recipe ); cachedRecipe.computeVisuals(); @@ -89,7 +95,7 @@ public class NEIInscriberRecipeHandler extends TemplateRecipeHandler @Override public void loadUsageRecipes( ItemStack ingredient ) { - for( InscriberRecipe recipe : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { CachedInscriberRecipe cachedRecipe = new CachedInscriberRecipe( recipe ); @@ -162,19 +168,22 @@ public class NEIInscriberRecipeHandler extends TemplateRecipeHandler public final ArrayList ingredients; public final PositionedStack result; - public CachedInscriberRecipe( InscriberRecipe recipe ) + public CachedInscriberRecipe( IInscriberRecipe recipe ) { - this.result = new PositionedStack( recipe.output, 108, 29 ); + this.result = new PositionedStack( recipe.getOutput(), 108, 29 ); this.ingredients = new ArrayList(); - if( recipe.plateA != null ) - this.ingredients.add( new PositionedStack( recipe.plateA, 40, 5 ) ); + for( ItemStack top : recipe.getTopOptional().asSet() ) + { + this.ingredients.add( new PositionedStack( top, 40, 5 ) ); + } - if( recipe.imprintable != null ) - this.ingredients.add( new PositionedStack( recipe.imprintable, 40 + 18, 28 ) ); + this.ingredients.add( new PositionedStack( recipe.getInputs(), 40 + 18, 28 ) ); - if( recipe.plateB != null ) - this.ingredients.add( new PositionedStack( recipe.plateB, 40, 51 ) ); + for( ItemStack bot : recipe.getBottomOptional().asSet() ) + { + this.ingredients.add( new PositionedStack( bot, 40, 51 ) ); + } } @Override diff --git a/src/main/java/appeng/recipes/RecipeHandler.java b/src/main/java/appeng/recipes/RecipeHandler.java index 8e06998ef..491ef0c78 100644 --- a/src/main/java/appeng/recipes/RecipeHandler.java +++ b/src/main/java/appeng/recipes/RecipeHandler.java @@ -30,6 +30,8 @@ import java.util.Map.Entry; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import javax.annotation.Nonnull; + import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -63,6 +65,12 @@ import appeng.recipes.handlers.IWebsiteSerializer; import appeng.recipes.handlers.OreRegistration; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class RecipeHandler implements IRecipeHandler { @@ -84,21 +92,18 @@ public class RecipeHandler implements IRecipeHandler this.data.Handlers.add( ch ); } - public String getName( IIngredient i ) + public String getName( @Nonnull IIngredient i ) { try { for( ItemStack is : i.getItemStackSet() ) { - try - { - return this.getName( is ); - } - catch( RecipeError ignored ) - { - } + return this.getName( is ); } } + catch( RecipeError ignored ) + { + } catch( Throwable t ) { t.printStackTrace(); diff --git a/src/main/java/appeng/recipes/handlers/Inscribe.java b/src/main/java/appeng/recipes/handlers/Inscribe.java index 58b767332..620a6b7fd 100644 --- a/src/main/java/appeng/recipes/handlers/Inscribe.java +++ b/src/main/java/appeng/recipes/handlers/Inscribe.java @@ -19,113 +19,48 @@ package appeng.recipes.handlers; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import net.minecraft.item.ItemStack; +import appeng.api.AEApi; import appeng.api.exceptions.MissingIngredientError; -import appeng.api.exceptions.RecipeError; import appeng.api.exceptions.RegistrationError; -import appeng.api.recipes.ICraftHandler; -import appeng.api.recipes.IIngredient; -import appeng.recipes.RecipeHandler; -import appeng.util.Platform; +import appeng.api.features.IInscriberRecipe; +import appeng.api.features.InscriberProcessType; +import appeng.core.features.registries.entries.InscriberRecipe; -public class Inscribe implements ICraftHandler, IWebsiteSerializer +/** + * recipe translation for inscribe process + * + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ +public final class Inscribe extends InscriberProcess { - - public static final HashSet PLATES = new HashSet(); - public static final HashSet INPUTS = new HashSet(); - public static final LinkedList RECIPES = new LinkedList(); - public boolean usePlates = false; - IIngredient imprintable; - IIngredient plateA; - IIngredient plateB; - IIngredient output; - - @Override - public void setup( List> input, List> output ) throws RecipeError - { - if( output.size() == 1 && output.get( 0 ).size() == 1 ) - { - if( input.size() == 1 && input.get( 0 ).size() > 1 ) - { - this.imprintable = input.get( 0 ).get( 0 ); - - this.plateA = input.get( 0 ).get( 1 ); - - if( input.get( 0 ).size() > 2 ) - this.plateB = input.get( 0 ).get( 2 ); - - this.output = output.get( 0 ).get( 0 ); - } - else - throw new RecipeError( "Inscriber recipes cannot have rows, and must have more then one input." ); - } - else - throw new RecipeError( "Inscriber recipes must produce a single output." ); - } - @Override public void register() throws RegistrationError, MissingIngredientError { - if( this.imprintable != null ) - Collections.addAll( INPUTS, this.imprintable.getItemStackSet() ); + if ( this.getImprintable() == null ) + return; + if ( this.getOutput() == null ) + return; - if( this.plateA != null ) - Collections.addAll( PLATES, this.plateA.getItemStackSet() ); + final ItemStack[] realInput = this.getImprintable().getItemStackSet(); + final List inputs = new ArrayList( realInput.length ); + Collections.addAll( inputs, realInput ); + final ItemStack top = (this.getTopOptional() == null) ? null : this.getTopOptional().getItemStack(); + final ItemStack bot = (this.getBotOptional() == null) ? null : this.getBotOptional().getItemStack(); + final ItemStack output = this.getOutput().getItemStack(); + final InscriberProcessType type = InscriberProcessType.Inscribe; - if( this.plateB != null ) - Collections.addAll( PLATES, this.plateB.getItemStackSet() ); + IInscriberRecipe recipe = new InscriberRecipe( inputs, output, top, bot, type ); - InscriberRecipe ir = new InscriberRecipe( this.imprintable.getItemStackSet(), this.plateA == null ? null : this.plateA.getItemStack(), this.plateB == null ? null : this.plateB.getItemStack(), this.output.getItemStack(), this.usePlates ); - RECIPES.add( ir ); - } - - @Override - public String getPattern( RecipeHandler h ) - { - String o = "inscriber " + this.output.getQty() + '\n'; - - o += h.getName( this.output ) + '\n'; - - if( this.plateA != null ) - o += h.getName( this.plateA ) + '\n'; - - o += h.getName( this.imprintable ); - - if( this.plateB != null ) - o += '\n' + h.getName( this.plateB ); - - return o; - } - - @Override - public boolean canCraft( ItemStack reqOutput ) throws RegistrationError, MissingIngredientError - { - return Platform.isSameItemPrecise( this.output.getItemStack(), reqOutput ); - } - - public static class InscriberRecipe - { - - public final boolean usePlates; - public final ItemStack plateA; - public final ItemStack[] imprintable; - public final ItemStack plateB; - public final ItemStack output; - - public InscriberRecipe( ItemStack[] imprintable, ItemStack plateA, ItemStack plateB, ItemStack out, boolean usePlates ) - { - this.imprintable = imprintable; - this.usePlates = usePlates; - this.plateA = plateA; - this.plateB = plateB; - this.output = out; - } + AEApi.instance().registries().inscriber().addRecipe( recipe ); } } diff --git a/src/main/java/appeng/recipes/handlers/InscriberProcess.java b/src/main/java/appeng/recipes/handlers/InscriberProcess.java new file mode 100644 index 000000000..8f8d2ed37 --- /dev/null +++ b/src/main/java/appeng/recipes/handlers/InscriberProcess.java @@ -0,0 +1,115 @@ +package appeng.recipes.handlers; + + +import java.util.List; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; + +import appeng.api.exceptions.MissingIngredientError; +import appeng.api.exceptions.RecipeError; +import appeng.api.exceptions.RegistrationError; +import appeng.api.recipes.ICraftHandler; +import appeng.api.recipes.IIngredient; +import appeng.recipes.RecipeHandler; +import appeng.util.Platform; + + +/** + * basic inscriber process for recipes + * + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ +public abstract class InscriberProcess implements ICraftHandler, IWebsiteSerializer +{ + @Nullable + private IIngredient imprintable; + + @Nullable + private IIngredient topOptional; + + @Nullable + private IIngredient botOptional; + + @Nullable + private IIngredient output; + + @Override + public void setup( List> input, List> output ) throws RecipeError + { + if( output.size() == 1 && output.get( 0 ).size() == 1 ) + { + if( input.size() == 1 && input.get( 0 ).size() > 1 ) + { + this.imprintable = input.get( 0 ).get( 0 ); + + this.topOptional = input.get( 0 ).get( 1 ); + + if( input.get( 0 ).size() > 2 ) + this.botOptional = input.get( 0 ).get( 2 ); + + this.output = output.get( 0 ).get( 0 ); + } + else + throw new RecipeError( "Inscriber recipes cannot have rows, and must have more then one input." ); + } + else + throw new RecipeError( "Inscriber recipes must produce a single output." ); + } + + @Override + public boolean canCraft( ItemStack reqOutput ) throws RegistrationError, MissingIngredientError + { + return this.output != null && Platform.isSameItemPrecise( this.output.getItemStack(), reqOutput ); + } + + @Override + public String getPattern( RecipeHandler handler ) + { + String pattern = "inscriber "; + + if ( this.output != null ) + { + pattern += this.output.getQty() + '\n'; + pattern += handler.getName( this.output ) + '\n'; + } + + if( this.topOptional != null ) + pattern += handler.getName( this.topOptional ) + '\n'; + + if ( this.imprintable != null ) + pattern += handler.getName( this.imprintable ); + + if( this.botOptional != null ) + pattern += '\n' + handler.getName( this.botOptional ); + + return pattern; + } + + @Nullable + protected IIngredient getImprintable() + { + return this.imprintable; + } + + @Nullable + protected IIngredient getTopOptional() + { + return this.topOptional; + } + + @Nullable + protected IIngredient getBotOptional() + { + return this.botOptional; + } + + @Nullable + protected IIngredient getOutput() + { + return this.output; + } +} diff --git a/src/main/java/appeng/recipes/handlers/Press.java b/src/main/java/appeng/recipes/handlers/Press.java index 9005ce076..5ccaceaeb 100644 --- a/src/main/java/appeng/recipes/handlers/Press.java +++ b/src/main/java/appeng/recipes/handlers/Press.java @@ -19,11 +19,48 @@ package appeng.recipes.handlers; -public class Press extends Inscribe -{ +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; - public Press() +import net.minecraft.item.ItemStack; + +import appeng.api.AEApi; +import appeng.api.exceptions.MissingIngredientError; +import appeng.api.exceptions.RegistrationError; +import appeng.api.features.IInscriberRecipe; +import appeng.api.features.InscriberProcessType; +import appeng.core.features.registries.entries.InscriberRecipe; + + +/** + * recipe translation for pressing in the inscriber + * + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ +public final class Press extends InscriberProcess +{ + @Override + public void register() throws RegistrationError, MissingIngredientError { - this.usePlates = true; + if ( this.getImprintable() == null ) + return; + if ( this.getOutput() == null ) + return; + + final ItemStack[] realInput = this.getImprintable().getItemStackSet(); + final List inputs = new ArrayList( realInput.length ); + Collections.addAll( inputs, realInput ); + final ItemStack top = ( this.getTopOptional() == null ) ? null : this.getTopOptional().getItemStack(); + final ItemStack bot = ( this.getBotOptional() == null ) ? null : this.getBotOptional().getItemStack(); + final ItemStack output = this.getOutput().getItemStack(); + final InscriberProcessType type = InscriberProcessType.Press; + + IInscriberRecipe recipe = new InscriberRecipe( inputs, output, top, bot, type ); + + AEApi.instance().registries().inscriber().addRecipe( recipe ); } } diff --git a/src/main/java/appeng/tile/misc/TileInscriber.java b/src/main/java/appeng/tile/misc/TileInscriber.java index 7ad3a48a6..72f65ed2b 100644 --- a/src/main/java/appeng/tile/misc/TileInscriber.java +++ b/src/main/java/appeng/tile/misc/TileInscriber.java @@ -22,6 +22,8 @@ package appeng.tile.misc; import java.io.IOException; import java.util.ArrayList; import java.util.EnumSet; +import java.util.List; +import javax.annotation.Nullable; import io.netty.buffer.ByteBuf; @@ -31,12 +33,16 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import com.google.common.collect.Lists; + import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.PowerMultiplier; import appeng.api.config.Upgrades; import appeng.api.definitions.IComparableDefinition; import appeng.api.definitions.ITileDefinition; +import appeng.api.features.IInscriberRecipe; +import appeng.api.features.InscriberProcessType; import appeng.api.implementations.IUpgradeableHost; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; @@ -46,13 +52,12 @@ import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickingRequest; import appeng.api.util.AECableType; import appeng.api.util.IConfigManager; +import appeng.core.features.registries.entries.InscriberRecipe; import appeng.core.settings.TickRates; import appeng.helpers.Reflected; import appeng.me.GridAccessException; import appeng.parts.automation.DefinitionUpgradeInventory; import appeng.parts.automation.UpgradeInventory; -import appeng.recipes.handlers.Inscribe; -import appeng.recipes.handlers.Inscribe.InscriberRecipe; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; import appeng.tile.grid.AENetworkPowerTile; @@ -66,6 +71,12 @@ import appeng.util.inv.WrapperInventoryRange; import appeng.util.item.AEItemStack; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, IUpgradeableHost, IConfigManagerHost { @@ -220,8 +231,8 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, return true; } - for( ItemStack s : Inscribe.PLATES ) - if( Platform.isSameItemPrecise( s, itemstack ) ) + for( ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() ) + if( Platform.isSameItemPrecise( optionals, itemstack ) ) return true; } @@ -286,7 +297,8 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, return this.smash; } - public InscriberRecipe getTask() + @Nullable + public IInscriberRecipe getTask() { ItemStack plateA = this.getStackInSlot( 0 ); ItemStack plateB = this.getStackInSlot( 1 ); @@ -337,25 +349,28 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, else display.removeTag( "Name" ); - return new InscriberRecipe( new ItemStack[] { startingItem }, plateA, plateB, renamedItem, false ); + final List inputs = Lists.newArrayList( startingItem ); + final InscriberProcessType type = InscriberProcessType.Inscribe; + + return new InscriberRecipe( inputs, renamedItem, plateA, plateB, type ); } } - for( InscriberRecipe i : Inscribe.RECIPES ) + for( IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) { - boolean matchA = ( plateA == null && i.plateA == null ) || ( Platform.isSameItemPrecise( plateA, i.plateA ) ) && // and... - ( plateB == null && i.plateB == null ) | ( Platform.isSameItemPrecise( plateB, i.plateB ) ); + boolean matchA = ( plateA == null && !recipe.getTopOptional().isPresent() ) || ( Platform.isSameItemPrecise( plateA, recipe.getTopOptional().orNull() ) ) && // and... + ( plateB == null && !recipe.getBottomOptional().isPresent() ) | ( Platform.isSameItemPrecise( plateB, recipe.getBottomOptional().orNull() ) ); - boolean matchB = ( plateB == null && i.plateA == null ) || ( Platform.isSameItemPrecise( plateB, i.plateA ) ) && // and... - ( plateA == null && i.plateB == null ) | ( Platform.isSameItemPrecise( plateA, i.plateB ) ); + boolean matchB = ( plateB == null && !recipe.getTopOptional().isPresent() ) || ( Platform.isSameItemPrecise( plateB, recipe.getTopOptional().orNull() ) ) && // and... + ( plateA == null && !recipe.getBottomOptional().isPresent() ) | ( Platform.isSameItemPrecise( plateA, recipe.getBottomOptional().orNull() ) ); if( matchA || matchB ) { - for( ItemStack option : i.imprintable ) + for( ItemStack option : recipe.getInputs() ) { if( Platform.isSameItemPrecise( option, this.getStackInSlot( 2 ) ) ) - return i; + return recipe; } } } @@ -367,21 +382,19 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, { if( this.smash ) { - this.finalStep++; if( this.finalStep == 8 ) { - - InscriberRecipe out = this.getTask(); + final IInscriberRecipe out = this.getTask(); if( out != null ) { - ItemStack is = out.output.copy(); + final ItemStack outputCopy = out.getOutput().copy(); InventoryAdaptor ad = InventoryAdaptor.getAdaptor( new WrapperInventoryRange( this.inv, 3, 1, true ), ForgeDirection.UNKNOWN ); - if( ad.addItems( is ) == null ) + if( ad.addItems( outputCopy ) == null ) { this.processingTime = 0; - if( out.usePlates ) + if( out.getProcessType() == InscriberProcessType.Press ) { this.setInventorySlotContents( 0, null ); this.setInventorySlotContents( 1, null ); @@ -437,12 +450,12 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, if( this.processingTime > this.maxProcessingTime ) { this.processingTime = this.maxProcessingTime; - InscriberRecipe out = this.getTask(); + IInscriberRecipe out = this.getTask(); if( out != null ) { - ItemStack is = out.output.copy(); + ItemStack outputCopy = out.getOutput().copy(); InventoryAdaptor ad = InventoryAdaptor.getAdaptor( new WrapperInventoryRange( this.inv, 3, 1, true ), ForgeDirection.UNKNOWN ); - if( ad.simulateAdd( is ) == null ) + if( ad.simulateAdd( outputCopy ) == null ) { this.smash = true; this.finalStep = 0; diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index e574653c5..a374f1d81 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -32,6 +32,8 @@ import java.util.Random; import java.util.Set; import java.util.WeakHashMap; +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Tessellator; @@ -140,6 +142,12 @@ import appeng.util.item.OreReference; import appeng.util.prioitylist.IPartitionList; +/** + * @author AlgorithmX2 + * @author thatsIch + * @version rv2 + * @since rv0 + */ public class Platform { @@ -1119,7 +1127,7 @@ public class Platform return StatCollector.translateToLocal( string ); } - public static boolean isSameItemPrecise( ItemStack is, ItemStack filter ) + public static boolean isSameItemPrecise( @Nullable ItemStack is, @Nullable ItemStack filter ) { return isSameItem( is, filter ) && sameStackStags( is, filter ); } @@ -1707,7 +1715,7 @@ public class Platform return false; } - public static boolean isSameItem( ItemStack left, ItemStack right ) + public static boolean isSameItem( @Nullable ItemStack left, @Nullable ItemStack right ) { return left != null && right != null && left.isItemEqual( right ); }