/* * Minecraft Forge * Copyright (c) 2016. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.minecraftforge.client.model.pipeline; import net.minecraft.block.Block.EnumOffsetType; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.color.BlockColors; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockAccess; public class BlockInfo { private final BlockColors colors; private IBlockAccess world; private IBlockState state; private BlockPos blockPos; private final boolean[][][] translucent = new boolean[3][3][3]; private final int[][][] s = new int[3][3][3]; private final int[][][] b = new int[3][3][3]; private final float[][][][] skyLight = new float[3][2][2][2]; private final float[][][][] blockLight = new float[3][2][2][2]; private final float[][][] ao = new float[3][3][3]; private float shx = 0, shy = 0, shz = 0; private int cachedTint = -1; private int cachedMultiplier = -1; public BlockInfo(BlockColors colors) { this.colors = colors; } public int getColorMultiplier(int tint) { if(cachedTint == tint) return cachedMultiplier; cachedTint = tint; cachedMultiplier = colors.colorMultiplier(state, world, blockPos, tint); return cachedMultiplier; } public void updateShift() { Vec3d offset = state.getOffset(world, blockPos); shx = (float) offset.xCoord; shy = (float) offset.yCoord; shz = (float) offset.zCoord; } @Deprecated public void updateShift(boolean ignoreY) { updateShift(); } public void setWorld(IBlockAccess world) { this.world = world; cachedTint = -1; cachedMultiplier = -1; } public void setState(IBlockState state) { this.state = state; cachedTint = -1; cachedMultiplier = -1; } public void setBlockPos(BlockPos blockPos) { this.blockPos = blockPos; cachedTint = -1; cachedMultiplier = -1; shx = shy = shz = 0; } private float combine(int c, int s1, int s2, int s3) { if(c == 0) c = Math.max(0, Math.max(s1, s2) - 1); if(s1 == 0) s1 = Math.max(0, c - 1); if(s2 == 0) s2 = Math.max(0, c - 1); if(s3 == 0) s3 = Math.max(0, Math.max(s1, s2) - 1); return (float)(c + s1 + s2 + s3) * 0x20 / (4 * 0xFFFF); } public void updateLightMatrix() { boolean full = false; for(int x = 0; x <= 2; x++) { for(int y = 0; y <= 2; y++) { for(int z = 0; z <= 2; z++) { BlockPos pos = blockPos.add(x - 1, y - 1, z - 1); IBlockState state = world.getBlockState(pos); translucent[x][y][z] = state.isTranslucent(); //translucent[x][y][z] = world.getBlockState(pos).getBlock().getLightOpacity(world, pos) == 0; int brightness = state.getPackedLightmapCoords(world, pos); s[x][y][z] = (brightness >> 0x14) & 0xF; b[x][y][z] = (brightness >> 0x04) & 0xF; ao[x][y][z] = state.getAmbientOcclusionLightValue(); if(x == 1 && y == 1 && z == 1) { full = state.isFullCube(); } } } } if(!full) { for(EnumFacing side : EnumFacing.values()) { int x = side.getFrontOffsetX() + 1; int y = side.getFrontOffsetY() + 1; int z = side.getFrontOffsetZ() + 1; s[x][y][z] = Math.max(s[1][1][1] - 1, s[x][y][z]); b[x][y][z] = Math.max(b[1][1][1] - 1, b[x][y][z]); } } for(int x = 0; x < 2; x++) { for(int y = 0; y < 2; y++) { for(int z = 0; z < 2; z++) { int x1 = x * 2; int y1 = y * 2; int z1 = z * 2; boolean tx = translucent[x1][1][z1] || translucent[x1][y1][1]; skyLight[0][x][y][z] = combine(s[x1][1][1], s[x1][1][z1], s[x1][y1][1], tx ? s[x1][y1][z1] : s[x1][1][1]); blockLight[0][x][y][z] = combine(b[x1][1][1], b[x1][1][z1], b[x1][y1][1], tx ? b[x1][y1][z1] : b[x1][1][1]); boolean ty = translucent[x1][y1][1] || translucent[1][y1][z1]; skyLight[1][x][y][z] = combine(s[1][y1][1], s[x1][y1][1], s[1][y1][z1], ty ? s[x1][y1][z1] : s[1][y1][1]); blockLight[1][x][y][z] = combine(b[1][y1][1], b[x1][y1][1], b[1][y1][z1], ty ? b[x1][y1][z1] : b[1][y1][1]); boolean tz = translucent[1][y1][z1] || translucent[x1][1][z1]; skyLight[2][x][y][z] = combine(s[1][1][z1], s[1][y1][z1], s[x1][1][z1], tz ? s[x1][y1][z1] : s[1][1][z1]); blockLight[2][x][y][z] = combine(b[1][1][z1], b[1][y1][z1], b[x1][1][z1], tz ? b[x1][y1][z1] : b[1][1][z1]); } } } } public IBlockAccess getWorld() { return world; } public IBlockState getState() { return state; } public BlockPos getBlockPos() { return blockPos; } public boolean[][][] getTranslucent() { return translucent; } public float[][][][] getSkyLight() { return skyLight; } public float[][][][] getBlockLight() { return blockLight; } public float[][][] getAo() { return ao; } public float getShx() { return shx; } public float getShy() { return shy; } public float getShz() { return shz; } public int getCachedTint() { return cachedTint; } public int getCachedMultiplier() { return cachedMultiplier; } }