From f93e75304bcfaf4a7d5ea0403f9d2d753b1f3003 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Thu, 21 Jul 2016 16:52:38 +0200
Subject: [PATCH] Workbench - Map cloning/extending

---
 .../api/recipes/I_CraftingRecipeWrapper.java  |  12 ++
 .../api/recipes/I_RecipeRequirements.java     |  11 +-
 src/java/mmm/recipes/RCraftingWrappers.java   |   2 +
 .../mmm/recipes/RMapCloningRecipeWrapper.java |  78 ++++++++++++
 .../RMapCloningRecipeWrapperFactory.java      |  31 +++++
 .../recipes/RMapExtendingRecipeWrapper.java   | 111 ++++++++++++++++++
 .../RMapExtendingRecipeWrapperFactory.java    |  31 +++++
 src/java/mmm/recipes/RRequirements.java       |  19 +--
 .../tech/base/workbench/TBWBContainer.java    |   7 +-
 .../tech/base/workbench/TBWBCraftingSlot.java |   6 +-
 src/java/mmm/tech/base/workbench/TBWBGui.java |   5 +-
 src/resources/assets/mmm/lang/en_US.lang      |   3 +
 12 files changed, 294 insertions(+), 22 deletions(-)
 create mode 100644 src/java/mmm/recipes/RMapCloningRecipeWrapper.java
 create mode 100644 src/java/mmm/recipes/RMapCloningRecipeWrapperFactory.java
 create mode 100644 src/java/mmm/recipes/RMapExtendingRecipeWrapper.java
 create mode 100644 src/java/mmm/recipes/RMapExtendingRecipeWrapperFactory.java

diff --git a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java
index 92438e7..9818dfd 100644
--- a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java
+++ b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java
@@ -17,6 +17,18 @@ public interface I_CraftingRecipeWrapper
 	public ItemStack getOutput( );
 
 
+	default ItemStack getActualOutput( final IInventory input )
+	{
+		return this.getOutput( ).copy( );
+	}
+
+
+	default boolean canShiftClick( )
+	{
+		return true;
+	}
+
+
 	public void addInputsToDisplay( IInventory displayInventory );
 
 
diff --git a/src/java/mmm/core/api/recipes/I_RecipeRequirements.java b/src/java/mmm/core/api/recipes/I_RecipeRequirements.java
index 12e578b..730fc5d 100644
--- a/src/java/mmm/core/api/recipes/I_RecipeRequirements.java
+++ b/src/java/mmm/core/api/recipes/I_RecipeRequirements.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import net.minecraft.inventory.IInventory;
 import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
 
 
 
@@ -20,17 +21,17 @@ public interface I_RecipeRequirements
 	List< ItemStack > getItemTypes( int pos );
 
 
-	boolean checkItemStack( int pos , ItemStack stack );
+	boolean checkItemStack( int pos , ItemStack stack , World world );
 
 
-	boolean checkInventory( IInventory inventory );
+	boolean checkInventory( IInventory inventory , World world );
 
 
-	boolean checkInventory( IInventory inventory , int amount );
+	boolean checkInventory( IInventory inventory , int amount , World world );
 
 
-	public int getMaxOutput( IInventory inventory );
+	public int getMaxOutput( IInventory inventory , World world );
 
 
-	void removeFromInventory( IInventory inventory, int amount );
+	void removeFromInventory( IInventory inventory , int amount , World world );
 }
\ No newline at end of file
diff --git a/src/java/mmm/recipes/RCraftingWrappers.java b/src/java/mmm/recipes/RCraftingWrappers.java
index c1c2110..64e486a 100644
--- a/src/java/mmm/recipes/RCraftingWrappers.java
+++ b/src/java/mmm/recipes/RCraftingWrappers.java
@@ -62,5 +62,7 @@ public class RCraftingWrappers
 		RCraftingWrappers.register( new RShapelessOreRecipeWrapperFactory( ) );
 		RCraftingWrappers.register( new RShapedRecipeWrapperFactory( ) );
 		RCraftingWrappers.register( new RShapedOreRecipeWrapperFactory( ) );
+		RCraftingWrappers.register( new RMapCloningRecipeWrapperFactory( ) );
+		RCraftingWrappers.register( new RMapExtendingRecipeWrapperFactory( ) );
 	}
 }
diff --git a/src/java/mmm/recipes/RMapCloningRecipeWrapper.java b/src/java/mmm/recipes/RMapCloningRecipeWrapper.java
new file mode 100644
index 0000000..6b7a397
--- /dev/null
+++ b/src/java/mmm/recipes/RMapCloningRecipeWrapper.java
@@ -0,0 +1,78 @@
+package mmm.recipes;
+
+
+import mmm.core.api.recipes.I_CraftingRecipeWrapper;
+import mmm.core.api.recipes.I_RecipeRequirements;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.oredict.OreDictionary;
+
+
+
+public class RMapCloningRecipeWrapper
+		implements I_CraftingRecipeWrapper
+{
+
+	private final I_RecipeRequirements requirements;
+
+
+	public RMapCloningRecipeWrapper( )
+	{
+		final RRequirements reqs = new RRequirements( 2 );
+		reqs.put( 0 , new ItemStack( Items.FILLED_MAP , 1 , OreDictionary.WILDCARD_VALUE ) , 1 );
+		reqs.put( 1 , new ItemStack( Items.MAP ) , 1 );
+		this.requirements = reqs;
+	}
+
+
+	@Override
+	public String getIdentifier( )
+	{
+		return "MAP_CLONING";
+	}
+
+
+	@Override
+	public String getName( )
+	{
+		return "gui.mmm.recipes.map_cloning";
+	}
+
+
+	@Override
+	public ItemStack getOutput( )
+	{
+		return new ItemStack( Items.FILLED_MAP , 2 , 0 );
+	}
+
+
+	@Override
+	public ItemStack getActualOutput( final IInventory input )
+	{
+		int filledMapSlot = -1;
+		for ( int i = 0 ; i < input.getSizeInventory( ) && filledMapSlot == -1 ; i++ ) {
+			final ItemStack stack = input.getStackInSlot( i );
+			if ( stack != null && stack.getItem( ) == Items.FILLED_MAP ) {
+				filledMapSlot = i;
+			}
+		}
+		return new ItemStack( Items.FILLED_MAP , 2 , input.getStackInSlot( filledMapSlot ).getMetadata( ) );
+	}
+
+
+	@Override
+	public void addInputsToDisplay( final IInventory displayInventory )
+	{
+		displayInventory.setInventorySlotContents( 0 , new ItemStack( Items.FILLED_MAP , 1 , 0 ) );
+		displayInventory.setInventorySlotContents( 1 , new ItemStack( Items.MAP ) );
+	}
+
+
+	@Override
+	public I_RecipeRequirements getRequirements( )
+	{
+		return this.requirements;
+	}
+
+}
diff --git a/src/java/mmm/recipes/RMapCloningRecipeWrapperFactory.java b/src/java/mmm/recipes/RMapCloningRecipeWrapperFactory.java
new file mode 100644
index 0000000..df76b6e
--- /dev/null
+++ b/src/java/mmm/recipes/RMapCloningRecipeWrapperFactory.java
@@ -0,0 +1,31 @@
+package mmm.recipes;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+import mmm.core.api.recipes.I_CraftingRecipeWrapper;
+import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.item.crafting.RecipesMapCloning;
+
+
+
+public class RMapCloningRecipeWrapperFactory
+		implements I_CraftingRecipeWrapperFactory
+{
+
+	@Override
+	public Class< ? extends IRecipe > getRecipeClass( )
+	{
+		return RecipesMapCloning.class;
+	}
+
+
+	@Override
+	public List< I_CraftingRecipeWrapper > createWrappers( IRecipe recipe )
+	{
+		return Arrays.asList( new RMapCloningRecipeWrapper( ) );
+	}
+
+}
diff --git a/src/java/mmm/recipes/RMapExtendingRecipeWrapper.java b/src/java/mmm/recipes/RMapExtendingRecipeWrapper.java
new file mode 100644
index 0000000..1cacb2d
--- /dev/null
+++ b/src/java/mmm/recipes/RMapExtendingRecipeWrapper.java
@@ -0,0 +1,111 @@
+package mmm.recipes;
+
+
+import mmm.core.api.recipes.I_CraftingRecipeWrapper;
+import mmm.core.api.recipes.I_RecipeRequirements;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraft.world.storage.MapData;
+import net.minecraftforge.oredict.OreDictionary;
+
+
+
+public class RMapExtendingRecipeWrapper
+		implements I_CraftingRecipeWrapper
+{
+	private final RRequirements requirements = new RRequirements( 2 ) {
+
+		@Override
+		public boolean checkItemStack( final int pos , final ItemStack stack , final World world )
+		{
+			if ( !super.checkItemStack( pos , stack , world ) ) {
+				return false;
+			}
+
+			if ( stack.getItem( ) == Items.FILLED_MAP ) {
+				final MapData mapdata = Items.FILLED_MAP.getMapData( stack , world );
+				return mapdata == null ? false : mapdata.scale < 4;
+			}
+			return true;
+		}
+
+	};
+
+
+	public RMapExtendingRecipeWrapper( )
+	{
+		requirements.put( 0 , new ItemStack( Items.FILLED_MAP , 1 , OreDictionary.WILDCARD_VALUE ) , 1 );
+		requirements.put( 1 , new ItemStack( Items.PAPER ) , 8 );
+	}
+
+
+	@Override
+	public String getIdentifier( )
+	{
+		return "MAP_EXTENDING";
+	}
+
+
+	@Override
+	public String getName( )
+	{
+		return "gui.mmm.recipes.map_extending";
+	}
+
+
+	@Override
+	public ItemStack getOutput( )
+	{
+		return new ItemStack( Items.FILLED_MAP , 1 , 0 );
+	}
+
+
+	@Override
+	public ItemStack getActualOutput( final IInventory input )
+	{
+		int filledMapSlot = -1;
+		for ( int i = 0 ; i < input.getSizeInventory( ) && filledMapSlot == -1 ; i++ ) {
+			final ItemStack stack = input.getStackInSlot( i );
+			if ( stack != null && stack.getItem( ) == Items.FILLED_MAP ) {
+				filledMapSlot = i;
+			}
+		}
+
+		final ItemStack stack = input.getStackInSlot( filledMapSlot ).copy( );
+		stack.stackSize = 1;
+		if ( stack.getTagCompound( ) == null ) {
+			stack.setTagCompound( new NBTTagCompound( ) );
+		}
+		stack.getTagCompound( ).setInteger( "map_scale_direction" , 1 );
+		return stack;
+	}
+
+
+	@Override
+	public boolean canShiftClick( )
+	{
+		return false;
+	}
+
+
+	@Override
+	public void addInputsToDisplay( final IInventory displayInventory )
+	{
+		for ( int i = 0 ; i < 9 ; i++ ) {
+			displayInventory.setInventorySlotContents( i , i == 4
+					? new ItemStack( Items.FILLED_MAP , 1 , 0 ) //
+					: new ItemStack( Items.PAPER ) );
+		}
+	}
+
+
+	@Override
+	public I_RecipeRequirements getRequirements( )
+	{
+		return this.requirements;
+	}
+
+}
diff --git a/src/java/mmm/recipes/RMapExtendingRecipeWrapperFactory.java b/src/java/mmm/recipes/RMapExtendingRecipeWrapperFactory.java
new file mode 100644
index 0000000..ae38017
--- /dev/null
+++ b/src/java/mmm/recipes/RMapExtendingRecipeWrapperFactory.java
@@ -0,0 +1,31 @@
+package mmm.recipes;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+import mmm.core.api.recipes.I_CraftingRecipeWrapper;
+import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.item.crafting.RecipesMapExtending;
+
+
+
+public class RMapExtendingRecipeWrapperFactory
+		implements I_CraftingRecipeWrapperFactory
+{
+
+	@Override
+	public Class< ? extends IRecipe > getRecipeClass( )
+	{
+		return RecipesMapExtending.class;
+	}
+
+
+	@Override
+	public List< I_CraftingRecipeWrapper > createWrappers( final IRecipe recipe )
+	{
+		return Arrays.asList( new RMapExtendingRecipeWrapper( ) );
+	}
+
+}
diff --git a/src/java/mmm/recipes/RRequirements.java b/src/java/mmm/recipes/RRequirements.java
index 0520f32..94f9e91 100644
--- a/src/java/mmm/recipes/RRequirements.java
+++ b/src/java/mmm/recipes/RRequirements.java
@@ -8,6 +8,7 @@ import java.util.List;
 import mmm.core.api.recipes.I_RecipeRequirements;
 import net.minecraft.inventory.IInventory;
 import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
 import net.minecraftforge.oredict.OreDictionary;
 
 
@@ -75,7 +76,7 @@ class RRequirements
 
 
 	@Override
-	public boolean checkItemStack( final int pos , final ItemStack stack )
+	public boolean checkItemStack( final int pos , final ItemStack stack , World world )
 	{
 		if ( stack != null ) {
 			for ( final ItemStack target : this.getItemTypes( pos ) ) {
@@ -89,14 +90,14 @@ class RRequirements
 
 
 	@Override
-	public boolean checkInventory( final IInventory inventory )
+	public boolean checkInventory( final IInventory inventory , World world )
 	{
-		return this.checkInventory( inventory , 1 );
+		return this.checkInventory( inventory , 1 , world );
 	}
 
 
 	@Override
-	public boolean checkInventory( final IInventory inventory , final int amount )
+	public boolean checkInventory( final IInventory inventory , final int amount , World world )
 	{
 		final int nInvItems = inventory.getSizeInventory( );
 		for ( int i = 0 ; i < this.quantities.length ; i++ ) {
@@ -104,7 +105,7 @@ class RRequirements
 
 			for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) {
 				final ItemStack invStack = inventory.getStackInSlot( j );
-				if ( this.checkItemStack( i , invStack ) ) {
+				if ( this.checkItemStack( i , invStack , world ) ) {
 					nLeft -= invStack.stackSize;
 				}
 			}
@@ -118,7 +119,7 @@ class RRequirements
 
 
 	@Override
-	public int getMaxOutput( final IInventory inventory )
+	public int getMaxOutput( final IInventory inventory , World world )
 	{
 		final int nInvItems = inventory.getSizeInventory( );
 		int maxQuantity = Integer.MAX_VALUE;
@@ -127,7 +128,7 @@ class RRequirements
 
 			for ( int j = 0 ; j < nInvItems ; j++ ) {
 				final ItemStack invStack = inventory.getStackInSlot( j );
-				if ( this.checkItemStack( i , invStack ) ) {
+				if ( this.checkItemStack( i , invStack , world ) ) {
 					nFound += invStack.stackSize;
 				}
 			}
@@ -139,14 +140,14 @@ class RRequirements
 
 
 	@Override
-	public void removeFromInventory( final IInventory inventory , final int amount )
+	public void removeFromInventory( final IInventory inventory , final int amount , World world )
 	{
 		final int nInvItems = inventory.getSizeInventory( );
 		for ( int i = 0 ; i < this.quantities.length ; i++ ) {
 			int nLeft = this.quantities[ i ] * amount;
 			for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) {
 				final ItemStack invStack = inventory.getStackInSlot( j );
-				if ( this.checkItemStack( i , invStack ) ) {
+				if ( this.checkItemStack( i , invStack , world ) ) {
 					final int used = Math.min( nLeft , invStack.stackSize );
 					nLeft -= used;
 					if ( invStack.stackSize == used ) {
diff --git a/src/java/mmm/tech/base/workbench/TBWBContainer.java b/src/java/mmm/tech/base/workbench/TBWBContainer.java
index 1a13b98..44bc90a 100644
--- a/src/java/mmm/tech/base/workbench/TBWBContainer.java
+++ b/src/java/mmm/tech/base/workbench/TBWBContainer.java
@@ -82,12 +82,11 @@ public class TBWBContainer
 		}
 
 		final ItemStack slotStack = slot.getStack( );
-		final ItemStack outStack = slotStack.copy( );
 
 		final int group = this.slotGroups.getGroup( index );
 		if ( group == 3 ) {
 			// Craft as many as possible
-			if ( this.recipeWrapper == null ) {
+			if ( this.recipeWrapper == null || !this.recipeWrapper.canShiftClick( ) ) {
 				return null;
 			}
 			final IInventory storage = this.getStorage( );
@@ -96,11 +95,12 @@ public class TBWBContainer
 			}
 
 			// Can we?
-			if ( !this.recipeWrapper.getRequirements( ).checkInventory( storage ) ) {
+			if ( !this.recipeWrapper.getRequirements( ).checkInventory( storage , this.world ) ) {
 				return null;
 			}
 
 			// Merge it and remove ingredients
+			final ItemStack outStack = this.getCurrentRecipe( ).getActualOutput( storage );
 			if ( !this.mergeItemStack( outStack , 0 , 36 , false ) ) {
 				return null;
 			}
@@ -116,6 +116,7 @@ public class TBWBContainer
 
 		}
 
+		final ItemStack outStack = slotStack.copy( );
 		if ( group == 0 ) {
 			// Player inventory to storage
 			if ( !this.mergeItemStack( slotStack , 36 , 51 , false ) ) {
diff --git a/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java b/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java
index b4c0836..215c603 100644
--- a/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java
+++ b/src/java/mmm/tech/base/workbench/TBWBCraftingSlot.java
@@ -52,7 +52,7 @@ public class TBWBCraftingSlot
 		final ItemStack stack = this.getStack( );
 		final int qt = Math.max( amount - amount % stack.stackSize , stack.stackSize ) / stack.stackSize;
 		final IInventory storage = this.container.getStorage( );
-		if ( storage == null || !wrapper.getRequirements( ).checkInventory( storage , qt ) ) {
+		if ( storage == null || !wrapper.getRequirements( ).checkInventory( storage , qt , this.container.world ) ) {
 			return null;
 		}
 		return this.handleCrafting( qt );
@@ -75,13 +75,13 @@ public class TBWBCraftingSlot
 			return null;
 		}
 
-		final ItemStack stack = this.getStack( ).copy( );
+		final ItemStack stack = this.container.getCurrentRecipe( ).getActualOutput( storage );
 		stack.stackSize *= quantity;
 
 		FMLCommonHandler.instance( ).firePlayerCraftingEvent( this.player , stack , this.inventory );
 		stack.onCrafting( this.player.worldObj , this.player , quantity );
 		UAchievements.checkCraftingAchievements( this.player , stack.getItem( ) );
-		wrapper.getRequirements( ).removeFromInventory( storage , quantity );
+		wrapper.getRequirements( ).removeFromInventory( storage , quantity , this.container.world );
 		return stack;
 	}
 }
diff --git a/src/java/mmm/tech/base/workbench/TBWBGui.java b/src/java/mmm/tech/base/workbench/TBWBGui.java
index ccd94b2..f556343 100644
--- a/src/java/mmm/tech/base/workbench/TBWBGui.java
+++ b/src/java/mmm/tech/base/workbench/TBWBGui.java
@@ -103,7 +103,8 @@ public class TBWBGui
 		} else {
 			final TileEntity te = this.container.world.getTileEntity( this.container.position );
 			final I_RecipeRequirements requirements = this.recipes.get( this.currentRecipe ).getRequirements( );
-			canCraft = te instanceof TBWBTileEntity && requirements.checkInventory( ( (TBWBTileEntity) te ).storage );
+			canCraft = te instanceof TBWBTileEntity
+					&& requirements.checkInventory( ( (TBWBTileEntity) te ).storage , this.container.world );
 		}
 		if ( !canCraft ) {
 			UGui.drawIcon( this , this.guiLeft + 147 , this.guiTop + 51 , E_Icon.RED_CROSS );
@@ -135,7 +136,7 @@ public class TBWBGui
 
 		} else if ( typedChar == 't' || typedChar == 'T' ) {
 			this.tfSearch.setFocused( true );
-			
+
 		} else if ( keyCode == Keyboard.KEY_LEFT && this.bPrevious.enabled ) {
 			this.actionPerformed( this.bPrevious );
 
diff --git a/src/resources/assets/mmm/lang/en_US.lang b/src/resources/assets/mmm/lang/en_US.lang
index 500e895..6feb718 100644
--- a/src/resources/assets/mmm/lang/en_US.lang
+++ b/src/resources/assets/mmm/lang/en_US.lang
@@ -7,6 +7,9 @@ gui.mmm.tech.base.am.powered=Redstone Activates
 gui.mmm.tech.base.am.unpowered=Redstone Disables
 gui.mmm.tech.base.am.disabled=Deactivated
 
+gui.mmm.recipes.map_cloning=Clone Map
+gui.mmm.recipes.map_extending=Extend Map
+
 
 item.mmm.plant.fruit.tomato.name=Tomato
 item.mmm.plant.seeds.tomato.name=Tomato Seeds