210 lines
7 KiB
Java
210 lines
7 KiB
Java
|
package biomesoplenty.asm;
|
||
|
|
||
|
import static org.objectweb.asm.Opcodes.*;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Iterator;
|
||
|
import java.util.List;
|
||
|
|
||
|
import net.minecraft.client.Minecraft;
|
||
|
import net.minecraft.entity.Entity;
|
||
|
import net.minecraft.launchwrapper.IClassTransformer;
|
||
|
import net.minecraft.util.MathHelper;
|
||
|
import net.minecraft.world.World;
|
||
|
import net.minecraft.world.biome.BiomeGenBase;
|
||
|
import net.minecraftforge.common.ForgeDummyContainer;
|
||
|
|
||
|
import org.lwjgl.opengl.GL11;
|
||
|
import org.objectweb.asm.ClassReader;
|
||
|
import org.objectweb.asm.ClassWriter;
|
||
|
import org.objectweb.asm.Label;
|
||
|
import org.objectweb.asm.Opcodes;
|
||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||
|
import org.objectweb.asm.tree.ClassNode;
|
||
|
import org.objectweb.asm.tree.FieldInsnNode;
|
||
|
import org.objectweb.asm.tree.FrameNode;
|
||
|
import org.objectweb.asm.tree.InsnList;
|
||
|
import org.objectweb.asm.tree.InsnNode;
|
||
|
import org.objectweb.asm.tree.JumpInsnNode;
|
||
|
import org.objectweb.asm.tree.LabelNode;
|
||
|
import org.objectweb.asm.tree.LdcInsnNode;
|
||
|
import org.objectweb.asm.tree.LineNumberNode;
|
||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||
|
import org.objectweb.asm.tree.MethodNode;
|
||
|
import org.objectweb.asm.tree.VarInsnNode;
|
||
|
|
||
|
import biomesoplenty.interfaces.IBOPFog;
|
||
|
|
||
|
public class BOPFogDistance implements IClassTransformer
|
||
|
{
|
||
|
private static int fogX, fogZ;
|
||
|
|
||
|
private static boolean fogInit;
|
||
|
private static float storedFinalFogCloseness;
|
||
|
|
||
|
@Override
|
||
|
public byte[] transform(String name, String newname, byte[] bytes)
|
||
|
{
|
||
|
if (name.equals("net.minecraft.client.renderer.EntityRenderer"))
|
||
|
{
|
||
|
return patchEntityRenderer(newname, bytes, false);
|
||
|
}
|
||
|
|
||
|
if (name.equals("bfe"))
|
||
|
{
|
||
|
return patchEntityRenderer(newname, bytes, true);
|
||
|
}
|
||
|
|
||
|
return bytes;
|
||
|
}
|
||
|
|
||
|
public static byte[] patchEntityRenderer(String name, byte[] bytes, boolean obfuscated)
|
||
|
{
|
||
|
String targetMethodName = "";
|
||
|
|
||
|
if (obfuscated)
|
||
|
targetMethodName ="a";
|
||
|
else
|
||
|
targetMethodName ="setupFog";
|
||
|
|
||
|
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("(IF)V")))
|
||
|
{
|
||
|
AbstractInsnNode currentNode = null;
|
||
|
AbstractInsnNode targetNode = null;
|
||
|
|
||
|
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
|
||
|
|
||
|
int index = -1;
|
||
|
int timesFound = 0;
|
||
|
|
||
|
while (iter.hasNext())
|
||
|
{
|
||
|
index++;
|
||
|
currentNode = iter.next();
|
||
|
|
||
|
if (currentNode.getOpcode() == ALOAD)
|
||
|
{
|
||
|
if (timesFound == 22)
|
||
|
{
|
||
|
targetNode = currentNode;
|
||
|
fdiv_index = index;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
timesFound++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
mv.visitMethodInsn(INVOKESTATIC, "org/lwjgl/opengl/GL11", "glFogf", "(IF)V");
|
||
|
mv.visitLabel(l71);
|
||
|
mv.visitLineNumber(1922, l71);
|
||
|
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||
|
mv.visitVarInsn(ALOAD, 3);
|
||
|
mv.visitVarInsn(FLOAD, 6);
|
||
|
mv.visitMethodInsn(INVOKESTATIC, "biomesoplenty/asm/BOPFogDistance", "setBiomeFogDistance", "(Lnet/minecraft/entity/Entity;F)V");
|
||
|
mv.visitLabel(l32);
|
||
|
*/
|
||
|
|
||
|
InsnList toInject = new InsnList();
|
||
|
|
||
|
toInject.add(new VarInsnNode(ALOAD, 3));
|
||
|
toInject.add(new VarInsnNode(ILOAD, 1));
|
||
|
toInject.add(new VarInsnNode(FLOAD, 6));
|
||
|
if (obfuscated)
|
||
|
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/BOPFogDistance", "setBiomeFogDistance", "(Lnn;F)V"));
|
||
|
else
|
||
|
toInject.add(new MethodInsnNode(INVOKESTATIC, "biomesoplenty/asm/BOPFogDistance", "setBiomeFogDistance", "(Lnet/minecraft/entity/Entity;IF)V"));
|
||
|
|
||
|
m.instructions.insertBefore(m.instructions.get(fdiv_index), toInject);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
|
||
|
classNode.accept(writer);
|
||
|
return writer.toByteArray();
|
||
|
}
|
||
|
|
||
|
public static void setBiomeFogDistance(Entity entity, int distance, float farPlaneDistance)
|
||
|
{
|
||
|
World world = entity.worldObj;
|
||
|
|
||
|
int playerX = MathHelper.floor_double(entity.posX);
|
||
|
int playerZ = MathHelper.floor_double(entity.posZ);
|
||
|
|
||
|
if (playerX == fogX && playerZ == fogZ && fogInit)
|
||
|
{
|
||
|
if (distance < 0)
|
||
|
{
|
||
|
GL11.glFogf(GL11.GL_FOG_START, 0.0F);
|
||
|
GL11.glFogf(GL11.GL_FOG_END, farPlaneDistance * 0.8F);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GL11.glFogf(GL11.GL_FOG_START, farPlaneDistance * (storedFinalFogCloseness / 10));
|
||
|
GL11.glFogf(GL11.GL_FOG_END, Math.min(farPlaneDistance, 192.0F) * storedFinalFogCloseness);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fogInit = true;
|
||
|
|
||
|
int blenddistance = Minecraft.getMinecraft().gameSettings.fancyGraphics ? ForgeDummyContainer.blendRanges[Minecraft.getMinecraft().gameSettings.renderDistance] : 0;
|
||
|
|
||
|
int divider = 0;
|
||
|
|
||
|
float fogCloseness = 0.0F;
|
||
|
|
||
|
for (int x = -blenddistance; x <= blenddistance; ++x)
|
||
|
{
|
||
|
for (int z = -blenddistance; z <= blenddistance; ++z)
|
||
|
{
|
||
|
BiomeGenBase biome = world.getBiomeGenForCoords(playerX + x, playerZ + z);
|
||
|
|
||
|
if (biome instanceof IBOPFog)
|
||
|
{
|
||
|
fogCloseness += ((IBOPFog)biome).getFogCloseness();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fogCloseness += 1.0F;
|
||
|
}
|
||
|
|
||
|
divider++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float finalFogCloseness = fogCloseness / divider;
|
||
|
|
||
|
fogX = playerX;
|
||
|
fogZ = playerZ;
|
||
|
storedFinalFogCloseness = finalFogCloseness;
|
||
|
|
||
|
if (distance < 0)
|
||
|
{
|
||
|
GL11.glFogf(GL11.GL_FOG_START, 0.0F);
|
||
|
GL11.glFogf(GL11.GL_FOG_END, farPlaneDistance * 0.8F);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GL11.glFogf(GL11.GL_FOG_START, farPlaneDistance * (finalFogCloseness / 10));
|
||
|
GL11.glFogf(GL11.GL_FOG_END, Math.min(farPlaneDistance, 192.0F) * finalFogCloseness);
|
||
|
}
|
||
|
}
|
||
|
}
|