Remove duplicate code

This commit is contained in:
Ran
2021-12-01 19:15:30 +06:00
parent 9315fd6211
commit 1bd072bf0a
44 changed files with 8 additions and 5447 deletions
@@ -21,9 +21,9 @@ package com.seibel.lod.forge;
import com.seibel.lod.core.api.EventApi;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.event.TickEvent;
@@ -28,7 +28,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.McObjectConverter;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.RenderType;
@@ -1,17 +1,8 @@
package com.seibel.lod.forge.wrappers;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.forge.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
/**
* Binds all necessary dependencies so we
@@ -1,56 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers;
import java.nio.FloatBuffer;
import com.mojang.math.Matrix4f;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.core.Direction;
/**
* This class converts to and from Minecraft objects (Ex: Matrix4f)
* and objects we created (Ex: Mat4f).
*
* @author James Seibel
* @version 11-20-2021
*/
public class McObjectConverter
{
/** 4x4 float matrix converter */
public static Mat4f Convert(Matrix4f mcMatrix)
{
FloatBuffer buffer = FloatBuffer.allocate(16);
mcMatrix.store(buffer);
Mat4f matrix = new Mat4f(buffer);
matrix.transpose();
return matrix;
}
public static Direction Convert(LodDirection lodDirection)
{
return Direction.byName(lodDirection.name());
}
}
@@ -1,91 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.forge.wrappers.worldGeneration.WorldGeneratorWrapper;
/**
* This handles creating abstract wrapper objects.
*
* @author James Seibel
* @version 11-20-2021
*/
public class WrapperFactory implements IWrapperFactory
{
public static final WrapperFactory INSTANCE = new WrapperFactory();
@Override
public AbstractBlockPosWrapper createBlockPos()
{
return new BlockPosWrapper();
}
@Override
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
{
return new BlockPosWrapper(x,y,z);
}
@Override
public AbstractChunkPosWrapper createChunkPos()
{
return new ChunkPosWrapper();
}
@Override
public AbstractChunkPosWrapper createChunkPos(int x, int z)
{
return new ChunkPosWrapper(x, z);
}
@Override
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
{
return new ChunkPosWrapper(newChunkPos);
}
@Override
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
{
return new ChunkPosWrapper(blockPos);
}
@Override
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
{
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
}
}
@@ -1,35 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers;
import net.minecraft.world.level.levelgen.Heightmap;
/**
* Stores any variables or code that
* may be shared between wrapper objects.
*
* @author James Seibel
* @version 11-20-2021
*/
public class WrapperUtil
{
/** If we ever need to use a heightmap for any reason, use this one. */
public static final Heightmap.Types DEFAULT_HEIGHTMAP = Heightmap.Types.WORLD_SURFACE_WG;
}
@@ -1,46 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.block;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.world.level.block.Blocks;
/**
* Contains methods that would have been static in BlockColorWrapper.
* Since interfaces can't create/implement static methods we have
* to split the object up in two.
*
* @author James Seibel
* @version 11-17-2021
*/
public class BlockColorSingletonWrapper implements IBlockColorSingletonWrapper
{
public static final BlockColorSingletonWrapper INSTANCE = new BlockColorSingletonWrapper();
@Override
public IBlockColorWrapper getWaterColor()
{
return BlockColorWrapper.getBlockColorWrapper(Blocks.WATER.defaultBlockState(), new BlockPosWrapper(0,0, 0));
}
}
@@ -1,295 +0,0 @@
package com.seibel.lod.forge.wrappers.block;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BushBlock;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.GrassBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.TallGrassBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelDataMap;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockColorWrapper implements IBlockColorWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, IBlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
public static final AbstractBlockPosWrapper blockPos = new BlockPosWrapper(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 int color;
private boolean isColored;
private boolean toTint;
private boolean folliageTint;
private boolean grassTint;
private boolean waterTint;
/**Constructor only require for the block instance we are wrapping**/
public BlockColorWrapper(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
this.block = blockState.getBlock();
this.color = 0;
this.isColored = true;
this.toTint = false;
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 blockState of the block to wrap
*/
static public IBlockColorWrapper getBlockColorWrapper(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
//first we check if the block has already been wrapped
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
IBlockColorWrapper 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(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
TextureAtlasSprite texture;
List<BakedQuad> quads = null;
boolean isTinted = false;
int listSize = 0;
// first step is to check if this block has a tinted face
for (Direction direction : directions)
{
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
listSize = Math.max(listSize, quads.size());
for (BakedQuad bakedQuad : quads)
{
isTinted |= bakedQuad.isTinted();
}
}
//if it contains a tinted face then we store this block in the toTint set
if (isTinted)
this.toTint = true;
//now we get the first non empty face
for (Direction direction : directions)
{
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
{
isColored = true;
texture = mc.getModelManager().getBlockModelShaper().getTexture(block.defaultBlockState(), mc.getClientLevel(), ((BlockPosWrapper) blockPosWrapper).getBlockPos());
}
int count = 0;
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
int numberOfGreyPixel = 0;
int tempColor;
int colorMultiplier;
// generate the block's color
//for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
int frameIndex = 0; // TODO
{
// 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++)
{
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));
boolean isGray = colorMax < colorMin;
if (isGray)
numberOfGreyPixel++;
// for flowers, weight their non-green color higher
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
colorMultiplier = 5;
else
colorMultiplier = 1;
// add to the running averages
count += colorMultiplier;
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = 0;
else
{
// determine the average color
alpha /= count;
red /= count;
green /= count;
blue /= count;
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
}
// determine if this block should use the biome color tint
if ((grassInstance() || leavesInstance() || waterIstance()) && (float) numberOfGreyPixel / count > 0.75f)
this.toTint = true;
// we check which kind of tint we need to apply
this.grassTint = grassInstance() && toTint;
this.folliageTint = leavesInstance() && toTint;
this.waterTint = waterIstance() && toTint;
color = tempColor;
}
/** determine if the given block should use the biome's grass color */
private boolean grassInstance()
{
return block instanceof GrassBlock
|| block instanceof BushBlock
|| block instanceof TallGrassBlock;
}
/** determine if the given block should use the biome's foliage color */
private boolean leavesInstance()
{
return block instanceof LeavesBlock
|| block == Blocks.VINE
|| block == Blocks.SUGAR_CANE;
}
/** determine if the given block should use the biome's foliage color */
private boolean waterIstance()
{
return block == Blocks.WATER;
}
//--------------//
//Colors getters//
//--------------//
@Override
public boolean hasColor()
{
return isColored;
}
@Override
public int getColor()
{
return color;
}
//------------//
//Tint getters//
//------------//
@Override
public boolean hasTint()
{
return toTint;
}
@Override
public boolean hasGrassTint()
{
return grassTint;
}
@Override
public boolean hasFolliageTint()
{
return folliageTint;
}
@Override
public boolean hasWaterTint()
{
return waterTint;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockColorWrapper))
return false;
BlockColorWrapper that = (BlockColorWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -1,84 +0,0 @@
package com.seibel.lod.forge.wrappers.block;
import java.util.Objects;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import net.minecraft.core.BlockPos;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockPosWrapper extends AbstractBlockPosWrapper
{
private BlockPos.MutableBlockPos blockPos;
public BlockPosWrapper()
{
this.blockPos = new BlockPos.MutableBlockPos(0,0,0);
}
public BlockPosWrapper(int x, int y, int z)
{
this.blockPos = new BlockPos.MutableBlockPos(x, y, z);
}
@Override
public void set(int x, int y, int z)
{
blockPos.set(x, y, z);
}
@Override
public int getX()
{
return blockPos.getX();
}
@Override
public int getY()
{
return blockPos.getY();
}
@Override
public int getZ()
{
return blockPos.getZ();
}
@Override
public int get(LodDirection.Axis axis)
{
return axis.choose(getX(), getY(), getZ());
}
public BlockPos.MutableBlockPos getBlockPos()
{
return blockPos;
}
@Override public boolean equals(Object o)
{
return blockPos.equals(o);
}
@Override public int hashCode()
{
return Objects.hash(blockPos);
}
@Override
public BlockPosWrapper offset(int x, int y, int z)
{
blockPos.set(blockPos.getX() + x, blockPos.getY() + y, blockPos.getZ() + z);
return this;
}
}
@@ -1,159 +0,0 @@
package com.seibel.lod.forge.wrappers.block;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockShapeWrapper implements IBlockShapeWrapper
{
//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, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper 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, AbstractBlockPosWrapper 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(IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
{
ChunkAccess chunk = ((ChunkWrapper) chunkWrapper).getChunk();
BlockPos blockPos = ((BlockPosWrapper) 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())
{
AABB 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();
}
}
@Override
public boolean ofBlockToAvoid()
{
return block.equals(Blocks.AIR)
|| block.equals(Blocks.CAVE_AIR)
|| block.equals(Blocks.BARRIER);
}
//-----------------//
//Avoidance getters//
//-----------------//
@Override
public boolean isNonFull()
{
return nonFull;
}
@Override
public boolean hasNoCollision()
{
return noCollision;
}
@Override
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);
}
}
@@ -1,116 +0,0 @@
package com.seibel.lod.forge.wrappers.chunk;
import java.util.Objects;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class ChunkPosWrapper extends AbstractChunkPosWrapper
{
private net.minecraft.world.level.ChunkPos chunkPos;
public ChunkPosWrapper()
{
this.chunkPos = new ChunkPos(0, 0);
}
public ChunkPosWrapper(BlockPos blockPos)
{
this.chunkPos = new ChunkPos(blockPos);
}
public ChunkPosWrapper(AbstractChunkPosWrapper newChunkPos)
{
this.chunkPos = ((ChunkPosWrapper) newChunkPos).chunkPos;
}
public ChunkPosWrapper(AbstractBlockPosWrapper blockPos)
{
this.chunkPos = new ChunkPos(((BlockPosWrapper) blockPos).getBlockPos());
}
public ChunkPosWrapper(int chunkX, int chunkZ)
{
this.chunkPos = new ChunkPos(chunkX, chunkZ);
}
public ChunkPosWrapper(ChunkPos pos)
{
this.chunkPos = pos;
}
@Override
public int getX()
{
return chunkPos.x;
}
@Override
public int getZ()
{
return chunkPos.z;
}
@Override
public int getMinBlockX()
{
return chunkPos.getMinBlockX();
}
@Override
public int getMinBlockZ()
{
return chunkPos.getMinBlockZ();
}
@Override
public int getRegionX()
{
return chunkPos.getRegionX();
}
@Override
public int getRegionZ()
{
return chunkPos.getRegionZ();
}
public ChunkPos getChunkPos()
{
return chunkPos;
}
@Override
public boolean equals(Object o)
{
return chunkPos.equals(o);
}
@Override
public int hashCode()
{
return Objects.hash(chunkPos);
}
@Override
public AbstractBlockPosWrapper getWorldPosition()
{
// the parameter here is the y position
BlockPos blockPos = chunkPos.getMiddleBlockPosition(0);
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
}
@@ -1,130 +0,0 @@
package com.seibel.lod.forge.wrappers.chunk;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.forge.wrappers.WrapperUtil;
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.block.BlockShapeWrapper;
import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkAccess;
/**
*
* @author James Seibel
* @version 11-21-2021
*/
public class ChunkWrapper implements IChunkWrapper
{
private ChunkAccess chunk;
private AbstractChunkPosWrapper chunkPos;
@Override
public int getHeight(){
return chunk.getMaxBuildHeight();
}
@Override
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos)
{
BlockState blockState = chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos());
//This type of block is always in water
if((blockState.getBlock() instanceof LiquidBlock))// && !(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;
}
@Override
public int getHeightMapValue(int xRel, int zRel)
{
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
}
@Override
public IBiomeWrapper getBiome(int xRel, int yAbs, int zRel)
{
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2));
}
@Override
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos)
{
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()), blockPos);
}
@Override
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos)
{
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock(), this, blockPos);
}
public ChunkWrapper(ChunkAccess chunk)
{
this.chunk = chunk;
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
}
public ChunkAccess getChunk(){
return chunk;
}
@Override
public AbstractChunkPosWrapper getPos()
{
return chunkPos;
}
@Override
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());
}
@Override
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos)
{
// TODO Auto-generated method stub
return false;
}
@Override
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos)
{
// TODO Auto-generated method stub
return 0;
}
}
@@ -1,166 +0,0 @@
package com.seibel.lod.forge.wrappers.minecraft;
import java.awt.*;
import java.util.HashSet;
import com.mojang.math.Vector3f;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LevelRenderer.RenderChunkInfo;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.core.BlockPos;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.phys.Vec3;
import org.lwjgl.opengl.GL15;
/**
* A singleton that contains everything
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 11-18-2021
*/
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
private final static Minecraft mc = Minecraft.getInstance();
@Override
public Vec3f getLookAtVector()
{
Camera camera = gameRenderer.getMainCamera();
Vector3f cameraDir = camera.getLookVector();
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
}
@Override
public AbstractBlockPosWrapper getCameraBlockPosition()
{
Camera camera = gameRenderer.getMainCamera();
BlockPos blockPos = camera.getBlockPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@Override
public boolean playerHasBlindnessEffect()
{
return mc.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
}
@Override
public Vec3d getCameraExactPosition()
{
Camera camera = gameRenderer.getMainCamera();
Vec3 projectedView = camera.getPosition();
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
}
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true)));
}
@Override
public double getGamma()
{
return mc.options.gamma;
}
@Override
public Color getFogColor()
{
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
}
@Override
public Color getSkyColor()
{
if (mc.level.dimensionType().hasSkyLight())
{
Vec3 colorValues = mc.level.getSkyColor(mc.gameRenderer.getMainCamera().getPosition(), mc.getFrameTime());
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
}
else
{
return new Color(0, 0, 0);
}
}
@Override
public double getFov(float partialTicks)
{
return gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
}
/** Measured in chunks */
@Override
public int getRenderDistance()
{
return mc.options.renderDistance;
}
@Override
public int getScreenWidth()
{
return mc.getWindow().getWidth();
}
@Override
public int getScreenHeight()
{
return mc.getWindow().getHeight();
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
@Override
public HashSet<AbstractChunkPosWrapper> getRenderedChunks()
{
HashSet<AbstractChunkPosWrapper> loadedPos = new HashSet<>();
// Wow, those are some long names!
// go through every RenderInfo to get the compiled chunks
LevelRenderer renderer = mc.levelRenderer;
for (RenderChunkInfo worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
{
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
if (!compiledChunk.hasNoRenderableLayers())
{
// add the ChunkPos for every rendered chunk
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
loadedPos.add(new ChunkPosWrapper(bpos));
}
}
return loadedPos;
}
}
@@ -1,418 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.minecraft;
import java.awt.Color;
import java.io.File;
import java.util.ArrayList;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.seibel.lod.ModInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.forge.wrappers.misc.LightMapWrapper;
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import net.minecraft.CrashReport;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.server.IntegratedServer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.dimension.DimensionType;
/**
* A singleton that wraps the Minecraft class
* to allow for easier movement between Minecraft versions.
*
* @author James Seibel
* @version 9-16-2021
*/
public class MinecraftWrapper implements IMinecraftWrapper
{
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
private final Minecraft mc = Minecraft.getInstance();
/**
* The lightmap for the current:
* Time, dimension, brightness setting, etc.
*/
private NativeImage lightMap = null;
private ProfilerWrapper profilerWrapper;
private MinecraftWrapper()
{
}
//================//
// helper methods //
//================//
/**
* This should be called at the beginning of every frame to
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
* <p>
* LightMaps and other time sensitive objects fall in this category. <br> <br>
* <p>
* This doesn't affect OpenGL objects in any way.
*/
@Override
public void clearFrameObjectCache()
{
lightMap = null;
}
//=================//
// method wrappers //
//=================//
@Override
public float getShade(LodDirection lodDirection)
{
Direction mcDir = McObjectConverter.Convert(lodDirection);
return mc.level.getShade(mcDir, true);
}
@Override
public boolean hasSinglePlayerServer()
{
return mc.hasSingleplayerServer();
}
@Override
public String getCurrentServerName()
{
return mc.getCurrentServer().name;
}
@Override
public String getCurrentServerIp()
{
return mc.getCurrentServer().ip;
}
@Override
public String getCurrentServerVersion()
{
return mc.getCurrentServer().version.getString();
}
/** Returns the dimension the player is currently in */
@Override
public IDimensionTypeWrapper getCurrentDimension()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
}
@Override
public String getCurrentDimensionId()
{
return LodUtil.getDimensionIDFromWorld(WorldWrapper.getWorldWrapper(mc.level));
}
/** This texture changes every frame */
@Override
public ILightMapWrapper getCurrentLightMap()
{
// get the current lightMap if the cache is empty
if (lightMap == null)
{
LightTexture tex = mc.gameRenderer.lightTexture();
lightMap = tex.lightPixels;
}
return new LightMapWrapper(lightMap);
}
/**
* Returns the color int at the given pixel coordinates
* from the current lightmap.
* @param u x location in texture space
* @param v z location in texture space
*/
@Override
public int getColorIntFromLightMap(int u, int v)
{
if (lightMap == null)
{
// make sure the lightMap is up-to-date
getCurrentLightMap();
}
return lightMap.getPixelRGBA(u, v);
}
/**
* Returns the Color at the given pixel coordinates
* from the current lightmap.
* @param u x location in texture space
* @param v z location in texture space
*/
@Override
public Color getColorFromLightMap(int u, int v)
{
return LodUtil.intToColor(lightMap.getPixelRGBA(u, v));
}
//=============//
// Simple gets //
//=============//
public LocalPlayer getPlayer()
{
return mc.player;
}
@Override
public boolean playerExists()
{
return mc.player != null;
}
@Override
public BlockPosWrapper getPlayerBlockPos()
{
BlockPos playerPos = getPlayer().blockPosition();
return new BlockPosWrapper(playerPos.getX(), playerPos.getY(), playerPos.getZ());
}
@Override
public ChunkPosWrapper getPlayerChunkPos()
{
ChunkPos playerPos = getPlayer().chunkPosition();
return new ChunkPosWrapper(playerPos.x, playerPos.z);
}
public Options getOptions()
{
return mc.options;
}
public ModelManager getModelManager()
{
return mc.getModelManager();
}
public ClientLevel getClientLevel()
{
return mc.level;
}
@Override
public IWorldWrapper getWrappedServerWorld()
{
if (mc.level == null)
return null;
DimensionType dimension = mc.level.dimensionType();
IntegratedServer server = mc.getSingleplayerServer();
if (server == null)
return null;
ServerLevel serverWorld = null;
Iterable<ServerLevel> worlds = server.getAllLevels();
for (ServerLevel world : worlds)
{
if (world.dimensionType() == dimension)
{
serverWorld = world;
break;
}
}
return WorldWrapper.getWorldWrapper(serverWorld);
}
public WorldWrapper getWrappedClientLevel()
{
return WorldWrapper.getWorldWrapper(mc.level);
}
public WorldWrapper getWrappedServerLevel()
{
if (mc.level == null)
return null;
DimensionType dimension = mc.level.dimensionType();
IntegratedServer server = mc.getSingleplayerServer();
if (server == null)
return null;
Iterable<ServerLevel> worlds = server.getAllLevels();
ServerLevel returnWorld = null;
for (ServerLevel world : worlds)
{
if (world.dimensionType() == dimension)
{
returnWorld = world;
break;
}
}
return WorldWrapper.getWorldWrapper(returnWorld);
}
@Override
public IWorldWrapper getWrappedClientWorld()
{
return WorldWrapper.getWorldWrapper(mc.level);
}
@Override
public File getGameDirectory()
{
return mc.gameDirectory;
}
@Override
public IProfilerWrapper getProfiler()
{
if (profilerWrapper == null)
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
else if (mc.getProfiler() != profilerWrapper.profiler)
profilerWrapper.profiler = mc.getProfiler();
return profilerWrapper; }
public ClientPacketListener getConnection()
{
return mc.getConnection();
}
public GameRenderer getGameRenderer()
{
return mc.gameRenderer;
}
public Entity getCameraEntity()
{
return mc.cameraEntity;
}
public Window getWindow()
{
return mc.getWindow();
}
@Override
public float getSkyDarken(float partialTicks)
{
return mc.level.getSkyDarken(partialTicks);
}
public IntegratedServer getSinglePlayerServer()
{
return mc.getSingleplayerServer();
}
@Override
public boolean connectedToServer()
{
return mc.getCurrentServer() != null;
}
public ServerData getCurrentServer()
{
return mc.getCurrentServer();
}
public LevelRenderer getLevelRenderer()
{
return mc.levelRenderer;
}
/** Returns all worlds available to the server */
@Override
public ArrayList<IWorldWrapper> getAllServerWorlds()
{
ArrayList<IWorldWrapper> worlds = new ArrayList<IWorldWrapper>();
Iterable<ServerLevel> serverWorlds = mc.getSingleplayerServer().getAllLevels();
for (ServerLevel world : serverWorlds)
{
worlds.add(WorldWrapper.getWorldWrapper(world));
}
return worlds;
}
@Override
public void sendChatMessage(String string)
{
getPlayer().sendMessage(new TextComponent(string), getPlayer().getUUID());
}
/**
* Crashes Minecraft, displaying the given errorMessage <br> <br>
* In the following format: <br>
*
* The game crashed whilst <strong>errorMessage</strong> <br>
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
* Exit Code: -1 <br>
*/
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
}
@@ -1,41 +0,0 @@
package com.seibel.lod.forge.wrappers.minecraft;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import net.minecraft.util.profiling.ProfilerFiller;
/**
* @author James Seibel
* @version 11-20-2021
*/
public class ProfilerWrapper implements IProfilerWrapper
{
public ProfilerFiller profiler;
public ProfilerWrapper(ProfilerFiller newProfiler)
{
profiler = newProfiler;
}
/** starts a new section inside the currently running section */
@Override
public void push(String newSection)
{
profiler.push(newSection);
}
/** ends the currently running section and starts a new one */
@Override
public void popPush(String newSection)
{
profiler.popPush(newSection);
}
/** ends the currently running section */
@Override
public void pop()
{
profiler.pop();
}
}
@@ -1,29 +0,0 @@
package com.seibel.lod.forge.wrappers.misc;
import com.mojang.blaze3d.platform.NativeImage;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class LightMapWrapper implements ILightMapWrapper
{
static NativeImage lightMap = null;
public LightMapWrapper(NativeImage newLightMap)
{
lightMap = newLightMap;
}
public static void setLightMap(NativeImage newLightMap)
{
lightMap = newLightMap;
}
@Override
public int getLightValue(int skyLight, int blockLight)
{
return lightMap.getPixelRGBA(skyLight, blockLight);
}
}
@@ -1,59 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.world;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeColorWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.client.renderer.BiomeColors;
/**
* @author Cola?
* @version 11-15-2021
*/
public class BiomeColorWrapperSingleton implements IBiomeColorWrapperSingleton
{
private static final BiomeColorWrapperSingleton instance = new BiomeColorWrapperSingleton();
@Override
public IBiomeColorWrapperSingleton getInstance()
{
return instance;
}
@Override
public int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageGrassColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageWaterColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageFoliageColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
}
@@ -1,157 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.world;
import java.awt.Color;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.MaterialColor;
//This class wraps the minecraft BlockPos.Mutable (and BlockPos) class
public class BiomeWrapper implements IBiomeWrapper
{
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
private Biome biome;
public BiomeWrapper(Biome biome)
{
this.biome = biome;
}
static public IBiomeWrapper getBiomeWrapper(Biome biome)
{
//first we check if the biome has already been wrapped
if(biomeWrapperMap.containsKey(biome) && biomeWrapperMap.get(biome) != null)
return biomeWrapperMap.get(biome);
//if it hasn't been created yet, we create it and save it in the map
BiomeWrapper biomeWrapper = new BiomeWrapper(biome);
biomeWrapperMap.put(biome, biomeWrapper);
//we return the newly created wrapper
return biomeWrapper;
}
/** Returns a color int for the given biome. */
@Override
public int getColorForBiome(int x, int z)
{
int colorInt;
switch (biome.getBiomeCategory())
{
case NETHER:
colorInt = Blocks.NETHERRACK.defaultBlockState().getMaterial().getColor().col;
break;
case THEEND:
colorInt = Blocks.END_STONE.defaultBlockState().getMaterial().getColor().col;
break;
case BEACH:
case DESERT:
colorInt = Blocks.SAND.defaultBlockState().getMaterial().getColor().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;
}
@Override
public int getGrassTint(int x, int z)
{
return biome.getGrassColor(x, z);
}
@Override
public int getFolliageTint()
{
return biome.getFoliageColor();
}
@Override
public int getWaterTint()
{
return biome.getWaterColor();
}
@Override public boolean equals(Object obj)
{
if (this == obj)
return true;
if (!(obj instanceof BiomeWrapper))
return false;
BiomeWrapper that = (BiomeWrapper) obj;
return Objects.equals(biome, that.biome);
}
@Override public int hashCode()
{
return Objects.hash(biome);
}
}
@@ -1,82 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.world;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import net.minecraft.world.level.dimension.DimensionType;
/**
*
* @author James Seibel
* @version 11-21-2021
*/
public class DimensionTypeWrapper implements IDimensionTypeWrapper
{
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType)
{
this.dimensionType = dimensionType;
}
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
{
//first we check if the biome has already been wrapped
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
return dimensionTypeWrapperMap.get(dimensionType);
//if it hasn't been created yet, we create it and save it in the map
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
//we return the newly created wrapper
return dimensionTypeWrapper;
}
public static void clearMap()
{
dimensionTypeWrapperMap.clear();
}
@Override
public String getDimensionName()
{
return dimensionType.effectsLocation().getPath();
}
@Override
public boolean hasCeiling()
{
return dimensionType.hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return dimensionType.hasSkyLight();
}
}
@@ -1,173 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.forge.wrappers.world;
import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelAccessor;
import org.jetbrains.annotations.Nullable;
/**
* @author James Seibel
* @author ??
* @version 11-21-2021
*/
public class WorldWrapper implements IWorldWrapper
{
private static final ConcurrentMap<LevelAccessor, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
private final LevelAccessor world;
public final WorldType worldType;
public WorldWrapper(LevelAccessor newWorld)
{
world = newWorld;
if (world.getClass() == ServerLevel.class)
worldType = WorldType.ServerWorld;
else if (world.getClass() == ClientLevel.class)
worldType = WorldType.ClientWorld;
else
worldType = WorldType.Unknown;
}
@Nullable
public static WorldWrapper getWorldWrapper(LevelAccessor world)
{
if (world == null) return null;
//first we check if the biome has already been wrapped
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
return worldWrapperMap.get(world);
//if it hasn't been created yet, we create it and save it in the map
WorldWrapper worldWrapper = new WorldWrapper(world);
worldWrapperMap.put(world, worldWrapper);
//we return the newly created wrapper
return worldWrapper;
}
public static void clearMap()
{
worldWrapperMap.clear();
}
@Override
public WorldType getWorldType()
{
return worldType;
}
@Override
public DimensionTypeWrapper getDimensionType()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
}
@Override
public int getBlockLight(AbstractBlockPosWrapper blockPos)
{
return world.getLightEngine().blockEngine.getLightValue(((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getSkyLight(AbstractBlockPosWrapper blockPos)
{
return world.getLightEngine().skyEngine.getLightValue(((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public IBiomeWrapper getBiome(AbstractBlockPosWrapper blockPos)
{
return BiomeWrapper.getBiomeWrapper(world.getBiome(((BlockPosWrapper) blockPos).getBlockPos()));
}
public LevelAccessor getWorld()
{
return world;
}
@Override
public boolean hasCeiling()
{
return world.dimensionType().hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return world.dimensionType().hasSkyLight();
}
@Override
public boolean isEmpty()
{
return world == null;
}
@Override
public int getHeight()
{
return world.getHeight();
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
@Override
public File getSaveFolder() throws UnsupportedOperationException
{
if (worldType != WorldType.ServerWorld)
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
ServerChunkCache chunkSource = ((ServerLevel) world).getChunkSource();
return chunkSource.getDataStorage().dataFolder;
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
public ServerLevel getServerWorld() throws UnsupportedOperationException
{
if (worldType != WorldType.ServerWorld)
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
return (ServerLevel) world;
}
@Override
public int getSeaLevel()
{
// TODO this is depreciated, what should we use instead?
return world.getSeaLevel();
}
}
@@ -1,369 +0,0 @@
package com.seibel.lod.forge.wrappers.worldGeneration;
import java.util.concurrent.ConcurrentHashMap;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
/**
* @author James Seibel
* @version 11-13-2021
*/
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
/**
* If a configured feature fails for whatever reason,
* add it to this list. This will hopefully remove any
* features that could cause issues down the line.
*/
private static final ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> FEATURES_TO_AVOID = new ConcurrentHashMap<>();
public final ServerLevel serverWorld;
public final LodDimension lodDim;
public final LodBuilder lodBuilder;
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
{
super(newLodBuilder, newLodDimension, worldWrapper);
lodBuilder = newLodBuilder;
lodDim = newLodDimension;
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
}
/** takes about 2-5 ms */
@Override
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
{
// List<IChunk> chunkList = new LinkedList<>();
// ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
// chunkList.add(chunk);
//
// ServerChunkProvider chunkSource = serverWorld.getChunkSource();
// ChunkGenerator chunkGen = chunkSource.generator;
//
// // generate the terrain (this is thread safe)
// ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// // override the chunk status, so we can run the next generator stage
// chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
// chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
// chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
//
//
//
//
// // generate fake height data for this LOD
// int seaLevel = serverWorld.getSeaLevel();
//
// boolean simulateHeight = generationMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
// boolean inTheEnd = false;
//
// // add fake heightmap data so our LODs aren't at height 0
// Heightmap heightmap = new Heightmap(chunk, WrapperUtil.DEFAULT_HEIGHTMAP);
// for (int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++)
// {
// for (int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++)
// {
// if (simulateHeight)
// {
// // these heights are of course aren't super accurate,
// // they are just to simulate height data where there isn't any
// switch (chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
// {
// case NETHER:
// heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
// break;
//
// case EXTREME_HILLS:
// heightmap.setHeight(x, z, seaLevel + 30);
// break;
// case MESA:
// case JUNGLE:
// heightmap.setHeight(x, z, seaLevel + 20);
// break;
// case BEACH:
// heightmap.setHeight(x, z, seaLevel + 5);
// break;
// case NONE:
// heightmap.setHeight(x, z, 0);
// break;
//
// case OCEAN:
// case RIVER:
// heightmap.setHeight(x, z, seaLevel);
// break;
//
// case THEEND:
// inTheEnd = true;
// break;
//
// // DESERT
// // FOREST
// // ICY
// // MUSHROOM
// // SAVANNA
// // SWAMP
// // TAIGA
// // PLAINS
// default:
// heightmap.setHeight(x, z, seaLevel + 10);
// break;
// }// heightmap switch
// }
// else
// {
// // we aren't simulating height
// // always use sea level
// heightmap.setHeight(x, z, seaLevel);
// }
// }// z
// }// x
//
// chunk.setHeightmap(WrapperUtil.DEFAULT_HEIGHTMAP, heightmap.getRawData());
//
//
// if (!inTheEnd)
// {
// lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
// }
// else
// {
// // if we are in the end, don't generate any chunks.
// // 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, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
// }
//
//
//// long startTime = System.currentTimeMillis();
//// long endTime = System.currentTimeMillis();
//// System.out.println(endTime - startTime);
}
/** takes about 10 - 20 ms */
@Override
public void generateSurface(AbstractChunkPosWrapper pos)
{
// List<IChunk> chunkList = new LinkedList<>();
// ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
// chunkList.add(chunk);
// LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
//
// ServerChunkProvider chunkSource = serverWorld.getChunkSource();
// ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
// TemplateManager templateManager = serverWorld.getStructureManager();
// ChunkGenerator chunkGen = chunkSource.generator;
//
//
// // generate the terrain (this is thread safe)
// ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// // override the chunk status, so we can run the next generator stage
// chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
// chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
// ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
//
// // this feature has been proven to be thread safe,
// // so we will add it
// IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC);
// snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
//
//
// 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());*/
}
/**
* takes about 15 - 20 ms
* <p>
* Causes concurrentModification Exceptions,
* which could cause instability or world generation bugs
*/
@Override
public void generateFeatures(AbstractChunkPosWrapper pos)
{
// List<IChunk> chunkList = new LinkedList<>();
// ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
// chunkList.add(chunk);
// LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
//
// ServerChunkProvider chunkSource = serverWorld.getChunkSource();
// ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
// TemplateManager templateManager = serverWorld.getStructureManager();
// ChunkGenerator chunkGen = chunkSource.generator;
//
//
// // generate the terrain (this is thread safe)
// ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// // override the chunk status, so we can run the next generator stage
// chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
// chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
// ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
//
//
// // get all the biomes in the chunk
// HashSet<Biome> biomes = new HashSet<>();
// for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
// {
// for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
// {
// Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
//
// // Issue #35
// // For some reason Jungle biomes cause incredible lag
// // the features here must be interacting with each other
// // in unpredictable ways (specifically tree feature generation).
// // When generating Features my CPU usage generally hovers around 30 - 40%
// // when generating Jungles it spikes to 100%.
// if (biome.getBiomeCategory() != Biome.Category.JUNGLE)
// {
// // should probably use the heightmap here instead of seaLevel,
// // but this seems to get the job done well enough
// biomes.add(biome);
// }
// }
// }
//
// boolean allowUnstableFeatures = CONFIG.client().worldGenerator().getAllowUnstableFeatureGeneration();
//
// // generate all the features related to this chunk.
// // this may or may not be thread safe
// for (Biome biome : biomes)
// {
// List<List<Supplier<ConfiguredFeature<?, ?>>>> featuresForState = biome.generationSettings.features();
//
// for (List<Supplier<ConfiguredFeature<?, ?>>> suppliers : featuresForState)
// {
// for (Supplier<ConfiguredFeature<?, ?>> featureSupplier : suppliers)
// {
// ConfiguredFeature<?, ?> configuredFeature = featureSupplier.get();
//
// if (!allowUnstableFeatures &&
// FEATURES_TO_AVOID.containsKey(configuredFeature.hashCode()))
// continue;
//
//
// try
// {
// configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition());
// }
// catch (ConcurrentModificationException | UnsupportedOperationException e)
// {
// // This will happen. I'm not sure what to do about it
// // except pray that it doesn't affect the normal world generation
// // in any harmful way.
// // Update: this can cause crashes and high CPU usage.
//
// // Issue #35
// // I tried cloning the config for each feature, but that
// // path was blocked since I can't clone lambda methods.
// // I tried using a deep cloning library and discovered
// // the problem there.
// // ( https://github.com/kostaskougios/cloning
// // and
// // https://github.com/EsotericSoftware/kryo )
//
// if (!allowUnstableFeatures)
// FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
//// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
// }
// // This will happen when the LodServerWorld
// // isn't able to return something that a feature
// // generator needs
// catch (Exception e)
// {
// // I'm not sure what happened, print to the log
//
// e.printStackTrace();
//
// if (!allowUnstableFeatures)
// FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
//// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
// }
// }
// }
// }
//
// // generate a Lod like normal
// lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.FEATURES));
}
/**
* Generates using MC's ServerWorld.
* <p>
* on pre generated chunks 0 - 1 ms <br>
* on un generated chunks 0 - 50 ms <br>
* with the median seeming to hover around 15 - 30 ms <br>
* and outliers in the 100 - 200 ms range <br>
* <p>
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
@Override
public void generateFull(AbstractChunkPosWrapper pos)
{
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(serverWorld.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FEATURES)), new LodBuilderConfig(DistanceGenerationMode.FULL));
}
/*
* performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
true/false is whether they generated blocks or not
the time is how long it took to generate
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
ChunkStatus.BIOMES 1 - 10 ms false (no height)
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
ChunkStatus.FEATURES 7 - 25 ms true
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
ChunkStatus.LIGHT 20 - 40 ms true
ChunkStatus.FULL 30 - 50 ms true
ChunkStatus.SPAWN 50 - 80 ms true
At this point I would suggest using FEATURES, as it generates snow and trees
(and any other object that are needed to make biomes distinct)
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
*/
}