Add IMinecraftRenderWrapper

This commit is contained in:
James Seibel
2021-11-18 20:38:16 -06:00
parent 03f85c1d23
commit 00058a22cf
20 changed files with 616 additions and 197 deletions
@@ -31,8 +31,8 @@ import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.ThreadMapUtil;
import com.seibel.lod.core.wrapperAdapters.SingletonHandler;
import com.seibel.lod.core.wrapperAdapters.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
import net.minecraft.profiler.IProfiler;
@@ -51,7 +51,8 @@ public class ClientApi
public static LodRenderer renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
private final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
private final IMinecraftRenderWrapper mcRender = SingletonHandler.get(IMinecraftRenderWrapper.class);
private final EventApi eventApi = EventApi.INSTANCE;
private final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
@@ -119,7 +120,7 @@ public class ClientApi
// these can't be set until after the buffers are built (in renderer.drawLODs)
// otherwise the buffers may be set to the wrong size, or not changed at all
ApiShared.previousChunkRenderDistance = mc.getRenderDistance();
ApiShared.previousChunkRenderDistance = mcRender.getRenderDistance();
ApiShared.previousLodRenderDistance = config.client().graphics().quality().getLodChunkRenderDistance();
}
catch (Exception e)
@@ -36,7 +36,6 @@ import com.seibel.lod.core.wrapperAdapters.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperAdapters.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperAdapters.world.IWorldWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
/**
* This holds the methods that should be called
@@ -50,7 +49,7 @@ public class EventApi
{
public static final EventApi INSTANCE = new EventApi();
private final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
private final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
/**
@@ -61,7 +61,6 @@ import com.seibel.lod.core.wrapperAdapters.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.block.BlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
/**
* This object creates the buffers that are
@@ -73,7 +72,7 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
public class LodBufferBuilderFactory
{
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
/** The thread used to generate new LODs off the main thread. */
public static final ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(LodBufferBuilderFactory.class.getSimpleName() + " - main"));
@@ -58,7 +58,7 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
*/
public class LodBuilder
{
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
private static final IBlockColorSingletonWrapper blockColorSingleton = SingletonHandler.get(IBlockColorSingletonWrapper.class);
private final ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName()));
@@ -51,7 +51,7 @@ import net.minecraftforge.common.WorldWorkerManager;
*/
public class LodWorldGenerator
{
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
/** This holds the thread used to generate new LODs off the main thread. */
private final ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " world generator"));
@@ -43,7 +43,7 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
public class Box
{
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
public static final int ADJACENT_HEIGHT_INDEX = 0;
public static final int ADJACENT_DEPTH_INDEX = 1;
@@ -60,7 +60,7 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
public class LodDimension
{
private final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
public final IDimensionTypeWrapper dimension;
@@ -0,0 +1,257 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.objects.math;
import com.seibel.lod.core.util.LodUtil;
/**
* This is closer to MC's implementation of a
* 3 element float vector than a 3 element double
* vector. Hopefully that shouldn't cause any issues.
*
* @author James Seibel
* @version 11-18-2021
*/
public class Vec3d
{
public static Vec3d XNeg = new Vec3d(-1.0F, 0.0F, 0.0F);
public static Vec3d XPos = new Vec3d(1.0F, 0.0F, 0.0F);
public static Vec3d YNeg = new Vec3d(0.0F, -1.0F, 0.0F);
public static Vec3d YPos = new Vec3d(0.0F, 1.0F, 0.0F);
public static Vec3d ZNeg = new Vec3d(0.0F, 0.0F, -1.0F);
public static Vec3d ZPos = new Vec3d(0.0F, 0.0F, 1.0F);
public static final Vec3d ZERO_VECTOR = new Vec3d(0.0D, 0.0D, 0.0D);
public double x;
public double y;
public double z;
public Vec3d()
{
}
public Vec3d(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
Vec3d Vec3f = (Vec3d) obj;
if (Double.compare(Vec3f.x, this.x) != 0)
{
return false;
}
else if (Double.compare(Vec3f.y, this.y) != 0)
{
return false;
}
else
{
return Double.compare(Vec3f.z, this.z) == 0;
}
}
else
{
return false;
}
}
@Override
public int hashCode()
{
long longVal = Double.doubleToLongBits(this.x);
int intVal = (int) (longVal ^ longVal >>> 32);
longVal = Double.doubleToLongBits(this.y);
intVal = 31 * intVal + (int) (longVal ^ longVal >>> 32);
longVal = Double.doubleToLongBits(this.z);
return 31 * intVal + (int) (longVal ^ longVal >>> 32);
}
public void mul(double scalar)
{
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
}
public void mul(double x, double y, double z)
{
this.x *= x;
this.y *= y;
this.z *= z;
}
public void clamp(double min, double max)
{
this.x = LodUtil.clamp(min, this.x, max);
this.y = LodUtil.clamp(min, this.y, max);
this.z = LodUtil.clamp(min, this.z, max);
}
public void set(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public void add(double x, double y, double z)
{
this.x += x;
this.y += y;
this.z += z;
}
public void add(Vec3d vector)
{
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;
}
public void subtract(Vec3d vector)
{
this.x -= vector.x;
this.y -= vector.y;
this.z -= vector.z;
}
public double dotProduct(Vec3d vector)
{
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
}
public Vec3d normalize()
{
double value = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
return value < 1.0E-4D ? ZERO_VECTOR : new Vec3d(this.x / value, this.y / value, this.z / value);
}
public void crossProduct(Vec3d vector)
{
double f = this.x;
double f1 = this.y;
double f2 = this.z;
double f3 = vector.x;
double f4 = vector.y;
double f5 = vector.z;
this.x = f1 * f5 - f2 * f4;
this.y = f2 * f3 - f * f5;
this.z = f * f4 - f1 * f3;
}
/* Matrix3f is not currently needed/implemented
public void transform(Matrix3f p_229188_1_)
{
double f = this.x;
double f1 = this.y;
double f2 = this.z;
this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2;
this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2;
this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2;
}
*/
/* Quaternions are not currently needed/implemented
public void transform(Quaternion p_214905_1_)
{
Quaternion quaternion = new Quaternion(p_214905_1_);
quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F));
Quaternion quaternion1 = new Quaternion(p_214905_1_);
quaternion1.conj();
quaternion.mul(quaternion1);
this.set(quaternion.i(), quaternion.j(), quaternion.k());
}
*/
/* not currently needed
* percent may actually be partial ticks (which is available when rendering)
public void linearInterp(Vec3f resultingVector, double percent)
{
double f = 1.0F - percent;
this.x = this.x * f + resultingVector.x * percent;
this.y = this.y * f + resultingVector.y * percent;
this.z = this.z * f + resultingVector.z * percent;
}
*/
/* Quaternions are not currently needed/implemented
public Quaternion rotation(double p_229193_1_)
{
return new Quaternion(this, p_229193_1_, false);
}
@OnlyIn(Dist.CLIENT)
public Quaternion rotationDegrees(double p_229187_1_)
{
return new Quaternion(this, p_229187_1_, true);
}
*/
public Vec3d copy()
{
return new Vec3d(this.x, this.y, this.z);
}
/* not currently needed/implemented
public void map(double2doubleFunction p_229191_1_)
{
this.x = p_229191_1_.get(this.x);
this.y = p_229191_1_.get(this.y);
this.z = p_229191_1_.get(this.z);
}
*/
@Override
public String toString()
{
return "[" + this.x + ", " + this.y + ", " + this.z + "]";
}
// Forge start
public Vec3d(double[] values)
{
set(values);
}
public void set(double[] values)
{
this.x = values[0];
this.y = values[1];
this.z = values[2];
}
}
@@ -55,7 +55,7 @@ public class GlProxy
{
private static GlProxy instance = null;
private static IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
/** Minecraft's GLFW window */
@@ -29,7 +29,6 @@ import org.lwjgl.opengl.NVFogDistance;
import com.seibel.lod.api.lod.ApiShared;
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory;
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory.VertexBuffersAndOffset;
import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
@@ -37,6 +36,8 @@ import com.seibel.lod.core.enums.rendering.FogQuality;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.objects.lod.RegionPos;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.objects.opengl.LodVertexBuffer;
import com.seibel.lod.core.objects.rending.NearFarFogSettings;
import com.seibel.lod.core.render.shader.LodShaderProgram;
@@ -49,16 +50,9 @@ import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.block.BlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.wrappers.handlers.ReflectionHandler;
import com.seibel.lod.wrappers.minecraft.McObjectConverter;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftRenderWrapper;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.potion.Effects;
import net.minecraft.profiler.IProfiler;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
/**
* This is where all the magic happens. <br>
@@ -69,11 +63,11 @@ import net.minecraft.util.math.vector.Vector3f;
*/
public class LodRenderer
{
/**
* this is the light used when rendering the LODs,
* it should be something different from what is used by Minecraft
*/
private static final int LOD_GL_LIGHT_NUMBER = GL15.GL_LIGHT2;
// /**
// * this is the light used when rendering the LODs,
// * it should be something different from what is used by Minecraft
// */
// private static final int LOD_GL_LIGHT_NUMBER = GL15.GL_LIGHT2;
/**
* If true the LODs colors will be replaced with
@@ -81,9 +75,10 @@ public class LodRenderer
*/
public DebugMode previousDebugMode = DebugMode.OFF;
private final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private final GameRenderer gameRender;
private final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
private final MinecraftRenderWrapper mcRenderer = MinecraftRenderWrapper.INSTANCE;
private final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private IProfiler profiler;
private int farPlaneBlockDistance;
@@ -98,6 +93,7 @@ public class LodRenderer
* These have to be separate because we can't override the
* buffers in the VBOs (and we don't want to)
*/
@SuppressWarnings("unused")
private int[][][] storageBufferIds;
private ChunkPosWrapper vbosCenter = new ChunkPosWrapper(0, 0);
@@ -139,9 +135,6 @@ public class LodRenderer
public LodRenderer(LodBufferBuilderFactory newLodNodeBufferBuilder)
{
mc = MinecraftWrapper.INSTANCE;
gameRender = mc.getGameRenderer();
lodBufferBuilderFactory = newLodNodeBufferBuilder;
}
@@ -172,7 +165,7 @@ public class LodRenderer
return;
}
if (mc.getPlayer().getActiveEffectsMap().get(Effects.BLINDNESS) != null)
if (mcRenderer.playerHasBlindnessEffect())
{
// if the player is blind don't render LODs,
// and don't change minecraft's fog
@@ -251,7 +244,7 @@ public class LodRenderer
Mat4f modelViewMatrix = offsetTheModelViewMatrix(mcModelViewMatrix, partialTicks);
vanillaBlockRenderedDistance = mc.getRenderDistance() * LodUtil.CHUNK_WIDTH;
vanillaBlockRenderedDistance = mcRenderer.getRenderDistance() * LodUtil.CHUNK_WIDTH;
// required for setupFog and setupProjectionMatrix
if (mc.getWrappedClientWorld().getDimensionType().hasCeiling())
farPlaneBlockDistance = Math.min(config.client().graphics().quality().getLodChunkRenderDistance(), LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * LodUtil.CHUNK_WIDTH;
@@ -289,16 +282,15 @@ public class LodRenderer
if (vbos != null)
{
ActiveRenderInfo camera = mc.getGameRenderer().getMainCamera();
Vector3f cameraDir = camera.getLookVector();
Vec3f cameraDir = mcRenderer.getLookAtVector();
// TODO re-enable once rendering is totally working
boolean cullingDisabled = true; //LodConfig.client().graphics.advancedGraphicsOption.disableDirectionalCulling.get();
boolean renderBufferStorage = config.client().graphics().advancedGraphics().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
// boolean renderBufferStorage = config.client().graphics().advancedGraphics().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
// used to determine what type of fog to render
int halfWidth = vbos.length / 2;
int quarterWidth = vbos.length / 4;
// int halfWidth = vbos.length / 2;
// int quarterWidth = vbos.length / 4;
// where the center of the built buffers is (needed when culling regions)
RegionPos vboCenterRegionPos = new RegionPos(vbosCenter);
@@ -338,7 +330,7 @@ public class LodRenderer
x + vboCenterRegionPos.x - (lodDim.getWidth() / 2),
z + vboCenterRegionPos.z - (lodDim.getWidth() / 2));
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(camera.getBlockPosition(), cameraDir, vboPos.blockPos()))
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(mcRenderer.getCameraBlockPosition(), cameraDir, vboPos.blockPos()))
{
// TODO add fog to the fragment shader
// if ((x > halfWidth - quarterWidth && x < halfWidth + quarterWidth)
@@ -428,6 +420,7 @@ public class LodRenderer
// Setup Functions //
//=================//
@SuppressWarnings("unused")
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
{
if (fogQuality == FogQuality.OFF)
@@ -506,6 +499,7 @@ public class LodRenderer
* Revert any changes that were made to the fog
* and sets up the fog for Minecraft.
*/
@SuppressWarnings("unused")
private void cleanupFog(NearFarFogSettings fogSettings,
float defaultFogStartDist, float defaultFogEndDist,
int defaultFogMode, int defaultFogDistance)
@@ -548,8 +542,7 @@ public class LodRenderer
private Mat4f offsetTheModelViewMatrix(Mat4f mcModelViewMatrix, float partialTicks)
{
// get all relevant camera info
ActiveRenderInfo camera = mc.getGameRenderer().getMainCamera();
Vector3d projectedView = camera.getPosition();
Vec3d projectedView = mcRenderer.getCameraExactPosition();
// translate the camera relative to the regions' center
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
@@ -573,15 +566,15 @@ public class LodRenderer
// create the new projection matrix
Mat4f lodProj = Mat4f.perspective(
getFov(partialTicks, true),
(float) this.mc.getWindow().getScreenWidth() / (float) this.mc.getWindow().getScreenHeight(),
mcRenderer.getFov(partialTicks),
(float) this.mcRenderer.getScreenWidth() / (float) this.mcRenderer.getScreenHeight(),
config.client().graphics().advancedGraphics().getUseExtendedNearClipPlane() ? vanillaBlockRenderedDistance / 5 : 1,
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2);
// get Minecraft's un-edited projection matrix
// (this is before it is zoomed, distorted, etc.)
Mat4f defaultMcProj = McObjectConverter.Convert(mc.getGameRenderer().getProjectionMatrix(mc.getGameRenderer().getMainCamera(), partialTicks, true));
Mat4f defaultMcProj = mcRenderer.getDefaultProjectionMatrix(partialTicks);
// true here means use "use fov setting" (probably)
// this logic strips away the defaultMcProj matrix, so we
@@ -686,15 +679,9 @@ public class LodRenderer
{
lodBufferBuilderFactory.destroyBuffers();
}
// TODO move this into the MC wrapper
private double getFov(float partialTicks, boolean useFovSetting)
{
return mc.getGameRenderer().getFov(mc.getGameRenderer().getMainCamera(), partialTicks, useFovSetting);
}
/** Return what fog settings should be used when rendering. */
@SuppressWarnings("unused")
private NearFarFogSettings determineFogSettings()
{
NearFarFogSettings fogSettings = new NearFarFogSettings();
@@ -796,7 +783,7 @@ public class LodRenderer
/** Determines if the LODs should have a fullRegen or partialRegen */
private void determineIfLodsShouldRegenerate(LodDimension lodDim, float partialTicks)
{
short chunkRenderDistance = (short) mc.getRenderDistance();
short chunkRenderDistance = (short) mcRenderer.getRenderDistance();
int vanillaRenderedChunksWidth = chunkRenderDistance * 2 + 2;
//=============//
@@ -869,10 +856,10 @@ public class LodRenderer
// (just in case the minLightingDifference is too large to notice the change)
|| (skyBrightness == 1.0f && prevSkyBrightness != 1.0f) // noon
|| (skyBrightness == 0.2f && prevSkyBrightness != 0.2f) // midnight
|| mc.getOptions().gamma != prevBrightness)
|| mcRenderer.getGamma() != prevBrightness)
{
fullRegen = true;
prevBrightness = mc.getOptions().gamma;
prevBrightness = mcRenderer.getGamma();
prevSkyBrightness = skyBrightness;
}
@@ -917,15 +904,15 @@ public class LodRenderer
//==============//
// determine which LODs should not be rendered close to the player
HashSet<ChunkPos> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, mc.getPlayerBlockPos());
HashSet<ChunkPosWrapper> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, mc.getPlayerBlockPos());
int xIndex;
int zIndex;
for (ChunkPos pos : chunkPosToSkip)
for (ChunkPosWrapper pos : chunkPosToSkip)
{
vanillaRenderedChunksEmptySkip = false;
xIndex = (pos.x - mc.getPlayerChunkPos().getX()) + (chunkRenderDistance + 1);
zIndex = (pos.z - mc.getPlayerChunkPos().getZ()) + (chunkRenderDistance + 1);
xIndex = (pos.getX() - mc.getPlayerChunkPos().getX()) + (chunkRenderDistance + 1);
zIndex = (pos.getZ() - mc.getPlayerChunkPos().getZ()) + (chunkRenderDistance + 1);
// sometimes we are given chunks that are outside the render distance,
// This prevents index out of bounds exceptions
@@ -19,15 +19,11 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperAdapters.SingletonHandler;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.block.BlockPosWrapper;
import com.seibel.lod.core.wrapperAdapters.block.AbstractBlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3f;
import com.seibel.lod.wrappers.minecraft.MinecraftRenderWrapper;
/**
* This holds miscellaneous helper code
@@ -38,7 +34,7 @@ import net.minecraft.util.math.vector.Vector3f;
*/
public class RenderUtil
{
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
/**
@@ -47,11 +43,11 @@ public class RenderUtil
*/
public static boolean isChunkPosInLoadedArea(ChunkPosWrapper pos, ChunkPosWrapper center)
{
return (pos.getX() >= center.getX() - mc.getRenderDistance()
&& pos.getX() <= center.getX() + mc.getRenderDistance())
return (pos.getX() >= center.getX() - MC_RENDER.getRenderDistance()
&& pos.getX() <= center.getX() + MC_RENDER.getRenderDistance())
&&
(pos.getZ() >= center.getZ() - mc.getRenderDistance()
&& pos.getZ() <= center.getZ() + mc.getRenderDistance());
(pos.getZ() >= center.getZ() - MC_RENDER.getRenderDistance()
&& pos.getZ() <= center.getZ() + MC_RENDER.getRenderDistance());
}
/**
@@ -60,11 +56,11 @@ public class RenderUtil
*/
public static boolean isCoordinateInLoadedArea(int x, int z, int centerCoordinate)
{
return (x >= centerCoordinate - mc.getRenderDistance()
&& x <= centerCoordinate + mc.getRenderDistance())
return (x >= centerCoordinate - MC_RENDER.getRenderDistance()
&& x <= centerCoordinate + MC_RENDER.getRenderDistance())
&&
(z >= centerCoordinate - mc.getRenderDistance()
&& z <= centerCoordinate + mc.getRenderDistance());
(z >= centerCoordinate - MC_RENDER.getRenderDistance()
&& z <= centerCoordinate + MC_RENDER.getRenderDistance());
}
@@ -88,24 +84,24 @@ public class RenderUtil
* Returns true if one of the region's 4 corners is in front
* of the camera.
*/
public static boolean isRegionInViewFrustum(BlockPos playerBlockPos, Vector3f cameraDir, BlockPosWrapper vboCenterPos)
public static boolean isRegionInViewFrustum(AbstractBlockPosWrapper playerBlockPos, Vec3f cameraDir, AbstractBlockPosWrapper vboCenterPos)
{
// convert the vbo position into a direction vector
// starting from the player's position
Vector3f vboVec = new Vector3f(vboCenterPos.getX(), 0, vboCenterPos.getZ());
Vector3f playerVec = new Vector3f(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
Vec3f vboVec = new Vec3f(vboCenterPos.getX(), 0, vboCenterPos.getZ());
Vec3f playerVec = new Vec3f(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
vboVec.sub(playerVec);
Vector3f vboCenterVec = vboVec;
vboVec.subtract(playerVec);
Vec3f vboCenterVec = vboVec;
int halfRegionWidth = LodUtil.REGION_WIDTH / 2;
// calculate the 4 corners
Vector3f vboSeVec = new Vector3f(vboCenterVec.x() + halfRegionWidth, vboCenterVec.y(), vboCenterVec.z() + halfRegionWidth);
Vector3f vboSwVec = new Vector3f(vboCenterVec.x() - halfRegionWidth, vboCenterVec.y(), vboCenterVec.z() + halfRegionWidth);
Vector3f vboNwVec = new Vector3f(vboCenterVec.x() - halfRegionWidth, vboCenterVec.y(), vboCenterVec.z() - halfRegionWidth);
Vector3f vboNeVec = new Vector3f(vboCenterVec.x() + halfRegionWidth, vboCenterVec.y(), vboCenterVec.z() - halfRegionWidth);
Vec3f vboSeVec = new Vec3f(vboCenterVec.x + halfRegionWidth, vboCenterVec.y, vboCenterVec.z + halfRegionWidth);
Vec3f vboSwVec = new Vec3f(vboCenterVec.x - halfRegionWidth, vboCenterVec.y, vboCenterVec.z + halfRegionWidth);
Vec3f vboNwVec = new Vec3f(vboCenterVec.x - halfRegionWidth, vboCenterVec.y, vboCenterVec.z - halfRegionWidth);
Vec3f vboNeVec = new Vec3f(vboCenterVec.x + halfRegionWidth, vboCenterVec.y, vboCenterVec.z - halfRegionWidth);
// if any corner is visible, this region should be rendered
return isNormalizedVectorInViewFrustum(vboSeVec, cameraDir) ||
@@ -118,11 +114,11 @@ public class RenderUtil
* Currently takes the dot product of the two vectors,
* but in the future could do more complicated frustum culling tests.
*/
private static boolean isNormalizedVectorInViewFrustum(Vector3f objectVector, Vector3f cameraDir)
private static boolean isNormalizedVectorInViewFrustum(Vec3f objectVector, Vec3f cameraDir)
{
// the -0.1 is to offer a slight buffer, so we are
// more likely to render LODs and thus, hopefully prevent
// flickering or odd disappearances
return objectVector.dot(cameraDir) > -0.1;
return objectVector.dotProduct(cameraDir) > -0.1;
}
}
@@ -33,7 +33,7 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
*/
public class ColorUtil
{
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(IMinecraftWrapper.class);
public static int rgbToInt(int red, int green, int blue)
@@ -25,6 +25,7 @@ import com.seibel.lod.core.enums.config.HorizontalResolution;
import com.seibel.lod.core.wrapperAdapters.SingletonHandler;
import com.seibel.lod.core.wrapperAdapters.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
/**
@@ -34,18 +35,19 @@ import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
*/
public class DetailDistanceUtil
{
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
private static final double genMultiplier = 1.0;
private static final double treeGenMultiplier = 1.0;
private static final double treeCutMultiplier = 1.0;
private static byte minGenDetail = config.client().graphics().quality().getDrawResolution().detailLevel;
private static byte minDrawDetail = (byte) Math.max(config.client().graphics().quality().getDrawResolution().detailLevel, config.client().graphics().quality().getDrawResolution().detailLevel);
private static byte minGenDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel;
private static byte minDrawDetail = (byte) Math.max(CONFIG.client().graphics().quality().getDrawResolution().detailLevel, CONFIG.client().graphics().quality().getDrawResolution().detailLevel);
private static final int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1;
private static final int minDistance = 0;
private static int minDetailDistance = (int) (mc.getRenderDistance()*16 * 1.42f);
private static int maxDistance = config.client().graphics().quality().getLodChunkRenderDistance() * 16 * 2;
private static int minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f);
private static int maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 2;
private static final HorizontalResolution[] lodGenDetails = {
@@ -65,10 +67,10 @@ public class DetailDistanceUtil
public static void updateSettings()
{
minDetailDistance = (int) (mc.getRenderDistance()*16 * 1.42f);
minGenDetail = config.client().graphics().quality().getDrawResolution().detailLevel;
minDrawDetail = (byte) Math.max(config.client().graphics().quality().getDrawResolution().detailLevel, config.client().graphics().quality().getDrawResolution().detailLevel);
maxDistance = config.client().graphics().quality().getLodChunkRenderDistance() * 16 * 8;
minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f);
minGenDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel;
minDrawDetail = (byte) Math.max(CONFIG.client().graphics().quality().getDrawResolution().detailLevel, CONFIG.client().graphics().quality().getDrawResolution().detailLevel);
maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 8;
}
public static int baseDistanceFunction(int detail)
@@ -78,15 +80,15 @@ public class DetailDistanceUtil
if (detail >= maxDetail)
return maxDistance;
if (config.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
if (CONFIG.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
return detail * 0x10000; //if you want more you are doing wrong
int distanceUnit = config.client().graphics().quality().getHorizontalScale().distanceUnit;
if (config.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale().distanceUnit;
if (CONFIG.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
return (detail * distanceUnit);
else
{
double base = config.client().graphics().quality().getHorizontalQuality().quadraticBase;
double base = CONFIG.client().graphics().quality().getHorizontalQuality().quadraticBase;
return (int) (Math.pow(base, detail) * distanceUnit);
}
}
@@ -101,14 +103,14 @@ public class DetailDistanceUtil
int detail;
if (distance == 0
|| (distance < minDetailDistance && useRenderMinDistance)
|| config.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
|| CONFIG.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
return minDetail;
int distanceUnit = config.client().graphics().quality().getHorizontalScale().distanceUnit;
if (config.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale().distanceUnit;
if (CONFIG.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
detail = (byte) distance / distanceUnit;
else
{
double base = config.client().graphics().quality().getHorizontalQuality().quadraticBase;
double base = CONFIG.client().graphics().quality().getHorizontalQuality().quadraticBase;
double logBase = Math.log(base);
//noinspection IntegerDivisionInFloatingPointContext
detail = (byte) (Math.log(distance / distanceUnit) / logBase);
@@ -138,7 +140,7 @@ public class DetailDistanceUtil
public static DistanceGenerationMode getDistanceGenerationMode(int detail)
{
return config.client().worldGenerator().getDistanceGenerationMode();
return CONFIG.client().worldGenerator().getDistanceGenerationMode();
}
public static byte getLodDrawDetail(int detail)
@@ -170,7 +172,7 @@ public class DetailDistanceUtil
public static int getMaxVerticalData(int detail)
{
return config.client().graphics().quality().getVerticalQuality().maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)];
return CONFIG.client().graphics().quality().getVerticalQuality().maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)];
}
}
@@ -38,13 +38,8 @@ import com.seibel.lod.core.wrapperAdapters.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperAdapters.world.IWorldWrapper;
import com.seibel.lod.wrappers.block.BlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftRenderWrapper;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
@@ -57,8 +52,9 @@ import net.minecraft.world.gen.Heightmap;
*/
public class LodUtil
{
private static final IMinecraftWrapper mc = SingletonHandler.get(MinecraftWrapper.class);
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
/**
* Vanilla render distances less than or equal to this will not allow partial
@@ -158,33 +154,16 @@ public class LodUtil
/**
* Gets the first valid ServerWorld.
* @return null if there are no ServerWorlds
*/
// public static ServerWorld getFirstValidServerWorld()
// {
// if (mc.hasSinglePlayerServer())
// return null;
//
// Iterable<ServerWorld> worlds = mc.getSinglePlayerServer().getAllLevels();
//
// for (ServerWorld world : worlds)
// return world;
//
// return null;
// }
/**
* Gets the ServerWorld for the relevant dimension.
* @return null if there is no ServerWorld for the given dimension
*/
public static IWorldWrapper getServerWorldFromDimension(IDimensionTypeWrapper newDimension)
{
if(!mc.hasSinglePlayerServer())
if(!MC.hasSinglePlayerServer())
return null;
Iterable<IWorldWrapper> worlds = mc.getAllServerWorlds();
Iterable<IWorldWrapper> worlds = MC.getAllServerWorlds();
IWorldWrapper returnWorld = null;
for (IWorldWrapper world : worlds)
@@ -239,7 +218,7 @@ public class LodUtil
*/
public static String getWorldID(IWorldWrapper world)
{
if (mc.hasSinglePlayerServer())
if (MC.hasSinglePlayerServer())
{
// chop off the dimension ID as it is not needed/wanted
String dimId = getDimensionIDFromWorld(world);
@@ -267,7 +246,7 @@ public class LodUtil
*/
public static String getDimensionIDFromWorld(IWorldWrapper world)
{
if (mc.hasSinglePlayerServer())
if (MC.hasSinglePlayerServer())
{
// this will return the world save location
// and the dimension folder
@@ -287,10 +266,9 @@ public class LodUtil
/** returns the server name, IP and game version. */
public static String getServerId()
{
ServerData server = mc.getCurrentServer();
String serverName = server.name.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverIp = server.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverMcVersion = server.version.getString().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverName = MC.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverIp = MC.getCurrentServerIp().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverMcVersion = MC.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
return serverName + ", IP " + serverIp + ", GameVersion " + serverMcVersion;
}
@@ -346,14 +324,14 @@ public class LodUtil
* Get a HashSet of all ChunkPos within the normal render distance
* that should not be rendered.
*/
public static HashSet<ChunkPos> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPosWrapper blockPosWrapper)
public static HashSet<ChunkPosWrapper> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPosWrapper blockPosWrapper)
{
int chunkRenderDist = mc.getRenderDistance();
int chunkRenderDist = MC_RENDER.getRenderDistance();
ChunkPosWrapper centerChunk = new ChunkPosWrapper(blockPosWrapper);
int skipRadius;
VanillaOverdraw overdraw = config.client().graphics().advancedGraphics().getVanillaOverdraw();
HorizontalResolution drawRes = config.client().graphics().quality().getDrawResolution();
VanillaOverdraw overdraw = CONFIG.client().graphics().advancedGraphics().getVanillaOverdraw();
HorizontalResolution drawRes = CONFIG.client().graphics().quality().getDrawResolution();
// apply distance based rules for dynamic overdraw
if (overdraw == VanillaOverdraw.DYNAMIC
@@ -416,7 +394,7 @@ public class LodUtil
// get the chunks that are going to be rendered by Minecraft
HashSet<ChunkPos> posToSkip = getRenderedChunks();
HashSet<ChunkPosWrapper> posToSkip = MC_RENDER.getRenderedChunks();
// remove everything outside the skipRadius,
@@ -429,8 +407,7 @@ public class LodUtil
{
if (x <= centerChunk.getX() - skipRadius || x >= centerChunk.getX() + skipRadius
|| z <= centerChunk.getZ() - skipRadius || z >= centerChunk.getZ() + skipRadius)
posToSkip.remove(new ChunkPos(x, z));
posToSkip.remove(new ChunkPosWrapper(x, z));
}
}
}
@@ -438,38 +415,6 @@ public class LodUtil
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
public static HashSet<ChunkPos> getRenderedChunks()
{
HashSet<ChunkPos> loadedPos = new HashSet<>();
// Wow, those are some long names!
// go through every RenderInfo to get the compiled chunks
WorldRenderer renderer = mc.getLevelRenderer();
for (WorldRenderer.LocalRenderInformationContainer worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
{
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
if (!compiledChunk.hasNoRenderableLayers())
{
// add the ChunkPos for every rendered chunk
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
loadedPos.add(new ChunkPos(bpos));
}
}
return loadedPos;
}
/**
* This method find if a given chunk is a border chunk of the renderable ones
* @param vanillaRenderedChunks matrix of the vanilla rendered chunks
@@ -498,10 +443,10 @@ public class LodUtil
/** This is copied from Minecraft's MathHelper class */
public static float fastInvSqrt(float numb)
{
float half = 0.5F * numb;
int i = Float.floatToIntBits(numb);
i = 1597463007 - (i >> 1);
numb = Float.intBitsToFloat(i);
return numb * (1.5F - half * numb * numb);
}
float half = 0.5F * numb;
int i = Float.floatToIntBits(numb);
i = 1597463007 - (i >> 1);
numb = Float.intBitsToFloat(i);
return numb * (1.5F - half * numb * numb);
}
}
@@ -0,0 +1,27 @@
package com.seibel.lod.core.wrapperAdapters.block;
import com.seibel.lod.core.enums.LodDirection;
public abstract class AbstractBlockPosWrapper
{
public AbstractBlockPosWrapper()
{
}
public AbstractBlockPosWrapper(int x, int y, int z)
{
}
public abstract void set(int x, int y, int z);
public abstract int getX();
public abstract int getY();
public abstract int getZ();
public abstract int get(LodDirection.Axis axis);
/** returns itself */
public abstract AbstractBlockPosWrapper offset(int x, int y, int z);
}
@@ -0,0 +1,49 @@
package com.seibel.lod.core.wrapperAdapters.minecraft;
import java.util.HashSet;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperAdapters.block.AbstractBlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
/**
* Contains everything related to
* rendering in Minecraft.
*
* @author James Seibel
* @version 11-18-2021
*/
public interface IMinecraftRenderWrapper
{
public Vec3f getLookAtVector();
public AbstractBlockPosWrapper getCameraBlockPosition();
public boolean playerHasBlindnessEffect();
public Vec3d getCameraExactPosition();
public Mat4f getDefaultProjectionMatrix(float partialTicks);
public double getGamma();
public double getFov(float partialTicks);
/** Measured in chunks */
public int getRenderDistance();
public int getScreenWidth();
public int getScreenHeight();
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
public HashSet<ChunkPosWrapper> getRenderedChunks();
}
@@ -66,6 +66,10 @@ public interface IMinecraftWrapper
public boolean hasSinglePlayerServer();
public String getCurrentServerName();
public String getCurrentServerIp();
public String getCurrentServerVersion();
/** Returns the dimension the player is currently in */
public DimensionTypeWrapper getCurrentDimension();
@@ -112,9 +116,6 @@ public interface IMinecraftWrapper
public WorldWrapper getWrappedClientWorld();
/** Measured in chunks */
public int getRenderDistance();
public File getGameDirectory();
public IProfiler getProfiler();
@@ -140,8 +141,12 @@ public interface IMinecraftWrapper
*/
public void crashMinecraft(String errorMessage, Throwable exception);
@@ -3,9 +3,11 @@ package com.seibel.lod.wrappers;
import com.seibel.lod.core.wrapperAdapters.SingletonHandler;
import com.seibel.lod.core.wrapperAdapters.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperAdapters.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftWrapper;
import com.seibel.lod.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.wrappers.minecraft.MinecraftWrapper;
/**
@@ -24,5 +26,6 @@ public class DependencySetup
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
}
}
@@ -0,0 +1,137 @@
package com.seibel.lod.wrappers.minecraft;
import java.util.HashSet;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperAdapters.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperAdapters.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.wrappers.block.BlockPosWrapper;
import com.seibel.lod.wrappers.chunk.ChunkPosWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.potion.Effects;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
/**
* A singleton that contains everything
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 11-18-2021
*/
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
private final static Minecraft mc = Minecraft.getInstance();
@Override
public Vec3f getLookAtVector()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
Vector3f cameraDir = camera.getLookVector();
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
}
@Override
public AbstractBlockPosWrapper getCameraBlockPosition()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
BlockPos blockPos = camera.getBlockPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@Override
public boolean playerHasBlindnessEffect()
{
return mc.player.getActiveEffectsMap().get(Effects.BLINDNESS) != null;
}
@Override
public Vec3d getCameraExactPosition()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
Vector3d projectedView = camera.getPosition();
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
}
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getMainCamera(), partialTicks, true));
}
@Override
public double getGamma()
{
return mc.options.gamma;
}
@Override
public double getFov(float partialTicks)
{
return gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
}
/** Measured in chunks */
@Override
public int getRenderDistance()
{
return mc.options.renderDistance;
}
@Override
public int getScreenWidth()
{
return mc.getWindow().getWidth();
}
@Override
public int getScreenHeight()
{
return mc.getWindow().getHeight();
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
@Override
public HashSet<ChunkPosWrapper> getRenderedChunks()
{
HashSet<ChunkPosWrapper> loadedPos = new HashSet<>();
// Wow, those are some long names!
// go through every RenderInfo to get the compiled chunks
WorldRenderer renderer = mc.levelRenderer;
for (WorldRenderer.LocalRenderInformationContainer worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
{
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
if (!compiledChunk.hasNoRenderableLayers())
{
// add the ChunkPos for every rendered chunk
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
loadedPos.add(new ChunkPosWrapper(bpos));
}
}
return loadedPos;
}
}
@@ -121,6 +121,24 @@ public class MinecraftWrapper implements IMinecraftWrapper
return mc.hasSingleplayerServer();
}
@Override
public String getCurrentServerName()
{
return mc.getCurrentServer().name;
}
@Override
public String getCurrentServerIp()
{
return mc.getCurrentServer().ip;
}
@Override
public String getCurrentServerVersion()
{
return mc.getCurrentServer().version.getString();
}
/** Returns the dimension the player is currently in */
@Override
public DimensionTypeWrapper getCurrentDimension()
@@ -259,13 +277,6 @@ public class MinecraftWrapper implements IMinecraftWrapper
return WorldWrapper.getWorldWrapper(mc.level);
}
/** Measured in chunks */
@Override
public int getRenderDistance()
{
return mc.options.renderDistance;
}
@Override
public File getGameDirectory()
{
@@ -364,6 +375,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
Minecraft.crash(report);
}