/*
* This file is part of Cubic Chunks Mod, licensed under the MIT License (MIT).
*
* Copyright (c) 2015 contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package cubicchunks.client;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkCache;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import cubicchunks.util.Coords;
import cubicchunks.world.ICubicWorld;
import cubicchunks.world.cube.Cube;
public class RenderCubeCache extends ChunkCache {
protected int cubeY;
protected Cube[][][] cubeArrays;
private ICubicWorld world;
public RenderCubeCache(ICubicWorld world, BlockPos from, BlockPos to, int subtract) {
super((World) world, from, to, subtract);
this.world = world;
this.cubeY = Coords.blockToCube(from.getY() - subtract);
int cubeXEnd = Coords.blockToCube(to.getX() + subtract);
int cubeYEnd = Coords.blockToCube(to.getY() + subtract);
int cubeZEnd = Coords.blockToCube(to.getZ() + subtract);
cubeArrays = new Cube[cubeXEnd - this.chunkX + 1][cubeYEnd - this.cubeY + 1][cubeZEnd - this.chunkZ + 1];
for (int currentCubeX = chunkX; currentCubeX <= cubeXEnd; currentCubeX++) {
for (int currentCubeY = cubeY; currentCubeY <= cubeYEnd; currentCubeY++) {
for (int currentCubeZ = chunkZ; currentCubeZ <= cubeZEnd; currentCubeZ++) {
cubeArrays[currentCubeX - chunkX][currentCubeY - cubeY][currentCubeZ -
chunkZ] = world.getCubeFromCubeCoords(currentCubeX, currentCubeY, currentCubeZ);
}
}
}
}
@SideOnly(Side.CLIENT)
public int getCombinedLight(BlockPos pos, int lightValue) {
int blockLight = this.getLightForExt(EnumSkyBlock.SKY, pos);
int skyLight = this.getLightForExt(EnumSkyBlock.BLOCK, pos);
if (skyLight < lightValue) {
skyLight = lightValue;
}
return blockLight << 20 | skyLight << 4;
}
@Override
@Nullable public TileEntity getTileEntity(BlockPos pos) {
int arrayX = Coords.blockToCube(pos.getX()) - this.chunkX;
int arrayY = Coords.blockToCube(pos.getY()) - this.cubeY;
int arrayZ = Coords.blockToCube(pos.getZ()) - this.chunkZ;
if (arrayX < 0 || arrayX >= this.cubeArrays.length ||
arrayY < 0 || arrayY >= this.cubeArrays[arrayX].length ||
arrayZ < 0 || arrayZ >= this.cubeArrays[arrayX][arrayY].length) {
return null;
}
if (this.cubeArrays[arrayX][arrayY][arrayZ] == null) {
return null;
}
return this.cubeArrays[arrayX][arrayY][arrayZ].getTileEntity(pos, Chunk.EnumCreateEntityType.IMMEDIATE);
}
@Override
public IBlockState getBlockState(BlockPos pos) {
if (pos.getY() < world.getMinHeight() | pos.getY() >= world.getMaxHeight()) {
return Blocks.AIR.getDefaultState();
}
int arrayX = Coords.blockToCube(pos.getX()) - this.chunkX;
int arrayY = Coords.blockToCube(pos.getY()) - this.cubeY;
int arrayZ = Coords.blockToCube(pos.getZ()) - this.chunkZ;
if (arrayX < 0 || arrayX >= this.cubeArrays.length ||
arrayY < 0 || arrayY >= this.cubeArrays[arrayX].length ||
arrayZ < 0 || arrayZ >= this.cubeArrays[arrayX][arrayY].length) {
return Blocks.AIR.getDefaultState();
}
Cube cube = this.cubeArrays[arrayX][arrayY][arrayZ];
if (cube != null) {
return cube.getBlockState(pos);
}
return Blocks.AIR.getDefaultState();
}
private int getLightForExt(EnumSkyBlock type, BlockPos pos) {
if (type == EnumSkyBlock.SKY && this.worldObj.provider.getHasNoSky()) {
return 0;
}
if (pos.getY() < world.getMinHeight() && pos.getY() >= world.getMaxHeight()) {
return type.defaultLightValue;
}
if (this.getBlockState(pos).useNeighborBrightness()) {
int max = 0;
for (EnumFacing enumfacing : EnumFacing.values()) {
int current = this.getLightFor(type, pos.offset(enumfacing));
if (current > max) {
max = current;
}
if (max >= 15) {
return max;
}
}
return max;
}
int arrayX = Coords.blockToCube(pos.getX()) - this.chunkX;
int arrayY = Coords.blockToCube(pos.getY()) - this.cubeY;
int arrayZ = Coords.blockToCube(pos.getZ()) - this.chunkZ;
if (arrayX < 0 || arrayX >= this.cubeArrays.length ||
arrayY < 0 || arrayY >= this.cubeArrays[arrayX].length ||
arrayZ < 0 || arrayZ >= this.cubeArrays[arrayX][arrayY].length) {
return type.defaultLightValue;
}
Cube cube = this.cubeArrays[arrayX][arrayY][arrayZ];
if (cube == null) {
return type.defaultLightValue;
}
return cube.getLightFor(type, pos);
}
@Override
public int getLightFor(EnumSkyBlock type, BlockPos pos) {
if (pos.getY() < world.getMinHeight() && pos.getY() >= world.getMaxHeight()) {
return type.defaultLightValue;
}
int arrayX = Coords.blockToCube(pos.getX()) - this.chunkX;
int arrayY = Coords.blockToCube(pos.getY()) - this.cubeY;
int arrayZ = Coords.blockToCube(pos.getZ()) - this.chunkZ;
if (arrayX < 0 || arrayX >= this.cubeArrays.length ||
arrayY < 0 || arrayY >= this.cubeArrays[arrayX].length ||
arrayZ < 0 || arrayZ >= this.cubeArrays[arrayX][arrayY].length) {
return type.defaultLightValue;
}
Cube cube = this.cubeArrays[arrayX][arrayY][arrayZ];
if (cube == null) {
return type.defaultLightValue;
}
return cube.getLightFor(type, pos);
}
@Override
public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean defaultValue) {
//TODO: remove this comment when the bug is fixed in forge: CubicChunks: fix forge bug #3026
if (pos.getY() < world.getMinHeight() || pos.getY() >= world.getMaxHeight()) {
return defaultValue;
}
int arrayX = Coords.blockToCube(pos.getX()) - this.chunkX;
int arrayY = Coords.blockToCube(pos.getY()) - this.cubeY;
int arrayZ = Coords.blockToCube(pos.getZ()) - this.chunkZ;
if (arrayX < 0 || arrayX >= this.cubeArrays.length ||
arrayY < 0 || arrayY >= this.cubeArrays[arrayX].length ||
arrayZ < 0 || arrayZ >= this.cubeArrays[arrayX][arrayY].length) {
return defaultValue;
}
Cube cube = this.cubeArrays[arrayX][arrayY][arrayZ];
if (cube == null) {
return defaultValue;
}
IBlockState state = getBlockState(pos);
return state.getBlock().isSideSolid(state, this, pos, side);
}
}