Near-perfect match Minecraft map shading

This commit is contained in:
Howard Stark 2018-08-21 10:21:43 -07:00
parent dcd379f44c
commit 135149603f
No known key found for this signature in database
GPG Key ID: 9FA4E350B33067F3
1 changed files with 32 additions and 6 deletions

View File

@ -4,7 +4,9 @@ import baritone.bot.Baritone;
import baritone.bot.utils.BlockStateInterface;
import baritone.bot.utils.pathing.BetterBlockPos;
import net.minecraft.block.material.MapColor;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.MutableBlockPos;
import net.minecraft.world.chunk.Chunk;
import org.lwjgl.util.Color;
@ -52,21 +54,45 @@ public class MapChunk {
return new File(new File(Baritone.INSTANCE.getDir(), "map"), "chunk" + chunk.x + "-" + chunk.z + ".png").toPath();
}
/**
* getColor is a re-implementation of the Minecraft ItemMap's
* surface mapping system. This is significantly less convoluted
* than the poorly de-obfuscated code.
*
* We perform shading of the given coordinate relative to the
* position one to the north of the coordinate, as can be seen
* in Minecraft's maps.
*
* @param x relative x coordinate to the start of the chunk
* @param z relative z coord.
* @return Integer RGB value with contextual shading
*/
public int getColor(int x, int z) {
int chunkX = chunk.getPos().getXStart() + x;
int chunkZ = chunk.getPos().getZStart() + z;
MutableBlockPos blockPos = new MutableBlockPos(chunkX, chunk.getHeight(new BetterBlockPos(chunkX, 0, chunkZ)), chunkZ);
MapColor color = BlockStateInterface.get(blockPos).getMapColor(chunk.getWorld(), blockPos);
int colorValue = color != MapColor.AIR ? color.colorValue : BlockStateInterface.get(blockPos.move(EnumFacing.DOWN)).getMapColor(chunk.getWorld(), blockPos).colorValue;
// The chunk heightMap returns the first non-full block above the surface, including bushes.
// We have to check this and shift our block down by one if the color is "air" (as in, there's no real block there)
int colorValue = color != MapColor.AIR ? color.colorValue : BlockStateInterface.get(blockPos.down()).getMapColor(chunk.getWorld(), blockPos).colorValue;
int red = (colorValue >> 16) & 0xFF;
int green = (colorValue >> 8) & 0xFF;
int blue = colorValue & 0xFF;
float heightCoef = (((float) blockPos.getY()) / 255) + 0.5f;
colorValue = (int) (red * heightCoef);
colorValue = (colorValue << 8) + (int) (green * heightCoef);
colorValue = (colorValue << 8) + (int) (blue * heightCoef);
return colorValue;
// Now we get the proper block for the position one to the north.
BlockPos offset = blockPos.offset(EnumFacing.NORTH);
offset = new BlockPos(offset.getX(), chunk.getHeight(offset), offset.getZ());
// And once again, check to make sure we have an actual colored block an not "air"
if(BlockStateInterface.get(offset).getMapColor(chunk.getWorld(), offset) == MapColor.AIR)
offset = offset.down();
// We start the heightCoef at 0.8 to darken the colors similar to vanilla Minecraft's.
float heightCoef = 0.8f + (Math.signum(blockPos.getY() - offset.getY()) * 0.2f);
int newColor = Math.min(255, (int) (red * heightCoef));
newColor = (newColor << 8) + Math.min(255, (int) (green * heightCoef));
newColor = (newColor << 8) + Math.min(255, (int) (blue * heightCoef));
return newColor;
}
}