moved recipes into own class for vanilla

added gregtech recipe options
This commit is contained in:
Johannes Lohrer 2015-04-18 22:24:30 +02:00
parent 419697a0c7
commit c81efe9779
7 changed files with 404 additions and 117 deletions

View File

@ -77,13 +77,14 @@ class Proxy {
OpenComputers.channel.register(server.PacketHandler)
Loot.init()
Recipes.init()
Achievement.init()
EntityRegistry.registerModEntity(classOf[Drone], "Drone", 0, OpenComputers, 80, 1, true)
OpenComputers.log.info("Initializing mod integration.")
Mods.init()
OpenComputers.log.info("Initializing Recipes.")
Recipes.init()
}
def postInit(e: FMLPostInitializationEvent) {

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.recipe
import java.io.File
import java.io.FileReader
import java.util
import com.typesafe.config._
import cpw.mods.fml.common.Loader
@ -22,6 +23,7 @@ import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.FurnaceRecipes
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.RegistryNamespaced
import net.minecraftforge.fluids.{Fluid, FluidRegistry}
import net.minecraftforge.oredict.OreDictionary
import net.minecraftforge.oredict.RecipeSorter
import net.minecraftforge.oredict.RecipeSorter.Category
@ -34,6 +36,12 @@ object Recipes {
val list = mutable.LinkedHashMap.empty[ItemStack, String]
val oreDictEntries = mutable.LinkedHashMap.empty[String, ItemStack]
var hadErrors = false
val recipeMap = mutable.LinkedHashMap.empty[String, (ItemStack, Config) => Unit]
def registerRecipe(name: String, recipe: (ItemStack, Config) => Unit): Unit = {
recipeMap += name -> recipe
}
def addBlock(instance: Block, name: String, oreDict: String = null) = {
Items.registerBlock(instance, name)
@ -254,21 +262,10 @@ object Recipes {
val recipe = list.getConfig(name)
val recipeType = tryGetType(recipe)
try {
recipeType match {
case "shaped" => addShapedRecipe(output, recipe)
case "shapeless" => addShapelessRecipe(output, recipe)
case "furnace" => addFurnaceRecipe(output, recipe)
case "gt_assembler" =>
if (Mods.GregTech.isAvailable) {
addGTAssemblingMachineRecipe(output, recipe)
}
else {
OpenComputers.log.error(s"Skipping GregTech assembler recipe for '$name' because GregTech is not present, you will not be able to craft this item.")
hadErrors = true
}
case other =>
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid recipe type '$other'.")
hadErrors = true
recipeMap.get(recipeType) match {
case Some(x) => x(output, recipe)
case _ => OpenComputers.log.error(s"Failed adding $recipeType recipe for '$name', you will not be able to craft this item!")
}
}
catch {
@ -291,106 +288,79 @@ object Recipes {
hadErrors = true
}
}
catch {
case e: Throwable =>
OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item.", e)
hadErrors = true
// private def addRecipe(output: ItemStack, list: Config, name: String) = try {
// if (list.hasPath(name)) {
// val value = list.getValue(name)
// value.valueType match {
// case ConfigValueType.OBJECT =>
// val recipe = list.getConfig(name)
// val recipeType = tryGetType(recipe)
// try {
// recipeType match {
// case "shaped" => addShapedRecipe(output, recipe)
// case "shapeless" => addShapelessRecipe(output, recipe)
// case "furnace" => addFurnaceRecipe(output, recipe)
// case "gt_assembler" =>
// if (Mods.GregTech.isAvailable) {
// addGTAssemblingMachineRecipe(output, recipe)
// }
// else {
// OpenComputers.log.error(s"Skipping GregTech assembler recipe for '$name' because GregTech is not present, you will not be able to craft this item.")
// hadErrors = true
// }
// case "gt_alloysmelter" =>
// if (Mods.GregTech.isAvailable) {
// addGTAlloySmelterRecipe(output, recipe)
// }
// else {
// OpenComputers.log.error(s"Skipping GregTech alloy smelter recipe for '$name' because GregTech is not present, you will not be able to craft this item.")
// hadErrors = true
// }
// case other =>
// OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid recipe type '$other'.")
// hadErrors = true
// }
// }
// catch {
// case e: RecipeException =>
// OpenComputers.log.error(s"Failed adding $recipeType recipe for '$name', you will not be able to craft this item! The error was: ${e.getMessage}")
// hadErrors = true
// }
// case ConfigValueType.BOOLEAN =>
// // Explicitly disabled, keep in NEI if true.
// if (!value.unwrapped.asInstanceOf[Boolean]) {
// hide(output)
// }
// case _ =>
// OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item. The error was: Invalid value for recipe.")
// hadErrors = true
// }
// }
// else {
// OpenComputers.log.warn(s"No recipe for '$name', you will not be able to craft this item. To suppress this warning, disable the recipe (assign `false` to it).")
// hadErrors = true
// }
// }
// catch {
// case e: Throwable =>
// OpenComputers.log.error(s"Failed adding recipe for '$name', you will not be able to craft this item.", e)
// hadErrors = true
// }
def parseFluidIngredient(entry: AnyRef): Option[Fluid] = entry match {
case name: String => {
if (name == null || name.trim.isEmpty) None
else if (FluidRegistry.getFluid(name) != null) Option(FluidRegistry.getFluid(name))
else None
}
case _ => None
}
private def addShapedRecipe(output: ItemStack, recipe: Config) {
val rows = recipe.getList("input").unwrapped().map {
case row: java.util.List[AnyRef]@unchecked => row.map(parseIngredient)
case other => throw new RecipeException(s"Invalid row entry for shaped recipe (not a list: $other).")
}
output.stackSize = tryGetCount(recipe)
var number = -1
var shape = mutable.ArrayBuffer.empty[String]
val input = mutable.ArrayBuffer.empty[AnyRef]
for (row <- rows) {
val (pattern, ingredients) = row.foldLeft((new StringBuilder, Seq.empty[AnyRef]))((acc, ingredient) => {
val (pattern, ingredients) = acc
ingredient match {
case _@(_: ItemStack | _: String) =>
number += 1
(pattern.append(('a' + number).toChar), ingredients ++ Seq(Char.box(('a' + number).toChar), ingredient))
case _ => (pattern.append(' '), ingredients)
}
})
shape += pattern.toString
input ++= ingredients
}
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapedOreRecipe(output, shape ++ input: _*))
}
}
private def addShapelessRecipe(output: ItemStack, recipe: Config) {
val input = recipe.getValue("input").unwrapped() match {
case list: java.util.List[AnyRef]@unchecked => list.map(parseIngredient)
case other => Seq(parseIngredient(other))
}
output.stackSize = tryGetCount(recipe)
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(output, input: _*))
}
}
private def addGTAssemblingMachineRecipe(output: ItemStack, recipe: Config) {
val inputs = (recipe.getValue("input").unwrapped() match {
case list: java.util.List[AnyRef]@unchecked => list.map(parseIngredient)
case other => Seq(parseIngredient(other))
}) map {
case null => Array.empty[ItemStack]
case stack: ItemStack => Array(stack)
case name: String => Array(OreDictionary.getOres(name): _*)
case other => throw new RecipeException(s"Invalid ingredient type: $other.")
}
output.stackSize = tryGetCount(recipe)
if (inputs.size < 1 || inputs.size > 2) {
throw new RecipeException(s"Invalid recipe length: ${inputs.size}, should be 1 or 2.")
}
val inputCount = recipe.getIntList("count")
if (inputCount.size() != inputs.size) {
throw new RecipeException(s"Ingredient and input count mismatch: ${inputs.size} != ${inputCount.size}.")
}
val eu = recipe.getInt("eu")
val duration = recipe.getInt("time")
(inputs, inputCount).zipped.foreach((stacks, count) => stacks.foreach(stack => if (stack != null && count > 0) stack.stackSize = stack.getMaxStackSize min count))
inputs.padTo(2, null)
if (inputs.head != null) {
for (input1 <- inputs.head) {
if (inputs.last != null) {
for (input2 <- inputs.last)
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, input2, output, duration, eu)
}
else gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, null, output, duration, eu)
}
}
}
private def addFurnaceRecipe(output: ItemStack, recipe: Config) {
val input = parseIngredient(recipe.getValue("input").unwrapped())
output.stackSize = tryGetCount(recipe)
input match {
case stack: ItemStack =>
FurnaceRecipes.smelting.func_151394_a(stack, output, 0)
case name: String =>
for (stack <- OreDictionary.getOres(name)) {
FurnaceRecipes.smelting.func_151394_a(stack, output, 0)
}
case _ =>
}
}
private def parseIngredient(entry: AnyRef) = entry match {
def parseIngredient(entry: AnyRef) = entry match {
case map: java.util.Map[AnyRef, AnyRef]@unchecked =>
if (map.contains("oreDict")) {
map.get("oreDict") match {
@ -453,7 +423,7 @@ object Recipes {
private def tryGetType(recipe: Config) = if (recipe.hasPath("type")) recipe.getString("type") else "shaped"
private def tryGetCount(recipe: Config) = if (recipe.hasPath("output")) recipe.getInt("output") else 1
def tryGetCount(recipe: Config) = if (recipe.hasPath("output")) recipe.getInt("output") else 1
private def tryGetId(ingredient: java.util.Map[AnyRef, AnyRef]): Int =
if (ingredient.contains("subID")) ingredient.get("subID") match {
@ -492,6 +462,6 @@ object Recipes {
}
}
private class RecipeException(message: String) extends RuntimeException(message)
class RecipeException(message: String) extends RuntimeException(message)
}

View File

@ -40,7 +40,7 @@ object Mods {
val Forestry = new SimpleMod(IDs.Forestry)
val ForgeMultipart = new SimpleMod(IDs.ForgeMultipart)
val Galacticraft = new SimpleMod(IDs.Galacticraft, providesPower = true)
val GregTech = new ClassBasedMod(IDs.GregTech,"gregtech.api.GregTech_API")()
val GregTech = new ClassBasedMod(IDs.GregTech, "gregtech.api.GregTech_API")()
val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2, providesPower = true)
val IndustrialCraft2Classic = new SimpleMod(IDs.IndustrialCraft2Classic, providesPower = true)
val Mekanism = new SimpleMod(IDs.Mekanism, providesPower = true)
@ -155,7 +155,8 @@ object Mods {
final val Factorization = "factorization"
final val Forestry = "Forestry"
final val ForgeMultipart = "ForgeMultipart"
final val DeepStorageUnit = "MineFactoryReloaded|DeepStorageUnit" // Doesn't really exist.
final val DeepStorageUnit = "MineFactoryReloaded|DeepStorageUnit"
// Doesn't really exist.
final val Galacticraft = "Galacticraft API"
final val GregTech = "gregtech"
final val IndustrialCraft2 = "IC2"

View File

@ -15,5 +15,7 @@ object ModGregtech extends ModProxy {
MinecraftForge.EVENT_BUS.register(EventHandlerGregTech)
Driver.add(new DriverEnergyContainer)
RecipeRegistry.init()
}
}

View File

@ -0,0 +1,236 @@
package li.cil.oc.integration.gregtech
import java.util
import com.typesafe.config.Config
import li.cil.oc.common.recipe.Recipes
import li.cil.oc.common.recipe.Recipes.RecipeException
import net.minecraft.item.ItemStack
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.oredict.OreDictionary
import scala.collection.convert.WrapAsScala._
object RecipeRegistry {
def getGTRecipesWithEU(output: ItemStack, recipe: Config): (Array[ItemStack], Option[Array[ItemStack]], Option[FluidStack], Option[FluidStack], Option[ItemStack], Int, Int) = {
val inputs = (recipe.getValue("input").unwrapped() match {
case list: util.List[AnyRef]@unchecked => list.map(Recipes.parseIngredient)
case other => Seq(Recipes.parseIngredient(other))
}) map {
case null => Array.empty[ItemStack]
case stack: ItemStack => Array(stack)
case name: String => Array(OreDictionary.getOres(name): _*)
case other => throw new RecipeException(s"Invalid ingredient type: $other.")
}
output.stackSize = Recipes.tryGetCount(recipe)
if (inputs.size < 1 || inputs.size > 2) {
throw new RecipeException(s"Invalid recipe length: ${inputs.size}, should be 1 or 2.")
}
val inputCount = recipe.getIntList("count")
if (inputCount.size() != inputs.size) {
throw new RecipeException(s"Ingredient and input count mismatch: ${inputs.size} != ${inputCount.size}.")
}
var inputFluidStack: Option[FluidStack] = None: Option[FluidStack]
if (recipe.hasPath("inputLiquid")) Recipes.parseFluidIngredient(recipe.getString("inputLiquid")) match {
case Some(fluid) =>
var inputFluidAmount = 1000
if (recipe.hasPath("inputFluidAmount")) inputFluidAmount = recipe.getInt("inputFluidAmount")
inputFluidStack = Option(new FluidStack(fluid, inputFluidAmount))
case _ =>
}
var outputFluidStack: Option[FluidStack] = None: Option[FluidStack]
if (recipe.hasPath("outputLiquid")) Recipes.parseFluidIngredient(recipe.getString("outputLiquid")) match {
case Some(fluid) =>
var fluidAmount = 1000
if (recipe.hasPath("outputFluidAmount")) fluidAmount = recipe.getInt("outputFluidAmount")
outputFluidStack = Option(new FluidStack(fluid, fluidAmount))
case _ =>
}
val eu = recipe.getInt("eu")
val duration = recipe.getInt("time")
//TODO add output
val additionalOutput: Option[ItemStack] = None
(inputs, inputCount).zipped.foreach((stacks, count) => stacks.foreach(stack => if (stack != null && count > 0) stack.stackSize = stack.getMaxStackSize min count))
inputs.padTo(2, null)
val input = inputs.head
(input, Option(inputs.last), inputFluidStack, outputFluidStack, additionalOutput, eu, duration)
}
def addGTAlloySmelterRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
inputs2 match {
case Some(inputs2List) =>
for (input2 <- inputs2List)
gregtech.api.GregTech_API.sRecipeAdder.addAlloySmelterRecipe(input1, input2, output, duration, eu)
case None =>
gregtech.api.GregTech_API.sRecipeAdder.addAlloySmelterRecipe(input1, null, output, duration, eu)
}
}
}
def addGTAssemblingMachineRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
inputs2 match {
case Some(inputs2List) =>
for (input2 <- inputs2List)
fluidStackIn match {
case Some(fluid) =>
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, input2, fluid, output, duration, eu)
case None =>
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, input2, output, duration, eu)
}
case None =>
fluidStackIn match {
case Some(fluid) =>
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, null, fluid, output, duration, eu)
case None =>
gregtech.api.GregTech_API.sRecipeAdder.addAssemblerRecipe(input1, null, output, duration, eu)
}
}
}
}
def addGTBenderRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
gregtech.api.GregTech_API.sRecipeAdder.addBenderRecipe(input1, output, duration, eu)
}
}
def addGTCutterRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
var add :ItemStack = null
additionalOutput match{
case Some(a) => add = a
case _=>
}
for (input1 <- inputs1) {
fluidStackIn match {
case Some(fluid) =>
gregtech.api.GregTech_API.sRecipeAdder.addCutterRecipe(input1, fluid, output, add, duration, eu)
case None =>
gregtech.api.GregTech_API.sRecipeAdder.addCutterRecipe(input1, output, add, duration, eu)
}
}
}
def addGTCannerRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
var add :ItemStack = null
additionalOutput match{
case Some(a) => add = a
case _=>
}
for (input1 <- inputs1) {
inputs2 match {
case Some(inputs2List) =>
for (input2 <- inputs2List)
gregtech.api.GregTech_API.sRecipeAdder.addCannerRecipe(input1, input2, output, add, duration, eu)
case None =>
gregtech.api.GregTech_API.sRecipeAdder.addCannerRecipe(input1, null, output, add, duration, eu)
}
}
}
def addGTChemicalRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
inputs2 match {
case Some(inputs2List) =>
for (input2 <- inputs2List)
fluidStackIn match {
case Some(fluid) =>
fluidStackOut match {
case Some(fluidOut) =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, input2, fluid, fluidOut, output, duration)
case _ =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, input2, fluid, null, output, duration)
}
case None =>
fluidStackOut match {
case Some(fluidOut) =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, input2, null, fluidOut, output, duration)
case _ =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, input2, output, duration)
}
}
case None =>
fluidStackIn match {
case Some(fluid) =>
fluidStackOut match {
case Some(fluidOut) =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, null, fluid, fluidOut, output, duration)
case _ =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, null, fluid, null, output, duration)
}
case None =>
fluidStackOut match {
case Some(fluidOut) =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, null, null, fluidOut, output, duration)
case _ =>
gregtech.api.GregTech_API.sRecipeAdder.addChemicalRecipe(input1, null, output, duration)
}
}
}
}
}
def addGTCNCRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
gregtech.api.GregTech_API.sRecipeAdder.addCNCRecipe(input1, output, duration, eu)
}
}
def addGTLatheRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
var add :ItemStack = null
additionalOutput match{
case Some(a) => add = a
case _=>
}
for (input1 <- inputs1) {
gregtech.api.GregTech_API.sRecipeAdder.addLatheRecipe(input1, output, add, duration, eu)
}
}
def addGTWireMillRecipe(output: ItemStack, recipe: Config) {
val (inputs1, inputs2, fluidStackIn, fluidStackOut, additionalOutput, eu, duration) = getGTRecipesWithEU(output, recipe)
for (input1 <- inputs1) {
gregtech.api.GregTech_API.sRecipeAdder.addWiremillRecipe(input1, output, duration, eu)
}
}
def init(): Unit = {
Recipes.registerRecipe("gt_alloySmelter", addGTAlloySmelterRecipe)
Recipes.registerRecipe("gt_assembler", addGTAssemblingMachineRecipe)
Recipes.registerRecipe("gt_bender", addGTBenderRecipe)
Recipes.registerRecipe("gt_canner", addGTCannerRecipe)
Recipes.registerRecipe("gt_chemical", addGTChemicalRecipe)
Recipes.registerRecipe("gt_cnc", addGTCNCRecipe)
Recipes.registerRecipe("gt_cutter", addGTCutterRecipe)
Recipes.registerRecipe("gt_lathe", addGTLatheRecipe)
Recipes.registerRecipe("gt_wiremill", addGTWireMillRecipe)
}
}

View File

@ -34,5 +34,6 @@ object ModVanilla extends ModProxy {
Driver.add(ConverterNBT)
Driver.add(ConverterWorld)
Driver.add(ConverterWorldProvider)
RecipeRegistry.init()
}
}

View File

@ -0,0 +1,76 @@
package li.cil.oc.integration.vanilla
import com.typesafe.config.Config
import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc.common.recipe.Recipes.RecipeException
import li.cil.oc.common.recipe.{Recipes, ExtendedShapelessOreRecipe, ExtendedShapedOreRecipe}
import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.FurnaceRecipes
import net.minecraftforge.oredict.OreDictionary
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
object RecipeRegistry {
def addShapedRecipe(output: ItemStack, recipe: Config) {
val rows = recipe.getList("input").unwrapped().map {
case row: java.util.List[AnyRef]@unchecked => row.map(Recipes.parseIngredient)
case other => throw new RecipeException(s"Invalid row entry for shaped recipe (not a list: $other).")
}
output.stackSize = Recipes.tryGetCount(recipe)
var number = -1
var shape = mutable.ArrayBuffer.empty[String]
val input = mutable.ArrayBuffer.empty[AnyRef]
for (row <- rows) {
val (pattern, ingredients) = row.foldLeft((new StringBuilder, Seq.empty[AnyRef]))((acc, ingredient) => {
val (pattern, ingredients) = acc
ingredient match {
case _@(_: ItemStack | _: String) =>
number += 1
(pattern.append(('a' + number).toChar), ingredients ++ Seq(Char.box(('a' + number).toChar), ingredient))
case _ => (pattern.append(' '), ingredients)
}
})
shape += pattern.toString
input ++= ingredients
}
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapedOreRecipe(output, shape ++ input: _*))
}
}
def addShapelessRecipe(output: ItemStack, recipe: Config) {
val input = recipe.getValue("input").unwrapped() match {
case list: java.util.List[AnyRef]@unchecked => list.map(Recipes.parseIngredient)
case other => Seq(Recipes.parseIngredient(other))
}
output.stackSize = Recipes.tryGetCount(recipe)
if (input.size > 0 && output.stackSize > 0) {
GameRegistry.addRecipe(new ExtendedShapelessOreRecipe(output, input: _*))
}
}
def addFurnaceRecipe(output: ItemStack, recipe: Config) {
val input = Recipes.parseIngredient(recipe.getValue("input").unwrapped())
output.stackSize = Recipes.tryGetCount(recipe)
input match {
case stack: ItemStack =>
FurnaceRecipes.smelting.func_151394_a(stack, output, 0)
case name: String =>
for (stack <- OreDictionary.getOres(name)) {
FurnaceRecipes.smelting.func_151394_a(stack, output, 0)
}
case _ =>
}
}
def init(): Unit = {
Recipes.registerRecipe("shaped", addShapedRecipe)
Recipes.registerRecipe("shapeless", addShapelessRecipe)
Recipes.registerRecipe("furnace", addFurnaceRecipe)
}
}