Fixed everything
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.common.LodCommonMain;
|
||||
import com.seibel.lod.common.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
@@ -9,7 +8,6 @@ import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
@@ -25,12 +23,11 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
*/
|
||||
public class DependencySetup {
|
||||
public static void createInitialBindings() {
|
||||
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
||||
if (!LodCommonMain.serverSided) {
|
||||
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
|
||||
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
||||
}
|
||||
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||
DependencySetupDoneCheck.isDone = true;
|
||||
|
||||
@@ -46,9 +46,17 @@ public class McObjectConverter
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static final Direction[] directions;
|
||||
static {
|
||||
LodDirection[] lodDirs = LodDirection.values();
|
||||
directions = new Direction[lodDirs.length];
|
||||
for (LodDirection lodDir : lodDirs) {
|
||||
directions[lodDir.ordinal()] = Direction.byName(lodDir.name());
|
||||
}
|
||||
}
|
||||
|
||||
public static Direction Convert(LodDirection lodDirection)
|
||||
{
|
||||
return Direction.byName(lodDirection.name());
|
||||
return directions[lodDirection.ordinal()];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,13 @@ public class VersionConstants implements IVersionConstants {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasBatchGenerationImplementation() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean hasBatchGenerationImplementation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaRenderedChunkSquare() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-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.common.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
package com.seibel.lod.common.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.common.LodCommonMain;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
|
||||
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.*;
|
||||
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, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
|
||||
// public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
public static final AbstractBlockPosWrapper blockPos = new BlockPosWrapper(0, 0, 0);
|
||||
public static final 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 final Block block;
|
||||
private int color;
|
||||
private boolean isColored;
|
||||
private boolean toTint;
|
||||
private boolean foliageTint;
|
||||
private boolean grassTint;
|
||||
private boolean waterTint;
|
||||
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockColorWrapper(Block block)
|
||||
{
|
||||
this.block = block;
|
||||
this.color = 0;
|
||||
this.isColored = true;
|
||||
this.toTint = false;
|
||||
this.foliageTint = false;
|
||||
this.grassTint = false;
|
||||
this.waterTint = false;
|
||||
setupColorAndTint();
|
||||
/*StringBuilder s = new StringBuilder();
|
||||
s.append(block + "\n"
|
||||
+ Integer.toHexString(
|
||||
Minecraft.getInstance().getBlockColors().createDefault().getColor(
|
||||
block.defaultBlockState(),
|
||||
(World) MinecraftWrapper.INSTANCE.getWrappedServerLevel().getLevel(),
|
||||
blockPosWrapper.getBlockPos())) + "\n"
|
||||
);
|
||||
for(Property x : Minecraft.getInstance().getBlockColors().getColoringProperties(block))
|
||||
s.append(x.getName() + " " + x.getPossibleValues() + '\n');
|
||||
System.out.println(s);*/
|
||||
//System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block object of the block to wrap
|
||||
*/
|
||||
public static IBlockColorWrapper getBlockColorWrapper(Block block)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if (blockColorWrapperMap.containsKey(block) && blockColorWrapperMap.get(block) != null)
|
||||
return blockColorWrapperMap.get(block);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockColorWrapper blockWrapper = new BlockColorWrapper(block);
|
||||
blockColorWrapperMap.put(block, 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 = block.defaultBlockState();
|
||||
//BlockPosWrapper blockPosWrapper = new 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);
|
||||
// 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);
|
||||
if (!quads.isEmpty() && !(block instanceof RotatedPillarBlock && direction == Direction.UP))
|
||||
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++)
|
||||
boolean lookForTint = grassInstance() || leavesInstance();
|
||||
|
||||
int frameIndex = 0; // TODO
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getWidth(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getHeight(); v++)
|
||||
{
|
||||
//FIXME: Better way on the TextureAtlasSpriteWrapper!!!
|
||||
tempColor = LodCommonMain.forge ?
|
||||
LodCommonMain.forgeMethodCaller.getPixelRGBA(texture, frameIndex, u, v)
|
||||
: TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v);
|
||||
|
||||
if (tempColor == 0)
|
||||
continue;
|
||||
|
||||
if (lookForTint)
|
||||
{
|
||||
// determine if this pixel is gray
|
||||
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
int colorMin = 16 + 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) * ColorUtil.getAlpha(tempColor) * colorMultiplier;
|
||||
red += ColorUtil.getBlue(tempColor) * ColorUtil.getBlue(tempColor) * colorMultiplier;
|
||||
green += ColorUtil.getGreen(tempColor) * ColorUtil.getGreen(tempColor) * colorMultiplier;
|
||||
blue += ColorUtil.getRed(tempColor) * ColorUtil.getRed(tempColor) * colorMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = 0;
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
(int) Math.sqrt(alpha / count),
|
||||
(int) Math.sqrt(red / count),
|
||||
(int) Math.sqrt(green / count),
|
||||
(int) Math.sqrt(blue / count));
|
||||
}
|
||||
|
||||
// determine if this block should use the biome color tint
|
||||
if ((lookForTint && (float) numberOfGreyPixel / count > 0.75f) || waterInstance())
|
||||
this.toTint = true;
|
||||
|
||||
// we check which kind of tint we need to apply
|
||||
this.grassTint = grassInstance() && toTint;
|
||||
|
||||
this.foliageTint = leavesInstance() && toTint;
|
||||
|
||||
this.waterTint = waterInstance() ;
|
||||
|
||||
//hardcoded leaves
|
||||
if (block == Blocks.SPRUCE_LEAVES)
|
||||
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF619961);
|
||||
else if (block == Blocks.BIRCH_LEAVES)
|
||||
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF80A755);
|
||||
else
|
||||
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 IGrowable
|
||||
// || block instanceof AbstractPlantBlock
|
||||
// || block instanceof AbstractTopPlantBlock
|
||||
|| block instanceof TallGrassBlock;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean leavesInstance()
|
||||
{
|
||||
return (block instanceof LeavesBlock && block != Blocks.SPRUCE_LEAVES && block != Blocks.BIRCH_LEAVES/* && block != Blocks.AZALEA_LEAVES && block != Blocks.FLOWERING_AZALEA_LEAVES*/)
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.SUGAR_CANE;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean waterInstance()
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return block.getName().toString();
|
||||
}
|
||||
|
||||
//--------------//
|
||||
//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 foliageTint;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
package com.seibel.lod.common.wrappers.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.BlockDetail;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.FlowerBlock;
|
||||
import net.minecraft.world.level.block.LeavesBlock;
|
||||
import net.minecraft.world.level.block.LiquidBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class BlockDetailMap
|
||||
{
|
||||
public static final int FLOWER_COLOR_SCALE = 5;
|
||||
|
||||
public static final Random random = new Random(0);
|
||||
|
||||
//TODO: Perhaps make this not just use the first frame?
|
||||
//FIXME: Stuff is wrong.
|
||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, boolean useFlowerScaling, boolean useFastLeaf) {
|
||||
|
||||
int count = 0;
|
||||
double alpha = 0;
|
||||
double red = 0;
|
||||
double green = 0;
|
||||
double blue = 0;
|
||||
int tempColor;
|
||||
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getWidth(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getHeight(); v++)
|
||||
{
|
||||
//note: Minecraft color format is: 0xAA BB GG RR
|
||||
//________ DH mod color format is: 0xAA RR GG BB
|
||||
//OpenGL RGBA format native order: 0xRR GG BB AA
|
||||
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
|
||||
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
|
||||
|
||||
double r = ((tempColor & 0x000000FF) )/255.;
|
||||
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
|
||||
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
|
||||
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
|
||||
int scale = 1;
|
||||
|
||||
if (useFastLeaf) {
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
a = 1.;
|
||||
} else if (a==0.) {
|
||||
continue;
|
||||
} else if (useFlowerScaling && (g+0.1<b || g+0.1<r)) {
|
||||
scale = FLOWER_COLOR_SCALE;
|
||||
}
|
||||
|
||||
count += scale;
|
||||
alpha += a*a*scale;
|
||||
red += r*r*scale;
|
||||
green += g*g*scale;
|
||||
blue += b*b*scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = ColorUtil.rgbToInt(255,255,0,255);
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
(int) (Math.sqrt(alpha/count)*255.),
|
||||
(int) (Math.sqrt(red / count)*255.),
|
||||
(int) (Math.sqrt(green / count)*255.),
|
||||
(int) (Math.sqrt(blue / count)*255.));
|
||||
}
|
||||
// TODO: Remove this when transparency is added!
|
||||
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
ColorUtil.getAlpha(tempColor),
|
||||
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
|
||||
);
|
||||
|
||||
return tempColor;
|
||||
}
|
||||
|
||||
|
||||
static class BlockDetailCache {
|
||||
static BlockDetailCache NULL_BLOCK_DETAIL = new BlockDetailCache();
|
||||
|
||||
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
|
||||
|
||||
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
|
||||
|
||||
ConcurrentHashMap<Biome, BlockDetail> biomeDetailMap = null;
|
||||
BlockDetail blockDetail;
|
||||
BlockDetail defaultTintedDetail = null;
|
||||
boolean requireResolving;
|
||||
@SuppressWarnings("unused")
|
||||
boolean requireShade; //TODO: Add back using this in renderer
|
||||
@SuppressWarnings("unused")
|
||||
boolean scaleFlowerColor; //FIXME: Do I need to scale the tint color???
|
||||
int tintIndex;
|
||||
|
||||
static boolean isBlockToBeAvoid(Block b) {
|
||||
for (Block bta : BLOCK_TO_AVOID)
|
||||
if (bta==b) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean hasNoCollision(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
if (!bs.getFluidState().isEmpty() || bs.getBlock() instanceof LiquidBlock) // Is blockState a fluid?
|
||||
return false;
|
||||
if (bs.getCollisionShape(getter, pos).isEmpty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
static boolean hasOnlyNonFullFace(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
if (!bs.getFluidState().isEmpty() || bs.getBlock() instanceof LiquidBlock) // Is blockState a fluid?
|
||||
return false;
|
||||
VoxelShape voxelShape = bs.getShape(getter, pos);
|
||||
if (voxelShape.isEmpty()) return true;
|
||||
AABB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
return xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||
}
|
||||
|
||||
static BlockDetailCache make(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
boolean noCol, nonFull, canOcclude;
|
||||
if(!bs.getFluidState().isEmpty()) {
|
||||
bs = bs.getFluidState().createLegacyBlock();
|
||||
FluidState fs = bs.getFluidState();
|
||||
fs.getType();
|
||||
noCol = false;
|
||||
nonFull = false;
|
||||
canOcclude = false;
|
||||
BlockDetailCache result = new BlockDetailCache(fs);
|
||||
//ApiShared.LOGGER.info(fs.toString()+" = ["+result+"]");
|
||||
return result;
|
||||
} else {
|
||||
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
|
||||
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||
//BlocksToAvoid toAvoid = CONFIG.client().worldGenerator().getBlocksToAvoid();
|
||||
noCol = hasNoCollision(bs, pos, getter);
|
||||
nonFull = hasOnlyNonFullFace(bs, pos, getter);
|
||||
canOcclude = bs.canOcclude();
|
||||
List<BakedQuad> quads = null;
|
||||
for (Direction direction : DIRECTION_ORDER)
|
||||
{
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(bs).getQuads(bs, direction, random);
|
||||
if (!quads.isEmpty() && !(bs.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
|
||||
break;
|
||||
};
|
||||
if (quads == null || quads.isEmpty()) return NULL_BLOCK_DETAIL;
|
||||
BlockDetailCache result = new BlockDetailCache(canOcclude, noCol, nonFull, quads.get(0),
|
||||
bs.getBlock() instanceof FlowerBlock, bs.getBlock() instanceof LeavesBlock);
|
||||
// ApiShared.LOGGER.info(bs.toString()+" = ["+result+"]");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
BlockDetailCache(boolean isFullBlock, boolean noCol, boolean nonFull, BakedQuad quad, boolean useFlowerScaling, boolean useFastLeaf) {
|
||||
requireResolving = quad.isTinted();
|
||||
requireShade = quad.isShade();
|
||||
tintIndex = quad.getTintIndex();
|
||||
scaleFlowerColor = useFlowerScaling;
|
||||
blockDetail = new BlockDetail(calculateColorFromTexture(quad.getSprite(), useFlowerScaling, useFastLeaf), isFullBlock, noCol, nonFull);
|
||||
if (quad.isTinted()) biomeDetailMap = new ConcurrentHashMap<Biome, BlockDetail>();
|
||||
}
|
||||
|
||||
BlockDetailCache(FluidState fluid) {
|
||||
requireResolving = true; // TODO: Maybe in the future recheck that there really is no way to see if a fluid needs tinting
|
||||
requireShade = false;
|
||||
tintIndex = 0; // Vanilla doesn't use this index currently. (Checked at 1.18.X, See BlockColors.class)
|
||||
scaleFlowerColor = false;
|
||||
TextureAtlasSprite text = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(fluid.createLegacyBlock()).getParticleIcon();
|
||||
blockDetail = new BlockDetail(calculateColorFromTexture(text, false, false), true, false, false);
|
||||
biomeDetailMap = new ConcurrentHashMap<Biome, BlockDetail>();
|
||||
}
|
||||
|
||||
private BlockDetailCache()
|
||||
{
|
||||
//DUMMY CREATOR
|
||||
}
|
||||
|
||||
BlockDetail getResolvedBlockDetail(BlockState bs, int x, int y, int z, LevelReader getter) {
|
||||
if (!requireResolving) return blockDetail;
|
||||
BlockPos pos = new BlockPos(x,y,z);
|
||||
Biome biome = getter.getBiome(pos);
|
||||
BlockDetail tintDetail = biomeDetailMap.get(biome);
|
||||
if (tintDetail == null) {
|
||||
if (!bs.getFluidState().isEmpty()) bs = bs.getFluidState().createLegacyBlock();
|
||||
BlockColors bc = Minecraft.getInstance().getBlockColors();
|
||||
int tintColor = bc.getColor(bs, getter, pos, tintIndex);
|
||||
tintColor = ColorUtil.multiplyARGBwithRGB(blockDetail.color, tintColor);
|
||||
tintDetail = new BlockDetail(tintColor, blockDetail.isFullBlock,
|
||||
blockDetail.hasNoCollision, blockDetail.hasOnlyNonFullFace);
|
||||
BlockDetail tintDetailCAS = biomeDetailMap.putIfAbsent(biome, tintDetail);
|
||||
if (tintDetailCAS != null) tintDetail = tintDetailCAS;
|
||||
}
|
||||
return tintDetail;
|
||||
}
|
||||
|
||||
// Note: this one won't resolve biome based or pos based colors. (Kinda like GUI block icons)
|
||||
BlockDetail getResolvedBlockDetail(BlockState bs) {
|
||||
if (!requireResolving) return blockDetail;
|
||||
if (defaultTintedDetail != null) return defaultTintedDetail;
|
||||
|
||||
BlockColors bc = Minecraft.getInstance().getBlockColors();
|
||||
if (!bs.getFluidState().isEmpty()) bs = bs.getFluidState().createLegacyBlock();
|
||||
int tintColor = bc.getColor(bs, null, null, tintIndex);
|
||||
if (tintColor == -1) {
|
||||
defaultTintedDetail = blockDetail;
|
||||
}
|
||||
else {
|
||||
defaultTintedDetail = new BlockDetail(ColorUtil.multiplyARGBwithRGB(blockDetail.color, tintColor),
|
||||
blockDetail.isFullBlock, blockDetail.hasNoCollision, blockDetail.hasOnlyNonFullFace);
|
||||
}
|
||||
return defaultTintedDetail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[BlockDetail: "+blockDetail+", RequireResolving: "+requireResolving+", requireShade: "+requireShade+", scaleFlowerColor: "+scaleFlowerColor+"]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static ConcurrentHashMap<BlockState, BlockDetailCache> map = new ConcurrentHashMap<BlockState, BlockDetailCache>();
|
||||
|
||||
private BlockDetailMap() {}
|
||||
|
||||
private static BlockDetailCache getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
BlockDetailCache cache = map.get(bs);
|
||||
if (cache != null) return cache;
|
||||
if (bs.getFluidState().isEmpty()) {
|
||||
cache = BlockDetailCache.make(bs, pos, getter);
|
||||
} else {
|
||||
cache = BlockDetailCache.make(bs.getFluidState().createLegacyBlock(), pos, getter);
|
||||
}
|
||||
BlockDetailCache cacheCAS = map.putIfAbsent(bs, cache);
|
||||
return cacheCAS==null ? cache : cacheCAS;
|
||||
}
|
||||
|
||||
|
||||
// Return null means skip the block
|
||||
public static BlockDetail getBlockDetail(BlockState bs) {
|
||||
BlockDetailCache cache = getOrMakeBlockDetailCache(bs, new BlockPos(0, 0, 0), null);
|
||||
if (cache == BlockDetailCache.NULL_BLOCK_DETAIL) return null;
|
||||
return cache.getResolvedBlockDetail(bs);
|
||||
}
|
||||
|
||||
// Return null means skip the block
|
||||
public static BlockDetail getBlockDetailWithCompleteTint(BlockState bs, int x, int y, int z, LevelReader tintGetter) {
|
||||
BlockDetailCache cache = getOrMakeBlockDetailCache(bs, new BlockPos(x,y,z), tintGetter);
|
||||
if (cache == BlockDetailCache.NULL_BLOCK_DETAIL) return null;
|
||||
return cache.getResolvedBlockDetail(bs, x, y, z, tintGetter);
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.block;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.common.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, int x, int y, int z)
|
||||
{
|
||||
this.block = block;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = ofBlockToAvoid();
|
||||
setupShapes(chunkWrapper, x, y, z);
|
||||
//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, int x, int y, int z)
|
||||
{
|
||||
//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, x, y, z);
|
||||
blockShapeWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
private void setupShapes(IChunkWrapper chunkWrapper, int x, int y, int z)
|
||||
{
|
||||
ChunkAccess chunk = ((ChunkWrapper) chunkWrapper).getChunk();
|
||||
BlockPos blockPos = new BlockPos(x, y, z);
|
||||
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,19 +1,19 @@
|
||||
package com.seibel.lod.common.wrappers.chunk;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.BlockDetail;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.lod.common.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.common.wrappers.block.BlockColorWrapper;
|
||||
import com.seibel.lod.common.wrappers.block.BlockShapeWrapper;
|
||||
import com.seibel.lod.common.wrappers.block.BlockDetailMap;
|
||||
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.QuartPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.LiquidBlock;
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
|
||||
@@ -33,7 +34,7 @@ import net.minecraft.world.level.levelgen.Heightmap;
|
||||
public class ChunkWrapper implements IChunkWrapper
|
||||
{
|
||||
private ChunkAccess chunk;
|
||||
private BlockAndTintGetter lightSource;
|
||||
private LevelReader lightSource;
|
||||
|
||||
@Override
|
||||
public int getHeight(){
|
||||
@@ -65,19 +66,9 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockColorWrapper getBlockColorWrapper(int x, int y, int z)
|
||||
{
|
||||
public BlockDetail getBlockDetail(int x, int y, int z) {
|
||||
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
|
||||
Block block = blockState.getBlock();
|
||||
return BlockColorWrapper.getBlockColorWrapper(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockShapeWrapper getBlockShapeWrapper(int x, int y, int z)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
|
||||
Block block = blockState.getBlock();
|
||||
return BlockShapeWrapper.getBlockShapeWrapper(block, this, x, y, z);
|
||||
return BlockDetailMap.getBlockDetailWithCompleteTint(blockState, x, y, z, lightSource);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -86,7 +77,7 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
this.chunk = chunk;
|
||||
this.lightSource = null;
|
||||
}
|
||||
public ChunkWrapper(ChunkAccess chunk, BlockAndTintGetter lightSource)
|
||||
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.lightSource = lightSource;
|
||||
@@ -175,4 +166,16 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
if (lightSource == null) return -1;
|
||||
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesNearbyChunksExist() {
|
||||
if (lightSource instanceof LightedWorldGenRegion) return true;
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (dx==0 && dz==0) continue;
|
||||
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-28
@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||
@@ -181,7 +182,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
MinecraftWrapper.INSTANCE.sendChatMessage(
|
||||
"\u00A7eOverdraw prevention will be worse than normal.");
|
||||
} catch (Exception e2) {}
|
||||
ClientApi.LOGGER.error("getVanillaRenderedChunks Error: {}", e);
|
||||
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: {}", e);
|
||||
usingBackupGetVanillaRenderedChunks = true;
|
||||
}
|
||||
}
|
||||
@@ -189,33 +190,6 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getMaximumRenderedChunks()
|
||||
{
|
||||
//TODO: Make this a circle
|
||||
IMinecraftWrapper mcWrapper = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
|
||||
|
||||
int chunkRenderDist = this.getRenderDistance();
|
||||
|
||||
AbstractChunkPosWrapper centerChunkPos = mcWrapper.getPlayerChunkPos();
|
||||
int startChunkX = centerChunkPos.getX() - chunkRenderDist;
|
||||
int startChunkZ = centerChunkPos.getZ() - chunkRenderDist;
|
||||
|
||||
// add every position within render distance
|
||||
HashSet<AbstractChunkPosWrapper> renderedPos = new HashSet<AbstractChunkPosWrapper>();
|
||||
for (int chunkX = 0; chunkX < (chunkRenderDist * 2+1); chunkX++)
|
||||
{
|
||||
for(int chunkZ = 0; chunkZ < (chunkRenderDist * 2+1); chunkZ++)
|
||||
{
|
||||
renderedPos.add(factory.createChunkPos(startChunkX + chunkX, startChunkZ + chunkZ));
|
||||
}
|
||||
}
|
||||
|
||||
return renderedPos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int[] getLightmapPixels()
|
||||
|
||||
@@ -26,6 +26,7 @@ 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.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
@@ -418,7 +419,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
|
||||
@Override
|
||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||
{
|
||||
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||
ApiShared.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
Minecraft.crash(report);
|
||||
}
|
||||
|
||||
+18
-17
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
@@ -251,7 +252,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
if (!unsafeThreadingRecorded && !f.isDone()) {
|
||||
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Unsafe Threading in Chunk Generator Detected!");
|
||||
MC.sendChatMessage("\u00A7eTo increase stability, it is recommended to set world generation threads count to 1.");
|
||||
ClientApi.LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
|
||||
ApiShared.LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
|
||||
unsafeThreadingRecorded = true;
|
||||
}
|
||||
return f.join();
|
||||
@@ -299,8 +300,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
ClientApi.LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
|
||||
ClientApi.LOGGER.error("Exception: ", e);
|
||||
ApiShared.LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
|
||||
ApiShared.LOGGER.error("Exception: ", e);
|
||||
unknownExceptionCount++;
|
||||
lastExceptionTriggerTime = System.nanoTime();
|
||||
}
|
||||
@@ -311,12 +312,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
|
||||
{
|
||||
ClientApi.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
||||
ClientApi.LOGGER.info("Dump PrefEvent: " + event.pEvent);
|
||||
ApiShared.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
||||
ApiShared.LOGGER.info("Dump PrefEvent: " + event.pEvent);
|
||||
try
|
||||
{
|
||||
if (!event.terminate())
|
||||
ClientApi.LOGGER.error("Failed to terminate the stuck generation event!");
|
||||
ApiShared.LOGGER.error("Failed to terminate the stuck generation event!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -328,7 +329,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
try {
|
||||
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Too many exceptions in Batching World Generator! Disabling the generator.");
|
||||
} catch (Exception e) {}
|
||||
ClientApi.LOGGER.error("Too many exceptions in Batching World Generator! Now disabling.");
|
||||
ApiShared.LOGGER.error("Too many exceptions in Batching World Generator! Now disabling.");
|
||||
unknownExceptionCount = 0;
|
||||
CONFIG.client().worldGenerator().setEnableDistantGeneration(false);
|
||||
}
|
||||
@@ -337,14 +338,14 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
|
||||
{
|
||||
super(serverlevel, lodBuilder, lodDim);
|
||||
ClientApi.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
|
||||
ApiShared.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
|
||||
ChunkGenerator generator = ((WorldWrapper) serverlevel).getServerWorld().getChunkSource().getGenerator();
|
||||
if (!(generator instanceof NoiseBasedChunkGenerator ||
|
||||
generator instanceof DebugLevelSource ||
|
||||
generator instanceof FlatLevelSource)) {
|
||||
MC.sendChatMessage("\u00A74\u00A7l\u00A7uWARNING: Distant Horizons: Unknown Chunk Generator Detected! Distant Generation May Fail!");
|
||||
MC.sendChatMessage("\u00A7eIf it does crash, set Distant Generation to OFF or Generation Mode to None.");
|
||||
ClientApi.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
|
||||
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
|
||||
}
|
||||
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
|
||||
}
|
||||
@@ -359,7 +360,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientApi.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
}
|
||||
if (chunkData == null)
|
||||
{
|
||||
@@ -370,7 +371,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
try {
|
||||
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
|
||||
} catch (Exception e) {
|
||||
ClientApi.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
|
||||
}
|
||||
}
|
||||
@@ -380,7 +381,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
public void generateLodFromList(GenerationEvent e)
|
||||
{
|
||||
if (ENABLE_EVENT_LOGGING)
|
||||
ClientApi.LOGGER.info("Lod Generate Event: " + e.pos);
|
||||
ApiShared.LOGGER.info("Lod Generate Event: " + e.pos);
|
||||
e.pEvent.beginNano = System.nanoTime();
|
||||
GridList<ChunkAccess> referencedChunks;
|
||||
DistanceGenerationMode generationMode;
|
||||
@@ -479,7 +480,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
if (isFull)
|
||||
{
|
||||
if (ENABLE_LOAD_EVENT_LOGGING)
|
||||
ClientApi.LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
ApiShared.LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
|
||||
}
|
||||
@@ -505,7 +506,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
if (ENABLE_PERF_LOGGING)
|
||||
{
|
||||
e.tParam.perf.recordEvent(e.pEvent);
|
||||
ClientApi.LOGGER.info(e.tParam.perf);
|
||||
ApiShared.LOGGER.info(e.tParam.perf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,14 +589,14 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
|
||||
@Override
|
||||
public void stop(boolean blocking) {
|
||||
ClientApi.LOGGER.info("Batch Chunk Generator shutting down...");
|
||||
ApiShared.LOGGER.info("Batch Chunk Generator shutting down...");
|
||||
executors.shutdownNow();
|
||||
if (blocking) try {
|
||||
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
|
||||
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
|
||||
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -6,6 +6,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
@@ -70,7 +71,7 @@ public final class GenerationEvent
|
||||
public boolean terminate()
|
||||
{
|
||||
future.cancel(true);
|
||||
ClientApi.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
|
||||
return future.isCancelled();
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -30,7 +31,7 @@ import net.minecraft.world.level.material.Fluids;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ChunkLoader {
|
||||
private static final Logger LOGGER = ClientApi.LOGGER;
|
||||
private static final Logger LOGGER = ApiShared.LOGGER;
|
||||
|
||||
private static LevelChunkSection[] readSections(WorldGenLevel level, LevelLightEngine lightEngine,
|
||||
ChunkPos chunkPos, CompoundTag tagLevel) {
|
||||
|
||||
+2
-1
@@ -3,6 +3,7 @@ package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
|
||||
@@ -183,7 +184,7 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
}
|
||||
}
|
||||
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
|
||||
ClientApi.LOGGER.info("WorldGen requiring " + chunkStatus
|
||||
ApiShared.LOGGER.info("WorldGen requiring " + chunkStatus
|
||||
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
|
||||
debugTriggeredForStatus = chunkStatus;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.seibel.lod.fabric;
|
||||
|
||||
import com.seibel.lod.common.LodCommonMain;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
@@ -64,7 +65,7 @@ public class Main implements ClientModInitializer
|
||||
LodCommonMain.startup(null, false);
|
||||
DependencySetup.createInitialBindings();
|
||||
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
|
||||
// Check if this works
|
||||
client_proxy = new ClientProxy();
|
||||
@@ -81,6 +82,6 @@ public class Main implements ClientModInitializer
|
||||
LodCommonMain.initConfig();
|
||||
LodCommonMain.startup(null, true);
|
||||
DependencySetup.createInitialBindings();
|
||||
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.seibel.lod.common.forge.LodForgeMethodCaller;
|
||||
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
@@ -71,7 +72,7 @@ public class ForgeMain implements LodForgeMethodCaller
|
||||
LodCommonMain.initConfig();
|
||||
LodCommonMain.startup(this, !FMLLoader.getDist().isClient());
|
||||
ForgeDependencySetup.createInitialBindings();
|
||||
ClientApi.LOGGER.info("Distant Horizons initializing...");
|
||||
ApiShared.LOGGER.info("Distant Horizons initializing...");
|
||||
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||
|
||||
if (ReflectionHandler.instance.optifinePresent()) {
|
||||
|
||||
Reference in New Issue
Block a user