Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5
This commit is contained in:
@@ -415,7 +415,7 @@ public class LodBufferBuilder
|
||||
|
||||
//We send the call to create the vertices
|
||||
LodConfig.CLIENT.graphics.advancedGraphicsOption.lodTemplate.get().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, data, adjData,
|
||||
detailLevel, posX, posZ, box, renderer.previousDebugMode, renderer.lightMap, adjShadeDisabled);
|
||||
detailLevel, posX, posZ, box, renderer.previousDebugMode, adjShadeDisabled);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -40,7 +39,7 @@ public abstract class AbstractLodTemplate
|
||||
|
||||
/** Uploads the given LOD to the buffer. */
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled);
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled);
|
||||
|
||||
/** add the given position and color to the buffer */
|
||||
protected void addPosAndColor(BufferBuilder buffer,
|
||||
|
||||
+2
-4
@@ -25,10 +25,8 @@ import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -47,7 +45,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled)
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
if (box == null)
|
||||
return;
|
||||
@@ -128,7 +126,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
color = box.getColor(direction);
|
||||
skyLight = box.getSkyLight(direction, verticalFaceIndex);
|
||||
blockLight = box.getBlockLight();
|
||||
color = ColorUtil.applyLightValue(color, skyLight, blockLight, MinecraftWrapper.INSTANCE.getCurrentLightMap());
|
||||
color = ColorUtil.applyLightValue(color, skyLight, blockLight);
|
||||
addPosAndColor(buffer,
|
||||
box.getX(direction, vertexIndex),
|
||||
box.getY(direction, vertexIndex, verticalFaceIndex),
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -41,7 +40,7 @@ public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled)
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -39,7 +38,7 @@ public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled)
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
@@ -19,22 +19,15 @@
|
||||
|
||||
package com.seibel.lod.builders.lodBuilding;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.HorizontalResolution;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
@@ -42,47 +35,24 @@ import com.seibel.lod.util.LevelPosUtil;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.util.ThreadMapUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockColorWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockShapeWrapper;
|
||||
import com.seibel.lod.wrappers.Chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.wrappers.Chunk.ChunkWrapper;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.block.AbstractPlantBlock;
|
||||
import net.minecraft.block.AbstractTopPlantBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.BushBlock;
|
||||
import net.minecraft.block.FlowerBlock;
|
||||
import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.ILiquidContainer;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.SixWayBlock;
|
||||
import net.minecraft.block.TallGrassBlock;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.data.BlockModelProvider;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import com.seibel.lod.wrappers.World.BiomeColorWrapper;
|
||||
import com.seibel.lod.wrappers.World.BiomeWrapper;
|
||||
import com.seibel.lod.wrappers.World.WorldWrapper;
|
||||
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeColors;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
/**
|
||||
* This object is in charge of creating Lod related objects.
|
||||
*
|
||||
*
|
||||
* @author Cola
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
@@ -94,18 +64,6 @@ public class LodBuilder
|
||||
|
||||
private final ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName()));
|
||||
|
||||
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
|
||||
public static final int CHUNK_DATA_WIDTH = LodUtil.CHUNK_WIDTH;
|
||||
public static final int CHUNK_SECTION_HEIGHT = CHUNK_DATA_WIDTH;
|
||||
public static final ConcurrentMap<Block, Integer> colorMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Integer> tintColor = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Boolean> toTint = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ConcurrentMap<Block, Boolean> notFullBlock = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Boolean> smallBlock = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
|
||||
/** If no blocks are found in the area in determineBottomPointForArea return this */
|
||||
public static final short DEFAULT_DEPTH = 0;
|
||||
@@ -131,12 +89,12 @@ public class LodBuilder
|
||||
|
||||
}
|
||||
|
||||
public void generateLodNodeAsync(IChunk chunk, LodWorld lodWorld, IWorld world)
|
||||
public void generateLodNodeAsync(ChunkWrapper chunk, LodWorld lodWorld, IWorld world)
|
||||
{
|
||||
generateLodNodeAsync(chunk, lodWorld, world, DistanceGenerationMode.SERVER);
|
||||
}
|
||||
|
||||
public void generateLodNodeAsync(IChunk chunk, LodWorld lodWorld, IWorld world, DistanceGenerationMode generationMode)
|
||||
public void generateLodNodeAsync(ChunkWrapper chunk, LodWorld lodWorld, IWorld world, DistanceGenerationMode generationMode)
|
||||
{
|
||||
if (lodWorld == null || lodWorld.getIsWorldNotLoaded())
|
||||
return;
|
||||
@@ -191,7 +149,7 @@ public class LodBuilder
|
||||
* Creates a LodNode for a chunk in the given world.
|
||||
* @throws IllegalArgumentException thrown if either the chunk or world is null.
|
||||
*/
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunk chunk) throws IllegalArgumentException
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, ChunkWrapper chunk) throws IllegalArgumentException
|
||||
{
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig());
|
||||
}
|
||||
@@ -200,7 +158,7 @@ public class LodBuilder
|
||||
* Creates a LodNode for a chunk in the given world.
|
||||
* @throws IllegalArgumentException thrown if either the chunk or world is null.
|
||||
*/
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunk chunk, LodBuilderConfig config)
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, ChunkWrapper chunk, LodBuilderConfig config)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if (chunk == null)
|
||||
@@ -233,36 +191,33 @@ public class LodBuilder
|
||||
{
|
||||
startX = detail.startX[i];
|
||||
startZ = detail.startZ[i];
|
||||
endX = detail.endX[i];
|
||||
endZ = detail.endZ[i];
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
|
||||
|
||||
//lodDim.clear(detailLevel, posX, posZ);
|
||||
if (data != null && data.length != 0)
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().getX() * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().getZ() * 16 + startZ, detail.detailLevel);
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, data, false);
|
||||
}
|
||||
}
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().getX(), chunk.getPos().getZ());
|
||||
}
|
||||
|
||||
/** creates a vertical DataPoint */
|
||||
private long[] createVerticalDataToMerge(HorizontalResolution detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
|
||||
private long[] createVerticalDataToMerge(HorizontalResolution detail, ChunkWrapper chunk, LodBuilderConfig config, int startX, int startZ)
|
||||
{
|
||||
// equivalent to 2^detailLevel
|
||||
int size = 1 << detail.detailLevel;
|
||||
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel);
|
||||
|
||||
int verticalData = DataPointUtil.worldHeight / 2 + 1;
|
||||
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
ChunkPosWrapper chunkPos = chunk.getPos();
|
||||
int height;
|
||||
int depth;
|
||||
int color;
|
||||
@@ -279,7 +234,7 @@ public class LodBuilder
|
||||
boolean hasCeiling = mc.getClientWorld().dimensionType().hasCeiling();
|
||||
boolean hasSkyLight = mc.getClientWorld().dimensionType().hasSkyLight();
|
||||
boolean isDefault;
|
||||
BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0);
|
||||
BlockPosWrapper blockPos = new BlockPosWrapper();
|
||||
int index;
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
@@ -295,7 +250,7 @@ public class LodBuilder
|
||||
boolean topBlock = true;
|
||||
while (yAbs > 0)
|
||||
{
|
||||
height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
|
||||
height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
|
||||
// If the lod is at the default height, it must be void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
@@ -307,13 +262,13 @@ public class LodBuilder
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
if (hasCeiling && topBlock)
|
||||
{
|
||||
yAbs = depth;
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock);
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos);
|
||||
blockPos.set(xAbs, yAbs - 1, zAbs);
|
||||
}
|
||||
else
|
||||
@@ -340,67 +295,38 @@ public class LodBuilder
|
||||
* Find the lowest valid point from the bottom.
|
||||
* Used when creating a vertical LOD.
|
||||
*/
|
||||
private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
|
||||
private short determineBottomPointFrom(ChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs, BlockPosWrapper blockPos)
|
||||
{
|
||||
short depth = DEFAULT_DEPTH;
|
||||
/*if (config.useHeightmap)
|
||||
|
||||
for (int y = yAbs; y >= 0; y--)
|
||||
{
|
||||
// when using the generated heightmap there is no data about the lowest point
|
||||
depth = 0; //DEFAULT_DEPTH == 0
|
||||
}
|
||||
else
|
||||
{*/
|
||||
boolean voidData = true;
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
|
||||
{
|
||||
for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
|
||||
blockPos.set(xAbs, y, zAbs);
|
||||
if (!isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs)
|
||||
continue;
|
||||
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel);
|
||||
if (!isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
|
||||
voidData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!voidData)
|
||||
depth = (short) (y + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
return depth;
|
||||
}
|
||||
|
||||
/** Find the highest valid point from the Top */
|
||||
private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
|
||||
private short determineHeightPointFrom(ChunkWrapper chunk, LodBuilderConfig config, int xAbs, int yAbs, int zAbs, BlockPosWrapper blockPos)
|
||||
{
|
||||
short height = DEFAULT_HEIGHT;
|
||||
if (config.useHeightmap)
|
||||
height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
height = (short) chunk.getHeightMapValue(xAbs, zAbs);
|
||||
else
|
||||
{
|
||||
boolean voidData = true;
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
|
||||
for (int y = yAbs; y >= 0; y--)
|
||||
{
|
||||
for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
|
||||
blockPos.set(xAbs, y, zAbs);
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs)
|
||||
continue;
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel);
|
||||
if (isLayerValidLodPoint(chunk, blockPos))
|
||||
{
|
||||
height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
|
||||
voidData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!voidData)
|
||||
height = (short) (y + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return height;
|
||||
@@ -416,26 +342,19 @@ public class LodBuilder
|
||||
* Generate the color for the given chunk using biome water color, foliage
|
||||
* color, and grass color.
|
||||
*/
|
||||
private int generateLodColor(IChunk chunk, LodBuilderConfig config, int xRel, int yAbs, int zRel, BlockPos.Mutable blockPos)
|
||||
private int generateLodColor(ChunkWrapper chunk, LodBuilderConfig config, int xRel, int yAbs, int zRel, BlockPosWrapper blockPos)
|
||||
{
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
int colorInt = 0;
|
||||
if (config.useBiomeColors)
|
||||
{
|
||||
// I have no idea why I need to bit shift to the right, but
|
||||
// if I don't the biomes don't show up correctly.
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2);
|
||||
colorInt = getColorForBiome(xRel, zRel, biome);
|
||||
colorInt = chunk.getBiome(xRel, yAbs, zRel).getColorForBiome(xRel, zRel);
|
||||
}
|
||||
else
|
||||
{
|
||||
int sectionIndex = Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT);
|
||||
int yRel = Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT);
|
||||
if (chunkSections[sectionIndex] != null)
|
||||
{
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel);
|
||||
colorInt = getColorForBlock(chunk, blockPos);
|
||||
}
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, yAbs, chunk.getPos().getMinBlockZ() + zRel);
|
||||
colorInt = getColorForBlock(chunk, blockPos);
|
||||
|
||||
// if we are skipping non-full and non-solid blocks that means we ignore
|
||||
// snow, flowers, etc. Get the above block so we can still get the color
|
||||
@@ -443,13 +362,13 @@ public class LodBuilder
|
||||
int aboveColorInt = 0;
|
||||
if (LodConfig.CLIENT.worldGenerator.blockToAvoid.get().nonFull || LodConfig.CLIENT.worldGenerator.blockToAvoid.get().noCollision)
|
||||
{
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel + 1, chunk.getPos().getMinBlockZ() + zRel);
|
||||
blockPos.set(chunk.getPos().getMinBlockX() + xRel, yAbs + 1, chunk.getPos().getMinBlockZ() + zRel);
|
||||
aboveColorInt = getColorForBlock(chunk, blockPos);
|
||||
}
|
||||
|
||||
if (colorInt == 0 && yAbs > 0)
|
||||
// if this block is invisible, check the block below it
|
||||
colorInt = generateLodColor(chunk, config, xRel, yAbs - 1, zRel, blockPos);
|
||||
//if (colorInt == 0 && yAbs > 0)
|
||||
// if this block is invisible, check the block below it
|
||||
// colorInt = generateLodColor(chunk, config, xRel, yAbs - 1, zRel, blockPos);
|
||||
|
||||
// override this block's color if there was a block above this
|
||||
// and we were avoiding non-full/non-solid blocks
|
||||
@@ -461,21 +380,16 @@ public class LodBuilder
|
||||
}
|
||||
|
||||
/** Gets the light value for the given block position */
|
||||
private int getLightValue(IChunk chunk, BlockPos.Mutable blockPos, boolean hasCeiling, boolean hasSkyLight, boolean topBlock)
|
||||
private int getLightValue(ChunkWrapper chunk, BlockPosWrapper blockPos, boolean hasCeiling, boolean hasSkyLight, boolean topBlock)
|
||||
{
|
||||
int skyLight = 0;
|
||||
int blockLight;
|
||||
// 1 means the lighting is a guess
|
||||
int isDefault = 0;
|
||||
|
||||
WorldWrapper world = MinecraftWrapper.INSTANCE.getWrappedServerWorld();
|
||||
|
||||
ClientWorld clientWorld = mc.getClientWorld();
|
||||
if (clientWorld == null)
|
||||
return 0;
|
||||
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(clientWorld.dimensionType());
|
||||
|
||||
|
||||
int blockBrightness = chunk.getLightEmission(blockPos);
|
||||
int blockBrightness = chunk.getEmittedBrightness(blockPos);
|
||||
// get the air block above or below this block
|
||||
if (hasCeiling && topBlock)
|
||||
blockPos.set(blockPos.getX(), blockPos.getY() - 1, blockPos.getZ());
|
||||
@@ -484,15 +398,19 @@ public class LodBuilder
|
||||
|
||||
|
||||
|
||||
if (serverWorld != null)
|
||||
if (!world.isEmpty())
|
||||
{
|
||||
// server world sky light (always accurate)
|
||||
blockLight = serverWorld.getBrightness(LightType.BLOCK, blockPos);
|
||||
if(topBlock && !hasCeiling && hasSkyLight)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
if (topBlock && !hasCeiling && hasSkyLight)
|
||||
skyLight = DEFAULT_MAX_LIGHT;
|
||||
else
|
||||
skyLight = serverWorld.getBrightness(LightType.SKY, blockPos);
|
||||
|
||||
{
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
else
|
||||
skyLight = 0;
|
||||
}
|
||||
if (!topBlock && skyLight == 15)
|
||||
{
|
||||
// we are on predicted terrain, and we don't know what the light here is,
|
||||
@@ -508,8 +426,11 @@ public class LodBuilder
|
||||
}
|
||||
else
|
||||
{
|
||||
world = MinecraftWrapper.INSTANCE.getWrappedClientWorld();
|
||||
if (world.isEmpty())
|
||||
return 0;
|
||||
// client world sky light (almost never accurate)
|
||||
blockLight = clientWorld.getBrightness(LightType.BLOCK, blockPos);
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
// estimate what the lighting should be
|
||||
if (hasSkyLight || !hasCeiling)
|
||||
{
|
||||
@@ -517,7 +438,12 @@ public class LodBuilder
|
||||
skyLight = DEFAULT_MAX_LIGHT;
|
||||
else
|
||||
{
|
||||
skyLight = clientWorld.getBrightness(LightType.SKY, blockPos);
|
||||
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
else
|
||||
skyLight = 0;
|
||||
|
||||
if (!chunk.isLightCorrect() && (skyLight == 0 || skyLight == 15))
|
||||
{
|
||||
// we don't know what the light here is,
|
||||
@@ -531,6 +457,8 @@ public class LodBuilder
|
||||
skyLight = 0;
|
||||
}
|
||||
}
|
||||
if (hasSkyLight)
|
||||
skyLight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,151 +467,12 @@ public class LodBuilder
|
||||
return blockLight + (skyLight << 4) + (isDefault << 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the color of the given block from its texture
|
||||
* and store it for later use.
|
||||
*/
|
||||
private int getColorTextureForBlock(BlockState blockState, BlockPos blockPos, boolean useTopTexture)
|
||||
{
|
||||
// use the pre-generated color if we can
|
||||
Block block = blockState.getBlock();
|
||||
if (colorMap.containsKey(block) && toTint.containsKey(block))
|
||||
return colorMap.get(block);
|
||||
|
||||
World world = mc.getClientWorld();
|
||||
TextureAtlasSprite texture;
|
||||
List<BakedQuad> quads = null;
|
||||
int tintIndex = Integer.MIN_VALUE;
|
||||
boolean isTinted = false;
|
||||
int listSize = 0;
|
||||
// get the first quad we can for this block
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(blockState).getQuads(blockState, direction, new Random(0), dataMap);
|
||||
listSize = Math.max(listSize, quads.size());
|
||||
for (BakedQuad bakedQuad : quads)
|
||||
{
|
||||
isTinted |= bakedQuad.isTinted();
|
||||
tintIndex = Math.max(tintIndex, bakedQuad.getTintIndex());
|
||||
}
|
||||
}
|
||||
toTint.put(block, isTinted);
|
||||
tintColor.put(block, tintIndex);
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(blockState).getQuads(blockState, direction, new Random(0), dataMap);
|
||||
if (!quads.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
if (useTopTexture && !quads.isEmpty())
|
||||
texture = quads.get(0).getSprite();
|
||||
else
|
||||
texture = mc.getModelManager().getBlockModelShaper().getTexture(blockState, world, blockPos);
|
||||
|
||||
|
||||
int count = 0;
|
||||
int alpha = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int numberOfGreyPixel = 0;
|
||||
int color;
|
||||
int colorMultiplier;
|
||||
|
||||
// generate the block's color
|
||||
for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getHeight(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getWidth(); v++)
|
||||
{
|
||||
if (texture.isTransparent(frameIndex, u, v))
|
||||
continue;
|
||||
|
||||
color = texture.getPixelRGBA(frameIndex, u, v);
|
||||
|
||||
// determine if this pixel is gray
|
||||
int colorMax = Math.max(Math.max(ColorUtil.getBlue(color), ColorUtil.getGreen(color)), ColorUtil.getRed(color));
|
||||
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(color), ColorUtil.getGreen(color)), ColorUtil.getRed(color));
|
||||
boolean isGray = colorMax < colorMin;
|
||||
if (isGray)
|
||||
numberOfGreyPixel++;
|
||||
|
||||
|
||||
// for flowers, weight their non-green color higher
|
||||
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(color) > (ColorUtil.getBlue(color) + 30)) || !(ColorUtil.getGreen(color) > (ColorUtil.getRed(color) + 30))))
|
||||
colorMultiplier = 5;
|
||||
else
|
||||
colorMultiplier = 1;
|
||||
|
||||
|
||||
// add to the running averages
|
||||
count += colorMultiplier;
|
||||
alpha += ColorUtil.getAlpha(color) * colorMultiplier;
|
||||
red += ColorUtil.getBlue(color) * colorMultiplier;
|
||||
green += ColorUtil.getGreen(color) * colorMultiplier;
|
||||
blue += ColorUtil.getRed(color) * colorMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
color = 0;
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
alpha /= count;
|
||||
red /= count;
|
||||
green /= count;
|
||||
blue /= count;
|
||||
color = ColorUtil.rgbToInt(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
// determine if this block should use the biome color tint
|
||||
if ((useGrassTint(block) || useLeafTint(block) || useWaterTint(block)) && (float) numberOfGreyPixel / count > 0.75f)
|
||||
toTint.replace(block, true);
|
||||
|
||||
// add the newly generated block color to the map for later use
|
||||
colorMap.put(block, color);
|
||||
return color;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's grass color */
|
||||
private boolean useGrassTint(Block block)
|
||||
{
|
||||
return block instanceof GrassBlock
|
||||
|| block instanceof BushBlock
|
||||
|| block instanceof IGrowable
|
||||
|| block instanceof AbstractPlantBlock
|
||||
|| block instanceof AbstractTopPlantBlock
|
||||
|| block instanceof TallGrassBlock;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean useLeafTint(Block block)
|
||||
{
|
||||
return block instanceof LeavesBlock
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.SUGAR_CANE;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's water color */
|
||||
private boolean useWaterTint(Block block)
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
/** Returns a color int for the given block. */
|
||||
private int getColorForBlock(IChunk chunk, BlockPos blockPos)
|
||||
private int getColorForBlock(ChunkWrapper chunk, BlockPosWrapper blockPos)
|
||||
{
|
||||
|
||||
|
||||
int blockColor;
|
||||
int colorOfBlock;
|
||||
int colorInt;
|
||||
|
||||
int xRel = blockPos.getX() - chunk.getPos().getMinBlockX();
|
||||
@@ -692,251 +481,75 @@ public class LodBuilder
|
||||
int y = blockPos.getY();
|
||||
int z = blockPos.getZ();
|
||||
|
||||
//Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, y >> 2, zRel >> 2);
|
||||
BlockState blockState = chunk.getBlockState(blockPos);
|
||||
BlockColorWrapper blockColorWrapper;
|
||||
BlockShapeWrapper blockShapeWrapper = chunk.getBlockShapeWrapper(blockPos);
|
||||
|
||||
if(isInWater(blockState))
|
||||
blockState = Blocks.WATER.defaultBlockState();
|
||||
if (chunk.isWaterLogged(blockPos))
|
||||
{
|
||||
BiomeWrapper biome = chunk.getBiome(xRel, y, zRel);
|
||||
return biome.getWaterTint();
|
||||
}
|
||||
else
|
||||
{
|
||||
blockColorWrapper = chunk.getBlockColorWrapper(blockPos);
|
||||
}
|
||||
|
||||
// block special cases
|
||||
// TODO: this needs to be replaced by a config file of some sort
|
||||
if (blockState == Blocks.AIR.defaultBlockState()
|
||||
|| blockState == Blocks.CAVE_AIR.defaultBlockState()
|
||||
|| blockState == Blocks.BARRIER.defaultBlockState())
|
||||
if (blockShapeWrapper.isToAvoid())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockColor = getColorTextureForBlock(blockState, blockPos, true);
|
||||
colorOfBlock = blockColorWrapper.getColor();
|
||||
|
||||
//if the blockColor is 0 we reset it and don't use the faceColor
|
||||
if (blockColor == 0)
|
||||
{
|
||||
tintColor.remove(blockState.getBlock());
|
||||
toTint.remove(blockState.getBlock());
|
||||
colorMap.remove(blockState.getBlock());
|
||||
blockColor = getColorTextureForBlock(blockState, blockPos, false);
|
||||
}
|
||||
|
||||
//if the blockColor is still 0 we use the default material color
|
||||
if (blockColor == 0)
|
||||
if (blockColorWrapper.hasTint())
|
||||
{
|
||||
tintColor.replace(blockState.getBlock(), 0);
|
||||
toTint.replace(blockState.getBlock(), false);
|
||||
colorMap.replace(blockState.getBlock(), blockState.getBlock().defaultMaterialColor().col);
|
||||
}
|
||||
|
||||
if (toTint.get(blockState.getBlock()))
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, y >> 2, zRel >> 2);
|
||||
|
||||
ClientWorld clientWorld = mc.getClientWorld();
|
||||
if (clientWorld == null)
|
||||
return 0;
|
||||
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(clientWorld.dimensionType());
|
||||
WorldWrapper world = MinecraftWrapper.INSTANCE.getWrappedServerWorld();
|
||||
|
||||
if (world.isEmpty())
|
||||
{
|
||||
world = MinecraftWrapper.INSTANCE.getWrappedClientWorld();
|
||||
}
|
||||
|
||||
int tintValue;
|
||||
if (useGrassTint(blockState.getBlock()))
|
||||
if (blockColorWrapper.hasGrassTint())
|
||||
{
|
||||
// grass and green plants
|
||||
try
|
||||
{
|
||||
tintValue = BiomeColors.getAverageGrassColor(serverWorld, blockPos);
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
tintValue = biome.getGrassColor(x, z);
|
||||
}
|
||||
tintValue = BiomeColorWrapper.getGrassColor(world, blockPos);
|
||||
}
|
||||
else if (useWaterTint(blockState.getBlock()))
|
||||
else if (blockColorWrapper.hasFolliageTint())
|
||||
{
|
||||
// water
|
||||
try
|
||||
{
|
||||
tintValue = BiomeColors.getAverageWaterColor(serverWorld, blockPos);
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
tintValue = biome.getWaterColor();
|
||||
}
|
||||
tintValue = BiomeColorWrapper.getFoliageColor(world, blockPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// leaves
|
||||
try
|
||||
{
|
||||
tintValue = BiomeColors.getAverageFoliageColor(serverWorld, blockPos);
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
tintValue = biome.getFoliageColor();
|
||||
}
|
||||
//we can reintroduce this with the wrappers
|
||||
tintValue = BiomeColorWrapper.getWaterColor(world, blockPos);
|
||||
}
|
||||
colorInt = ColorUtil.multiplyRGBcolors(tintValue | 0xFF000000, blockColor);
|
||||
colorInt = ColorUtil.multiplyRGBcolors(tintValue | 0xFF000000, colorOfBlock);
|
||||
}
|
||||
else
|
||||
colorInt = blockColor;
|
||||
colorInt = colorOfBlock;
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
/** Returns a color int for the given biome. */
|
||||
private int getColorForBiome(int x, int z, Biome biome)
|
||||
{
|
||||
int colorInt;
|
||||
|
||||
switch (biome.getBiomeCategory())
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = Blocks.NETHERRACK.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
colorInt = Blocks.END_STONE.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case BEACH:
|
||||
case DESERT:
|
||||
colorInt = Blocks.SAND.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
colorInt = Blocks.STONE.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case MUSHROOM:
|
||||
colorInt = MaterialColor.COLOR_LIGHT_GRAY.col;
|
||||
break;
|
||||
|
||||
case ICY:
|
||||
colorInt = Blocks.SNOW.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case MESA:
|
||||
colorInt = Blocks.RED_SAND.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
colorInt = biome.getWaterColor();
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
case FOREST:
|
||||
case TAIGA:
|
||||
case JUNGLE:
|
||||
case PLAINS:
|
||||
case SAVANNA:
|
||||
case SWAMP:
|
||||
default:
|
||||
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
|
||||
tmp = tmp.darker();
|
||||
colorInt = LodUtil.colorToInt(tmp);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
private boolean isInWater(BlockState blockState)
|
||||
{
|
||||
//This type of block is always in water
|
||||
if((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
return true;
|
||||
|
||||
//This type of block could be in water
|
||||
if(blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).isPresent() && blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).get())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Is the block at the given blockPos a valid LOD point? */
|
||||
private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos)
|
||||
private boolean isLayerValidLodPoint(ChunkWrapper chunk, BlockPosWrapper blockPos)
|
||||
{
|
||||
|
||||
BlockState blockState = chunk.getBlockState(blockPos);
|
||||
|
||||
if (isInWater(blockState))
|
||||
if (chunk.isWaterLogged(blockPos))
|
||||
return true;
|
||||
|
||||
boolean nonFullAvoidance = LodConfig.CLIENT.worldGenerator.blockToAvoid.get().nonFull;
|
||||
boolean noCollisionAvoidance = LodConfig.CLIENT.worldGenerator.blockToAvoid.get().noCollision;
|
||||
if (blockState != null)
|
||||
{
|
||||
if (nonFullAvoidance)
|
||||
{
|
||||
if(!blockState.getFluidState().isEmpty() || blockState.getBlock() instanceof SixWayBlock)
|
||||
{
|
||||
notFullBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
if (!notFullBlock.containsKey(blockState.getBlock()) || notFullBlock.get(blockState.getBlock()) == null)
|
||||
{
|
||||
VoxelShape voxelShape = blockState.getBlock().defaultBlockState().getShape(chunk, blockPos);
|
||||
|
||||
if (!voxelShape.isEmpty())
|
||||
{
|
||||
AxisAlignedBB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
if (xWidth < 1 && zWidth < 1 && yWidth < 1)
|
||||
notFullBlock.put(blockState.getBlock(), true);
|
||||
else
|
||||
notFullBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
notFullBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (notFullBlock.get(blockState.getBlock()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (noCollisionAvoidance)
|
||||
{
|
||||
if(!blockState.getFluidState().isEmpty() || blockState.getBlock() instanceof SixWayBlock)
|
||||
smallBlock.put(blockState.getBlock(), false);
|
||||
|
||||
if (!smallBlock.containsKey(blockState.getBlock()) || smallBlock.get(blockState.getBlock()) == null)
|
||||
{
|
||||
VoxelShape voxelShape = blockState.getCollisionShape(chunk, blockPos);
|
||||
if (!blockState.getFluidState().isEmpty())
|
||||
{
|
||||
smallBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (voxelShape.isEmpty())
|
||||
{
|
||||
smallBlock.put(blockState.getBlock(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
smallBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (smallBlock.get(blockState.getBlock()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return blockState.getBlock() != Blocks.AIR
|
||||
&& blockState.getBlock() != Blocks.CAVE_AIR
|
||||
&& blockState.getBlock() != Blocks.BARRIER;
|
||||
}
|
||||
|
||||
return false;
|
||||
boolean nonFullAvoidance = LodConfig.CLIENT.worldGenerator.blockToAvoid.get().nonFull;
|
||||
boolean noCollisionAvoidance = LodConfig.CLIENT.worldGenerator.blockToAvoid.get().noCollision;
|
||||
|
||||
BlockShapeWrapper block = chunk.getBlockShapeWrapper(blockPos);
|
||||
return !block.isToAvoid()
|
||||
&& !(nonFullAvoidance && block.isNonFull())
|
||||
&& !(noCollisionAvoidance && block.hasNoCollision());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import com.seibel.lod.wrappers.Chunk.ChunkWrapper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -384,7 +385,7 @@ public class LodGenWorker implements IWorker
|
||||
|
||||
if (!inTheEnd)
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(true, true, false));
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -392,7 +393,7 @@ public class LodGenWorker implements IWorker
|
||||
// Since we don't know where the islands are, everything
|
||||
// generates the same, and it looks awful.
|
||||
//TODO it appears that 'if' can be collapsed, but comment says that it should not be a case
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(true, true, false));
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
|
||||
|
||||
@@ -432,7 +433,7 @@ public class LodGenWorker implements IWorker
|
||||
snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
|
||||
|
||||
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(DistanceGenerationMode.SURFACE));
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.SURFACE));
|
||||
|
||||
/*TODO if we want to use Biome utils and terrain utils for overworld
|
||||
* lodBuilder.generateLodNodeFromChunk(lodDim, pos ,detailLevel, serverWorld.getSeed());*/
|
||||
@@ -558,7 +559,7 @@ public class LodGenWorker implements IWorker
|
||||
}
|
||||
|
||||
// generate a Lod like normal
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(DistanceGenerationMode.FEATURES));
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.FEATURES));
|
||||
}
|
||||
|
||||
|
||||
@@ -573,7 +574,7 @@ public class LodGenWorker implements IWorker
|
||||
*/
|
||||
private void generateWithServer()
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, serverWorld.getChunk(pos.x, pos.z, ChunkStatus.FEATURES), new LodBuilderConfig(DistanceGenerationMode.SERVER));
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(serverWorld.getChunk(pos.x, pos.z, ChunkStatus.FEATURES)), new LodBuilderConfig(DistanceGenerationMode.SERVER));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.proxy;
|
||||
|
||||
import com.seibel.lod.wrappers.Chunk.ChunkWrapper;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -213,7 +214,7 @@ public class ClientProxy
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
lodBuilder.generateLodNodeAsync(event.getChunk(), lodWorld, event.getWorld(), DistanceGenerationMode.SERVER);
|
||||
lodBuilder.generateLodNodeAsync(new ChunkWrapper(event.getChunk()), lodWorld, event.getWorld(), DistanceGenerationMode.SERVER);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -283,7 +284,7 @@ public class ClientProxy
|
||||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
|
||||
{
|
||||
// recreate the LOD where the blocks were changed
|
||||
lodBuilder.generateLodNodeAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld());
|
||||
lodBuilder.generateLodNodeAsync(new ChunkWrapper(event.getWorld().getChunk(event.getPos())), lodWorld, event.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
@@ -104,9 +103,6 @@ public class LodRenderer
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private int[] previousPos = new int[] { 0, 0, 0 };
|
||||
|
||||
public NativeImage lightMap = null;
|
||||
public NativeImage lastLightMap = null;
|
||||
|
||||
// these variables are used to determine if the buffers should be rebuilt
|
||||
private float prevSkyBrightness = 0;
|
||||
private double prevBrightness = 0;
|
||||
@@ -866,10 +862,9 @@ 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 || lightMap == null)
|
||||
|| mc.getOptions().gamma != prevBrightness)
|
||||
{
|
||||
fullRegen = true;
|
||||
lightMap = mc.getCurrentLightMap();
|
||||
prevBrightness = mc.getOptions().gamma;
|
||||
prevSkyBrightness = skyBrightness;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.seibel.lod.util;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -78,9 +78,9 @@ public class ColorUtil
|
||||
}
|
||||
|
||||
/** This method apply the lightmap to the color to use */
|
||||
public static int applyLightValue(int color, int skyLight, int blockLight, NativeImage lightMap)
|
||||
public static int applyLightValue(int color, int skyLight, int blockLight)
|
||||
{
|
||||
int lightColor = lightMap.getPixelRGBA(blockLight, skyLight);
|
||||
int lightColor = MinecraftWrapper.INSTANCE.getColorIntFromLightMap(blockLight, skyLight);
|
||||
int red = ColorUtil.getBlue(lightColor);
|
||||
int green = ColorUtil.getGreen(lightColor);
|
||||
int blue = ColorUtil.getRed(lightColor);
|
||||
|
||||
@@ -125,11 +125,11 @@ public class ThreadMapUtil
|
||||
if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
long[][] array = new long[5][];
|
||||
int size = 1;
|
||||
int size;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
size = 1 << i;
|
||||
array[i] = new long[size * size * DataPointUtil.worldHeight / 2 + 1];
|
||||
size = size << 1;
|
||||
}
|
||||
threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
|
||||
+56
-53
@@ -6,72 +6,74 @@ import net.minecraft.block.*;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
//This class wraps the minecraft Block class
|
||||
public class BlockWrapper
|
||||
public class BlockColorWrapper
|
||||
{
|
||||
//set of block which require tint
|
||||
public static final ConcurrentMap<Block, BlockWrapper> blockWrapperMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
|
||||
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
public static final BlockPos blockPos = new BlockPos(0,0,0);
|
||||
public static Random random = new Random(0);
|
||||
|
||||
//public static BlockColourWrapper WATER_COLOR = getBlockColorWrapper(Blocks.WATER);
|
||||
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
|
||||
|
||||
private Block block;
|
||||
private boolean nonFull;
|
||||
private boolean noCollision;
|
||||
private int color;
|
||||
private boolean isColored;
|
||||
private boolean toTint;
|
||||
private boolean leavesTint;
|
||||
private boolean folliageTint;
|
||||
private boolean grassTint;
|
||||
private boolean waterTint;
|
||||
|
||||
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockWrapper(Block block)
|
||||
public BlockColorWrapper(BlockState blockState, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
this.nonFull = true;
|
||||
this.noCollision = true;
|
||||
this.block = blockState.getBlock();
|
||||
this.color = 0;
|
||||
this.isColored = true;
|
||||
this.toTint = false;
|
||||
this.block = block;
|
||||
setupColorAndTint();
|
||||
setupShapes();
|
||||
this.folliageTint = false;
|
||||
this.grassTint = false;
|
||||
this.waterTint = false;
|
||||
setupColorAndTint(blockState,blockPosWrapper);
|
||||
System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
|
||||
}
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block Block object to wrap
|
||||
* @param blockState of the block to wrap
|
||||
*/
|
||||
static public BlockWrapper getBlockWrapper(Block block)
|
||||
static public BlockColorWrapper getBlockColorWrapper(BlockState blockState, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if(blockWrapperMap.containsKey(block) && blockWrapperMap.get(block) != null)
|
||||
return blockWrapperMap.get(block);
|
||||
if (blockColorWrapperMap.containsKey(blockState.getBlock()) && blockColorWrapperMap.get(blockState.getBlock()) != null)
|
||||
return blockColorWrapperMap.get(blockState.getBlock());
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockWrapper blockWrapper = new BlockWrapper(block);
|
||||
blockWrapperMap.put(block, blockWrapper);
|
||||
BlockColorWrapper blockWrapper = new BlockColorWrapper(blockState, blockPosWrapper);
|
||||
blockColorWrapperMap.put(blockState.getBlock(), blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the color of the given block from its texture
|
||||
* and store it for later use.
|
||||
*/
|
||||
private void setupColorAndTint()
|
||||
private void setupColorAndTint(BlockState blockState, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
TextureAtlasSprite texture;
|
||||
@@ -81,9 +83,9 @@ public class BlockWrapper
|
||||
int listSize = 0;
|
||||
|
||||
// first step is to check if this block has a tinted face
|
||||
for (Direction direction : Direction.values())
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(block.defaultBlockState(), direction, random, dataMap);
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||
listSize = Math.max(listSize, quads.size());
|
||||
for (BakedQuad bakedQuad : quads)
|
||||
{
|
||||
@@ -92,23 +94,27 @@ public class BlockWrapper
|
||||
}
|
||||
|
||||
//if it contains a tinted face then we store this block in the toTint set
|
||||
if(isTinted)
|
||||
if (isTinted)
|
||||
this.toTint = true;
|
||||
|
||||
//now we get the first non empty face
|
||||
for (Direction direction : Direction.values())
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(block.defaultBlockState(), direction, random, dataMap);
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||
if (!quads.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
//the quads list is not empty we extract the first one
|
||||
if (!quads.isEmpty())
|
||||
{
|
||||
isColored = true;
|
||||
texture = quads.get(0).getSprite();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
isColored = true;
|
||||
texture = mc.getModelManager().getBlockModelShaper().getTexture(block.defaultBlockState(), mc.getClientWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
@@ -128,11 +134,12 @@ public class BlockWrapper
|
||||
{
|
||||
for (int v = 0; v < texture.getWidth(); v++)
|
||||
{
|
||||
if (texture.isTransparent(frameIndex, u, v))
|
||||
continue;
|
||||
|
||||
tempColor = texture.getPixelRGBA(frameIndex, u, v);
|
||||
|
||||
if (ColorUtil.getAlpha(texture.getPixelRGBA(frameIndex, u, v)) == 0)
|
||||
continue;
|
||||
|
||||
// determine if this pixel is gray
|
||||
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
@@ -177,14 +184,11 @@ public class BlockWrapper
|
||||
this.toTint = true;
|
||||
|
||||
// we check which kind of tint we need to apply
|
||||
if (grassInstance() && this.toTint)
|
||||
this.grassTint = true;
|
||||
this.grassTint = grassInstance() && toTint;
|
||||
|
||||
if (leavesInstance() && this.toTint)
|
||||
this.leavesTint = true;
|
||||
this.folliageTint = leavesInstance() && toTint;
|
||||
|
||||
if (waterIstance() && this.toTint)
|
||||
this.waterTint = true;
|
||||
this.waterTint = waterIstance() && toTint;
|
||||
|
||||
color = tempColor;
|
||||
}
|
||||
@@ -213,14 +217,10 @@ public class BlockWrapper
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
private void setupShapes(){
|
||||
|
||||
}
|
||||
|
||||
//--------------//
|
||||
//Colors getters//
|
||||
//--------------//
|
||||
|
||||
//--------------//
|
||||
//Colors getters//
|
||||
//--------------//
|
||||
|
||||
public boolean hasColor()
|
||||
{
|
||||
@@ -229,12 +229,12 @@ public class BlockWrapper
|
||||
|
||||
public int getColor()
|
||||
{
|
||||
return color;
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------//
|
||||
//Tint getters//
|
||||
//------------//
|
||||
|
||||
//------------//
|
||||
//Tint getters//
|
||||
//------------//
|
||||
|
||||
|
||||
public boolean hasTint()
|
||||
@@ -247,9 +247,9 @@ public class BlockWrapper
|
||||
return grassTint;
|
||||
}
|
||||
|
||||
public boolean hasLeavesTint()
|
||||
public boolean hasFolliageTint()
|
||||
{
|
||||
return leavesTint;
|
||||
return folliageTint;
|
||||
}
|
||||
|
||||
public boolean hasWaterTint()
|
||||
@@ -258,13 +258,15 @@ public class BlockWrapper
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockWrapper))
|
||||
if (!(o instanceof BlockColorWrapper))
|
||||
return false;
|
||||
BlockWrapper that = (BlockWrapper) o;
|
||||
BlockColorWrapper that = (BlockColorWrapper) o;
|
||||
return Objects.equals(block, that.block);
|
||||
}
|
||||
|
||||
@@ -274,3 +276,4 @@ public class BlockWrapper
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class BlockPosWrapper
|
||||
|
||||
public BlockPosWrapper()
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable();
|
||||
this.blockPos = new BlockPos.Mutable(0,0,0);
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z)
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
|
||||
package com.seibel.lod.wrappers.Block;
|
||||
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.wrappers.Chunk.ChunkWrapper;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
//This class wraps the minecraft Block class
|
||||
public class BlockShapeWrapper
|
||||
{
|
||||
//set of block which require tint
|
||||
public static final ConcurrentMap<Block, BlockShapeWrapper> blockShapeWrapperMap = new ConcurrentHashMap<>();
|
||||
public static BlockShapeWrapper WATER_SHAPE = new BlockShapeWrapper();
|
||||
|
||||
private Block block;
|
||||
private boolean toAvoid;
|
||||
private boolean nonFull;
|
||||
private boolean noCollision;
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockShapeWrapper(Block block, ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
this.block = block;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = ofBlockToAvoid();
|
||||
setupShapes(chunkWrapper, blockPosWrapper);
|
||||
System.out.println(block + " non full " + nonFull + " no collision " + noCollision + " to avoid " + toAvoid);
|
||||
}
|
||||
|
||||
private BlockShapeWrapper()
|
||||
{
|
||||
this.block = Blocks.WATER;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block Block object to wrap
|
||||
*/
|
||||
static public BlockShapeWrapper getBlockShapeWrapper(Block block, ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if (blockShapeWrapperMap.containsKey(block) && blockShapeWrapperMap.get(block) != null)
|
||||
return blockShapeWrapperMap.get(block);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockShapeWrapper blockWrapper = new BlockShapeWrapper(block, chunkWrapper, blockPosWrapper);
|
||||
blockShapeWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
private void setupShapes(ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
IBlockReader chunk = chunkWrapper.getChunk();
|
||||
BlockPos blockPos = blockPosWrapper.getBlockPos();
|
||||
boolean noCollisionSetted = false;
|
||||
boolean nonFullSetted = false;
|
||||
if (!block.defaultBlockState().getFluidState().isEmpty() || block instanceof SixWayBlock)
|
||||
{
|
||||
noCollisionSetted = true;
|
||||
nonFullSetted = true;
|
||||
noCollision = false;
|
||||
nonFull = false;
|
||||
}
|
||||
if (!nonFullSetted)
|
||||
{
|
||||
VoxelShape voxelShape = block.defaultBlockState().getShape(chunk, blockPos);
|
||||
|
||||
if (!voxelShape.isEmpty())
|
||||
{
|
||||
AxisAlignedBB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
nonFull = xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonFull = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!noCollisionSetted)
|
||||
{
|
||||
VoxelShape collisionShape = block.defaultBlockState().getCollisionShape(chunk, blockPos);
|
||||
noCollision = collisionShape.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ofBlockToAvoid()
|
||||
{
|
||||
return block.equals(Blocks.AIR)
|
||||
|| block.equals(Blocks.CAVE_AIR)
|
||||
|| block.equals(Blocks.BARRIER);
|
||||
}
|
||||
//-----------------//
|
||||
//Avoidance getters//
|
||||
//-----------------//
|
||||
|
||||
|
||||
public boolean isNonFull()
|
||||
{
|
||||
return nonFull;
|
||||
}
|
||||
|
||||
public boolean hasNoCollision()
|
||||
{
|
||||
return noCollision;
|
||||
}
|
||||
|
||||
public boolean isToAvoid()
|
||||
{
|
||||
return toAvoid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockShapeWrapper))
|
||||
return false;
|
||||
BlockShapeWrapper that = (BlockShapeWrapper) o;
|
||||
return Objects.equals(block, that.block);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(block);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,26 @@ public class ChunkPosWrapper
|
||||
return chunkPos.z;
|
||||
}
|
||||
|
||||
public int getMinBlockX()
|
||||
{
|
||||
return chunkPos.getMinBlockX();
|
||||
}
|
||||
|
||||
public int getMinBlockZ()
|
||||
{
|
||||
return chunkPos.getMinBlockZ();
|
||||
}
|
||||
|
||||
public int getRegionX()
|
||||
{
|
||||
return chunkPos.getRegionX();
|
||||
}
|
||||
|
||||
public int getRegionZ()
|
||||
{
|
||||
return chunkPos.getRegionZ();
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return chunkPos;
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
package com.seibel.lod.wrappers.Chunk;
|
||||
|
||||
import com.seibel.lod.wrappers.Block.BlockWrapper;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockColorWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockShapeWrapper;
|
||||
import com.seibel.lod.wrappers.World.BiomeWrapper;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ILiquidContainer;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
|
||||
public class ChunkWrapper
|
||||
@@ -10,20 +17,77 @@ public class ChunkWrapper
|
||||
private IChunk chunk;
|
||||
private ChunkPosWrapper chunkPos;
|
||||
|
||||
public int getHeight(){
|
||||
return chunk.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
public boolean isPositionInWater(BlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(blockPos.getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
if((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
return true;
|
||||
|
||||
//This type of block could be in water
|
||||
if(blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).isPresent() && blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).get())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getHeightMapValue(int xRel, int zRel){
|
||||
return chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
}
|
||||
|
||||
public BiomeWrapper getBiome(int xRel, int yAbs, int zRel)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2));
|
||||
}
|
||||
|
||||
public BlockColorWrapper getBlockColorWrapper(BlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(blockPos.getBlockPos()),blockPos);
|
||||
}
|
||||
|
||||
public BlockShapeWrapper getBlockShapeWrapper(BlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(blockPos.getBlockPos()).getBlock(), this, blockPos);
|
||||
}
|
||||
|
||||
public ChunkWrapper(IChunk chunk)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
|
||||
}
|
||||
|
||||
public BlockWrapper getBlock(BlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockWrapper.getBlockWrapper(chunk.getBlockState(blockPos.getBlockPos()).getBlock());
|
||||
public IChunk getChunk(){
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public ChunkPosWrapper getChunkPos(){
|
||||
public ChunkPosWrapper getPos(){
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
public boolean isLightCorrect(){
|
||||
return chunk.isLightCorrect();
|
||||
}
|
||||
|
||||
public boolean
|
||||
isWaterLogged(BlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(blockPos.getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
if((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
return true;
|
||||
|
||||
//This type of block could be in water
|
||||
if(blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).isPresent() && blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).get())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getEmittedBrightness(BlockPosWrapper blockPos)
|
||||
{
|
||||
return chunk.getLightEmission(blockPos.getBlockPos());
|
||||
|
||||
@@ -9,7 +9,7 @@ public class LigthMapWrapper
|
||||
|
||||
public static void setLightMap(NativeImage lightMap)
|
||||
{
|
||||
lightMap = null;
|
||||
lightMap = lightMap;
|
||||
}
|
||||
|
||||
public static int getLightValue(int skyLight, int blockLight)
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.seibel.lod.ModInfo;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import com.seibel.lod.wrappers.World.WorldWrapper;
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -44,6 +45,7 @@ import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft class
|
||||
@@ -183,6 +185,36 @@ public class MinecraftWrapper
|
||||
return mc.level;
|
||||
}
|
||||
|
||||
public WorldWrapper getWrappedClientWorld()
|
||||
{
|
||||
return WorldWrapper.getWorldWrapper(mc.level);
|
||||
}
|
||||
|
||||
public WorldWrapper getWrappedServerWorld()
|
||||
{
|
||||
|
||||
if (mc.level == null)
|
||||
return null;
|
||||
DimensionType dimension = mc.level.dimensionType();
|
||||
IntegratedServer server = mc.getSingleplayerServer();
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
Iterable<ServerWorld> worlds = server.getAllLevels();
|
||||
ServerWorld returnWorld = null;
|
||||
|
||||
for (ServerWorld world : worlds)
|
||||
{
|
||||
if (world.dimensionType() == dimension)
|
||||
{
|
||||
returnWorld = world;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return WorldWrapper.getWorldWrapper(returnWorld);
|
||||
}
|
||||
|
||||
/** Measured in chunks */
|
||||
public int getRenderDistance()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeColors;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
public class BiomeColorWrapper
|
||||
{
|
||||
|
||||
public static int getGrassColor(WorldWrapper worldWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
return BiomeColors.getAverageGrassColor(worldWrapper.getWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
public static int getWaterColor(WorldWrapper worldWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
|
||||
return BiomeColors.getAverageWaterColor(worldWrapper.getWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
public static int getFoliageColor(WorldWrapper worldWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
|
||||
return BiomeColors.getAverageFoliageColor(worldWrapper.getWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,16 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockWrapper;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.Block.BlockColorWrapper;
|
||||
import com.seibel.lod.wrappers.Block.BlockPosWrapper;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeColors;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -42,72 +48,55 @@ public class BiomeWrapper
|
||||
public int getColorForBiome(int x, int z)
|
||||
{
|
||||
int colorInt;
|
||||
int color;
|
||||
int tint;
|
||||
|
||||
switch (biome.getBiomeCategory())
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.NETHERRACK).getColor();
|
||||
colorInt = Blocks.NETHERRACK.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.END_STONE).getColor();
|
||||
colorInt = Blocks.END_STONE.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case BEACH:
|
||||
case DESERT:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.SAND).getColor();
|
||||
colorInt = Blocks.SAND.defaultBlockState().materialColor.col;
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.STONE).getColor();
|
||||
colorInt = Blocks.STONE.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case MUSHROOM:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.MYCELIUM).getColor();
|
||||
colorInt = MaterialColor.COLOR_LIGHT_GRAY.col;
|
||||
break;
|
||||
|
||||
case ICY:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.SNOW).getColor();
|
||||
colorInt = Blocks.SNOW.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case MESA:
|
||||
colorInt = BlockWrapper.getBlockWrapper(Blocks.RED_SAND).getColor();
|
||||
colorInt = Blocks.RED_SAND.defaultMaterialColor().col;
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
colorInt = biome.getWaterColor();
|
||||
break;
|
||||
|
||||
case SWAMP:
|
||||
case FOREST:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.OAK_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
case TAIGA:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.SPRUCE_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
case JUNGLE:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.JUNGLE_LEAVES).getColor();
|
||||
tint = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
case NONE:
|
||||
case FOREST:
|
||||
case TAIGA:
|
||||
case JUNGLE:
|
||||
case PLAINS:
|
||||
case SAVANNA:
|
||||
color = BlockWrapper.getBlockWrapper(Blocks.GRASS_BLOCK).getColor();
|
||||
tint = biome.getGrassColor(x,z);
|
||||
colorInt = ColorUtil.multiplyRGBcolors(color, tint);
|
||||
case SWAMP:
|
||||
default:
|
||||
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
|
||||
tmp = tmp.darker();
|
||||
colorInt = LodUtil.colorToInt(tmp);
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -115,6 +104,22 @@ public class BiomeWrapper
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
public int getGrassTint(int x, int z)
|
||||
{
|
||||
return biome.getGrassColor(x, z);
|
||||
}
|
||||
|
||||
public int getFolliageTint()
|
||||
{
|
||||
return biome.getFoliageColor();
|
||||
}
|
||||
|
||||
public int getWaterTint()
|
||||
{
|
||||
return biome.getWaterColor();
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.seibel.lod.wrappers.World;
|
||||
|
||||
|
||||
//We will use this class to get all the light information from the game like skylight, blocklight and light emission;
|
||||
public class WorldLightWrapper
|
||||
{
|
||||
}
|
||||
@@ -16,7 +16,8 @@ public class WorldWrapper
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public WorldWrapper getWorldWrapper(IWorld world)
|
||||
|
||||
public static WorldWrapper getWorldWrapper(IWorld world)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
|
||||
@@ -43,12 +44,12 @@ public class WorldWrapper
|
||||
|
||||
public int getBlockLight(BlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().skyEngine.getLightValue(blockPos.getBlockPos());
|
||||
return world.getLightEngine().blockEngine.getLightValue(blockPos.getBlockPos());
|
||||
}
|
||||
|
||||
public int getSkyLight(BlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().blockEngine.getLightValue(blockPos.getBlockPos());
|
||||
return world.getLightEngine().skyEngine.getLightValue(blockPos.getBlockPos());
|
||||
}
|
||||
|
||||
public BiomeWrapper getBiome(BlockPosWrapper blockPos)
|
||||
@@ -56,6 +57,11 @@ public class WorldWrapper
|
||||
return BiomeWrapper.getBiomeWrapper(world.getBiome(blockPos.getBlockPos()));
|
||||
}
|
||||
|
||||
public IWorld getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return world.dimensionType().hasCeiling();
|
||||
@@ -65,4 +71,9 @@ public class WorldWrapper
|
||||
{
|
||||
return world.dimensionType().hasSkyLight();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return world == null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user