Move everything relating to optifine's config into OfConfig

Have the fog type change based on what optifine's in game setting is.
Change 2 minor TODOs.
This commit is contained in:
James Seibel
2020-09-21 09:45:35 -05:00
parent c74b9f74d9
commit 23f0f2662a
6 changed files with 354 additions and 179 deletions
@@ -1,13 +1,13 @@
package backsun.lod.renderer;
import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Project;
import backsun.lod.util.OfConfig;
import backsun.lod.util.fog.FogMode;
import backsun.lod.util.fog.FogType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
@@ -27,16 +27,12 @@ public class LodRenderer
private Minecraft mc;
private float farPlaneDistance;
// make sure this is an even number, or else it won't align with the chunk grid
public final int viewDistanceMultiplier = 12;
public final int viewDistanceMultiplier = 12;
private Tessellator tessellator;
private BufferBuilder bufferBuilder;
private Method fovMethod = null;
private enum FogMode{NEAR, FAR, NONE};
private OfConfig ofConfig;
public LodRenderer()
@@ -46,16 +42,17 @@ public class LodRenderer
tessellator = Tessellator.getInstance();
bufferBuilder = tessellator.getBuffer();
setupFovMethod();
ofConfig = new OfConfig();
// GL11.GL_MODELVIEW //5888
// GL11.GL_PROJECTION //5889
}
public void drawLODs(Minecraft mc, float partialTicks)
{
if (fovMethod == null)
if (ofConfig.fovMethod == null)
{
// don't continue if we can't get the
// user's FOV
@@ -179,8 +176,8 @@ public class LodRenderer
//
double yoffset = -cameraY + mc.world.provider.getAverageGroundLevel();
// TODO fix this so that chunks outside of the view distance are loaded and the biomes are read
// TODO fix so that the chunks within view distance aren't always plains
// fix this so that chunks outside of the view distance are loaded and the biomes are read
// fix so that the chunks within view distance aren't always plains
// if(biome != null)
// {
// // add the color
@@ -296,7 +293,7 @@ public class LodRenderer
mc.world.profiler.endStartSection("LOD draw");
// send the LODs over to the GPU
sendDataToGPUandDraw(lodArray, colorArray, cameraX, cameraY ,cameraZ);
sendToGPUAndDraw(lodArray, colorArray, cameraX, cameraY ,cameraZ);
@@ -351,46 +348,12 @@ public class LodRenderer
GlStateManager.loadIdentity();
// farPlaneDistance // 10 chunks = 160
if (fovMethod != null)
{
try
{
Project.gluPerspective((float)fovMethod.invoke(mc.entityRenderer, new Object[]{partialTicks, true}), (float) mc.displayWidth / (float) mc.displayHeight, 0.05f, farPlaneDistance * viewDistanceMultiplier);
}
catch(InvocationTargetException | IllegalAccessException | IllegalArgumentException e)
{
// hopefully this should never be called
System.out.println(e);
}
}
}
private void setupFog(FogMode fogMode)
{
if(fogMode == FogMode.NONE)
{
GlStateManager.disableFog();
return;
}
if(fogMode == FogMode.NEAR)
// only continue if we can get the FOV
if (ofConfig.fovMethod != null)
{
// 2.0f
// 2.25f
GlStateManager.setFogEnd(farPlaneDistance * 2.0f);
GlStateManager.setFogStart(farPlaneDistance * 2.25f);
Project.gluPerspective(ofConfig.getFov(mc, partialTicks, true), (float) mc.displayWidth / (float) mc.displayHeight, 0.05f, farPlaneDistance * viewDistanceMultiplier);
}
else //if(fogMode == FogMode.FAR)
{
// 0.25f
// 0.5f
GlStateManager.setFogStart(farPlaneDistance * (viewDistanceMultiplier * 0.25f));
GlStateManager.setFogEnd(farPlaneDistance * (viewDistanceMultiplier * 0.5f));
}
GlStateManager.setFogDensity(0.1f);
// GlStateManager.enableFog();
}
@@ -399,8 +362,10 @@ public class LodRenderer
* @param bbArray bounding boxes to draw
* @param colorArray color of each box to draw
*/
private void sendDataToGPUandDraw(AxisAlignedBB[] bbArray, Color[] colorArray, double cameraX, double cameraY, double cameraZ)
private void sendToGPUAndDraw(AxisAlignedBB[] bbArray, Color[] colorArray, double cameraX, double cameraY, double cameraZ)
{
FogType fogType = ofConfig.getFogSetting();
int red;
int green;
int blue;
@@ -458,86 +423,54 @@ public class LodRenderer
// depending on how far away this bounding box is,
// either use near or far fog
double nearDist = Math.pow(farPlaneDistance * viewDistanceMultiplier * 0.5f, 2); //TODO only calculate this once
double nearDist = Math.pow(farPlaneDistance * viewDistanceMultiplier * 0.35f, 2); //TODO only calculate this once, also maybe use y axis as well?
double bbDist = Math.pow(bb.minX, 2) + Math.pow(bb.minZ, 2);
if (bbDist < nearDist)
setupFog(FogMode.NEAR);
else
setupFog(FogMode.FAR);
if (fogType != FogType.OFF)
{
if (bbDist < nearDist)
setupFog(FogMode.NEAR);
else
setupFog(FogMode.FAR);
}
// draw this LOD
tessellator.draw();
}
}
/**
* This sets the "getFOVModifier" method from the
* minecraft "EntityRenderer" class, so that we can get
* the FOV of the player at any time.
*
* This is required since Minecraft is obfuscated so
* we can't just look for 'getFOVModifier'
* we have to search for it based on its parameters and
* return type; which luckily are unique in the EntityRenderer
* class.
*/
private void setupFovMethod()
private void setupFog(FogMode fogMode)
{
// get every method from the entity renderer
Method[] methods = Minecraft.getMinecraft().entityRenderer.getClass().getDeclaredMethods();
Class<?> returnType;
Parameter[] params;
Method returnMethod = null;
for(Method m : methods)
if(fogMode == FogMode.NONE)
{
returnType = m.getReturnType();
params = m.getParameters();
// see if this method has the same return type
// and parameters as the 'getFOVModifier' method.
if (returnType.equals(float.class) &&
params.length == 2 &&
params[0].getType().equals(float.class) &&
params[1].getType().equals(boolean.class))
{
// only accept the first method that we find
if (returnMethod == null)
{
returnMethod = m;
}
else
{
// we found a second method that matches the
// outline we were looking for,
// to prevent unexpected behavior
// dont't set fovMethod.
// Since we aren't sure that
// this method is the right
// one, we may accidently mess
// up the entityRender by invoking
// it and we probably wouldn't get
// the FOV from it anyway.
System.err.println("Error: a second method that matches the parameters and return typ of 'getFOVModifier' was found, LODs won't be rendered.");
return;
}
}
GlStateManager.disableFog();
return;
}
// only set the method once we have gone through
// the whole array of methods, just to
// make sure we have the right one.
fovMethod = returnMethod;
// set up the method so we can invoke it later
fovMethod.setAccessible(true);
if(fogMode == FogMode.NEAR)
{
// 2.0f
// 2.25f
GlStateManager.setFogEnd(farPlaneDistance * 2.0f);
GlStateManager.setFogStart(farPlaneDistance * 2.25f);
}
else //if(fogMode == FogMode.FAR)
{
// 0.25f
// 0.5f
GlStateManager.setFogStart(farPlaneDistance * (viewDistanceMultiplier * 0.25f));
GlStateManager.setFogEnd(farPlaneDistance * (viewDistanceMultiplier * 0.5f));
}
GlStateManager.setFogDensity(0.1f);
GlStateManager.enableFog();
}
}
@@ -1,59 +0,0 @@
package backsun.lod.util;
import java.lang.reflect.Method;
/**
*
* @author James Seibel
* @version 09-17-2020
*/
public class Config
{
public static boolean zoomMode()
{
//TODO move this code so that we don't
// have to find the class and method each time
// we want the zoom status
try
{
Class<?> ofConfig = Class.forName("OfConfigReflector");
Method zoomMethod = ofConfig.getMethod("zoomMode");
return (boolean) zoomMethod.invoke(ofConfig);
}
catch(Exception e)
{
// the only way any exceptions should be thrown is if
// Optifine isn't installed or the method's name was
// changed.
System.err.println(e);
return false;
}
}
public static boolean isDynamicFov()
{
//TODO move this code so that we don't
// have to find the class and method each time
// we want the zoom status
try
{
Class<?> ofConfig = Class.forName("OfConfigReflector");
Method dynamicMethod = ofConfig.getMethod("isDynamicFov");
return (boolean) dynamicMethod.invoke(ofConfig);
}
catch(Exception e)
{
// the only way any exceptions should be thrown is if
// Optifine isn't installed or the method's name was
// changed.
System.err.println(e);
return false;
}
}
}
@@ -0,0 +1,94 @@
package backsun.lod.util;
import java.util.HashMap;
import java.util.Map;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
/**
*
* @author James Seibel
* @version 09-19-2020
*/
@Config(modid = Reference.MOD_ID)
public class LodConfig
{
@Config.Comment("This is an example boolean property.")
public static boolean fooBar = false;
@Config.Comment(
{"This is an example enum property.",
"It will use a GuiConfigEntries.CycleValueEntry in the config GUI."})
public static EnumExample exampleEnumProperty = EnumExample.VALUE_1;
@Config.Comment({"This an example Map field.", "It will be converted to a category containing a property for each key-value pair."})
public static final Map<String, Double> exampleMapField = new HashMap<>();
static
{
exampleMapField.put("foobar", 2.0);
exampleMapField.put("foobaz", 100.5);
exampleMapField.put("barbaz", Double.MAX_VALUE);
}
public static final Client client = new Client();
public enum EnumExample {
VALUE_1,
VALUE_2,
VALUE_3,
VALUE_4
}
public static class Client {
@Config.Comment("This is an example int property.")
public int baz = -100;
@Config.Comment("This is an example enum property in a subcategory "
+ "of the main category.")
public EnumExample exampleSubcategoryEnumProperty = EnumExample.VALUE_3;
@Config.Comment("This is an example enum property that "
+ "uses an enum defined in a nested class.")
public EnumExampleNested exampleNestedEnumProperty = EnumExampleNested.NESTED_2;
public enum EnumExampleNested {
NESTED_1,
NESTED_2,
NESTED_3,
NESTED_4,
NESTED_5
}
}
@Mod.EventBusSubscriber(modid = Reference.MOD_ID)
private static class EventHandler
{
/**
* Inject the new values and save
* to the config file when the
* config has been changed from the GUI.
*/
@SubscribeEvent
public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event) {
if (event.getModID().equals(Reference.MOD_ID))
{
ConfigManager.sync(Reference.MOD_ID, Config.Type.INSTANCE);
}
}
}
}
@@ -0,0 +1,182 @@
package backsun.lod.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import backsun.lod.util.fog.FogType;
import net.minecraft.client.Minecraft;
/**
*
* @author James Seibel
* @version 09-21-2020
*/
public class OfConfig
{
public Method fovMethod = null;
public Field ofFogField = null;
public OfConfig()
{
setupFovMethod();
setupFogField();
}
/**
* This sets the "getFOVModifier" method from the
* minecraft "EntityRenderer" class, so that we can get
* the FOV of the player at any time.
*
* This is required since Minecraft is obfuscated so
* we can't just look for 'getFOVModifier'
* we have to search for it based on its parameters and
* return type; which luckily are unique in the EntityRenderer
* class.
*/
private void setupFovMethod()
{
// get every method from the entity renderer
Method[] methods = Minecraft.getMinecraft().entityRenderer.getClass().getDeclaredMethods();
Class<?> returnType;
Parameter[] params;
Method returnMethod = null;
for(Method m : methods)
{
returnType = m.getReturnType();
params = m.getParameters();
// see if this method has the same return type
// and parameters as the 'getFOVModifier' method.
if (returnType.equals(float.class) &&
params.length == 2 &&
params[0].getType().equals(float.class) &&
params[1].getType().equals(boolean.class))
{
// only accept the first method that we find
if (returnMethod == null)
{
returnMethod = m;
}
else
{
// we found a second method that matches the
// outline we were looking for,
// to prevent unexpected behavior
// dont't set fovMethod.
// Since we aren't sure that
// this method is the right
// one, we may accidently mess
// up the entityRender by invoking
// it and we probably wouldn't get
// the FOV from it anyway.
System.err.println("Error: a second method that matches the parameters and return typ of 'getFOVModifier' was found, LODs won't be rendered.");
return;
}
}
}
// only set the method once we have gone through
// the whole array of methods, just to
// make sure we have the right one.
fovMethod = returnMethod;
// set up the method so we can invoke it later
fovMethod.setAccessible(true);
}
private void setupFogField()
{
// get every variable from the entity renderer
Field[] vars = Minecraft.getMinecraft().gameSettings.getClass().getDeclaredFields();
// try and find the ofFogType variable in gameSettings
for(Field f : vars)
{
if(f.getName().equals("ofFogType"))
{
ofFogField = f;
return;
}
}
// we didn't find the field,
// either optifine isn't installed, or
// optifine changed the name of the variable
ofFogField = null;
}
public FogType getFogSetting()
{
if (ofFogField == null)
{
// either optifine isn't installed,
// the variable name was changed,
// or the setup method wasn't called yet.
return FogType.UNKNOWN;
}
int returnNum = 0;
try
{
returnNum = (int)ofFogField.get(Minecraft.getMinecraft().gameSettings);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
System.out.println(e);
}
switch (returnNum)
{
case 0:
return FogType.UNKNOWN;
case 1:
return FogType.FAST;
case 2:
return FogType.FANCY;
case 3:
return FogType.OFF;
default:
return FogType.UNKNOWN;
}
}
public float getFov(Minecraft mc, float partialTicks, boolean useFovSetting)
{
try
{
return (float)fovMethod.invoke(mc.entityRenderer, new Object[]{partialTicks, useFovSetting});
}
catch(InvocationTargetException | IllegalAccessException | IllegalArgumentException e)
{
// hopefully this should never be called
System.out.println(e);
}
return 0.0f;
}
}
@@ -0,0 +1,12 @@
package backsun.lod.util.fog;
/**
* @author James Seibel
* @version 09-21-2020
*/
public enum FogMode
{
NEAR,
FAR,
NONE
}
@@ -0,0 +1,13 @@
package backsun.lod.util.fog;
/**
* @author James Seibel
* @version 09-21-2020
*/
public enum FogType
{
UNKNOWN,
FAST,
FANCY,
OFF;
}