From 726ceae91f5edc1f997cadd62bab6c1cf80ec565 Mon Sep 17 00:00:00 2001 From: Vexatos Date: Mon, 22 Feb 2016 14:25:03 +0100 Subject: [PATCH] Made Hover Boots dyeable. --- .../textures/items/HoverBoots.png | Bin 461 -> 420 bytes .../textures/items/HoverBootsLight.png | Bin 0 -> 198 bytes .../renderer/item/HoverBootRenderer.scala | 7 +- .../li/cil/oc/common/item/HoverBoots.scala | 43 ++++++--- .../cil/oc/common/recipe/ColorizeRecipe.scala | 85 ++++++++++++++++++ .../oc/common/recipe/DecolorizeRecipe.scala | 44 +++++++++ .../li/cil/oc/common/recipe/Recipes.scala | 6 ++ .../scala/li/cil/oc/util/ItemColorizer.scala | 47 ++++++++++ 8 files changed, 221 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/textures/items/HoverBootsLight.png create mode 100644 src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala create mode 100644 src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala create mode 100644 src/main/scala/li/cil/oc/util/ItemColorizer.scala diff --git a/src/main/resources/assets/opencomputers/textures/items/HoverBoots.png b/src/main/resources/assets/opencomputers/textures/items/HoverBoots.png index 0096a1ccd3efc4d3497d3fe6abee70ce87e9c6cb..1a7f2d070ee59d2138e4a1f20b67a63ba06ebb37 100644 GIT binary patch delta 273 zcmX@hyo7mzibz+0Pl#*9r3!IF@(X5gcy=QV z#7XjYcVXyYmGuB}I14-?iy0WWg+Z8+Vb&Z8pdfpRr>`sf112#Z1+JBu_ih4(CVRR# zhDcnF?Z3{~Y{28X_k=)T1CwaLt`~Cu|JU;BY6^Y-_~XSbwg|Tu3(sXQWcEKWWBRF% zj3V)anYT@pzI(^IFW%*7P$Or(p`Kakn=6ak)`gSS{*?}uX8FXpW|D}Yk6lX6L~f5` zJDI0;PI$h@!&!6zo9aW3^Vcu3zhUU}*E{{!|N873b9}0Ne#Krt%fG0&>YDgZhCAwP Vq1{|=OhETBc)I$ztaD0e0sv7uW)}be delta 314 zcmZ3&e3p5Filt3VtQ&&YGO)d;mK4R1_p+%0G|+7 zaYN&nFbijU&7vIdic1v}EvoC!Y&5z9l-4T=@(cb?3SemJFAfFjobT!47*cU7rthXu zlL3$G diff --git a/src/main/resources/assets/opencomputers/textures/items/HoverBootsLight.png b/src/main/resources/assets/opencomputers/textures/items/HoverBootsLight.png new file mode 100644 index 0000000000000000000000000000000000000000..f231225103e75edf8ef897d1f5d359ca9af2133e GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNlNgVR*`uuVD4P0|!35y=~400=2cZkG{t5t@>);Q~UAJ(f=vdKfk=Z{J--XQ|z3ct4F%U_5c0< l`dWNWepc2gi;ByP3=*5wT+HQO{RbM);OXk;vd$@?2>{JkNGkvU literal 0 HcmV?d00001 diff --git a/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala b/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala index b82ebd7cf..243308b3a 100644 --- a/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala +++ b/src/main/scala/li/cil/oc/client/renderer/item/HoverBootRenderer.scala @@ -92,6 +92,8 @@ object HoverBootRenderer extends ModelBiped { bipedEars.isHidden = true bipedCloak.isHidden = true + var lightColor = 0x66DD55 + override def render(entity: Entity, f0: Float, f1: Float, f2: Float, f3: Float, f4: Float, f5: Float): Unit = { // Because Forge is being a dummy... isSneak = entity.isSneaking @@ -104,7 +106,10 @@ object HoverBootRenderer extends ModelBiped { RenderState.disableLighting() GL11.glDepthFunc(GL11.GL_LEQUAL) GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE) - GL11.glColor3ub(0x66.toByte, 0xDD.toByte, 0x55.toByte) + val r = ((lightColor >>> 16) & 0xFF).toByte + val g = ((lightColor >>> 8) & 0xFF).toByte + val b = ((lightColor >>> 0) & 0xFF).toByte + GL11.glColor3ub(r, g, b) super.render(dt) diff --git a/src/main/scala/li/cil/oc/common/item/HoverBoots.scala b/src/main/scala/li/cil/oc/common/item/HoverBoots.scala index 81fc13bfd..10593e2a1 100644 --- a/src/main/scala/li/cil/oc/common/item/HoverBoots.scala +++ b/src/main/scala/li/cil/oc/common/item/HoverBoots.scala @@ -1,19 +1,17 @@ package li.cil.oc.common.item -import cpw.mods.fml.relauncher.Side -import cpw.mods.fml.relauncher.SideOnly +import cpw.mods.fml.relauncher.{Side, SideOnly} import li.cil.oc.Settings import li.cil.oc.client.renderer.item.HoverBootRenderer import li.cil.oc.common.item.data.HoverBootsData +import li.cil.oc.util.ItemColorizer import net.minecraft.client.model.ModelBiped -import net.minecraft.entity.Entity -import net.minecraft.entity.EntityLivingBase +import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.entity.player.EntityPlayer -import net.minecraft.item.EnumRarity -import net.minecraft.item.ItemArmor -import net.minecraft.item.ItemStack -import net.minecraft.potion.Potion -import net.minecraft.potion.PotionEffect +import net.minecraft.entity.{Entity, EntityLivingBase} +import net.minecraft.item.{EnumRarity, ItemArmor, ItemStack} +import net.minecraft.potion.{Potion, PotionEffect} +import net.minecraft.util.IIcon import net.minecraft.world.World class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, 3) with traits.SimpleItem with traits.Chargeable { @@ -56,7 +54,10 @@ class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, 3) with t @SideOnly(Side.CLIENT) override def getArmorModel(entityLiving: EntityLivingBase, itemStack: ItemStack, armorSlot: Int): ModelBiped = { - if (armorSlot == armorType) HoverBootRenderer + if (armorSlot == armorType) { + HoverBootRenderer.lightColor = if (ItemColorizer.hasColor(itemStack)) ItemColorizer.getColor(itemStack) else 0x66DD55 + HoverBootRenderer + } else super.getArmorModel(entityLiving, itemStack, armorSlot) } @@ -72,6 +73,28 @@ class HoverBoots extends ItemArmor(ItemArmor.ArmorMaterial.DIAMOND, 0, 3) with t } } + @SideOnly(Side.CLIENT) + var lightOverlay: IIcon = null + + @SideOnly(Side.CLIENT) + override def registerIcons(ir: IIconRegister): Unit = { + this.itemIcon = ir.registerIcon(this.getIconString) + this.lightOverlay = ir.registerIcon(this.getIconString + "Light") + } + + @SideOnly(Side.CLIENT) + override def requiresMultipleRenderPasses(): Boolean = true + + @SideOnly(Side.CLIENT) + override def getIconFromDamageForRenderPass(meta : Int, pass : Int): IIcon = if (pass == 1 ) lightOverlay else super.getIconFromDamageForRenderPass(meta, pass) + + override def getColorFromItemStack(itemStack: ItemStack, pass: Int): Int = { + if (pass == 1) { + return if (ItemColorizer.hasColor(itemStack)) ItemColorizer.getColor(itemStack) else 0x66DD55 + } + super.getColorFromItemStack(itemStack, pass) + } + override def getDisplayDamage(stack: ItemStack): Int = { val data = new HoverBootsData(stack) (Settings.get.bufferHoverBoots * (1 - data.charge / Settings.get.bufferHoverBoots)).toInt diff --git a/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala new file mode 100644 index 000000000..74a95919c --- /dev/null +++ b/src/main/scala/li/cil/oc/common/recipe/ColorizeRecipe.scala @@ -0,0 +1,85 @@ +package li.cil.oc.common.recipe + +import li.cil.oc.util.{Color, ItemColorizer} +import net.minecraft.entity.passive.EntitySheep +import net.minecraft.inventory.InventoryCrafting +import net.minecraft.item.crafting.IRecipe +import net.minecraft.item.{Item, ItemStack} +import net.minecraft.world.World + +/** + * @author asie, Vexatos + */ +class ColorizeRecipe(target: Item, source: Array[Item] = null) extends IRecipe { + val targetItem = target + val sourceItems = if (source != null) source else Array(targetItem) + + override def matches(crafting: InventoryCrafting, world: World): Boolean = { + val stacks = (0 until crafting.getSizeInventory).flatMap(i => Option(crafting.getStackInSlot(i))) + val targets = stacks.filter(stack => sourceItems.contains(stack.getItem) || stack.getItem == targetItem) + val other = stacks.filterNot(targets.contains) + targets.size == 1 && other.nonEmpty && other.forall(Color.isDye) + } + + override def getCraftingResult(crafting: InventoryCrafting): ItemStack = { + var targetStack: ItemStack = null + val color = Array[Int](0, 0, 0) + var colorCount = 0 + var maximum = 0 + + (0 until crafting.getSizeInventory).flatMap(i => Option(crafting.getStackInSlot(i))).foreach { stack => + if (sourceItems.contains(stack.getItem) + || stack.getItem == targetItem) { + targetStack = stack.copy() + targetStack.stackSize = 1 + } else { + val dye = Color.findDye(stack) + if (dye.isEmpty) + return null + + val itemColor = EntitySheep.fleeceColorTable(15 - Color.dyes.indexOf(dye.get)) + val red = (itemColor(0) * 255.0F).toInt + val green = (itemColor(1) * 255.0F).toInt + val blue = (itemColor(2) * 255.0F).toInt + maximum += Math.max(red, Math.max(green, blue)) + color(0) += red + color(1) += green + color(2) += blue + colorCount = colorCount + 1 + } + } + + if (targetStack == null) return null + + if (targetItem == targetStack.getItem) { + if (ItemColorizer.hasColor(targetStack)) { + val itemColor = ItemColorizer.getColor(targetStack) + val red = (itemColor >> 16 & 255).toFloat / 255.0F + val green = (itemColor >> 8 & 255).toFloat / 255.0F + val blue = (itemColor & 255).toFloat / 255.0F + maximum = (maximum.toFloat + Math.max(red, Math.max(green, blue)) * 255.0F).toInt + color(0) = (color(0).toFloat + red * 255.0F).toInt + color(1) = (color(1).toFloat + green * 255.0F).toInt + color(2) = (color(2).toFloat + blue * 255.0F).toInt + colorCount = colorCount + 1 + } + } else if (sourceItems.contains(targetStack.getItem)) { + targetStack = new ItemStack(targetItem, targetStack.stackSize, targetStack.getItemDamage) + } + + var red = color(0) / colorCount + var green = color(1) / colorCount + var blue = color(2) / colorCount + val max = maximum.toFloat / colorCount.toFloat + val div = Math.max(red, Math.max(green, blue)).toFloat + red = (red.toFloat * max / div).toInt + green = (green.toFloat * max / div).toInt + blue = (blue.toFloat * max / div).toInt + ItemColorizer.setColor(targetStack, (red << 16) | (green << 8) | blue) + targetStack + } + + override def getRecipeSize = 10 + + override def getRecipeOutput = null +} diff --git a/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala new file mode 100644 index 000000000..f6cdb547a --- /dev/null +++ b/src/main/scala/li/cil/oc/common/recipe/DecolorizeRecipe.scala @@ -0,0 +1,44 @@ +package li.cil.oc.common.recipe + +import li.cil.oc.util.ItemColorizer +import net.minecraft.init.Items +import net.minecraft.inventory.InventoryCrafting +import net.minecraft.item.crafting.IRecipe +import net.minecraft.item.{Item, ItemStack} +import net.minecraft.world.World + +/** + * @author Vexatos + */ +class DecolorizeRecipe(target: Item) extends IRecipe { + val targetItem = target + + override def matches(crafting: InventoryCrafting, world: World): Boolean = { + val stacks = (0 until crafting.getSizeInventory).flatMap(i => Option(crafting.getStackInSlot(i))) + val targets = stacks.filter(stack => stack.getItem == targetItem) + val other = stacks.filterNot(targets.contains) + targets.size == 1 && other.size == 1 && other.forall(_.getItem == Items.water_bucket) + } + + override def getCraftingResult(crafting: InventoryCrafting): ItemStack = { + var targetStack: ItemStack = null + + (0 until crafting.getSizeInventory).flatMap(i => Option(crafting.getStackInSlot(i))).foreach { stack => + if (stack.getItem == targetItem) { + targetStack = stack.copy() + targetStack.stackSize = 1 + } else if (stack.getItem != Items.water_bucket) { + return null + } + } + + if (targetStack == null) return null + + ItemColorizer.removeColor(targetStack) + targetStack + } + + override def getRecipeSize = 10 + + override def getRecipeOutput = null +} diff --git a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala b/src/main/scala/li/cil/oc/common/recipe/Recipes.scala index 9e1aa47e8..2a6e986be 100644 --- a/src/main/scala/li/cil/oc/common/recipe/Recipes.scala +++ b/src/main/scala/li/cil/oc/common/recipe/Recipes.scala @@ -89,6 +89,8 @@ object Recipes { def init() { RecipeSorter.register(Settings.namespace + "extshaped", classOf[ExtendedShapedOreRecipe], Category.SHAPED, "after:forge:shapedore") RecipeSorter.register(Settings.namespace + "extshapeless", classOf[ExtendedShapelessOreRecipe], Category.SHAPELESS, "after:forge:shapelessore") + RecipeSorter.register(Settings.namespace + "colorizer", classOf[ColorizeRecipe], Category.SHAPELESS, "after:forge:shapelessore") + RecipeSorter.register(Settings.namespace + "decolorizer", classOf[DecolorizeRecipe], Category.SHAPELESS, "after:oc:decolorizer") for ((name, stack) <- oreDictEntries) { if (!OreDictionary.getOres(name).contains(stack)) { @@ -322,6 +324,10 @@ object Recipes { api.Items.get(Constants.BlockName.AccessPoint).createItemStack(1)) GameRegistry.addShapelessRecipe(api.Items.get(Constants.BlockName.Relay).createItemStack(1), api.Items.get(Constants.BlockName.Switch).createItemStack(1)) + + // Hover Boot dyeing + GameRegistry.addRecipe(new ColorizeRecipe(api.Items.get(Constants.ItemName.HoverBoots).item())) + GameRegistry.addRecipe(new DecolorizeRecipe(api.Items.get(Constants.ItemName.HoverBoots).item())) } catch { case e: Throwable => OpenComputers.log.error("Error parsing recipes, you may not be able to craft any items from this mod!", e) diff --git a/src/main/scala/li/cil/oc/util/ItemColorizer.scala b/src/main/scala/li/cil/oc/util/ItemColorizer.scala new file mode 100644 index 000000000..7043d29ce --- /dev/null +++ b/src/main/scala/li/cil/oc/util/ItemColorizer.scala @@ -0,0 +1,47 @@ +package li.cil.oc.util + +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound + +/** + * @author asie, Vexatos + */ +object ItemColorizer { + /** + * Return whether the specified armor ItemStack has a color. + */ + def hasColor(stack: ItemStack): Boolean = stack.hasTagCompound && stack.getTagCompound.hasKey("display") && stack.getTagCompound.getCompoundTag("display").hasKey("color") + + /** + * Return the color for the specified armor ItemStack. + */ + def getColor(stack: ItemStack): Int = { + val tag = stack.getTagCompound + if (tag != null) { + val displayTag = tag.getCompoundTag("display") + if (displayTag == null) -1 else if (displayTag.hasKey("color")) displayTag.getInteger("color") else -1 + } + else -1 + } + + def removeColor(stack: ItemStack) { + val tag = stack.getTagCompound + if (tag != null) { + val displayTag = tag.getCompoundTag("display") + if (displayTag.hasKey("color")) displayTag.removeTag("color") + } + } + + def setColor(stack: ItemStack, color: Int) { + var tag = stack.getTagCompound + if (tag == null) { + tag = new NBTTagCompound + stack.setTagCompound(tag) + } + val displayTag = tag.getCompoundTag("display") + if (!tag.hasKey("display")) { + tag.setTag("display", displayTag) + } + displayTag.setInteger("color", color) + } +}