diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index 7adb8e3ff..faa65bb6a 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -47,7 +47,6 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.client.registry.ClientRegistry; @@ -515,20 +514,20 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon } } - @SideOnly(Side.CLIENT) - private static class DiskColorHandler implements IItemColor - { - private final ItemDiskLegacy disk; + @SideOnly(Side.CLIENT) + private static class DiskColorHandler implements IItemColor + { + private final ItemDiskLegacy disk; - private DiskColorHandler(ItemDiskLegacy disk) - { - this.disk = disk; - } + private DiskColorHandler( ItemDiskLegacy disk ) + { + this.disk = disk; + } - @Override - public int getColorFromItemstack( @Nonnull ItemStack stack, int layer) - { - return layer == 0 ? 0xFFFFFF : disk.getColor(stack); - } - } + @Override + public int getColorFromItemstack( @Nonnull ItemStack stack, int layer ) + { + return layer == 0 ? 0xFFFFFF : disk.getColour( stack ); + } + } } diff --git a/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java new file mode 100644 index 000000000..ce59b7fc5 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java @@ -0,0 +1,106 @@ +package dan200.computercraft.shared.common; + +import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.ColourTracker; +import dan200.computercraft.shared.util.ColourUtils; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeHooks; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ColourableRecipe implements IRecipe +{ + @Override + public boolean matches( @Nonnull InventoryCrafting inv, @Nonnull World worldIn ) + { + boolean hasColourable = false; + boolean hasDye = false; + for( int i = 0; i < inv.getSizeInventory(); i++ ) + { + ItemStack stack = inv.getStackInSlot( i ); + if( stack == null ) continue; + + if( stack.getItem() instanceof IColouredItem ) + { + if( hasColourable ) return false; + hasColourable = true; + } + else if( ColourUtils.getStackColour( stack ) >= 0 ) + { + hasDye = true; + } + else + { + return false; + } + } + + return hasColourable && hasDye; + } + + @Nullable + @Override + public ItemStack getCraftingResult( @Nonnull InventoryCrafting inv ) + { + ItemStack colourable = null; + + ColourTracker tracker = new ColourTracker(); + + for( int i = 0; i < inv.getSizeInventory(); ++i ) + { + ItemStack stack = inv.getStackInSlot( i ); + + if( stack == null ) continue; + + if( stack.getItem() instanceof IColouredItem ) + { + colourable = stack; + } + else + { + int index = ColourUtils.getStackColour( stack ); + if( index < 0 ) continue; + + Colour colour = Colour.values()[ index ]; + tracker.addColour( colour.getR(), colour.getG(), colour.getB() ); + } + } + + if( colourable == null ) + { + return null; + } + + return ((IColouredItem) colourable.getItem()).setColour( colourable, tracker.getColour() ); + } + + @Override + public int getRecipeSize() + { + return 2; + } + + @Nullable + @Override + public ItemStack getRecipeOutput() + { + return null; + } + + @Nonnull + @Override + public ItemStack[] getRemainingItems( @Nonnull InventoryCrafting inv ) + { + ItemStack[] results = new ItemStack[ inv.getSizeInventory() ]; + for( int i = 0; i < results.length; ++i ) + { + ItemStack stack = inv.getStackInSlot( i ); + results[ i ] = ForgeHooks.getContainerItem( stack ); + } + return results; + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/IColouredItem.java b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java new file mode 100644 index 000000000..fb28403bd --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java @@ -0,0 +1,10 @@ +package dan200.computercraft.shared.common; + +import net.minecraft.item.ItemStack; + +public interface IColouredItem +{ + int getColour( ItemStack stack ); + + ItemStack setColour( ItemStack stack, int colour ); +} diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java index 02df3b622..ab3c10330 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskExpanded.java @@ -44,7 +44,7 @@ public class ItemDiskExpanded extends ItemDiskLegacy return -1; } - @Override + @Override protected void setDiskID( ItemStack stack, int id ) { if( id >= 0 ) @@ -58,10 +58,18 @@ public class ItemDiskExpanded extends ItemDiskLegacy nbt.setInteger( "diskID", id ); } } - - public int getColor( ItemStack stack ) + + @Override + public int getColour( ItemStack stack ) { NBTTagCompound nbt = stack.getTagCompound(); - return nbt != null && nbt.hasKey("color") ? nbt.getInteger("color") : Colour.values()[ Math.min(15, stack.getItemDamage()) ].getHex(); + if( nbt != null && nbt.hasKey( "color" ) ) + { + return nbt.getInteger( "color" ); + } + else + { + return Colour.values()[ Math.min( 15, stack.getItemDamage() ) ].getHex(); + } } } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java index 6b5c3f0f5..05581bf54 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDiskLegacy.java @@ -10,6 +10,7 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.util.Colour; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; @@ -24,7 +25,7 @@ import javax.annotation.Nonnull; import java.util.List; public class ItemDiskLegacy extends Item - implements IMedia + implements IMedia, IColouredItem { public ItemDiskLegacy() { @@ -142,7 +143,8 @@ public class ItemDiskLegacy extends Item return ComputerCraftAPI.createSaveDirMount( world, "computer/disk/" + diskID, ComputerCraft.floppySpaceLimit ); } - public int getColor( ItemStack stack ) + @Override + public int getColour( ItemStack stack ) { return Colour.Blue.getHex(); } @@ -152,4 +154,10 @@ public class ItemDiskLegacy extends Item { return true; } + + @Override + public ItemStack setColour( ItemStack stack, int colour ) + { + return ItemDiskExpanded.createFromIDAndColour( getDiskID( stack ), getLabel( stack ), colour ); + } } diff --git a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java index 6a9191fd7..35bffc4f4 100644 --- a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java @@ -8,6 +8,8 @@ package dan200.computercraft.shared.media.recipes; import dan200.computercraft.shared.media.items.ItemDiskLegacy; import dan200.computercraft.shared.util.Colour; +import dan200.computercraft.shared.util.ColourTracker; +import dan200.computercraft.shared.util.ColourUtils; import net.minecraft.init.Items; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; @@ -18,129 +20,60 @@ import javax.annotation.Nonnull; public class DiskRecipe implements IRecipe { - public DiskRecipe() - { - } - @Override - public boolean matches( @Nonnull InventoryCrafting inventory, @Nonnull World world ) + public boolean matches( @Nonnull InventoryCrafting inv, @Nonnull World world ) { - boolean diskFound = false; boolean paperFound = false; boolean redstoneFound = false; - boolean dyeFound = false; - for (int var5 = 0; var5 < inventory.getSizeInventory(); ++var5) + for( int i = 0; i < inv.getSizeInventory(); ++i ) { - ItemStack var6 = inventory.getStackInSlot(var5); + ItemStack stack = inv.getStackInSlot( i ); - if (var6 != null) + if( stack != null ) { - if (var6.getItem() instanceof ItemDiskLegacy ) + if( stack.getItem() == Items.PAPER ) { - if (diskFound || redstoneFound || paperFound) // make sure no redstone or paper already accepted if disk there - { - return false; - } - - diskFound = true; - } - else if( var6.getItem() == Items.DYE ) - { - dyeFound = true; - } - else if( var6.getItem() == Items.PAPER ) - { - if(paperFound || diskFound) - { - return false; - } + if( paperFound ) return false; paperFound = true; } - else if (var6.getItem() == Items.REDSTONE) + else if( stack.getItem() == Items.REDSTONE ) { - if (redstoneFound || diskFound) - { - return false; - } - + if( redstoneFound ) return false; redstoneFound = true; } - else + else if( ColourUtils.getStackColour( stack ) < 0 ) { return false; } } } - - return (redstoneFound && paperFound) || (diskFound && dyeFound); + + return redstoneFound && paperFound; } @Override - public ItemStack getCraftingResult( @Nonnull InventoryCrafting par1InventoryCrafting) + public ItemStack getCraftingResult( @Nonnull InventoryCrafting inv ) { - int diskID = -1; - String diskLabel = null; + ColourTracker tracker = new ColourTracker(); - int[] var3 = new int[3]; - int var4 = 0; - int var5 = 0; - ItemDiskLegacy var6; - int var7; - int var9; - float var10; - float var11; - int var17; - boolean dyeFound = false; - - for (var7 = 0; var7 < par1InventoryCrafting.getSizeInventory(); ++var7) + for( int i = 0; i < inv.getSizeInventory(); ++i ) { - ItemStack var8 = par1InventoryCrafting.getStackInSlot(var7); + ItemStack stack = inv.getStackInSlot( i ); - if (var8 != null) + if( stack == null ) continue; + + if( stack.getItem() != Items.PAPER && stack.getItem() != Items.REDSTONE ) { - if (var8.getItem() instanceof ItemDiskLegacy ) - { - var6 = (ItemDiskLegacy)var8.getItem(); - diskID = var6.getDiskID( var8 ); - diskLabel = var6.getLabel( var8 ); - } - else if (var8.getItem() == Items.DYE) - { - dyeFound = true; - float[] var14 = Colour.values()[ var8.getItemDamage() & 0xf ].getRGB(); - int var16 = (int)(var14[0] * 255.0F); - int var15 = (int)(var14[1] * 255.0F); - var17 = (int)(var14[2] * 255.0F); - var4 += Math.max(var16, Math.max(var15, var17)); - var3[0] += var16; - var3[1] += var15; - var3[2] += var17; - ++var5; - } - else if (!(var8.getItem() != Items.PAPER || var8.getItem() != Items.REDSTONE)) - { - return null; - } + int index = ColourUtils.getStackColour( stack ); + if( index < 0 ) continue; + + Colour colour = Colour.values()[ index ]; + tracker.addColour( colour.getR(), colour.getG(), colour.getB() ); } } - - if( !dyeFound ) - { - return ItemDiskLegacy.createFromIDAndColour( diskID, diskLabel, Colour.Blue.getHex() ); - } - - var7 = var3[0] / var5; - int var13 = var3[1] / var5; - var9 = var3[2] / var5; - var10 = (float)var4 / (float)var5; - var11 = (float)Math.max(var7, Math.max(var13, var9)); - var7 = (int)((float)var7 * var10 / var11); - var13 = (int)((float)var13 * var10 / var11); - var9 = (int)((float)var9 * var10 / var11); - var17 = (var7 << 8) + var13; - var17 = (var17 << 8) + var9; - return ItemDiskLegacy.createFromIDAndColour( diskID, diskLabel, var17 ); + + return ItemDiskLegacy.createFromIDAndColour( -1, null, tracker.hasColour() ? tracker.getColour() : Colour.Blue.getHex() ); } @Override @@ -157,13 +90,13 @@ public class DiskRecipe implements IRecipe @Nonnull @Override - public ItemStack[] getRemainingItems( @Nonnull InventoryCrafting inventoryCrafting ) + public ItemStack[] getRemainingItems( @Nonnull InventoryCrafting inv ) { - ItemStack[] results = new ItemStack[ inventoryCrafting.getSizeInventory() ]; - for (int i = 0; i < results.length; ++i) + ItemStack[] results = new ItemStack[ inv.getSizeInventory() ]; + for( int i = 0; i < results.length; ++i ) { - ItemStack stack = inventoryCrafting.getStackInSlot(i); - results[i] = net.minecraftforge.common.ForgeHooks.getContainerItem(stack); + ItemStack stack = inv.getStackInSlot( i ); + results[ i ] = net.minecraftforge.common.ForgeHooks.getContainerItem( stack ); } return results; } diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index 749abf8e8..a4eb6cdf3 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -10,6 +10,7 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.core.computer.MainThread; +import dan200.computercraft.shared.common.ColourableRecipe; import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.computer.blocks.BlockCommandComputer; @@ -276,6 +277,7 @@ public abstract class ComputerCraftProxyCommon implements IComputerCraftProxy RecipeSorter.register( "computercraft:impostor", ImpostorRecipe.class, RecipeSorter.Category.SHAPED, "after:minecraft:shapeless" ); RecipeSorter.register( "computercraft:impostor_shapeless", ImpostorShapelessRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); RecipeSorter.register( "computercraft:disk", DiskRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); + RecipeSorter.register( "computercraft:colour", ColourableRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); RecipeSorter.register( "computercraft:printout", PrintoutRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); RecipeSorter.register( "computercraft:pocket_computer_upgrade", PocketComputerUpgradeRecipe.class, RecipeSorter.Category.SHAPELESS, "after:minecraft:shapeless" ); @@ -375,6 +377,9 @@ public abstract class ComputerCraftProxyCommon implements IComputerCraftProxy // Disk GameRegistry.addRecipe( new DiskRecipe() ); + // Colourable items (turtles, disks) + GameRegistry.addRecipe( new ColourableRecipe() ); + // Impostor Disk recipes (to fool NEI) ItemStack paper = new ItemStack( Items.PAPER, 1 ); ItemStack redstone = new ItemStack( Items.REDSTONE, 1 ); diff --git a/src/main/java/dan200/computercraft/shared/util/ColourTracker.java b/src/main/java/dan200/computercraft/shared/util/ColourTracker.java new file mode 100644 index 000000000..7be0ad300 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/ColourTracker.java @@ -0,0 +1,48 @@ +package dan200.computercraft.shared.util; + +/** + * A reimplementation of the colour system in {@link net.minecraft.item.crafting.RecipesArmorDyes}, but + * bundled together as an object. + */ +public class ColourTracker +{ + private int total; + private int totalR; + private int totalG; + private int totalB; + private int count; + + public void addColour( int r, int g, int b ) + { + total += Math.max( r, Math.max( g, b ) ); + totalR += r; + totalG += g; + totalB += b; + count++; + } + + public void addColour( float r, float g, float b ) + { + addColour( (int) (r * 255), (int) (g * 255), (int) (b * 255) ); + } + + public boolean hasColour() + { + return count > 0; + } + + public int getColour() + { + int avgR = totalR / count; + int avgG = totalG / count; + int avgB = totalB / count; + + float avgTotal = (float) total / (float) count; + float avgMax = (float) Math.max( avgR, Math.max( avgG, avgB ) ); + avgR = (int) (avgR * avgTotal / avgMax); + avgG = (int) (avgG * avgTotal / avgMax); + avgB = (int) (avgB * avgTotal / avgMax); + + return (avgR << 16) | (avgG << 8) | avgB; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/ColourUtils.java b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java new file mode 100644 index 000000000..020a37724 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java @@ -0,0 +1,37 @@ +package dan200.computercraft.shared.util; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; +import org.apache.commons.lang3.ArrayUtils; + +public class ColourUtils +{ + private static final String[] DYES = new String[] { + "dyeBlack", "dyeRed", "dyeGreen", "dyeBrown", + "dyeBlue", "dyePurple", "dyeCyan", "dyeLightGray", + "dyeGray", "dyePink", "dyeLime", "dyeYellow", + "dyeLightBlue", "dyeMagenta", "dyeOrange", "dyeWhite" + }; + + private static int[] ids; + + public static int getStackColour( ItemStack stack ) + { + if( ids == null ) + { + int ids[] = ColourUtils.ids = new int[ DYES.length ]; + for( int i = 0; i < DYES.length; i++ ) + { + ids[ i ] = OreDictionary.getOreID( DYES[ i ] ); + } + } + + for( int id : OreDictionary.getOreIDs( stack ) ) + { + int index = ArrayUtils.indexOf( ids, id ); + if( index >= 0 ) return index; + } + + return -1; + } +}