electrodynamics/src/main/scala/edx/core/resource/AutoResourceFactory.scala
2015-01-26 19:40:54 +08:00

256 lines
9.2 KiB
Scala

package edx.core.resource
import java.awt._
import java.awt.image.BufferedImage
import java.io.InputStream
import javax.imageio.ImageIO
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import cpw.mods.fml.common.registry.LanguageRegistry
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.basic.BasicContent
import edx.core.resource.content._
import edx.core.{Reference, Settings}
import net.minecraft.block.Block
import net.minecraft.client.Minecraft
import net.minecraft.init.Blocks
import net.minecraft.item.crafting.FurnaceRecipes
import net.minecraft.item.{Item, ItemStack}
import net.minecraft.util.{IIcon, ResourceLocation}
import net.minecraftforge.client.event.TextureStitchEvent
import net.minecraftforge.fluids.{Fluid, FluidContainerRegistry, FluidRegistry, FluidStack}
import net.minecraftforge.oredict.OreDictionary
import resonantengine.api.recipe.{MachineRecipes, RecipeType}
import resonantengine.lib.factory.resources.ResourceFactory
import resonantengine.lib.utility.LanguageUtility
import resonantengine.lib.wrapper.StringWrapper._
import scala.collection.convert.wrapAll._
import scala.collection.mutable
/**
* @author Calclavia
*/
object AutoResourceFactory
{
/**
* A list of materials
*/
val materials = mutable.Set.empty[String]
val blackList = Array("uranium")
/**
* Reference to computed color tint of auto-generated ores
*/
val iconColorCache = mutable.Map.empty[IIcon, Integer]
val moltenFluidMap = mutable.Map.empty[String, Block]
val moltenBucketMap = mutable.Map.empty[String, Item]
val mixtureBucketMap = mutable.Map.empty[String, Item]
def init()
{
//Register resource types
ResourceFactory.registerResourceItem("rubble", classOf[ItemRubble])
ResourceFactory.registerResourceItem("dust", classOf[ItemDust])
ResourceFactory.registerResourceItem("refinedDust", classOf[ItemRefinedDust])
ResourceFactory.registerResourceItem("bucketMolten", classOf[ItemMoltenBucket])
//Create copper and tin ingots and ores
ResourceFactory.registerMaterial("copper")
ResourceFactory.requestItem("ingot", "copper")
ResourceFactory.requestBlock("ore", "copper")
ResourceFactory.registerMaterialColor("copper", 0xC27A48)
ResourceFactory.registerMaterial("tin")
ResourceFactory.requestItem("ingot", "tin")
ResourceFactory.requestBlock("ore", "tin")
ResourceFactory.registerMaterialColor("tin", 0xAFBFB2)
OreDictionary.initVanillaEntries()
//Add vanilla ingots to auto generate
registerAutoMaterial("gold")
registerAutoMaterial("iron")
registerAutoMaterial("copper")
registerAutoMaterial("tin")
}
def registerAutoMaterial(material: String)
{
if (!materials.contains(material) && OreDictionary.getOres("ore" + material.capitalizeFirst).size > 0)
{
Settings.config.load()
val allowMaterial = Settings.config.get("Resource-Generator", "Enable " + material, true).getBoolean(true)
Settings.config.save()
if (allowMaterial && !blackList.contains(material))
{
materials += material
}
}
}
def postInit()
{
//Add vanilla ore processing recipes
MachineRecipes.instance.addRecipe(RecipeType.SMELTER.name, new FluidStack(FluidRegistry.LAVA, FluidContainerRegistry.BUCKET_VOLUME), new ItemStack(Blocks.stone))
MachineRecipes.instance.addRecipe(RecipeType.GRINDER.name, Blocks.cobblestone, Blocks.gravel)
MachineRecipes.instance.addRecipe(RecipeType.GRINDER.name, Blocks.stone, Blocks.cobblestone)
MachineRecipes.instance.addRecipe(RecipeType.SAWMILL.name, Blocks.log, new ItemStack(Blocks.planks, 7, 0))
MachineRecipes.instance.addRecipe(RecipeType.SIFTER.name, Blocks.gravel, Blocks.sand)
MachineRecipes.instance.addRecipe(RecipeType.SIFTER.name, Blocks.glass, Blocks.sand)
//Call generate() on all materials
materials.foreach(generate)
Reference.logger.fine("Resource Factory generated " + materials.size + " resources.")
}
def generate(material: String)
{
ResourceFactory.registerMaterial(material)
val nameCaps: String = LanguageUtility.capitalizeFirst(material)
var localizedName: String = material
//Fix the material name
val ingotNames = OreDictionary.getOres("ingot" + nameCaps)
if (ingotNames.size > 0)
{
val firstIngotStack = ingotNames(0)
localizedName = firstIngotStack.getDisplayName.trim
if (localizedName.getLocal != null && localizedName.getLocal != "")
localizedName = localizedName.getLocal
localizedName = localizedName.replaceAll("misc.ingot".getLocal, "").trim
}
//Generate molten fluid
val fluidMolten = new Fluid("molten" + nameCaps).setDensity(7).setViscosity(5000).setTemperature(273 + 1538)
FluidRegistry.registerFluid(fluidMolten)
LanguageRegistry.instance.addStringLocalization(fluidMolten.getUnlocalizedName, LanguageUtility.getLocal("misc.molten") + " " + localizedName)
val blockFluidMaterial = new BlockFluidMaterial(fluidMolten)
BasicContent.manager.newBlock("molten" + nameCaps, blockFluidMaterial)
moltenFluidMap += (material -> blockFluidMaterial)
//Generate resource items: moltenBucket, rubble, dust and refined dust
val results = ResourceFactory.requestItems(material, "ingot")
results.foreach(keyVal => LanguageRegistry.instance.addStringLocalization(keyVal._2.getUnlocalizedName + ".name", localizedName + " " + ("misc." + keyVal._1).getLocal))
val rubble = new ItemStack(ResourceFactory.getItem("rubble", material))
val dust = new ItemStack(ResourceFactory.getItem("dust", material))
val refinedDust = new ItemStack(ResourceFactory.getItem("refinedDust", material))
FluidContainerRegistry.registerFluidContainer(fluidMolten, new ItemStack(ResourceFactory.getItem("bucketMolten", material)))
//Add recipes
MachineRecipes.instance.addRecipe(RecipeType.SMELTER.name, new FluidStack(fluidMolten, FluidContainerRegistry.BUCKET_VOLUME), "ingot" + nameCaps)
MachineRecipes.instance.addRecipe(RecipeType.SIFTER.name, "rubble" + nameCaps, dust, dust)
MachineRecipes.instance.addRecipe(RecipeType.MIXER.name, "dust" + nameCaps, refinedDust)
FurnaceRecipes.smelting.func_151394_a(dust, OreDictionary.getOres("ingot" + nameCaps).get(0).copy, 0.7f)
FurnaceRecipes.smelting.func_151394_a(refinedDust, OreDictionary.getOres("ingot" + nameCaps).get(0).copy, 0.7f)
if (OreDictionary.getOres("ore" + nameCaps).size > 0)
MachineRecipes.instance.addRecipe(RecipeType.GRINDER.name, "ore" + nameCaps, "rubble" + nameCaps)
}
@SubscribeEvent
def oreRegisterEvent(evt: OreDictionary.OreRegisterEvent)
{
if (evt.Name.startsWith("ingot"))
{
val oreDictName = evt.Name.replace("ingot", "")
val materialName = oreDictName.decapitalizeFirst
registerAutoMaterial(materialName)
}
}
@SubscribeEvent
@SideOnly(Side.CLIENT)
def reloadTextures(e: TextureStitchEvent.Post)
{
computeColors()
}
@SideOnly(Side.CLIENT)
def computeColors()
{
for (material <- materials)
{
for (ingotStack <- OreDictionary.getOres("ingot" + LanguageUtility.capitalizeFirst(material)))
{
ResourceFactory.registerMaterialColor(material, getAverageColor(ingotStack))
}
}
}
/**
* Gets the average color of this item by looking at each pixel of the texture.
*
* @param itemStack - The itemStack
* @return The RGB hexadecimal color code.
*/
@SideOnly(Side.CLIENT)
def getAverageColor(itemStack: ItemStack): Int =
{
var totalR: Int = 0
var totalG: Int = 0
var totalB: Int = 0
var colorCount: Int = 0
val item: Item = itemStack.getItem
try
{
val icon: IIcon = item.getIconIndex(itemStack)
if (iconColorCache.containsKey(icon))
{
return iconColorCache(icon)
}
var iconString: String = icon.getIconName
if (iconString != null && !iconString.contains("MISSING_ICON_ITEM"))
{
iconString = (if (iconString.contains(":")) iconString.replace(":", ":" + Reference.itemTextureDirectory) else Reference.itemTextureDirectory + iconString) + ".png"
val textureLocation: ResourceLocation = new ResourceLocation(iconString)
val inputstream: InputStream = Minecraft.getMinecraft.getResourceManager.getResource(textureLocation).getInputStream
val bufferedimage: BufferedImage = ImageIO.read(inputstream)
val width: Int = bufferedimage.getWidth
val height: Int = bufferedimage.getWidth
for (x <- 0 until width; y <- 0 until height)
{
val rgb: Color = new Color(bufferedimage.getRGB(x, y))
val luma: Double = 0.2126 * rgb.getRed + 0.7152 * rgb.getGreen + 0.0722 * rgb.getBlue
if (luma > 40)
{
totalR += rgb.getRed
totalG += rgb.getGreen
totalB += rgb.getBlue
colorCount += 1
}
}
}
if (colorCount > 0)
{
totalR /= colorCount
totalG /= colorCount
totalB /= colorCount
val averageColor: Int = new Color(totalR, totalG, totalB).brighter.getRGB
iconColorCache.put(icon, averageColor)
return averageColor
}
}
catch
{
case e: Exception =>
{
Reference.logger.fine("Failed to compute colors for: " + item)
}
}
return 0xFFFFFF
}
}