Foliage, Grass and Water biome colours now smoothly transition from one biome to another. This smoothness is 100% configurable and is separate for each type (One value for Foliage, one for Grass and one for Water).

This commit is contained in:
Adubbz 2013-10-17 18:32:13 +11:00
parent 6fc4422b66
commit 6a64b26885
13 changed files with 533 additions and 21 deletions

View file

@ -0,0 +1,42 @@
package biomesoplenty.asm;
import java.io.File;
import java.util.Map;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
public class BOPFMLLoadingPlugin implements IFMLLoadingPlugin
{
public static File location;
@Override
public String[] getLibraryRequestClass()
{
return null;
}
@Override
public String[] getASMTransformerClass()
{
return new String[] {BOPBiomeTransitionSmoothing.class.getName()};
}
@Override
public String getModContainerClass()
{
return null;
}
@Override
public String getSetupClass()
{
return null;
}
@Override
public void injectData(Map<String, Object> data)
{
location = (File)data.get("coremodLocation");
}
}

View file

@ -0,0 +1,133 @@
package biomesoplenty.asm.smoothing;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
import biomesoplenty.asm.smoothing.block.BlockFluid;
import biomesoplenty.asm.smoothing.block.BlockGrass;
import biomesoplenty.asm.smoothing.block.BlockLeaves;
import biomesoplenty.asm.smoothing.block.BlockTallGrass;
import biomesoplenty.configuration.configfile.BOPConfigurationMisc;
public class BOPBiomeTransitionSmoothing implements IClassTransformer
{
@Override
public byte[] transform(String name, String newname, byte[] bytes)
{
if (name.equals("net.minecraft.block.BlockFluid"))
{
return BlockFluid.patchColourMultiplier(newname, bytes, false);
}
if (name.equals("pc"))
{
return BlockFluid.patchColourMultiplier(newname, bytes, true);
}
if (name.equals("net.minecraft.block.BlockGrass"))
{
return BlockGrass.patchColourMultiplier(newname, bytes, false);
}
if (name.equals("on"))
{
return BlockGrass.patchColourMultiplier(newname, bytes, true);
}
if (name.equals("net.minecraft.block.BlockLeaves"))
{
return BlockLeaves.patchColourMultiplier(newname, bytes, false);
}
if (name.equals("oz"))
{
return BlockLeaves.patchColourMultiplier(newname, bytes, true);
}
if (name.equals("net.minecraft.block.BlockTallGrass"))
{
return BlockTallGrass.patchColourMultiplier(newname, bytes, false);
}
if (name.equals("qv"))
{
return BlockTallGrass.patchColourMultiplier(newname, bytes, true);
}
return bytes;
}
public static int getGrassColourMultiplier(IBlockAccess world, int ox, int oy, int oz)
{
int distance = BOPConfigurationMisc.grassColourSmoothingArea;
int r = 0;
int g = 0;
int b = 0;
int divider = 0;
for (int x = -distance; x <= distance; ++x)
{
for (int z = -distance; z <= distance; ++z)
{
BiomeGenBase biome = world.getBiomeGenForCoords(ox + x, oz + z);
int colour = biome.getBiomeGrassColor();
r += (colour & 0xFF0000) >> 16;
g += (colour & 0x00FF00) >> 8;
b += colour & 0x0000FF;
divider++;
}
}
return (r / divider & 255) << 16 | (g / divider & 255) << 8 | b / divider & 255;
}
public static int getLeavesColourMultiplier(IBlockAccess world, int ox, int oy, int oz)
{
int distance = BOPConfigurationMisc.leavesColourSmoothingArea;
int r = 0;
int g = 0;
int b = 0;
int divider = 0;
for (int x = -distance; x <= distance; ++x)
{
for (int z = -distance; z <= distance; ++z)
{
BiomeGenBase biome = world.getBiomeGenForCoords(ox + x, oz + z);
int colour = biome.getBiomeFoliageColor();
r += (colour & 0xFF0000) >> 16;
g += (colour & 0x00FF00) >> 8;
b += colour & 0x0000FF;
divider++;
}
}
return (r / divider & 255) << 16 | (g / divider & 255) << 8 | b / divider & 255;
}
public static int getWaterColourMultiplier(IBlockAccess world, int ox, int oy, int oz)
{
int distance = BOPConfigurationMisc.waterColourSmoothingArea;
int r = 0;
int g = 0;
int b = 0;
int divider = 0;
for (int x = -distance; x <= distance; ++x)
{
for (int z = -distance; z <= distance; ++z)
{
BiomeGenBase biome = world.getBiomeGenForCoords(ox + x, oz + z);
int colour = biome.getWaterColorMultiplier();
r += (colour & 0xFF0000) >> 16;
g += (colour & 0x00FF00) >> 8;
b += colour & 0x0000FF;
divider++;
}
}
return (r / divider & 255) << 16 | (g / divider & 255) << 8 | b / divider & 255;
}
}

View file

@ -0,0 +1,85 @@
package biomesoplenty.asm.smoothing.block;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ICONST_0;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.IRETURN;
import java.util.Iterator;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
public class BlockFluid
{
public static byte[] patchColourMultiplier(String name, byte[] bytes, boolean obfuscated)
{
String targetMethodName = "";
if (obfuscated)
targetMethodName ="b";
else
targetMethodName ="colorMultiplier";
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
while (methods.hasNext())
{
MethodNode m = methods.next();
int fdiv_index = -1;
if (m.name.equals(targetMethodName) && (m.desc.equals("(Lnet/minecraft/world/IBlockAccess;III)I") || m.desc.equals("(Lcf;III)I")))
{
AbstractInsnNode currentNode = null;
AbstractInsnNode targetNode = null;
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
int index = -1;
while (iter.hasNext())
{
index++;
currentNode = iter.next();
if (currentNode.getOpcode() == ICONST_0)
{
targetNode = currentNode;
fdiv_index = index;
}
}
InsnList toInject = new InsnList();
toInject.add(new VarInsnNode(ALOAD, 1));
toInject.add(new VarInsnNode(ILOAD, 2));
toInject.add(new VarInsnNode(ILOAD, 3));
toInject.add(new VarInsnNode(ILOAD, 4));
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/smoothing/BOPBiomeTransitionSmoothing", "getWaterColourMultiplier", "(Lnet/minecraft/world/IBlockAccess;III)I"));
toInject.add(new InsnNode(IRETURN));
m.instructions.insertBefore(targetNode, toInject);
break;
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}

View file

@ -0,0 +1,83 @@
package biomesoplenty.asm.smoothing.block;
import static org.objectweb.asm.Opcodes.*;
import static org.objectweb.asm.tree.AbstractInsnNode.*;
import java.util.Iterator;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
public class BlockGrass
{
//ASM Injector
public static byte[] patchColourMultiplier(String name, byte[] bytes, boolean obfuscated)
{
String targetMethodName = "";
if (obfuscated)
targetMethodName ="b";
else
targetMethodName ="colorMultiplier";
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
while (methods.hasNext())
{
MethodNode m = methods.next();
int fdiv_index = -1;
if (m.name.equals(targetMethodName) && (m.desc.equals("(Lnet/minecraft/world/IBlockAccess;III)I") || m.desc.equals("(Lcf;III)I")))
{
AbstractInsnNode currentNode = null;
AbstractInsnNode targetNode = null;
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
int index = -1;
while (iter.hasNext())
{
index++;
currentNode = iter.next();
if (currentNode.getOpcode() == ICONST_0)
{
targetNode = currentNode;
fdiv_index = index;
}
}
InsnList toInject = new InsnList();
toInject.add(new VarInsnNode(ALOAD, 1));
toInject.add(new VarInsnNode(ILOAD, 2));
toInject.add(new VarInsnNode(ILOAD, 3));
toInject.add(new VarInsnNode(ILOAD, 4));
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/smoothing/BOPBiomeTransitionSmoothing", "getGrassColourMultiplier", "(Lnet/minecraft/world/IBlockAccess;III)I"));
toInject.add(new InsnNode(IRETURN));
m.instructions.insertBefore(targetNode, toInject);
break;
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}

View file

@ -0,0 +1,86 @@
package biomesoplenty.asm.smoothing.block;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ICONST_0;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.IRETURN;
import java.util.Iterator;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
public class BlockLeaves
{
//ASM Injector
public static byte[] patchColourMultiplier(String name, byte[] bytes, boolean obfuscated)
{
String targetMethodName = "";
if (obfuscated)
targetMethodName ="b";
else
targetMethodName ="colorMultiplier";
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
while (methods.hasNext())
{
MethodNode m = methods.next();
int fdiv_index = -1;
if (m.name.equals(targetMethodName) && (m.desc.equals("(Lnet/minecraft/world/IBlockAccess;III)I") || m.desc.equals("(Lcf;III)I")))
{
AbstractInsnNode currentNode = null;
AbstractInsnNode targetNode = null;
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
int index = -1;
while (iter.hasNext())
{
index++;
currentNode = iter.next();
if (currentNode.getOpcode() == ICONST_0)
{
targetNode = currentNode;
fdiv_index = index;
}
}
InsnList toInject = new InsnList();
toInject.add(new VarInsnNode(ALOAD, 1));
toInject.add(new VarInsnNode(ILOAD, 2));
toInject.add(new VarInsnNode(ILOAD, 3));
toInject.add(new VarInsnNode(ILOAD, 4));
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/smoothing/BOPBiomeTransitionSmoothing", "getLeavesColourMultiplier", "(Lnet/minecraft/world/IBlockAccess;III)I"));
toInject.add(new InsnNode(IRETURN));
m.instructions.insertBefore(targetNode, toInject);
break;
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}

View file

@ -0,0 +1,83 @@
package biomesoplenty.asm.smoothing.block;
import static org.objectweb.asm.Opcodes.*;
import static org.objectweb.asm.tree.AbstractInsnNode.*;
import java.util.Iterator;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
public class BlockTallGrass
{
//ASM Injector
public static byte[] patchColourMultiplier(String name, byte[] bytes, boolean obfuscated)
{
String targetMethodName = "";
if (obfuscated)
targetMethodName ="b";
else
targetMethodName ="colorMultiplier";
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
Iterator<MethodNode> methods = classNode.methods.iterator();
while (methods.hasNext())
{
MethodNode m = methods.next();
int fdiv_index = -1;
if (m.name.equals(targetMethodName) && (m.desc.equals("(Lnet/minecraft/world/IBlockAccess;III)I") || m.desc.equals("(Lcf;III)I")))
{
AbstractInsnNode currentNode = null;
AbstractInsnNode targetNode = null;
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
int index = -1;
while (iter.hasNext())
{
index++;
currentNode = iter.next();
if (currentNode.getOpcode() == ALOAD)
{
targetNode = currentNode;
fdiv_index = index;
}
}
InsnList toInject = new InsnList();
toInject.add(new VarInsnNode(ALOAD, 1));
toInject.add(new VarInsnNode(ILOAD, 2));
toInject.add(new VarInsnNode(ILOAD, 3));
toInject.add(new VarInsnNode(ILOAD, 4));
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/smoothing/BOPBiomeTransitionSmoothing", "getGrassColourMultiplier", "(Lnet/minecraft/world/IBlockAccess;III)I"));
toInject.add(new InsnNode(IRETURN));
m.instructions.insertBefore(targetNode, toInject);
break;
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}

View file

@ -17,6 +17,7 @@ import net.minecraft.world.World;
import net.minecraftforge.common.IShearable; import net.minecraftforge.common.IShearable;
import biomesoplenty.BiomesOPlenty; import biomesoplenty.BiomesOPlenty;
import biomesoplenty.api.Blocks; import biomesoplenty.api.Blocks;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Loader;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
@ -95,22 +96,7 @@ public class BlockBOPColorizedLeaves extends BlockLeavesBase implements IShearab
@Override @Override
public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{ {
int var6 = 0; return BOPBiomeTransitionSmoothing.getLeavesColourMultiplier(par1IBlockAccess, par2, par3, par4);
int var7 = 0;
int var8 = 0;
for (int var9 = -1; var9 <= 1; ++var9)
{
for (int var10 = -1; var10 <= 1; ++var10)
{
int var11 = par1IBlockAccess.getBiomeGenForCoords(par2 + var10, par4 + var9).getBiomeFoliageColor();
var6 += (var11 & 16711680) >> 16;
var7 += (var11 & 65280) >> 8;
var8 += var11 & 255;
}
}
return (var6 / 9 & 255) << 16 | (var7 / 9 & 255) << 8 | var8 / 9 & 255;
} }
@Override @Override

View file

@ -30,6 +30,8 @@ import net.minecraftforge.common.IShearable;
import biomesoplenty.BiomesOPlenty; import biomesoplenty.BiomesOPlenty;
import biomesoplenty.api.Blocks; import biomesoplenty.api.Blocks;
import biomesoplenty.api.Items; import biomesoplenty.api.Items;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
import biomesoplenty.asm.smoothing.block.BlockGrass;
import biomesoplenty.blocks.renderers.RenderUtils; import biomesoplenty.blocks.renderers.RenderUtils;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
@ -242,10 +244,10 @@ public class BlockBOPFoliage extends BlockFlower implements IShearable
{ {
if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) == 9) if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) == 9)
{ {
return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor(); return BOPBiomeTransitionSmoothing.getLeavesColourMultiplier(par1IBlockAccess, par2, par3, par4);
} }
return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeGrassColor(); return BOPBiomeTransitionSmoothing.getGrassColourMultiplier(par1IBlockAccess, par2, par3, par4);
} }
@Override @Override

View file

@ -16,6 +16,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.IShearable; import net.minecraftforge.common.IShearable;
import biomesoplenty.BiomesOPlenty; import biomesoplenty.BiomesOPlenty;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
public class BlockIvy extends Block implements IShearable public class BlockIvy extends Block implements IShearable
{ {
@ -249,7 +250,7 @@ public class BlockIvy extends Block implements IShearable
@Override @Override
public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{ {
return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor(); return BOPBiomeTransitionSmoothing.getLeavesColourMultiplier(par1IBlockAccess, par2, par3, par4);
} }
/** /**

View file

@ -12,6 +12,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import biomesoplenty.BiomesOPlenty; import biomesoplenty.BiomesOPlenty;
import biomesoplenty.api.Blocks; import biomesoplenty.api.Blocks;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
public class BlockMoss extends Block public class BlockMoss extends Block
{ {
@ -243,7 +244,7 @@ public class BlockMoss extends Block
@Override @Override
public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{ {
return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor(); return BOPBiomeTransitionSmoothing.getLeavesColourMultiplier(par1IBlockAccess, par2, par3, par4);
} }
/** /**

View file

@ -15,6 +15,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.IShearable; import net.minecraftforge.common.IShearable;
import biomesoplenty.BiomesOPlenty; import biomesoplenty.BiomesOPlenty;
import biomesoplenty.asm.smoothing.BOPBiomeTransitionSmoothing;
public class BlockWillow extends Block implements IShearable public class BlockWillow extends Block implements IShearable
{ {
@ -249,7 +250,7 @@ public class BlockWillow extends Block implements IShearable
@Override @Override
public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{ {
return par1IBlockAccess.getBiomeGenForCoords(par2, par4).getBiomeFoliageColor(); return BOPBiomeTransitionSmoothing.getLeavesColourMultiplier(par1IBlockAccess, par2, par3, par4);
} }
/** /**

View file

@ -28,6 +28,10 @@ public class BOPConfigurationMisc
public static int promisedLandSkyColor; public static int promisedLandSkyColor;
public static int grassColourSmoothingArea;
public static int leavesColourSmoothingArea;
public static int waterColourSmoothingArea;
public static void init(File configFile) public static void init(File configFile)
{ {
config = new Configuration(configFile); config = new Configuration(configFile);
@ -55,6 +59,10 @@ public class BOPConfigurationMisc
promisedLandSkyColor = config.get("Hard-Coded Colors", "Promised Land Sky Color", 50175, null).getInt(); promisedLandSkyColor = config.get("Hard-Coded Colors", "Promised Land Sky Color", 50175, null).getInt();
grassColourSmoothingArea = config.get("Biome Transition Colour Smoothing", "Grass Colour Smoothing Area", 7, "In Vanilla this is 1.").getInt();
leavesColourSmoothingArea = config.get("Biome Transition Colour Smoothing", "Leaves Colour Smoothing Area", 7, "In Vanilla this is 1.").getInt();
waterColourSmoothingArea = config.get("Biome Transition Colour Smoothing", "Water Colour Smoothing Area", 5, "In Vanilla this is 1.").getInt();
FMLCommonHandler.instance().getFMLLogger().log(Level.INFO, "[BiomesOPlenty] Generated Misc Config!"); FMLCommonHandler.instance().getFMLLogger().log(Level.INFO, "[BiomesOPlenty] Generated Misc Config!");
} }
catch (Exception e) catch (Exception e)

View file

@ -1,2 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
FMLCorePlugin: biomesoplenty.asm.BOPFMLLoadingPlugin