Compare commits

...

9 Commits

Author SHA1 Message Date
yueh c1197c0084 Updated to latest Forge RB. (#3250)
While this is not ideal for a stable release, switching to the latest RB
of Forge avoids the broken recipes in previous versions.
2017-11-26 15:46:38 +01:00
fscan f0d807f0a2 Rework ContainerInscriber validation (#3238)
* Correctly handle metadata wildcard for inscriber inputs
2017-11-26 15:46:02 +01:00
fscan 5fa2c0ab27 Deprecate AE2 recipe system. (#3247)
* Deprecate aerecipes to indicate that they are going away soon.
2017-11-26 15:45:34 +01:00
fscan 3063bd887c Revert DamageableRecipe changes (#3246)
Forge fixed this after all. This is no longer needed.
2017-11-26 15:44:56 +01:00
Florian Scandella fac4a8f9dc Fix typo 2017-11-26 14:38:09 +01:00
fscan 9d8226da19 Remove swingArm in IToolHammer implementation. (#3249)
Fixes #3248
2017-11-25 13:38:22 +01:00
yueh 33754d289d Fixes #932: Fire ExplosionEvent.Detonate when tiny TNT explodes. (#3229)
This still bypasses the start event to prevent it from ever being
cancelled.
2017-11-23 11:06:46 +01:00
fscan 959672dae3 Add CraftTweaker support (#3231) 2017-11-22 21:09:26 +01:00
fscan 90c17c09a8 Add custom recipe for damageable Ingredients (#3230) 2017-11-17 16:20:53 +01:00
31 changed files with 845 additions and 105 deletions
+52
View File
@@ -14,6 +14,7 @@
* [Building](#building) * [Building](#building)
* [Contribution](#contribution) * [Contribution](#contribution)
* [API](#applied-energistics-2-api) * [API](#applied-energistics-2-api)
* [CraftTweaker](#applied-energistics-2-crafttweaker)
* [Localization](#applied-energistics-2-localization) * [Localization](#applied-energistics-2-localization)
* [Credits](#credits) * [Credits](#credits)
@@ -154,6 +155,57 @@ Where the __ are filled in with the correct version criteria; AE2 is available f
An example string would be `appeng:appliedenergistics2:rv2-alpha-30:dev` An example string would be `appeng:appliedenergistics2:rv2-alpha-30:dev`
## Applied Energistics 2 CraftTweaker
### Inscriber
Add a recipe. When `inscribe` is true the bottom and top inputs are not consumed.
mods.appliedenergistics2.Inscriber.addRecipe(ItemStack output, ItemStack input, boolean inscribe,
@Optional ItemStack topInput, @Optional ItemStack bottomInput );
Remove all recipes for this output stack.
mods.appliedenergistics2.Inscriber.removeRecipe(ItemStack output);
### Grindstone
Add a recipe.
mods.appliedenergistics2.Grinder.addRecipe( ItemStack output, ItemStack input, int turns,
@Optional ItemStack secondary1Output, @Optional float secondary1Chance,
@Optional ItemStack secondary2Output, @Optional float secondary2Chance);
Remove recipes for this input.
mods.appliedenergistics2.Grinder.removeRecipe(ItemStack input);
### Spatial
Whitelist a TileEntity class for Spatial IO.
mods.appliedenergistics2.Spatial.whitelistEntity( String fullEntityClassName );
### Attunement
Attune a ItemStack or ModID to a specific P2P-Tunnel type. ModID's are used as fallback when no ItemStack was found.
mods.appliedenergistics2.Attunement.attuneME( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneME( String modID );
mods.appliedenergistics2.Attunement.attuneItem( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneItem( String modID );
mods.appliedenergistics2.Attunement.attuneFluid( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneFluid( String modID );
mods.appliedenergistics2.Attunement.attuneRedstone( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRedstone( String modID );
mods.appliedenergistics2.Attunement.attuneRF( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRF( String modID );
mods.appliedenergistics2.Attunement.attuneIC2( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneIC2( String modID );
mods.appliedenergistics2.Attunement.attuneLight( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneLight( String modID );
### Cannon
Add ammo types for the matter cannon.
mods.appliedenergistics2.Cannon.registerAmmo( ItemStack itemStack, double weight );
## Applied Energistics 2 Localization ## Applied Energistics 2 Localization
### English Text ### English Text
+1 -1
View File
@@ -9,7 +9,7 @@ aebasename=appliedenergistics2
######################################################### #########################################################
minecraft_version=1.12.2 minecraft_version=1.12.2
mcp_mappings=snapshot_20171003 mcp_mappings=snapshot_20171003
forge_version=14.23.0.2491 forge_version=14.23.1.2554
######################################################### #########################################################
# Installable # # Installable #
+6
View File
@@ -58,6 +58,11 @@ repositories {
name 'tehnut' name 'tehnut'
url "http://tehnut.info/maven" url "http://tehnut.info/maven"
} }
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
} }
configurations { configurations {
@@ -77,6 +82,7 @@ dependencies {
compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api" compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api"
compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api" compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api"
compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf" compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf"
compileOnly "CraftTweaker2:CraftTweaker2-API:4.+"
// at runtime, use the full JEI jar // at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}" runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -48,6 +48,7 @@ public interface IRecipeHandlerRegistry
* @param name name of crafthandler * @param name name of crafthandler
* @param handler class of crafthandler * @param handler class of crafthandler
*/ */
@Deprecated
void addNewCraftHandler( String name, Class<? extends ICraftHandler> handler ); void addNewCraftHandler( String name, Class<? extends ICraftHandler> handler );
/** /**
@@ -65,11 +66,13 @@ public interface IRecipeHandlerRegistry
* @return A recipe handler by name, returns null on failure. * @return A recipe handler by name, returns null on failure.
*/ */
@Nullable @Nullable
@Deprecated
ICraftHandler getCraftHandlerFor( String name ); ICraftHandler getCraftHandlerFor( String name );
/** /**
* @return a new recipe handler, which can be used to parse, and read recipe files. * @return a new recipe handler, which can be used to parse, and read recipe files.
*/ */
@Deprecated
IRecipeHandler createNewRecipehandler(); IRecipeHandler createNewRecipehandler();
/** /**
@@ -30,7 +30,7 @@ import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException; import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException; import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface ICraftHandler public interface ICraftHandler
{ {
@@ -29,7 +29,7 @@ import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException; import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException; import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface IIngredient public interface IIngredient
{ {
@@ -27,6 +27,7 @@ package appeng.api.recipes;
/** /**
* Represents the AE2 Recipe Loading/Reading Class * Represents the AE2 Recipe Loading/Reading Class
*/ */
@Deprecated
public interface IRecipeHandler public interface IRecipeHandler
{ {
@@ -28,7 +28,7 @@ import java.io.BufferedReader;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@Deprecated
public interface IRecipeLoader public interface IRecipeLoader
{ {
/** /**
@@ -92,7 +92,7 @@ public class GuiSpatialIOPort extends AEBaseGui
} }
else else
{ {
this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSSInvalid.getLocal(), 13, 93, 4210752 ); this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSInvalid.getLocal(), 13, 93, 4210752 );
} }
} }
@@ -120,28 +120,23 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
if( s == this.middle ) if( s == this.middle )
{ {
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() ) IItemDefinition press = AEApi.instance().definitions().materials().namePress();
if( press.isSameAs( top ) || press.isSameAs( bot ) )
{ {
if( Platform.itemComparisons().isSameItem( optional, is ) ) return !press.isSameAs( is );
{
return false;
}
} }
boolean matches = false; boolean matches = false;
boolean found = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{ {
final boolean matchA = ( top.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top, final boolean matchA = !top
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and... .isEmpty() && ( Platform.itemComparisons().isSameItem( top, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
( ( bot.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot, .itemComparisons()
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) ); .isSameItem( top, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
final boolean matchB = !bot
final boolean matchB = ( bot.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot, .isEmpty() && ( Platform.itemComparisons().isSameItem( bot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and... .itemComparisons()
( ( top.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top, .isSameItem( bot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
if( matchA || matchB ) if( matchA || matchB )
{ {
@@ -150,21 +145,19 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
{ {
if( Platform.itemComparisons().isSameItem( is, option ) ) if( Platform.itemComparisons().isSameItem( is, option ) )
{ {
found = true; return true;
} }
} }
} }
} }
if( matches )
if( matches && !found )
{ {
return false; return false;
} }
} }
else if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
{ {
ItemStack otherSlot = ItemStack.EMPTY; ItemStack otherSlot;
if( s == this.top ) if( s == this.top )
{ {
otherSlot = this.bottom.getStack(); otherSlot = this.bottom.getStack();
@@ -182,28 +175,24 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
} }
// everything else // everything else
boolean isValid = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{ {
if( Platform.itemComparisons().isSameItem( recipe.getTopOptional().orElse( ItemStack.EMPTY ), otherSlot ) ) boolean isValid = false;
if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) )
{ {
isValid = Platform.itemComparisons().isSameItem( is, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ); isValid = Platform.itemComparisons().isSameItem( is, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) );
} }
else if( Platform.itemComparisons().isSameItem( recipe.getBottomOptional().orElse( ItemStack.EMPTY ), otherSlot ) ) else if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) )
{ {
isValid = Platform.itemComparisons().isSameItem( is, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ); isValid = Platform.itemComparisons().isSameItem( is, recipe.getTopOptional().orElse( ItemStack.EMPTY ) );
} }
if( isValid ) if( isValid )
{ {
break; return true;
} }
} }
return false;
if( !isValid )
{
return false;
}
} }
return true; return true;
@@ -172,7 +172,7 @@ public class SlotRestrictedInput extends AppEngSlot
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() ) for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
{ {
if( Platform.itemComparisons().isSameItem( optional, i ) ) if( Platform.itemComparisons().isSameItem( i, optional ) )
{ {
return true; return true;
} }
+2
View File
@@ -189,6 +189,8 @@ public final class AppEng
AppEng.proxy.preinit(); AppEng.proxy.preinit();
} }
IntegrationRegistry.INSTANCE.preInit();
if( versionCheckerConfig.isVersionCheckingEnabled() ) if( versionCheckerConfig.isVersionCheckingEnabled() )
{ {
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig ); final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
@@ -118,7 +118,7 @@ public enum GuiText
RequiredPower, RequiredPower,
Efficiency, Efficiency,
SCSSize, SCSSize,
SCSSInvalid, SCSInvalid,
InWorldCrafting, InWorldCrafting,
inWorldFluix, inWorldFluix,
@@ -19,6 +19,8 @@
package appeng.entity; package appeng.entity;
import java.util.List;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@@ -136,19 +138,20 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
return; return;
} }
for( final Object e : this.world.getEntitiesWithinAABBExcludingEntity( this, final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 ) ) ) final AxisAlignedBB area = new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 );
final List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity( this, area );
net.minecraftforge.event.ForgeEventFactory.onExplosionDetonate( this.world, ex, list, 0.2f * 2d );
for( final Entity e : list )
{ {
if( e instanceof Entity ) e.attackEntityFrom( DamageSource.causeExplosionDamage( ex ), 6 );
{
( (Entity) e ).attackEntityFrom( DamageSource.causeExplosionDamage( (Explosion) null ), 6 );
}
} }
if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) ) if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) )
{ {
this.posY -= 0.25; this.posY -= 0.25;
final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
for( int x = (int) ( this.posX - 2 ); x <= this.posX + 2; x++ ) for( int x = (int) ( this.posX - 2 ); x <= this.posX + 2; x++ )
{ {
@@ -159,6 +162,7 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
final BlockPos point = new BlockPos( x, y, z ); final BlockPos point = new BlockPos( x, y, z );
final IBlockState state = this.world.getBlockState( point ); final IBlockState state = this.world.getBlockState( point );
final Block block = state.getBlock(); final Block block = state.getBlock();
if( block != null && !block.isAir( state, this.world, point ) ) if( block != null && !block.isAir( state, this.world, point ) )
{ {
float strength = (float) ( 2.3f - ( ( ( x + 0.5f ) - this.posX ) * ( ( x + 0.5f ) - this.posX ) + ( ( y + 0.5f ) - this.posY ) * ( ( y + 0.5f ) - this.posY ) + ( ( z + 0.5f ) - this.posZ ) * ( ( z + 0.5f ) - this.posZ ) ) ); float strength = (float) ( 2.3f - ( ( ( x + 0.5f ) - this.posX ) * ( ( x + 0.5f ) - this.posX ) + ( ( y + 0.5f ) - this.posY ) * ( ( y + 0.5f ) - this.posY ) + ( ( z + 0.5f ) - this.posZ ) * ( ( z + 0.5f ) - this.posZ ) ) );
@@ -47,13 +47,16 @@ public enum IntegrationRegistry
this.modules.add( new IntegrationNode( type.dspName, type.modID, type ) ); this.modules.add( new IntegrationNode( type.dspName, type.modID, type ) );
} }
public void init() public void preInit()
{ {
for( final IntegrationNode node : this.modules ) for( final IntegrationNode node : this.modules )
{ {
node.call( IntegrationStage.PRE_INIT ); node.call( IntegrationStage.PRE_INIT );
} }
}
public void init()
{
for( final IntegrationNode node : this.modules ) for( final IntegrationNode node : this.modules )
{ {
node.call( IntegrationStage.INIT ); node.call( IntegrationStage.INIT );
@@ -19,6 +19,7 @@
package appeng.integration; package appeng.integration;
import appeng.integration.modules.crafttweaker.CTModule;
import appeng.integration.modules.ic2.IC2Module; import appeng.integration.modules.ic2.IC2Module;
import appeng.integration.modules.jei.JEIModule; import appeng.integration.modules.jei.JEIModule;
import appeng.integration.modules.theoneprobe.TheOneProbeModule; import appeng.integration.modules.theoneprobe.TheOneProbeModule;
@@ -73,7 +74,16 @@ public enum IntegrationType
} }
}, },
TESLA( IntegrationSide.BOTH, "Tesla", "tesla" ); TESLA( IntegrationSide.BOTH, "Tesla", "tesla" ),
CRAFTTWEAKER( IntegrationSide.BOTH, "CraftTweaker", "crafttweaker" )
{
@Override
public IIntegrationModule createInstance()
{
return new CTModule();
}
};
public final IntegrationSide side; public final IntegrationSide side;
public final String dspName; public final String dspName;
@@ -0,0 +1,28 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.abstraction;
import appeng.integration.IIntegrationModule;
public interface ICraftTweaker extends IIntegrationModule
{
}
@@ -0,0 +1,132 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.config.TunnelType;
import appeng.api.features.IP2PTunnelRegistry;
@ZenClass( "mods.appliedenergistics2.Attunement" )
public class AttunementRegistry
{
private AttunementRegistry()
{
}
@ZenMethod
public static void attuneME( IIngredient itemStack )
{
attune( itemStack, TunnelType.ME );
}
@ZenMethod
public static void attuneME( String modId )
{
attune( modId, TunnelType.ME );
}
@ZenMethod
public static void attuneItem( IIngredient itemStack )
{
attune( itemStack, TunnelType.ITEM );
}
@ZenMethod
public static void attuneItem( String modId )
{
attune( modId, TunnelType.ITEM );
}
@ZenMethod
public static void attuneFluid( IIngredient itemStack )
{
attune( itemStack, TunnelType.FLUID );
}
@ZenMethod
public static void attuneFluid( String modId )
{
attune( modId, TunnelType.FLUID );
}
@ZenMethod
public static void attuneRedstone( IIngredient itemStack )
{
attune( itemStack, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRedstone( String modId )
{
attune( modId, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRF( IIngredient itemStack )
{
attune( itemStack, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneRF( String modId )
{
attune( modId, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneIC2( IIngredient itemStack )
{
attune( itemStack, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneIC2( String modId )
{
attune( modId, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneLight( IIngredient itemStack )
{
attune( itemStack, TunnelType.LIGHT );
}
@ZenMethod
public static void attuneLight( String modId )
{
attune( modId, TunnelType.LIGHT );
}
private static void attune( IIngredient itemStack, TunnelType type )
{
IP2PTunnelRegistry registry = AEApi.instance().registries().p2pTunnel();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.addNewAttunement( i, type ) ) );
}
private static void attune( String modid, TunnelType type )
{
AEApi.instance().registries().p2pTunnel().addNewAttunement( modid, type );
}
}
@@ -0,0 +1,130 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraftforge.oredict.OreDictionary;
import crafttweaker.CraftTweakerAPI;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import appeng.integration.abstraction.ICraftTweaker;
import appeng.util.Platform;
public class CTModule implements ICraftTweaker
{
static final List<IAction> MODIFICATIONS = new ArrayList<>();
@Override
public void preInit()
{
CraftTweakerAPI.registerClass( GrinderRecipes.class );
CraftTweakerAPI.registerClass( InscriberRecipes.class );
CraftTweakerAPI.registerClass( SpatialRegistry.class );
CraftTweakerAPI.registerClass( AttunementRegistry.class );
CraftTweakerAPI.registerClass( CannonRegistry.class );
}
@Override
public void postInit()
{
MODIFICATIONS.forEach( CraftTweakerAPI::apply );
}
public static ItemStack toStack( IItemStack iStack )
{
if( iStack == null )
{
return ItemStack.EMPTY;
}
else
{
return (ItemStack) iStack.getInternal();
}
}
public static List<ItemStack> toStackExpand( IItemStack iStack )
{
if( iStack == null )
{
return Collections.emptyList();
}
else
{
ItemStack is = (ItemStack) iStack.getInternal();
if( !is.isItemStackDamageable() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE )
{
NonNullList<ItemStack> ret = NonNullList.create();
is.getItem().getSubItems( CreativeTabs.SEARCH, ret );
return ret.stream().map( i -> new ItemStack( i.getItem(), iStack.getAmount(), i.getItemDamage() ) ).collect( Collectors.toList() );
}
else
{
return Collections.singletonList( is );
}
}
}
public static Optional<Collection<ItemStack>> toStacks( IIngredient ingredient )
{
if( ingredient == null )
{
return Optional.empty();
}
Set<ItemStack> ret = new TreeSet<>( CTModule::compareItemStacks );
ingredient.getItems().stream().map( CTModule::toStackExpand ).forEach( ret::addAll );
if( ret.isEmpty() )
{
return Optional.empty();
}
return Optional.of( ret );
}
private static int compareItemStacks( ItemStack a, ItemStack b )
{
if( Platform.itemComparisons().isSameItem( a, b ) )
{
return 0;
}
if( a == null )
{
return -1;
}
if( b == null )
{
return 1;
}
return System.identityHashCode( a ) - System.identityHashCode( b );
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IMatterCannonAmmoRegistry;
@ZenClass( "mods.appliedenergistics2.Cannon" )
public class CannonRegistry
{
private CannonRegistry()
{
}
@ZenMethod
public static void registerAmmo( IIngredient itemStack, double weight )
{
IMatterCannonAmmoRegistry registry = AEApi.instance().registries().matterCannon();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.registerAmmo( i, weight ) ) );
}
}
@@ -0,0 +1,127 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IGrinderRecipe;
import appeng.api.features.IGrinderRecipeBuilder;
@ZenClass( "mods.appliedenergistics2.Grinder" )
public class GrinderRecipes
{
private GrinderRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, int turns, @stanhebben.zenscript.annotations.Optional IItemStack secondary1Output, @stanhebben.zenscript.annotations.Optional Float secondary1Chance, @stanhebben.zenscript.annotations.Optional IItemStack secondary2Output, @stanhebben.zenscript.annotations.Optional Float secondary2Chance )
{
Collection<ItemStack> inStacks = CTModule.toStacks( input ).orElse( Collections.emptySet() );
for( ItemStack inStack : inStacks )
{
IGrinderRecipeBuilder builder = AEApi.instance().registries().grinder().builder();
builder.withInput( inStack )
.withOutput( CTModule.toStack( output ) )
.withTurns( turns );
final ItemStack s1 = CTModule.toStack( secondary1Output );
if( !s1.isEmpty() )
{
builder.withFirstOptional( s1, secondary1Chance == null ? 1.0f : secondary1Chance );
}
final ItemStack s2 = CTModule.toStack( secondary2Output );
if( !s2.isEmpty() )
{
builder.withFirstOptional( s2, secondary2Chance == null ? 1.0f : secondary2Chance );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
@ZenMethod
public static void removeRecipe( IIngredient input )
{
for( ItemStack inStack : CTModule.toStacks( input ).orElse( Collections.emptySet() ) )
{
CTModule.MODIFICATIONS.add( new Remove( inStack ) );
}
}
private static class Add implements IAction
{
private final IGrinderRecipe entry;
private Add( IGrinderRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().grinder().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Grinder Entry for " + entry.getInput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
IGrinderRecipe recipe = AEApi.instance().registries().grinder().getRecipeForInput( stack );
if( recipe != null )
{
AEApi.instance().registries().grinder().removeRecipe( recipe );
}
}
@Override
public String describe()
{
return "Removing Grinder Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,138 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IInscriberRecipe;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.IInscriberRegistry;
import appeng.api.features.InscriberProcessType;
@ZenClass( "mods.appliedenergistics2.Inscriber" )
public class InscriberRecipes
{
private InscriberRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, boolean inscribe, @stanhebben.zenscript.annotations.Optional IIngredient top, @stanhebben.zenscript.annotations.Optional IIngredient bottom )
{
Optional<Collection<ItemStack>> inStacks = CTModule.toStacks( input );
if( !inStacks.isPresent() )
{
return;
}
Collection<ItemStack> topList = CTModule.toStacks( top ).orElse( Collections.singleton( ItemStack.EMPTY ) );
Collection<ItemStack> bottomList = CTModule.toStacks( bottom ).orElse( Collections.singleton( ItemStack.EMPTY ) );
for( ItemStack topStack : topList )
{
for( ItemStack bottomStack : bottomList )
{
final IInscriberRecipeBuilder builder = AEApi.instance().registries().inscriber().builder();
builder.withProcessType( inscribe ? InscriberProcessType.INSCRIBE : InscriberProcessType.PRESS )
.withOutput( CTModule.toStack( output ) )
.withInputs( inStacks.get() );
if( !topStack.isEmpty() )
{
builder.withTopOptional( topStack );
}
if( !bottomStack.isEmpty() )
{
builder.withBottomOptional( bottomStack );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
}
@ZenMethod
public static void removeRecipe( IItemStack output )
{
CTModule.MODIFICATIONS.add( new Remove( (ItemStack) output.getInternal() ) );
}
private static class Add implements IAction
{
private final IInscriberRecipe entry;
private Add( IInscriberRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().inscriber().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Inscriber Entry for " + entry.getOutput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
final IInscriberRegistry inscriber = AEApi.instance().registries().inscriber();
inscriber.getRecipes()
.stream()
.filter( r -> r.getOutput().isItemEqual( this.stack ) )
.collect( Collectors.toList() )
.forEach( inscriber::removeRecipe );
}
@Override
public String describe()
{
return "Removing Inscriber Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import net.minecraft.tileentity.TileEntity;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.core.AELog;
@ZenClass( "mods.appliedenergistics2.Spatial" )
public class SpatialRegistry
{
private SpatialRegistry()
{
}
@ZenMethod
public static void whitelistEntity( String entityClassName )
{
Class<? extends TileEntity> entityClass = loadClass( entityClassName );
if( entityClass != null )
{
AEApi.instance().registries().movable().whiteListTileEntity( entityClass );
}
}
@SuppressWarnings( "unchecked" )
private static Class<? extends TileEntity> loadClass( String className )
{
try
{
return (Class<? extends TileEntity>) Class.forName( className );
}
catch( Exception e )
{
AELog.warn( e, "Failed to load TileEntity class '" + className + "'" );
}
return null;
}
}
@@ -219,13 +219,11 @@ public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench,
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos ) public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{ {
user.swingArm( user.getActiveHand() );
} }
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity ) public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{ {
user.swingArm( user.getActiveHand() );
} }
// IToolHammer - end // IToolHammer - end
@@ -103,14 +103,13 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolHamm
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos ) public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{ {
user.swingArm( user.getActiveHand() );
} }
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity ) public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{ {
user.swingArm( user.getActiveHand() );
} }
// IToolHammer - end // IToolHammer - end
// TODO: BC Wrench Integration // TODO: BC Wrench Integration
@@ -43,9 +43,9 @@ import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapedOreRecipe; import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe; import net.minecraftforge.oredict.ShapelessOreRecipe;
import appeng.api.AEApi;
import appeng.api.recipes.ResolverResult; import appeng.api.recipes.ResolverResult;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.AppEng; import appeng.core.AppEng;
@@ -72,6 +72,48 @@ public class PartRecipeFactory implements IRecipeFactory
} }
} }
public static ItemStack getResult( JsonObject json, JsonContext context )
{
JsonObject resultObject = JsonUtils.getJsonObject( json, "result" );
if( resultObject.has( "part" ) )
{
return getPart( resultObject );
}
else if( resultObject.has( "item" ) )
{
return CraftingHelper.getItemStack( resultObject, context );
}
else
{
throw new JsonSyntaxException( "Result has no 'part' or 'item' property." );
}
}
private static ItemStack getPart( JsonObject resultObject )
{
String ingredient = JsonUtils.getString( resultObject, "part" );
Object result = AEApi.instance().registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
return new ItemStack( item, JsonUtils.getInt( resultObject, "count", 1 ), resolverResult.damageValue, resolverResult.compound );
}
else
{
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
}
}
// Copied from ShapedOreRecipe.java, modified a bit. // Copied from ShapedOreRecipe.java, modified a bit.
private static ShapedOreRecipe shapedFactory( JsonContext context, JsonObject json ) private static ShapedOreRecipe shapedFactory( JsonContext context, JsonObject json )
{ {
@@ -141,28 +183,7 @@ public class PartRecipeFactory implements IRecipeFactory
throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys ); throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys );
} }
JsonObject resultObject = (JsonObject) json.get( "result" ); return new ShapedOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), getResult( json, context ), primer );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new ShapedOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), itemStack, primer );
}
// Should never reach this part unless mangled JSON or bug in AE.
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\nWas looking for : '" + ingredient + "'." );
} }
// Copied from ShapelessOreRecipe.java, modified a bit. // Copied from ShapelessOreRecipe.java, modified a bit.
@@ -181,28 +202,6 @@ public class PartRecipeFactory implements IRecipeFactory
throw new JsonParseException( "No ingredients for shapeless recipe" ); throw new JsonParseException( "No ingredients for shapeless recipe" );
} }
JsonObject resultObject = (JsonObject) json.get( "result" ); return new ShapelessOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), ings, getResult( json, context ) );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new ShapelessOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), ings, itemStack );
}
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
} }
} }
@@ -281,9 +281,13 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
@Nullable @Nullable
public IInscriberRecipe getTask() public IInscriberRecipe getTask()
{ {
final ItemStack plateA = this.topItemHandler.getStackInSlot( 0 ); return getTask( this.sideItemHandler.getStackInSlot( 0 ), this.topItemHandler.getStackInSlot( 0 ), this.bottomItemHandler.getStackInSlot( 0 ) );
final ItemStack plateB = this.bottomItemHandler.getStackInSlot( 0 ); }
ItemStack renamedItem = this.sideItemHandler.getStackInSlot( 0 );
@Nullable
private IInscriberRecipe getTask( final ItemStack input, final ItemStack plateA, final ItemStack plateB )
{
ItemStack renamedItem = input;
if( !plateA.isEmpty() && plateA.getCount() > 1 ) if( !plateA.isEmpty() && plateA.getCount() > 1 )
{ {
@@ -379,7 +383,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
{ {
for( final ItemStack option : recipe.getInputs() ) for( final ItemStack option : recipe.getInputs() )
{ {
if( Platform.itemComparisons().isSameItem( option, this.sideItemHandler.getStackInSlot( 0 ) ) ) if( Platform.itemComparisons().isSameItem( input, option ) )
{ {
return recipe; return recipe;
} }
@@ -606,7 +610,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
} }
for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() ) for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() )
{ {
if( Platform.itemComparisons().isSameItem( optionals, stack ) ) if( Platform.itemComparisons().isSameItem( stack, optionals ) )
{ {
return true; return true;
} }
@@ -110,7 +110,7 @@
<body> <body>
<div id="content"> <div id="content">
<div id="header"> <div id="header">
<h1>Custom Recipes</h1> <h1>Custom Recipes [DEPRECATED]</h1>
</div> </div>
<div id="body"> <div id="body">
@@ -1,3 +1,9 @@
##########################################################
# DEPRECATED #
# Until vanilla/Forge JSON is capable of supporting most #
# of our use cases use CraftTweaker for custom recipes #
##########################################################
# Crash on Issues # Crash on Issues
crash=false crash=false
@@ -1,3 +1,9 @@
##########################################################
# DEPRECATED #
# Until vanilla/Forge JSON is capable of supporting most #
# of our use cases use CraftTweaker for custom recipes #
##########################################################
# Forge Ore Dictionary # Forge Ore Dictionary
# logWood, slabWood, stairWood, treeSapling, treeLeaves, # logWood, slabWood, stairWood, treeSapling, treeLeaves,
# oreGold, oreIron, oreLapis, oreDiamond, oreRedstone, oreEmerald, oreQuartz, oreCoal, # oreGold, oreIron, oreLapis, oreDiamond, oreRedstone, oreEmerald, oreQuartz, oreCoal,
@@ -1,10 +1,9 @@
{ {
"type": "appliedenergistics2:part_shapeless",
"result": { "result": {
"type": "appliedenergistics2:part",
"part": "part.cable_anchor", "part": "part.cable_anchor",
"count": 3 "count": 3
}, },
"type": "appliedenergistics2:part_shapeless",
"ingredients": [ "ingredients": [
{ {
"item": "#appliedenergistics2:metalIngots" "item": "#appliedenergistics2:metalIngots"