package slimeknights.tconstruct.smeltery;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.eventbus.Subscribe;
import net.minecraft.block.Block;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.ShapedRecipes;
import net.minecraft.item.crafting.ShapelessRecipes;
import net.minecraft.util.IStringSerializable;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import slimeknights.mantle.block.EnumBlock;
import slimeknights.mantle.item.ItemBlockMeta;
import slimeknights.mantle.pulsar.pulse.Pulse;
import slimeknights.mantle.util.RecipeMatch;
import slimeknights.tconstruct.TinkerIntegration;
import slimeknights.tconstruct.common.CommonProxy;
import slimeknights.tconstruct.common.TinkerPulse;
import slimeknights.tconstruct.common.config.Config;
import slimeknights.tconstruct.library.TinkerRegistry;
import slimeknights.tconstruct.library.Util;
import slimeknights.tconstruct.library.materials.Material;
import slimeknights.tconstruct.library.smeltery.BucketCastingRecipe;
import slimeknights.tconstruct.library.smeltery.Cast;
import slimeknights.tconstruct.library.smeltery.CastingRecipe;
import slimeknights.tconstruct.library.smeltery.MeltingRecipe;
import slimeknights.tconstruct.library.smeltery.OreCastingRecipe;
import slimeknights.tconstruct.library.tinkering.MaterialItem;
import slimeknights.tconstruct.library.tools.IToolPart;
import slimeknights.tconstruct.shared.TinkerCommons;
import slimeknights.tconstruct.shared.TinkerFluids;
import slimeknights.tconstruct.shared.block.BlockSlime;
import slimeknights.tconstruct.smeltery.block.BlockCasting;
import slimeknights.tconstruct.smeltery.block.BlockFaucet;
import slimeknights.tconstruct.smeltery.block.BlockSeared;
import slimeknights.tconstruct.smeltery.block.BlockSearedFurnaceController;
import slimeknights.tconstruct.smeltery.block.BlockSearedGlass;
import slimeknights.tconstruct.smeltery.block.BlockSearedSlab;
import slimeknights.tconstruct.smeltery.block.BlockSearedSlab2;
import slimeknights.tconstruct.smeltery.block.BlockSearedStairs;
import slimeknights.tconstruct.smeltery.block.BlockSmelteryController;
import slimeknights.tconstruct.smeltery.block.BlockSmelteryIO;
import slimeknights.tconstruct.smeltery.block.BlockTank;
import slimeknights.tconstruct.smeltery.block.BlockTinkerTankController;
import slimeknights.tconstruct.smeltery.item.CastCustom;
import slimeknights.tconstruct.smeltery.item.ItemTank;
import slimeknights.tconstruct.smeltery.tileentity.TileCastingBasin;
import slimeknights.tconstruct.smeltery.tileentity.TileCastingTable;
import slimeknights.tconstruct.smeltery.tileentity.TileDrain;
import slimeknights.tconstruct.smeltery.tileentity.TileFaucet;
import slimeknights.tconstruct.smeltery.tileentity.TileSearedFurnace;
import slimeknights.tconstruct.smeltery.tileentity.TileSmeltery;
import slimeknights.tconstruct.smeltery.tileentity.TileSmelteryComponent;
import slimeknights.tconstruct.smeltery.tileentity.TileTank;
import slimeknights.tconstruct.smeltery.tileentity.TileTinkerTank;
import slimeknights.tconstruct.tools.TinkerMaterials;
@Pulse(id = TinkerSmeltery.PulseId, description = "The smeltery and items needed for it")
public class TinkerSmeltery extends TinkerPulse {
public static final String PulseId = "TinkerSmeltery";
public static final Logger log = Util.getLogger(PulseId);
@SidedProxy(clientSide = "slimeknights.tconstruct.smeltery.SmelteryClientProxy", serverSide = "slimeknights.tconstruct.common.CommonProxy")
public static CommonProxy proxy;
// Blocks
public static BlockSeared searedBlock;
public static BlockSmelteryController smelteryController;
public static BlockTank searedTank;
public static BlockFaucet faucet;
public static BlockCasting castingBlock;
public static BlockSmelteryIO smelteryIO;
public static Block searedGlass;
public static Block searedFurnaceController;
public static Block tinkerTankController;
public static Block searedSlab;
public static Block searedSlab2;
// stairs
public static Block searedStairsStone;
public static Block searedStairsCobble;
public static Block searedStairsPaver;
public static Block searedStairsBrick;
public static Block searedStairsBrickCracked;
public static Block searedStairsBrickFancy;
public static Block searedStairsBrickSquare;
public static Block searedStairsBrickTriangle;
public static Block searedStairsBrickSmall;
public static Block searedStairsRoad;
public static Block searedStairsTile;
public static Block searedStairsCreeper;
// Items
public static Cast cast;
public static CastCustom castCustom;
public static Cast clayCast;
// itemstacks!
public static ItemStack castIngot;
public static ItemStack castNugget;
public static ItemStack castGem;
public static ItemStack castShard;
public static ItemStack castPlate;
public static ItemStack castGear;
private static Map<Fluid, Set<Pair<List<ItemStack>, Integer>>> knownOreFluids = Maps.newHashMap();
public static List<FluidStack> castCreationFluids = Lists.newLinkedList();
public static List<FluidStack> clayCreationFluids = Lists.newLinkedList();
public static ImmutableSet<Block> validSmelteryBlocks;
public static ImmutableSet<Block> searedStairsSlabs;
public static ImmutableSet<Block> validTinkerTankBlocks;
public static ImmutableSet<Block> validTinkerTankFloorBlocks;
public static List<ItemStack> meltingBlacklist = Lists.newLinkedList();
// PRE-INITIALIZATION
@Subscribe
public void preInit(FMLPreInitializationEvent event) {
searedBlock = registerEnumBlock(new BlockSeared(), "seared");
smelteryController = registerBlock(new BlockSmelteryController(), "smeltery_controller");
searedTank = registerBlock(new ItemTank(new BlockTank()), "seared_tank");
faucet = registerBlock(new BlockFaucet(), "faucet");
castingBlock = registerBlock(new ItemBlockMeta(new BlockCasting()), "casting");
smelteryIO = registerEnumBlock(new BlockSmelteryIO(), "smeltery_io");
searedGlass = registerEnumBlock(new BlockSearedGlass(), "seared_glass");
searedFurnaceController = registerBlock(new BlockSearedFurnaceController(), "seared_furnace_controller");
tinkerTankController = registerBlock(new BlockTinkerTankController(), "tinker_tank_controller");
ItemBlockMeta.setMappingProperty(searedTank, BlockTank.TYPE);
ItemBlockMeta.setMappingProperty(castingBlock, BlockCasting.TYPE);
// slabs
searedSlab = registerEnumBlockSlab(new BlockSearedSlab(), "seared_slab");
searedSlab2 = registerEnumBlockSlab(new BlockSearedSlab2(), "seared_slab2");
// stairs
searedStairsStone = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.STONE, "seared_stairs_stone");
searedStairsCobble = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.COBBLE, "seared_stairs_cobble");
searedStairsPaver = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.PAVER, "seared_stairs_paver");
searedStairsBrick = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK, "seared_stairs_brick");
searedStairsBrickCracked = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK_CRACKED, "seared_stairs_brick_cracked");
searedStairsBrickFancy = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK_FANCY, "seared_stairs_brick_fancy");
searedStairsBrickSquare = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK_SQUARE, "seared_stairs_brick_square");
searedStairsBrickTriangle = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK_TRIANGLE, "seared_stairs_brick_triangle");
searedStairsBrickSmall = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.BRICK_SMALL, "seared_stairs_brick_small");
searedStairsRoad = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.ROAD, "seared_stairs_road");
searedStairsTile = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.TILE, "seared_stairs_tile");
searedStairsCreeper = registerBlockSearedStairsFrom(searedBlock, BlockSeared.SearedType.CREEPER, "seared_stairs_creeper");
registerTE(TileSmeltery.class, "smeltery_controller");
registerTE(TileSmelteryComponent.class, "smeltery_component");
registerTE(TileTank.class, "tank");
registerTE(TileFaucet.class, "faucet");
registerTE(TileCastingTable.class, "casting_table");
registerTE(TileCastingBasin.class, "casting_basin");
registerTE(TileDrain.class, "smeltery_drain");
registerTE(TileSearedFurnace.class, "seared_furnace");
registerTE(TileTinkerTank.class, "tinker_tank");
cast = registerItem(new Cast(), "cast");
castCustom = registerItem(new CastCustom(), "cast_custom");
castIngot = castCustom.addMeta(0, "ingot", Material.VALUE_Ingot);
castNugget = castCustom.addMeta(1, "nugget", Material.VALUE_Nugget);
castGem = castCustom.addMeta(2, "gem", Material.VALUE_Gem);
castPlate = castCustom.addMeta(3, "plate", Material.VALUE_Ingot);
castGear = castCustom.addMeta(4, "gear", Material.VALUE_Ingot * 4);
clayCast = registerItem(new Cast(), "clay_cast");
if(TinkerRegistry.getShard() != null) {
TinkerRegistry.addCastForItem(TinkerRegistry.getShard());
castShard = new ItemStack(cast);
Cast.setTagForPart(castShard, TinkerRegistry.getShard());
}
proxy.preInit();
TinkerRegistry.tabSmeltery.setDisplayIcon(new ItemStack(searedTank));
// smeltery blocks
ImmutableSet.Builder<Block> builder = ImmutableSet.builder();
builder.add(searedBlock);
builder.add(searedTank);
builder.add(smelteryIO);
builder.add(searedGlass);
validSmelteryBlocks = builder.build();
validTinkerTankBlocks = builder.build(); // same blocks right now
validTinkerTankFloorBlocks = ImmutableSet.of(searedBlock, searedGlass, smelteryIO);
// seared furnace ceiling blocks, no smelteryIO or seared glass
// does not affect sides, those are forced to use seared blocks/tanks where relevant
builder = ImmutableSet.builder();
builder.add(searedBlock);
builder.add(searedSlab);
builder.add(searedSlab2);
builder.add(searedStairsStone);
builder.add(searedStairsCobble);
builder.add(searedStairsPaver);
builder.add(searedStairsBrick);
builder.add(searedStairsBrickCracked);
builder.add(searedStairsBrickFancy);
builder.add(searedStairsBrickSquare);
builder.add(searedStairsBrickTriangle);
builder.add(searedStairsBrickSmall);
builder.add(searedStairsRoad);
builder.add(searedStairsTile);
builder.add(searedStairsCreeper);
searedStairsSlabs = builder.build();
}
// INITIALIZATION
@Subscribe
public void init(FMLInitializationEvent event) {
// done here so they're present for integration in MaterialIntegration and fluids in TinkerFluids are also initialized
castCreationFluids.add(new FluidStack(TinkerFluids.gold, Material.VALUE_Ingot * 2));
if(TinkerIntegration.isIntegrated(TinkerFluids.brass)) {
castCreationFluids.add(new FluidStack(TinkerFluids.brass, Material.VALUE_Ingot));
}
if(TinkerIntegration.isIntegrated(TinkerFluids.alubrass)) {
castCreationFluids.add(new FluidStack(TinkerFluids.alubrass, Material.VALUE_Ingot));
}
if(FluidRegistry.isFluidRegistered(TinkerFluids.clay)) {
clayCreationFluids.add(new FluidStack(TinkerFluids.clay, Material.VALUE_Ingot * 2));
}
registerRecipes();
proxy.init();
}
private void registerRecipes() {
// storing stacks for following recipes, mainly slabs and stairs
ItemStack stackSearedStone = new ItemStack(searedBlock, 1, BlockSeared.SearedType.STONE.getMeta());
ItemStack stackSearedCobble = new ItemStack(searedBlock, 1, BlockSeared.SearedType.COBBLE.getMeta());
ItemStack stackSearedPaver = new ItemStack(searedBlock, 1, BlockSeared.SearedType.PAVER.getMeta());
ItemStack stackSearedBrick = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK.getMeta());
ItemStack stackSearedBrickCracked = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK_CRACKED.getMeta());
ItemStack stackSearedBrickFancy = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK_FANCY.getMeta());
ItemStack stackSearedBrickSquare = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK_SQUARE.getMeta());
ItemStack stackSearedBrickTriangle = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK_TRIANGLE.getMeta());
ItemStack stackSearedBrickSmall = new ItemStack(searedBlock, 1, BlockSeared.SearedType.BRICK_SMALL.getMeta());
ItemStack stackSearedRoad = new ItemStack(searedBlock, 1, BlockSeared.SearedType.ROAD.getMeta());
ItemStack stackSearedTile = new ItemStack(searedBlock, 1, BlockSeared.SearedType.TILE.getMeta());
ItemStack stackSearedCreeper = new ItemStack(searedBlock, 1, BlockSeared.SearedType.CREEPER.getMeta());
// I AM GROUT
ItemStack grout = TinkerCommons.grout.copy();
grout.stackSize = 2;
GameRegistry.addRecipe(new ShapelessOreRecipe(grout, Items.CLAY_BALL, Blocks.GRAVEL, "sand"));
grout = grout.copy();
grout.stackSize = 8;
GameRegistry.addRecipe(new ShapelessOreRecipe(grout, Blocks.GRAVEL, "sand", Blocks.GRAVEL, "sand", Blocks.CLAY, "sand", Blocks.GRAVEL, "sand", Blocks.GRAVEL));
// seared bricks
ItemStack searedBrick = TinkerCommons.searedBrick;
GameRegistry.addSmelting(TinkerCommons.grout, searedBrick, 0);
GameRegistry.addShapedRecipe(stackSearedBrick, "bb", "bb", 'b', searedBrick);
// you always seem to have a few leftover bricks
GameRegistry.addShapedRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.BRICK.getMeta()), "bb", 'b', searedBrick);
// remaining smeltery component recipes
GameRegistry.addRecipe(new ItemStack(smelteryController),
"bbb", "b b", "bbb", 'b', searedBrick); // Controller
GameRegistry.addRecipe(new ItemStack(smelteryIO, 1, BlockSmelteryIO.IOType.DRAIN.getMeta()),
"b b", "b b", "b b", 'b', searedBrick); // Drain
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(searedTank, 1, BlockTank.TankType.TANK.getMeta()),
"bbb", "bgb", "bbb", 'b', searedBrick, 'g', "blockGlass")); // Tank
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(searedTank, 1, BlockTank.TankType.GAUGE.getMeta()),
"bgb", "ggg", "bgb", 'b', searedBrick, 'g', "blockGlass")); // Glass
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(searedTank, 1, BlockTank.TankType.WINDOW.getMeta()),
"bgb", "bgb", "bgb", 'b', searedBrick, 'g', "blockGlass")); // Window
// glass, requires clear glass rather than regular like the stained variants
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(searedGlass, 1, BlockSearedGlass.GlassType.GLASS.getMeta()),
" b ", "bgb", " b ", 'b', searedBrick, 'g', "blockGlass"));
GameRegistry.addRecipe(new ItemStack(castingBlock, 1, BlockCasting.CastingType.TABLE.getMeta()),
"bbb", "b b", "b b", 'b', searedBrick); // Table
GameRegistry.addRecipe(new ItemStack(castingBlock, 1, BlockCasting.CastingType.BASIN.getMeta()),
"b b", "b b", "bbb", 'b', searedBrick); // Basin
GameRegistry.addRecipe(new ItemStack(faucet),
"b b", " b ", 'b', searedBrick); // Faucet
//GameRegistry.addRecipe(new ItemStack(TinkerSmeltery.castingChannel, 4, 0), "b b", "bbb", 'b', searedBrick); // Channel
// seared furnace, uses a furnace in the center as just bricks gets the smeltery controller
// there is an alternative recipe below using the casting basin
GameRegistry.addRecipe(new ItemStack(searedFurnaceController), "bbb", "bfb", "bbb", 'b', searedBrick, 'f', Blocks.FURNACE);
// Tinker Tank, same as above but with a bucket
GameRegistry.addRecipe(new ItemStack(tinkerTankController), "bbb", "bub", "bbb", 'b', searedBrick, 'u', Items.BUCKET);
// polish stone into the paver
addSearedBrickRecipe(BlockSeared.SearedType.PAVER, BlockSeared.SearedType.STONE);
addSearedBrickRecipe(BlockSeared.SearedType.BRICK, BlockSeared.SearedType.PAVER);
// remaining seared bricks
addSearedBrickRecipe(BlockSeared.SearedType.BRICK_FANCY, BlockSeared.SearedType.BRICK);
addSearedBrickRecipe(BlockSeared.SearedType.BRICK_SQUARE, BlockSeared.SearedType.BRICK_FANCY);
addSearedBrickRecipe(BlockSeared.SearedType.BRICK_TRIANGLE, BlockSeared.SearedType.BRICK_SQUARE);
addSearedBrickRecipe(BlockSeared.SearedType.CREEPER, BlockSeared.SearedType.BRICK_TRIANGLE);
addSearedBrickRecipe(BlockSeared.SearedType.BRICK_SMALL, BlockSeared.SearedType.CREEPER);
addSearedBrickRecipe(BlockSeared.SearedType.TILE, BlockSeared.SearedType.BRICK_SMALL);
addSearedBrickRecipe(BlockSeared.SearedType.ROAD, BlockSeared.SearedType.TILE);
addSearedBrickRecipe(BlockSeared.SearedType.PAVER, BlockSeared.SearedType.ROAD);
GameRegistry.addSmelting(stackSearedBrick.copy(), stackSearedBrickCracked.copy(), 0.1f);
// slabs
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.STONE.getMeta()), stackSearedStone.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.COBBLE.getMeta()), stackSearedCobble.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.PAVER.getMeta()), stackSearedPaver.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.BRICK.getMeta()), stackSearedBrick.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.BRICK_CRACKED.getMeta()), stackSearedBrickCracked.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.BRICK_FANCY.getMeta()), stackSearedBrickFancy.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.BRICK_SQUARE.getMeta()), stackSearedBrickSquare.copy());
addSlabRecipe(new ItemStack(searedSlab, 1, BlockSearedSlab.SearedType.ROAD.getMeta()), stackSearedRoad.copy());
addSlabRecipe(new ItemStack(searedSlab2, 1, BlockSearedSlab2.SearedType.CREEPER.getMeta()), stackSearedCreeper.copy());
addSlabRecipe(new ItemStack(searedSlab2, 1, BlockSearedSlab2.SearedType.BRICK_TRIANGLE.getMeta()), stackSearedBrickTriangle.copy());
addSlabRecipe(new ItemStack(searedSlab2, 1, BlockSearedSlab2.SearedType.BRICK_SMALL.getMeta()), stackSearedBrickSmall.copy());
addSlabRecipe(new ItemStack(searedSlab2, 1, BlockSearedSlab2.SearedType.TILE.getMeta()), stackSearedTile.copy());
// stairs
addStairRecipe(searedStairsStone, stackSearedStone);
addStairRecipe(searedStairsCobble, stackSearedCobble);
addStairRecipe(searedStairsPaver, stackSearedPaver);
addStairRecipe(searedStairsBrick, stackSearedBrick);
addStairRecipe(searedStairsBrickCracked, stackSearedBrickCracked);
addStairRecipe(searedStairsBrickFancy, stackSearedBrickFancy);
addStairRecipe(searedStairsBrickSquare, stackSearedBrickSquare);
addStairRecipe(searedStairsRoad, stackSearedRoad);
addStairRecipe(searedStairsCreeper, stackSearedCreeper);
addStairRecipe(searedStairsBrickTriangle, stackSearedBrickTriangle);
addStairRecipe(searedStairsBrickSmall, stackSearedBrickSmall);
addStairRecipe(searedStairsTile, stackSearedTile);
}
private void addSearedBrickRecipe(BlockSeared.SearedType out, BlockSeared.SearedType in) {
addBrickRecipe(searedBlock, out, in);
}
// POST-INITIALIZATION
@Subscribe
public void postInit(FMLPostInitializationEvent event) {
registerSmelteryFuel();
registerMeltingCasting();
registerAlloys();
registerRecipeOredictMelting();
// register remaining cast creation
for(FluidStack fs : castCreationFluids) {
TinkerRegistry.registerTableCasting(new ItemStack(cast), null, fs.getFluid(), fs.amount);
TinkerRegistry.registerTableCasting(new CastingRecipe(castGem, RecipeMatch.of("gemEmerald"), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castIngot, RecipeMatch.of("ingotBrick"), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castIngot, RecipeMatch.of("ingotBrickNether"), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castIngot, new RecipeMatch.Item(TinkerCommons.searedBrick, 1), fs, true, true));
}
proxy.postInit();
}
private void registerSmelteryFuel() {
TinkerRegistry.registerSmelteryFuel(new FluidStack(FluidRegistry.LAVA, 50), 100);
}
private void registerMeltingCasting() {
int bucket = Fluid.BUCKET_VOLUME;
// bucket casting
TinkerRegistry.registerTableCasting(BucketCastingRecipe.INSTANCE);
// Water
Fluid water = FluidRegistry.WATER;
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(Blocks.ICE, bucket), water, 305));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(Blocks.PACKED_ICE, bucket * 2), water, 310));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(Blocks.SNOW, bucket), water, 305));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(Items.SNOWBALL, bucket / 8), water, 301));
// bloooooood
TinkerRegistry.registerMelting(Items.ROTTEN_FLESH, TinkerFluids.blood, 5);
if(TinkerCommons.matSlimeBallBlood != null) {
TinkerRegistry.registerTableCasting(TinkerCommons.matSlimeBallBlood.copy(), null, TinkerFluids.blood, 160);
}
// purple slime
TinkerRegistry.registerMelting(TinkerCommons.matSlimeBallPurple, TinkerFluids.purpleSlime, Material.VALUE_SlimeBall);
ItemStack slimeblock = new ItemStack(TinkerCommons.blockSlimeCongealed, 1, BlockSlime.SlimeType.PURPLE.meta);
TinkerRegistry.registerMelting(slimeblock, TinkerFluids.purpleSlime, Material.VALUE_SlimeBall * 4);
slimeblock = new ItemStack(TinkerCommons.blockSlime, 1, BlockSlime.SlimeType.PURPLE.meta);
TinkerRegistry.registerMelting(slimeblock, TinkerFluids.purpleSlime, Material.VALUE_SlimeBall * 9);
// seared stone, takes as long as a full block to melt, but gives less
TinkerRegistry.registerMelting(MeltingRecipe.forAmount(RecipeMatch.of("stone", Material.VALUE_SearedMaterial),
TinkerFluids.searedStone, Material.VALUE_Ore()));
TinkerRegistry.registerMelting(MeltingRecipe.forAmount(RecipeMatch.of("cobblestone", Material.VALUE_SearedMaterial),
TinkerFluids.searedStone, Material.VALUE_Ore()));
// obsidian
TinkerRegistry.registerMelting(MeltingRecipe.forAmount(RecipeMatch.of("obsidian", Material.VALUE_Ore()),
TinkerFluids.obsidian, Material.VALUE_Ore()));
// note that obsidian casting gives you 2 ingot value per obsidian, while part crafting only gives 1 per obsidian
registerToolpartMeltingCasting(TinkerMaterials.obsidian);
TinkerRegistry.registerBasinCasting(new ItemStack(Blocks.OBSIDIAN), null, TinkerFluids.obsidian, Material.VALUE_Ore());
// gold is melt and castable too, but no tools. Remaining materials are done directly in the MaterialIntegration
// gold is integrated via MaterialIntegration in TinkerIntegration now
// special melting
TinkerRegistry.registerMelting(Items.IRON_HORSE_ARMOR, TinkerFluids.iron, Material.VALUE_Ingot * 8);
TinkerRegistry.registerMelting(Items.GOLDEN_HORSE_ARMOR, TinkerFluids.gold, Material.VALUE_Ingot * 8);
// register stone toolpart melting
for(IToolPart toolPart : TinkerRegistry.getToolParts()) {
if(toolPart.canBeCasted()) {
if(toolPart instanceof MaterialItem) {
ItemStack stack = toolPart.getItemstackWithMaterial(TinkerMaterials.stone);
TinkerRegistry.registerMelting(stack, TinkerFluids.searedStone, (toolPart.getCost() * Material.VALUE_SearedMaterial) / Material.VALUE_Ingot);
}
}
}
// seared block casting and melting
ItemStack blockSeared = new ItemStack(searedBlock);
blockSeared.setItemDamage(BlockSeared.SearedType.STONE.getMeta());
TinkerRegistry.registerTableCasting(TinkerCommons.searedBrick, castIngot, TinkerFluids.searedStone, Material.VALUE_SearedMaterial);
TinkerRegistry.registerBasinCasting(blockSeared, null, TinkerFluids.searedStone, Material.VALUE_SearedBlock);
ItemStack searedCobble = new ItemStack(searedBlock, 1, BlockSeared.SearedType.COBBLE.getMeta());
TinkerRegistry.registerBasinCasting(new CastingRecipe(searedCobble, RecipeMatch.of("cobblestone"), TinkerFluids.searedStone, Material.VALUE_SearedBlock - Material.VALUE_SearedMaterial, true, false));
// seared furnaces have an additional recipe above using a crafting table, to allow creation without a smeltery
// this one is convenience for those with one
TinkerRegistry.registerBasinCasting(new CastingRecipe(new ItemStack(searedFurnaceController),
RecipeMatch.of(Blocks.FURNACE),
new FluidStack(TinkerFluids.searedStone, Material.VALUE_SearedMaterial * 8),
true, true));
// seared glass convenience recipe
TinkerRegistry.registerBasinCasting(new CastingRecipe(new ItemStack(searedGlass, 1, BlockSearedGlass.GlassType.GLASS.getMeta()),
RecipeMatch.of("blockGlass"),
new FluidStack(TinkerFluids.searedStone, Material.VALUE_SearedMaterial * 4),
true, true));
// basically a pseudo-oredict of the seared blocks to support wildcard value
TinkerRegistry.registerMelting(searedBlock, TinkerFluids.searedStone, Material.VALUE_SearedBlock);
TinkerRegistry.registerMelting(TinkerCommons.searedBrick, TinkerFluids.searedStone, Material.VALUE_SearedMaterial);
TinkerRegistry.registerMelting(MeltingRecipe.forAmount(RecipeMatch.of(TinkerCommons.grout, Material.VALUE_SearedMaterial), TinkerFluids.searedStone, Material.VALUE_SearedMaterial / 3));
// melt all the dirt into mud
ItemStack stack = new ItemStack(Blocks.DIRT, 1, OreDictionary.WILDCARD_VALUE);
RecipeMatch rm = new RecipeMatch.Item(stack, 1, Material.VALUE_Ingot);
TinkerRegistry.registerMelting(MeltingRecipe.forAmount(rm, TinkerFluids.dirt, Material.VALUE_BrickBlock));
TinkerRegistry.registerTableCasting(TinkerCommons.mudBrick, castIngot, TinkerFluids.dirt, Material.VALUE_Ingot);
// hardened clay
TinkerRegistry.registerMelting(Items.CLAY_BALL, TinkerFluids.clay, Material.VALUE_Ingot);
TinkerRegistry.registerMelting(Blocks.CLAY, TinkerFluids.clay, Material.VALUE_BrickBlock);
// decided against support for melting hardened clay. Once it's hardened, it stays hard. Same for bricks.
//TinkerRegistry.registerMelting(Blocks.hardened_clay, TinkerFluids.clay, Material.VALUE_BrickBlock);
//TinkerRegistry.registerMelting(Blocks.stained_hardened_clay, TinkerFluids.clay, Material.VALUE_BrickBlock);
TinkerRegistry.registerBasinCasting(new ItemStack(Blocks.HARDENED_CLAY), null, TinkerFluids.clay, Material.VALUE_BrickBlock);
// funny thing about hardened clay. If it's stained and you wash it with water, it turns back into regular hardened clay!
TinkerRegistry.registerBasinCasting(new CastingRecipe(
new ItemStack(Blocks.HARDENED_CLAY),
RecipeMatch.of(new ItemStack(Blocks.STAINED_HARDENED_CLAY, 1, OreDictionary.WILDCARD_VALUE)),
new FluidStack(FluidRegistry.WATER, 250),
150,
true,
false));
// let's allow bricks because we're nice
if(Config.castableBricks) {
TinkerRegistry.registerTableCasting(new ItemStack(Items.BRICK), castIngot, TinkerFluids.clay, Material.VALUE_Ingot);
}
// emerald melting and casting
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("gemEmerald", Material.VALUE_Gem), TinkerFluids.emerald));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("oreEmerald", (int) (Material.VALUE_Gem * Config.oreToIngotRatio)), TinkerFluids.emerald));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("blockEmerald", Material.VALUE_Gem * 9), TinkerFluids.emerald));
TinkerRegistry.registerTableCasting(new ItemStack(Items.EMERALD), castGem, TinkerFluids.emerald, Material.VALUE_Gem);
TinkerRegistry.registerBasinCasting(new ItemStack(Blocks.EMERALD_BLOCK), null, TinkerFluids.emerald, Material.VALUE_Gem * 9);
// glass melting and casting
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("sand", Material.VALUE_Glass), TinkerFluids.glass));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("blockGlass", Material.VALUE_Glass), TinkerFluids.glass));
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of("paneGlass", Material.VALUE_Glass * 6 / 16), TinkerFluids.glass));
TinkerRegistry.registerTableCasting(new CastingRecipe(new ItemStack(Blocks.GLASS_PANE), null, TinkerFluids.glass, Material.VALUE_Glass * 6 / 16, 50));
TinkerRegistry.registerBasinCasting(new CastingRecipe(new ItemStack(TinkerCommons.blockClearGlass), null, TinkerFluids.glass, Material.VALUE_Glass, 120));
// lavawood
TinkerRegistry.registerBasinCasting(new CastingRecipe(TinkerCommons.lavawood, RecipeMatch.of("plankWood"),
new FluidStack(FluidRegistry.LAVA, 250),
100, true, false));
// red sand
TinkerRegistry.registerBasinCasting(new CastingRecipe(new ItemStack(Blocks.SAND, 1, 1),
RecipeMatch.of(new ItemStack(Blocks.SAND, 1, 0)),
new FluidStack(TinkerFluids.blood, 10),
true, false));
// melt entities into a pulp
TinkerRegistry.registerEntityMelting(EntityIronGolem.class, new FluidStack(TinkerFluids.iron, 18));
TinkerRegistry.registerEntityMelting(EntitySnowman.class, new FluidStack(FluidRegistry.WATER, 100));
TinkerRegistry.registerEntityMelting(EntityVillager.class, new FluidStack(TinkerFluids.emerald, 6));
}
private void registerAlloys() {
// 1 bucket lava + 1 bucket water = 2 ingots = 1 block obsidian
// 1000 + 1000 = 288
// 125 + 125 = 36
if(Config.obsidianAlloy) {
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.obsidian, 36),
new FluidStack(FluidRegistry.WATER, 125),
new FluidStack(FluidRegistry.LAVA, 125));
}
// 1 bucket water + 4 seared ingot + 4 mud bricks = 1 block hardened clay
// 1000 + 288 + 576 = 576
// 250 + 72 + 144 = 144
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.clay, 144),
new FluidStack(FluidRegistry.WATER, 250),
new FluidStack(TinkerFluids.searedStone, 72),
new FluidStack(TinkerFluids.dirt, 144));
// 1 iron ingot + 1 purple slime ball + seared stone in molten form = 1 knightslime ingot
// 144 + 250 + 288 = 144
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.knightslime, 72),
new FluidStack(TinkerFluids.iron, 72),
new FluidStack(TinkerFluids.purpleSlime, 125),
new FluidStack(TinkerFluids.searedStone, 144));
// i iron ingot + 1 blood... unit thingie + 1/3 gem = 1 pigiron
// 144 + 99 + 222 = 144
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.pigIron, 144),
new FluidStack(TinkerFluids.iron, 48),
new FluidStack(TinkerFluids.blood, 33),
new FluidStack(TinkerFluids.emerald, 74));
// 1 ingot cobalt + 1 ingot ardite = 1 ingot manyullyn!
// 144 + 144 = 144
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.manyullyn, 2),
new FluidStack(TinkerFluids.cobalt, 2),
new FluidStack(TinkerFluids.ardite, 2));
// 3 ingots copper + 1 ingot tin = 4 ingots bronze
if(TinkerIntegration.isIntegrated(TinkerFluids.bronze) &&
TinkerIntegration.isIntegrated(TinkerFluids.copper) &&
TinkerIntegration.isIntegrated(TinkerFluids.tin)) {
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.bronze, 4),
new FluidStack(TinkerFluids.copper, 3),
new FluidStack(TinkerFluids.tin, 1));
}
// 1 ingot gold + 1 ingot silver = 2 ingots electrum
if(TinkerIntegration.isIntegrated(TinkerFluids.electrum) &&
TinkerIntegration.isIntegrated(TinkerFluids.gold) &&
TinkerIntegration.isIntegrated(TinkerFluids.silver)) {
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.electrum, 2),
new FluidStack(TinkerFluids.gold, 1),
new FluidStack(TinkerFluids.silver, 1));
}
// 1 ingot copper + 3 ingots aluminium = 4 ingots alubrass
if(TinkerIntegration.isIntegrated(TinkerFluids.alubrass) &&
TinkerIntegration.isIntegrated(TinkerFluids.copper) &&
TinkerIntegration.isIntegrated(TinkerFluids.aluminum)) {
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.alubrass, 4),
new FluidStack(TinkerFluids.copper, 1),
new FluidStack(TinkerFluids.aluminum, 3));
}
// 2 ingots copper + 1 ingot zinc = 3 ingots brass
if(TinkerIntegration.isIntegrated(TinkerFluids.brass) &&
TinkerIntegration.isIntegrated(TinkerFluids.copper) &&
TinkerIntegration.isIntegrated(TinkerFluids.zinc)) {
TinkerRegistry.registerAlloy(new FluidStack(TinkerFluids.brass, 3),
new FluidStack(TinkerFluids.copper, 2),
new FluidStack(TinkerFluids.zinc, 1));
}
}
public static void registerToolpartMeltingCasting(Material material) {
// melt ALL the toolparts n stuff. Also cast them.
Fluid fluid = material.getFluid();
for(IToolPart toolPart : TinkerRegistry.getToolParts()) {
if(!toolPart.canBeCasted()) {
continue;
}
if(toolPart instanceof MaterialItem) {
ItemStack stack = toolPart.getItemstackWithMaterial(material);
ItemStack cast = new ItemStack(TinkerSmeltery.cast);
Cast.setTagForPart(cast, stack.getItem());
if(fluid != null) {
// melting
TinkerRegistry.registerMelting(stack, fluid, toolPart.getCost());
// casting
TinkerRegistry.registerTableCasting(stack, cast, fluid, toolPart.getCost());
}
// register cast creation from the toolparts
for(FluidStack fs : castCreationFluids) {
TinkerRegistry.registerTableCasting(new CastingRecipe(cast,
RecipeMatch.ofNBT(stack),
fs,
true, true));
}
// clay casts
if(Config.claycasts) {
ItemStack clayCast = new ItemStack(TinkerSmeltery.clayCast);
Cast.setTagForPart(clayCast, stack.getItem());
if(fluid != null) {
RecipeMatch rm = RecipeMatch.ofNBT(clayCast);
FluidStack fs = new FluidStack(fluid, toolPart.getCost());
TinkerRegistry.registerTableCasting(new CastingRecipe(stack, rm, fs, true, false));
}
for(FluidStack fs : clayCreationFluids) {
TinkerRegistry.registerTableCasting(new CastingRecipe(clayCast,
RecipeMatch.ofNBT(stack),
fs,
true, true));
}
}
}
}
// same for shard
if(castShard != null) {
ItemStack stack = TinkerRegistry.getShard(material);
int cost = TinkerRegistry.getShard().getCost();
if(fluid != null) {
// melting
TinkerRegistry.registerMelting(stack, fluid, cost);
// casting
TinkerRegistry.registerTableCasting(stack, castShard, fluid, cost);
}
// register cast creation from the toolparts
for(FluidStack fs : castCreationFluids) {
TinkerRegistry.registerTableCasting(new CastingRecipe(castShard,
RecipeMatch.ofNBT(stack),
fs,
true, true));
}
}
}
/**
* Registers melting for all directly supported pre- and suffixes of the ore.
* E.g. "Iron" -> "ingotIron", "blockIron", "oreIron",
*/
public static void registerOredictMeltingCasting(Fluid fluid, String ore) {
ImmutableSet.Builder<Pair<List<ItemStack>, Integer>> builder = ImmutableSet.builder();
Pair<List<ItemStack>, Integer> nuggetOre = Pair.of(OreDictionary.getOres("nugget" + ore), Material.VALUE_Nugget);
Pair<List<ItemStack>, Integer> ingotOre = Pair.of(OreDictionary.getOres("ingot" + ore), Material.VALUE_Ingot);
Pair<List<ItemStack>, Integer> blockOre = Pair.of(OreDictionary.getOres("block" + ore), Material.VALUE_Block);
Pair<List<ItemStack>, Integer> oreOre = Pair.of(OreDictionary.getOres("ore" + ore), Material.VALUE_Ore());
Pair<List<ItemStack>, Integer> oreNetherOre = Pair.of(OreDictionary.getOres("oreNether" + ore), (int) (2 * Material.VALUE_Ingot * Config.oreToIngotRatio));
Pair<List<ItemStack>, Integer> oreDenseOre = Pair.of(OreDictionary.getOres("denseore" + ore), (int) (3 * Material.VALUE_Ingot * Config.oreToIngotRatio));
Pair<List<ItemStack>, Integer> orePoorOre = Pair.of(OreDictionary.getOres("orePoor" + ore), (int) (Material.VALUE_Nugget * Config.oreToIngotRatio));
Pair<List<ItemStack>, Integer> plateOre = Pair.of(OreDictionary.getOres("plate" + ore), Material.VALUE_Ingot);
Pair<List<ItemStack>, Integer> gearOre = Pair.of(OreDictionary.getOres("gear" + ore), Material.VALUE_Ingot * 4);
Pair<List<ItemStack>, Integer> dustOre = Pair.of(OreDictionary.getOres("dust" + ore), Material.VALUE_Ingot);
builder.add(nuggetOre, ingotOre, blockOre, oreOre, oreNetherOre, oreDenseOre, orePoorOre, plateOre, gearOre, dustOre);
Set<Pair<List<ItemStack>, Integer>> knownOres = builder.build();
// register oredicts
for(Pair<List<ItemStack>, Integer> pair : knownOres) {
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(pair.getLeft(), pair.getRight()), fluid));
}
// register oredict castings!
// ingot casting
TinkerRegistry.registerTableCasting(new OreCastingRecipe(ingotOre.getLeft(),
RecipeMatch.ofNBT(castIngot),
fluid,
ingotOre.getRight()));
// nugget casting
TinkerRegistry.registerTableCasting(new OreCastingRecipe(nuggetOre.getLeft(),
RecipeMatch.ofNBT(castNugget),
fluid,
nuggetOre.getRight()));
// block casting
TinkerRegistry.registerBasinCasting(new OreCastingRecipe(blockOre.getLeft(),
null, // no cast
fluid,
blockOre.getRight()));
// plate casting
TinkerRegistry.registerTableCasting(new OreCastingRecipe(plateOre.getLeft(),
RecipeMatch.ofNBT(castPlate),
fluid,
plateOre.getRight()));
// gear casting
TinkerRegistry.registerTableCasting(new OreCastingRecipe(gearOre.getLeft(),
RecipeMatch.ofNBT(castGear),
fluid,
gearOre.getRight()));
// and also cast creation!
for(FluidStack fs : castCreationFluids) {
TinkerRegistry.registerTableCasting(new CastingRecipe(castIngot, RecipeMatch.of(ingotOre.getLeft()), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castNugget, RecipeMatch.of(nuggetOre.getLeft()), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castPlate, RecipeMatch.of(plateOre.getLeft()), fs, true, true));
TinkerRegistry.registerTableCasting(new CastingRecipe(castGear, RecipeMatch.of(gearOre.getLeft()), fs, true, true));
}
// used for recipe detection
knownOreFluids.put(fluid, knownOres);
}
// take all fluids we registered oredicts for and scan all recipies for oredict-recipies that we can apply this to
private static void registerRecipeOredictMelting() {
// we go through all recipies, and if it's an ore recipe we go through its contents and check if it
// only consists of one of our known oredict entries
for(IRecipe irecipe : CraftingManager.getInstance().getRecipeList()) {
// blacklisted?
boolean blacklisted = false;
for(ItemStack blacklistItem : meltingBlacklist) {
if(OreDictionary.itemMatches(blacklistItem, irecipe.getRecipeOutput(), false)) {
blacklisted = true;
break;
}
}
// recipe already has a melting recipe?
if(blacklisted || TinkerRegistry.getMelting(irecipe.getRecipeOutput()) != null) {
continue;
}
List<Object> inputs;
if(irecipe instanceof ShapelessOreRecipe) {
inputs = ((ShapelessOreRecipe) irecipe).getInput();
}
else if(irecipe instanceof ShapedOreRecipe) {
inputs = Arrays.asList(((ShapedOreRecipe) irecipe).getInput());
}
else if(irecipe instanceof ShapelessRecipes) {
inputs = Lists.<Object>newLinkedList(((ShapelessRecipes) irecipe).recipeItems);
}
else if(irecipe instanceof ShapedRecipes) {
inputs = Arrays.asList((Object[]) ((ShapedRecipes) irecipe).recipeItems);
}
else {
// not an ore recipe, stop here because we can't handle it
continue;
}
// this map holds how much of which fluid is known of the recipe
// if an recipe contains an itemstack that can't be mapped to a fluid calculation is aborted
Map<Fluid, Integer> known = Maps.newHashMap();
for(Object o : inputs) {
// can contain nulls because of shapedrecipe
if(o == null) {
continue;
}
boolean found = false;
for(Map.Entry<Fluid, Set<Pair<List<ItemStack>, Integer>>> entry : knownOreFluids.entrySet()) {
// check if it's a known oredict (all oredict lists are equal if they match the same oredict)
// OR if it's an itemstack contained in one of our oredicts
for(Pair<List<ItemStack>, Integer> pair : entry.getValue()) {
if(o == pair.getLeft() || (o instanceof ItemStack && pair.getLeft().contains(o))) {
// matches! Update fluid amount known
Integer amount = known.get(entry.getKey()); // what we found for the liquid so far
if(amount == null) {
// nothing is what we found so far.
amount = 0;
}
amount += pair.getRight();
known.put(entry.getKey(), amount);
found = true;
break;
}
}
if(found) {
break;
}
}
// not a recipe we can process, contains an item that can't melt
if(!found) {
known.clear();
break;
}
}
// add a melting recipe for it
// we only support single-liquid recipies currently :I
if(known.keySet().size() == 1) {
Fluid fluid = known.keySet().iterator().next();
ItemStack output = irecipe.getRecipeOutput().copy();
int amount = known.get(fluid) / output.stackSize;
output.stackSize = 1;
TinkerRegistry.registerMelting(new MeltingRecipe(RecipeMatch.of(output, amount), fluid));
log.trace("Added automatic melting recipe for {} ({} {})", irecipe.getRecipeOutput().toString(), amount, fluid
.getName());
}
}
}
protected static <E extends Enum<E> & EnumBlock.IEnumMeta & IStringSerializable> BlockSearedStairs registerBlockSearedStairsFrom(EnumBlock<E> block, E value, String name) {
return registerBlock(new BlockSearedStairs(block.getDefaultState().withProperty(block.prop, value)), name);
}
}