diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java index 915d375ab..de5238018 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java @@ -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); } diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java index 118e571a2..daff1fa0f 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java @@ -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 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, diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java index a46c6af46..677dc7c7d 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java @@ -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 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), diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java index a7ec3c87b..dd88744ab 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java @@ -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 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!"); } diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java index 9ad30e317..765399455 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java @@ -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 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!"); } diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java index 152f58efa..972696ebb 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -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 colorMap = new ConcurrentHashMap<>(); - public static final ConcurrentMap tintColor = new ConcurrentHashMap<>(); - public static final ConcurrentMap toTint = new ConcurrentHashMap<>(); - - public static final ConcurrentMap notFullBlock = new ConcurrentHashMap<>(); - public static final ConcurrentMap 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 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()); + } } diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodGenWorker.java index 75b5ef576..7787664e7 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodGenWorker.java @@ -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)); } diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index 644531783..139f3ef8c 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -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()); } } diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index c9aa5fa6a..1753b90f6 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -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; } diff --git a/src/main/java/com/seibel/lod/util/ColorUtil.java b/src/main/java/com/seibel/lod/util/ColorUtil.java index 7a814dd08..d8456b9aa 100644 --- a/src/main/java/com/seibel/lod/util/ColorUtil.java +++ b/src/main/java/com/seibel/lod/util/ColorUtil.java @@ -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); diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index d70dbc0e8..c3eac5998 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -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); } diff --git a/src/main/java/com/seibel/lod/wrappers/Block/BlockWrapper.java b/src/main/java/com/seibel/lod/wrappers/Block/BlockColorWrapper.java similarity index 68% rename from src/main/java/com/seibel/lod/wrappers/Block/BlockWrapper.java rename to src/main/java/com/seibel/lod/wrappers/Block/BlockColorWrapper.java index 0f5bb38aa..c73e8d022 100644 --- a/src/main/java/com/seibel/lod/wrappers/Block/BlockWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/Block/BlockColorWrapper.java @@ -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 blockWrapperMap = new ConcurrentHashMap<>(); + public static final ConcurrentMap 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 } } + diff --git a/src/main/java/com/seibel/lod/wrappers/Block/BlockPosWrapper.java b/src/main/java/com/seibel/lod/wrappers/Block/BlockPosWrapper.java index 270b8b25a..6dd9d0f20 100644 --- a/src/main/java/com/seibel/lod/wrappers/Block/BlockPosWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/Block/BlockPosWrapper.java @@ -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) diff --git a/src/main/java/com/seibel/lod/wrappers/Block/BlockShapeWrapper.java b/src/main/java/com/seibel/lod/wrappers/Block/BlockShapeWrapper.java new file mode 100644 index 000000000..37f1da2e9 --- /dev/null +++ b/src/main/java/com/seibel/lod/wrappers/Block/BlockShapeWrapper.java @@ -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 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); + } +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkPosWrapper.java b/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkPosWrapper.java index 5fc84f5eb..88ae081ac 100644 --- a/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkPosWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkPosWrapper.java @@ -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; diff --git a/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkWrapper.java b/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkWrapper.java index 084db34e1..0a5fa6725 100644 --- a/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/Chunk/ChunkWrapper.java @@ -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()); diff --git a/src/main/java/com/seibel/lod/wrappers/LigthMapWrapper.java b/src/main/java/com/seibel/lod/wrappers/LigthMapWrapper.java index bb5eabf19..4647e3752 100644 --- a/src/main/java/com/seibel/lod/wrappers/LigthMapWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/LigthMapWrapper.java @@ -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) diff --git a/src/main/java/com/seibel/lod/wrappers/MinecraftWrapper.java b/src/main/java/com/seibel/lod/wrappers/MinecraftWrapper.java index 67f2297fe..8c7c2fcd6 100644 --- a/src/main/java/com/seibel/lod/wrappers/MinecraftWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/MinecraftWrapper.java @@ -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 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() { diff --git a/src/main/java/com/seibel/lod/wrappers/World/BiomeColorWrapper.java b/src/main/java/com/seibel/lod/wrappers/World/BiomeColorWrapper.java new file mode 100644 index 000000000..9ec7b0072 --- /dev/null +++ b/src/main/java/com/seibel/lod/wrappers/World/BiomeColorWrapper.java @@ -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()); + } +} diff --git a/src/main/java/com/seibel/lod/wrappers/World/BiomeWrapper.java b/src/main/java/com/seibel/lod/wrappers/World/BiomeWrapper.java index f14485f8c..317bc5710 100644 --- a/src/main/java/com/seibel/lod/wrappers/World/BiomeWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/World/BiomeWrapper.java @@ -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) diff --git a/src/main/java/com/seibel/lod/wrappers/World/WorldLightWrapper.java b/src/main/java/com/seibel/lod/wrappers/World/WorldLightWrapper.java new file mode 100644 index 000000000..e3a4483f6 --- /dev/null +++ b/src/main/java/com/seibel/lod/wrappers/World/WorldLightWrapper.java @@ -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 +{ +} diff --git a/src/main/java/com/seibel/lod/wrappers/World/WorldWrapper.java b/src/main/java/com/seibel/lod/wrappers/World/WorldWrapper.java index 4589c225a..99a57359a 100644 --- a/src/main/java/com/seibel/lod/wrappers/World/WorldWrapper.java +++ b/src/main/java/com/seibel/lod/wrappers/World/WorldWrapper.java @@ -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; + } }