Remove duplicate code
This commit is contained in:
@@ -21,9 +21,9 @@ package com.seibel.lod.fabric;
|
||||
|
||||
import com.seibel.lod.core.api.EventApi;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.fabric.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.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.seibel.lod.fabric.mixins;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.seibel.lod.common.wrappers.McObjectConverter;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -30,7 +31,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.fabric.wrappers.McObjectConverter;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
package com.seibel.lod.fabric.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.fabric.wrappers.config.LodConfigWrapperSingleton;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.fabric.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.fabric.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.fabric.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.fabric.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.fabric.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.fabric.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;
|
||||
}
|
||||
-46
@@ -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.fabric.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,296 +0,0 @@
|
||||
package com.seibel.lod.fabric.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.fabric.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;
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
|
||||
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);
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
|
||||
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().getParticleIcon(block.defaultBlockState());
|
||||
}
|
||||
|
||||
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 = TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v);
|
||||
|
||||
if (ColorUtil.getAlpha(TextureAtlasSpriteWrapper.getPixelRGBA(texture, 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.fabric.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.fabric.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.fabric.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 final Block block;
|
||||
private final 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);
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.seibel.lod.fabric.wrappers.block;
|
||||
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
|
||||
/**
|
||||
* For wrapping/utilizing around TextureAtlasSprite
|
||||
* @author Ran
|
||||
*/
|
||||
public class TextureAtlasSpriteWrapper {
|
||||
|
||||
/**
|
||||
* This code is from Minecraft Forge
|
||||
* Which is licensed under the terms of GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* The code has been modified to use TextureAtlasSprite
|
||||
*/
|
||||
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
|
||||
if (sprite.animatedTexture != null) {
|
||||
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
|
||||
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
|
||||
}
|
||||
|
||||
return sprite.mainImage[0].getPixelRGBA(x, y);
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package com.seibel.lod.fabric.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.fabric.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.fabric.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.fabric.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockColorWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockShapeWrapper;
|
||||
import com.seibel.lod.fabric.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;
|
||||
}
|
||||
}
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
package com.seibel.lod.fabric.wrappers.minecraft;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
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.fabric.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.fabric.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;
|
||||
|
||||
|
||||
/**
|
||||
* A singleton that contains everything
|
||||
* related to rendering in Minecraft.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-26-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];
|
||||
GL20.glGetFloatv(GL20.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,423 +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.fabric.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.core.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.fabric.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.fabric.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.fabric.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;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (mc.level != null)
|
||||
{
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
return mc.level.getShade(mcDir, true);
|
||||
}
|
||||
else return 0.0f;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@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.fabric.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.fabric.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);
|
||||
}
|
||||
}
|
||||
-59
@@ -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.fabric.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.fabric.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.fabric.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.fabric.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,174 +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.fabric.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.fabric.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 net.minecraft.world.level.LightLayer;
|
||||
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.getBrightness(LightLayer.BLOCK, ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getBrightness(LightLayer.SKY, ((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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-357
@@ -1,357 +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.fabric.wrappers.worldGeneration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.fabric.wrappers.WrapperUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.EmptyTickList;
|
||||
import net.minecraft.world.level.TickList;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.border.WorldBorder;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.storage.LevelData;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* This is a fake ServerWorld used when generating features.
|
||||
* It allows us to keep each LodChunk generation independent
|
||||
* of the actual ServerWorld, allowing
|
||||
* multithread generation.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodServerWorld implements WorldGenLevel
|
||||
{
|
||||
|
||||
public HashMap<Heightmap.Types, Heightmap> heightmaps = new HashMap<>();
|
||||
|
||||
public final ChunkAccess chunk;
|
||||
|
||||
public final ServerLevel serverWorld;
|
||||
|
||||
public LodServerWorld(ServerLevel newServerWorld, ChunkAccess newChunk)
|
||||
{
|
||||
chunk = newChunk;
|
||||
serverWorld = newServerWorld;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight(Heightmap.Types heightmapType, int x, int z)
|
||||
{
|
||||
// make sure the block position is set relative to the chunk
|
||||
x = x % LodUtil.CHUNK_WIDTH;
|
||||
x = (x < 0) ? x + 16 : x;
|
||||
|
||||
z = z % LodUtil.CHUNK_WIDTH;
|
||||
z = (z < 0) ? z + 16 : z;
|
||||
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(BlockPos pos)
|
||||
{
|
||||
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft)
|
||||
{
|
||||
return chunk.setBlockState(pos, state, false) == state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos)
|
||||
{
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos)
|
||||
{
|
||||
return chunk.getFluidState(pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> state)
|
||||
{
|
||||
return state.test(chunk.getBlockState(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidAtPosition(BlockPos blockPos, Predicate<FluidState> predicate) {
|
||||
return predicate.test(chunk.getFluidState(blockPos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickList<Block> getBlockTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull)
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos p_241827_1_, StructureFeature<?> p_241827_2_)
|
||||
{
|
||||
return serverWorld.startsForFeature(p_241827_1_, p_241827_2_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickList<Fluid> getLiquidTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelLightEngine getLightEngine()
|
||||
{
|
||||
return new LevelLightEngine(null, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return serverWorld.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryAccess registryAccess()
|
||||
{
|
||||
return serverWorld.registryAccess();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All methods below shouldn't be needed
|
||||
* and thus have been left unimplemented.
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public Random getRandom()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Player player, BlockPos pos, SoundEvent soundIn, SoundSource category, float volume,
|
||||
float pitch)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParticle(ParticleOptions particleData, double x, double y, double z, double xSpeed, double ySpeed,
|
||||
double zSpeed)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeManager getBiomeManager()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getShade(Direction p_230487_1_, boolean p_230487_2_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldBorder getWorldBorder()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBlock(BlockPos pos, boolean isMoving)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerLevel getLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkSource getChunkSource()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MinecraftServer getServer() {
|
||||
return serverWorld.getServer();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LevelData getLevelData()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void levelEvent(Player arg0, int arg1, BlockPos arg2, int arg3)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
|
||||
}
|
||||
|
||||
// TODO: Check if this causes any issues
|
||||
@Override
|
||||
public void gameEvent(@Nullable Entity entity, GameEvent gameEvent, BlockPos blockPos) {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Entity> getEntities(Entity arg0, AABB arg1, Predicate<? super Entity> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> entityTypeTest, AABB aABB, Predicate<? super T> predicate) {
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Entity> List<T> getEntitiesOfClass(Class<T> arg0, AABB arg1,
|
||||
Predicate<? super T> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<? extends Player> players()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSkyDarken()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isClientSide()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DimensionType dimensionType()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos p_175625_1_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
}
|
||||
-391
@@ -1,391 +0,0 @@
|
||||
package com.seibel.lod.fabric.wrappers.worldGeneration;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.LodUtil;
|
||||
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.fabric.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.fabric.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.fabric.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.SnowAndFreezeFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
|
||||
/**
|
||||
* @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<>();
|
||||
|
||||
private static ExecutorService Executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
|
||||
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<ChunkAccess> chunkList = new LinkedList<>();
|
||||
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
|
||||
chunkList.add(chunk);
|
||||
|
||||
ServerChunkCache chunkSource = serverWorld.getChunkSource();
|
||||
ChunkGenerator chunkGen = chunkSource.getGenerator();
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(Executor, serverWorld, chunkGen, serverWorld.getStructureManager(), (ThreadedLevelLightEngine) 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<ChunkAccess> chunkList = new LinkedList<>();
|
||||
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkCache chunkSource = serverWorld.getChunkSource();
|
||||
ThreadedLevelLightEngine lightEngine = (ThreadedLevelLightEngine) serverWorld.getLightEngine();
|
||||
StructureManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.getGenerator();
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(Executor, 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(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// TODO[FABRIC]: Find whay this dosnt work
|
||||
ChunkStatus.SURFACE.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
|
||||
// this feature has been proven to be thread safe,
|
||||
// so we will add it
|
||||
// SnowAndFreezeFeature snowFeature = new SnowAndFreezeFeature(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<ChunkAccess> chunkList = new LinkedList<>();
|
||||
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkCache chunkSource = serverWorld.getChunkSource();
|
||||
ThreadedLevelLightEngine lightEngine = (ThreadedLevelLightEngine) serverWorld.getLightEngine();
|
||||
StructureManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.getGenerator();
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(Executor, 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(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// TODO[FABRIC]: Find whay this dosnt work
|
||||
ChunkStatus.SURFACE.generate(Executor, 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.BiomeCategory.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)
|
||||
*/
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
-46
@@ -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;
|
||||
}
|
||||
}
|
||||
-166
@@ -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);
|
||||
}
|
||||
}
|
||||
-59
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-369
@@ -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)
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user