diff --git a/TODO.txt b/TODO.txt
index a764fd9..6b38f4d 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -44,8 +44,6 @@ materials.ores	No		Tin
 materials.ores	No		Zinc
 -------------------------------------------------------------------------------------------------------
 tech.base		No		Alloy furnace
-							-> make redstone activation configurable
-							-> make output hopper configurable
 							-> comparator signal configuration
 								(inventory mode w/ combinations, valid ingredients, burn time,
 								alloying time)
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFContainer.java b/src/java/mmm/tech/base/alloy_furnace/TBAFContainer.java
index 83c61d3..ce2156f 100644
--- a/src/java/mmm/tech/base/alloy_furnace/TBAFContainer.java
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFContainer.java
@@ -166,13 +166,41 @@ public class TBAFContainer
 
 	@Override
 	public void setActivationMode( final E_TBActivationMode mode )
+	{
+		if ( this.world.isRemote ) {
+			final TileEntity te = this.world.getTileEntity( this.position );
+			if ( te instanceof TBAFTileEntity ) {
+				( (TBAFTileEntity) te ).setActivationMode( mode );
+			}
+			URegistry.network.sendToServer( new TBActivationModeMessage( mode ) );
+		} else {
+			this.tileEntity.setActivationMode( mode );
+			this.tileEntity.forceUpdate( );
+		}
+	}
+
+
+	public int getFlags( )
 	{
 		final TileEntity te = this.world.getTileEntity( this.position );
 		if ( te instanceof TBAFTileEntity ) {
-			( (TBAFTileEntity) te ).setActivationMode( mode );
+			return ( (TBAFTileEntity) te ).flags;
 		}
+		return 0;
+	}
+
+
+	public void setFlags( final int flags )
+	{
 		if ( this.world.isRemote ) {
-			URegistry.network.sendToServer( new TBActivationModeMessage( mode ) );
+			final TileEntity te = this.world.getTileEntity( this.position );
+			if ( te instanceof TBAFTileEntity ) {
+				( (TBAFTileEntity) te ).flags = flags;
+				URegistry.network.sendToServer( new TBAFMessage( flags ) );
+			}
+		} else {
+			this.tileEntity.flags = flags;
+			this.tileEntity.forceUpdate( );
 		}
 	}
 
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFGui.java b/src/java/mmm/tech/base/alloy_furnace/TBAFGui.java
index ca89205..3312c88 100644
--- a/src/java/mmm/tech/base/alloy_furnace/TBAFGui.java
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFGui.java
@@ -176,8 +176,7 @@ public class TBAFGui
 				gui.setRecipe( gui.currentRecipe - 1 );
 			} else if ( button == this.bConfirm ) {
 				final MAlloyRecipe recipe = gui.recipes.get( gui.currentRecipe );
-				URegistry.network.sendToServer( //
-						new TBAFMessage( gui.container.position , recipe.name , true ) );
+				URegistry.network.sendToServer( new TBAFMessage( recipe.name , true ) );
 				gui.container.tileEntity.recipe = recipe;
 			} else {
 				return false;
@@ -211,6 +210,9 @@ public class TBAFGui
 			extends A_UGTab
 	{
 		private GuiButton bActivationMode;
+		private GuiButton bInputInvalid;
+		private GuiButton bOutputInvalidInput;
+		private GuiButton bOutputInvalidFuel;
 
 
 		private ConfigTab( )
@@ -229,9 +231,16 @@ public class TBAFGui
 		{
 			super.initGui( x , y );
 
-			this.bActivationMode = new GuiButton( 100 , x + 10 , y + 10 , this.parent.getXSize( ) - 20 , 20 ,
-					this.getActivationText( ) );
+			this.bActivationMode = new GuiButton( 100 , x + 10 , y + 10 , this.parent.getXSize( ) - 20 , 20 , "" );
 			this.buttons.add( this.bActivationMode );
+
+			this.bInputInvalid = new GuiButton( 100 , x + 10 , y + 40 , this.parent.getXSize( ) - 20 , 20 , "" );
+			this.buttons.add( this.bInputInvalid );
+
+			this.bOutputInvalidInput = new GuiButton( 100 , x + 10 , y + 70 , this.parent.getXSize( ) - 20 , 20 , "" );
+			this.buttons.add( this.bOutputInvalidInput );
+			this.bOutputInvalidFuel = new GuiButton( 100 , x + 10 , y + 94 , this.parent.getXSize( ) - 20 , 20 , "" );
+			this.buttons.add( this.bOutputInvalidFuel );
 		}
 
 
@@ -239,6 +248,9 @@ public class TBAFGui
 		public void drawBackground( final float partialTicks , final int mouseX , final int mouseY )
 		{
 			this.bActivationMode.displayString = this.getActivationText( );
+			this.bInputInvalid.displayString = this.getInputHopperText( );
+			this.bOutputInvalidInput.displayString = this.getOutputHopperInputText( );
+			this.bOutputInvalidFuel.displayString = this.getOutputHopperFuelText( );
 			super.drawBackground( partialTicks , mouseX , mouseY );
 		}
 
@@ -246,11 +258,27 @@ public class TBAFGui
 		@Override
 		public boolean onActionPerformed( final GuiButton button )
 		{
+			final TBAFContainer cont = (TBAFContainer) this.parent.container;
 			if ( button == this.bActivationMode ) {
-				final TBAFContainer cont = (TBAFContainer) this.parent.container;
 				cont.setActivationMode( cont.getActivationMode( ).next( ) );
 				return true;
 			}
+
+			if ( button == this.bInputInvalid ) {
+				cont.setFlags( cont.getFlags( ) ^ TBAFTileEntity.F_IH_INVALID );
+				return true;
+			}
+
+			if ( button == this.bOutputInvalidInput ) {
+				cont.setFlags( cont.getFlags( ) ^ TBAFTileEntity.F_OH_INVALID_INPUT );
+				return true;
+			}
+
+			if ( button == this.bOutputInvalidFuel ) {
+				cont.setFlags( cont.getFlags( ) ^ TBAFTileEntity.F_OH_INVALID_FUEL );
+				return true;
+			}
+
 			return super.onActionPerformed( button );
 		}
 
@@ -260,6 +288,36 @@ public class TBAFGui
 			return I18n.format( ( (TBAFContainer) this.parent.container ).getActivationMode( ).getDisplayName( ) );
 		}
 
+
+		private String getInputHopperText( )
+		{
+			final boolean active = ( ( (TBAFContainer) this.parent.container ).getFlags( )
+					& TBAFTileEntity.F_IH_INVALID ) != 0;
+			return I18n.format( active
+					? "container.mmm.alloy_furnace.cfg.ihinv.yes" //
+					: "container.mmm.alloy_furnace.cfg.ihinv.no" );
+		}
+
+
+		private String getOutputHopperInputText( )
+		{
+			final boolean active = ( ( (TBAFContainer) this.parent.container ).getFlags( )
+					& TBAFTileEntity.F_OH_INVALID_INPUT ) != 0;
+			return I18n.format( active
+					? "container.mmm.alloy_furnace.cfg.ohinvin.yes" //
+					: "container.mmm.alloy_furnace.cfg.ohinvin.no" );
+		}
+
+
+		private String getOutputHopperFuelText( )
+		{
+			final boolean active = ( ( (TBAFContainer) this.parent.container ).getFlags( )
+					& TBAFTileEntity.F_OH_INVALID_FUEL ) != 0;
+			return I18n.format( active
+					? "container.mmm.alloy_furnace.cfg.ohinvf.yes" //
+					: "container.mmm.alloy_furnace.cfg.ohinvf.no" );
+		}
+
 	}
 
 	private ArrayList< MAlloyRecipe > recipes;
@@ -295,8 +353,7 @@ public class TBAFGui
 		}
 
 		this.container.setCurrentRecipe( rName , false );
-		URegistry.network.sendToServer( //
-				new TBAFMessage( this.container.position , rName , false ) );
+		URegistry.network.sendToServer( new TBAFMessage( rName , false ) );
 		( (RecipeTab) this.tabs[ 1 ] ).enableButtons( );
 	}
 
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFInputHopper.java b/src/java/mmm/tech/base/alloy_furnace/TBAFInputHopper.java
new file mode 100644
index 0000000..e45135e
--- /dev/null
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFInputHopper.java
@@ -0,0 +1,33 @@
+package mmm.tech.base.alloy_furnace;
+
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.items.wrapper.InvWrapper;
+
+
+
+public class TBAFInputHopper
+		extends InvWrapper
+{
+
+	private final TBAFTileEntity tileEntity;
+
+
+	public TBAFInputHopper( final TBAFTileEntity tileEntity )
+	{
+		super( tileEntity.input );
+		this.tileEntity = tileEntity;
+	}
+
+
+	@Override
+	public ItemStack insertItem( final int slot , final ItemStack stack , final boolean simulate )
+	{
+		if ( stack != null && ( this.tileEntity.flags & TBAFTileEntity.F_IH_INVALID ) == 0
+				&& !this.tileEntity.recipe.hasInput( stack ) ) {
+			return stack;
+		}
+		return super.insertItem( slot , stack , simulate );
+	}
+
+}
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFMessage.java b/src/java/mmm/tech/base/alloy_furnace/TBAFMessage.java
index 4a32d4f..d37ef65 100644
--- a/src/java/mmm/tech/base/alloy_furnace/TBAFMessage.java
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFMessage.java
@@ -6,7 +6,6 @@ import mmm.utils.I_UMessage;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.inventory.Container;
 import net.minecraft.util.ResourceLocation;
-import net.minecraft.util.math.BlockPos;
 import net.minecraftforge.fml.common.network.ByteBufUtils;
 
 
@@ -14,9 +13,13 @@ import net.minecraftforge.fml.common.network.ByteBufUtils;
 public class TBAFMessage
 		implements I_UMessage
 {
-	private BlockPos blockPos;
-	private ResourceLocation selected;
-	private boolean confirm;
+	private static final int MT_RECIPE = 0;
+	private static final int MT_SET_RECIPE = 1;
+	private static final int MT_SET_FLAGS = 2;
+
+	private int type;
+	private ResourceLocation recipe;
+	private int flags;
 
 
 	public TBAFMessage( )
@@ -25,40 +28,64 @@ public class TBAFMessage
 	}
 
 
-	public TBAFMessage( final BlockPos blockPos , final ResourceLocation selected , final boolean confirm )
+	public TBAFMessage( final ResourceLocation selected , final boolean confirm )
 	{
-		this.blockPos = blockPos;
-		this.selected = selected;
-		this.confirm = confirm;
+		this.type = confirm ? TBAFMessage.MT_SET_RECIPE : TBAFMessage.MT_RECIPE;
+		this.recipe = selected;
+	}
+
+
+	public TBAFMessage( int flags )
+	{
+		this.type = MT_SET_FLAGS;
+		this.flags = flags;
 	}
 
 
 	@Override
 	public void fromBytes( final ByteBuf buf )
 	{
-		this.blockPos = new BlockPos( buf.readInt( ) , buf.readInt( ) , buf.readInt( ) );
-		if ( buf.readBoolean( ) ) {
-			this.selected = new ResourceLocation( ByteBufUtils.readUTF8String( buf ) ,
-					ByteBufUtils.readUTF8String( buf ) );
-		} else {
-			this.selected = null;
+		this.type = buf.readByte( );
+		switch ( this.type ) {
+
+			case MT_RECIPE:
+			case MT_SET_RECIPE:
+				if ( buf.readBoolean( ) ) {
+					this.recipe = new ResourceLocation( ByteBufUtils.readUTF8String( buf ) ,
+							ByteBufUtils.readUTF8String( buf ) );
+				} else {
+					this.recipe = null;
+				}
+				break;
+
+			case MT_SET_FLAGS:
+				this.flags = buf.readByte( );
+				break;
+
 		}
-		this.confirm = buf.readBoolean( );
 	}
 
 
 	@Override
 	public void toBytes( final ByteBuf buf )
 	{
-		buf.writeInt( this.blockPos.getX( ) );
-		buf.writeInt( this.blockPos.getY( ) );
-		buf.writeInt( this.blockPos.getZ( ) );
-		buf.writeBoolean( this.selected != null );
-		if ( this.selected != null ) {
-			ByteBufUtils.writeUTF8String( buf , this.selected.getResourceDomain( ) );
-			ByteBufUtils.writeUTF8String( buf , this.selected.getResourcePath( ) );
+		buf.writeByte( this.type );
+		switch ( this.type ) {
+
+			case MT_RECIPE:
+			case MT_SET_RECIPE:
+				buf.writeBoolean( this.recipe != null );
+				if ( this.recipe != null ) {
+					ByteBufUtils.writeUTF8String( buf , this.recipe.getResourceDomain( ) );
+					ByteBufUtils.writeUTF8String( buf , this.recipe.getResourcePath( ) );
+				}
+				break;
+
+			case MT_SET_FLAGS:
+				buf.writeByte( this.flags );
+				break;
+
 		}
-		buf.writeBoolean( this.confirm );
 	}
 
 
@@ -66,9 +93,23 @@ public class TBAFMessage
 	public void handleOnServer( final EntityPlayerMP player )
 	{
 		final Container curCont = player.openContainer;
-		if ( curCont instanceof TBAFContainer ) {
-			final TBAFContainer container = (TBAFContainer) curCont;
-			container.setCurrentRecipe( this.selected , this.confirm );
+		if ( ! ( curCont instanceof TBAFContainer ) ) {
+			return;
+		}
+
+		final TBAFContainer container = (TBAFContainer) curCont;
+
+		switch ( this.type ) {
+
+			case MT_RECIPE:
+			case MT_SET_RECIPE:
+				container.setCurrentRecipe( this.recipe , this.type == TBAFMessage.MT_SET_RECIPE );
+				break;
+				
+			case MT_SET_FLAGS:
+				container.setFlags( flags );
+				break;
+
 		}
 	}
 
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFOutputHopper.java b/src/java/mmm/tech/base/alloy_furnace/TBAFOutputHopper.java
index d36109b..5b383ff 100644
--- a/src/java/mmm/tech/base/alloy_furnace/TBAFOutputHopper.java
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFOutputHopper.java
@@ -70,17 +70,18 @@ public class TBAFOutputHopper
 		// Extracting invalid input items
 		final int nInputSlots = this.tileEntity.input.getSizeInventory( );
 		if ( slot < nInputSlots ) {
-			if ( this.tileEntity.recipe.hasInput( stackInSlot ) ) {
+			if ( ( this.tileEntity.flags & TBAFTileEntity.F_OH_INVALID_INPUT ) == 0
+					|| this.tileEntity.recipe.hasInput( stackInSlot ) ) {
 				return null;
 			}
-			// XXX check configuration
 			return this.doExtractItems( this.tileEntity.input , stackInSlot , slot , amount , simulate );
 		}
 
 		// Extracting invalid fuel items
 		final int nFuelSlots = this.tileEntity.fuel.getSizeInventory( );
 		if ( slot < nInputSlots + nFuelSlots ) {
-			if ( TileEntityFurnace.isItemFuel( stackInSlot ) ) {
+			if ( ( this.tileEntity.flags & TBAFTileEntity.F_OH_INVALID_FUEL ) == 0
+					|| TileEntityFurnace.isItemFuel( stackInSlot ) ) {
 				return null;
 			}
 			return this.doExtractItems( this.tileEntity.fuel , stackInSlot , slot - nInputSlots , amount , simulate );
diff --git a/src/java/mmm/tech/base/alloy_furnace/TBAFTileEntity.java b/src/java/mmm/tech/base/alloy_furnace/TBAFTileEntity.java
index 76bcfdd..88d622e 100644
--- a/src/java/mmm/tech/base/alloy_furnace/TBAFTileEntity.java
+++ b/src/java/mmm/tech/base/alloy_furnace/TBAFTileEntity.java
@@ -30,6 +30,12 @@ public class TBAFTileEntity
 		extends TileEntity
 		implements ITickable , I_TBConfigurableActivation
 {
+	/** Output hopper collects invalid input? */
+	public static final int F_OH_INVALID_INPUT = 1 << 0;
+	/** Output hopper collects invalid fuel? */
+	public static final int F_OH_INVALID_FUEL = 1 << 1;
+	/** Input hopper allows invalid input? */
+	public static final int F_IH_INVALID = 1 << 2;
 
 	public final UInventoryGrid input;
 	public final UInventoryGrid fuel;
@@ -43,6 +49,8 @@ public class TBAFTileEntity
 	private int burnTotal;
 	private E_TBActivationMode activationMode;
 
+	public int flags;
+
 	private final IItemHandler inputHopper;
 	private final IItemHandler fuelHopper;
 	private final IItemHandler outputHopper;
@@ -51,12 +59,21 @@ public class TBAFTileEntity
 	public TBAFTileEntity( )
 	{
 		this.input = new UInventoryGrid( "Input" , 3 , 5 );
-		this.fuel = new UInventoryGrid( "Fuel" , 2 , 2 );
+		this.fuel = new UInventoryGrid( "Fuel" , 2 , 2 ) {
+
+			@Override
+			public boolean isItemValidForSlot( int index , ItemStack stack )
+			{
+				return super.isItemValidForSlot( index , stack ) && TileEntityFurnace.isItemFuel( stack );
+			}
+
+		};
 		this.output = new UInventoryGrid( "Output" , 2 , 5 );
 		this.recipe = MAlloyRecipe.REGISTRY.getRecipes( ).get( 0 );
 		this.activationMode = E_TBActivationMode.ALWAYS_ACTIVE;
+		this.flags = TBAFTileEntity.F_OH_INVALID_INPUT | TBAFTileEntity.F_OH_INVALID_FUEL;
 
-		this.inputHopper = new InvWrapper( this.input );
+		this.inputHopper = new TBAFInputHopper( this );
 		this.fuelHopper = new InvWrapper( this.fuel );
 		this.outputHopper = new TBAFOutputHopper( this );
 	}
@@ -171,9 +188,7 @@ public class TBAFTileEntity
 		}
 
 		if ( dirty ) {
-			this.markDirty( );
-			final IBlockState state = this.worldObj.getBlockState( this.pos );
-			this.worldObj.notifyBlockUpdate( this.pos , state , state , 3 );
+			this.forceUpdate( );
 		}
 	}
 
@@ -258,13 +273,19 @@ public class TBAFTileEntity
 		this.recipe = recipe;
 
 		if ( !this.worldObj.isRemote ) {
-			this.markDirty( );
-			final IBlockState state = this.worldObj.getBlockState( this.pos );
-			this.worldObj.notifyBlockUpdate( this.pos , state , state , 3 );
+			this.forceUpdate( );
 		}
 	}
 
 
+	public void forceUpdate( )
+	{
+		this.markDirty( );
+		final IBlockState state = this.worldObj.getBlockState( this.pos );
+		this.worldObj.notifyBlockUpdate( this.pos , state , state , 3 );
+	}
+
+
 	public boolean isBurning( )
 	{
 		return this.burnTotal != 0;
@@ -461,7 +482,7 @@ public class TBAFTileEntity
 			this.recipe = MAlloyRecipe.REGISTRY.getRecipes( ).get( 0 );
 		}
 
-		byte am = compound.getByte( "ActivationMode" );
+		final byte am = compound.getByte( "ActivationMode" );
 		switch ( am ) {
 			default:
 				// XXX log
@@ -478,6 +499,7 @@ public class TBAFTileEntity
 				this.activationMode = E_TBActivationMode.DISABLED;
 				break;
 		}
+		this.flags = compound.getByte( "Flags" );
 
 		this.burnCurrent = compound.getInteger( "BurnCurrent" );
 		this.burnTotal = compound.getInteger( "BurnTotal" );
@@ -500,6 +522,7 @@ public class TBAFTileEntity
 	{
 		compound.setString( "Recipe" , this.recipe.name.toString( ) );
 		compound.setByte( "ActivationMode" , (byte) this.activationMode.ordinal( ) );
+		compound.setByte( "Flags" , (byte) this.flags );
 		if ( this.alloying != null ) {
 			compound.setString( "AlloyRecipe" , this.alloying.name.toString( ) );
 			compound.setInteger( "AlloyCurrent" , this.alloyCurrent );
diff --git a/src/resources/assets/mmm/lang/en_US.lang b/src/resources/assets/mmm/lang/en_US.lang
index 3d2e8f8..5df3778 100644
--- a/src/resources/assets/mmm/lang/en_US.lang
+++ b/src/resources/assets/mmm/lang/en_US.lang
@@ -25,6 +25,12 @@ item.mmm.tech.base.alloy_furnace.name=Alloy Furnace
 container.mmm.alloy_furnace.contents=Furnace Contents
 container.mmm.alloy_furnace.recipe=Alloy Selection
 container.mmm.alloy_furnace.select=Select Alloy
+container.mmm.alloy_furnace.cfg.ihinv.yes=Allow invalid hopper input
+container.mmm.alloy_furnace.cfg.ihinv.no=Block invalid hopper input
+container.mmm.alloy_furnace.cfg.ohinvin.yes=Remove invalid input
+container.mmm.alloy_furnace.cfg.ohinvin.no=Keep invalid input
+container.mmm.alloy_furnace.cfg.ohinvf.yes=Remove spent fuel buckets
+container.mmm.alloy_furnace.cfg.ohinvf.no=Keep spent fuel buckets
 
 
 item.mmm.tech.tools.copper.shovel.name=Copper Shovel