/*
* 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.visibility;
import net.minecraft.util.math.ChunkPos;
import java.util.Set;
import java.util.function.Consumer;
import cubicchunks.util.CubePos;
public class CuboidalCubeSelector extends CubeSelector {
@Override
public void forAllVisibleFrom(CubePos cubePos, int horizontalViewDistance, int verticalViewDistance, Consumer<CubePos> consumer) {
int cubeX = cubePos.getX();
int cubeY = cubePos.getY();
int cubeZ = cubePos.getZ();
for (int x = cubeX - horizontalViewDistance; x <= cubeX + horizontalViewDistance; x++) {
for (int y = cubeY - verticalViewDistance; y <= cubeY + verticalViewDistance; y++) {
for (int z = cubeZ - horizontalViewDistance; z <= cubeZ + horizontalViewDistance; z++) {
consumer.accept(new CubePos(x, y, z));
}
}
}
}
@Override
public void findChanged(CubePos oldPos, CubePos newPos,
int horizontalViewDistance, int verticalViewDistance,
Set<CubePos> cubesToRemove, Set<CubePos> cubesToLoad,
Set<ChunkPos> columnsToRemove, Set<ChunkPos> columnsToLoad) {
int oldX = oldPos.getX();
int oldY = oldPos.getY();
int oldZ = oldPos.getZ();
int newX = newPos.getX();
int newY = newPos.getY();
int newZ = newPos.getZ();
int dx = newX - oldX;
int dy = newY - oldY;
int dz = newZ - oldZ;
for (int currentX = newX - horizontalViewDistance; currentX <= newX + horizontalViewDistance; ++currentX) {
for (int currentZ = newZ - horizontalViewDistance; currentZ <= newZ + horizontalViewDistance; ++currentZ) {
//first handle columns
//is current position outside of the old render distance square?
if (!this.isPointWithinCubeVolume(oldX, 0, oldZ, currentX, 0, currentZ, horizontalViewDistance, verticalViewDistance)) {
columnsToLoad.add(new ChunkPos(currentX, currentZ));
}
//if we moved the current point to where it would be previously,
//would it be outside of current render distance square?
if (!this.isPointWithinCubeVolume(newX, 0, newZ, currentX - dx, 0, currentZ - dz, horizontalViewDistance, verticalViewDistance)) {
columnsToRemove.add(new ChunkPos(currentX - dx, currentZ - dz));
}
for (int currentY = newY - verticalViewDistance; currentY <= newY + verticalViewDistance; ++currentY) {
//now handle cubes, the same way
if (!this.isPointWithinCubeVolume(oldX, oldY, oldZ, currentX, currentY, currentZ,
horizontalViewDistance, verticalViewDistance)) {
cubesToLoad.add(new CubePos(currentX, currentY, currentZ));
}
if (!this.isPointWithinCubeVolume(newX, newY, newZ, currentX - dx, currentY - dy, currentZ - dz,
horizontalViewDistance, verticalViewDistance)) {
cubesToRemove.add(new CubePos(currentX - dx, currentY - dy, currentZ - dz));
}
}
}
}
assert cubesToLoad.stream().allMatch(pos -> !cubesToRemove.contains(pos)) : "cubesToRemove contains element from cubesToLoad!";
assert columnsToLoad.stream().allMatch(pos -> !columnsToRemove.contains(pos)) : "columnsToRemove contains element from columnsToLoad!";
}
@Override
public void findAllUnloadedOnViewDistanceDecrease(CubePos playerPos,
int oldHorizontalViewDistance, int newHorizontalViewDistance,
int oldVerticalViewDistance, int newVerticalViewDistance,
Set<CubePos> cubesToUnload, Set<ChunkPos> columnsToUnload) {
int playerCubeX = playerPos.getX();
int playerCubeY = playerPos.getY();
int playerCubeZ = playerPos.getZ();
for (int cubeX = playerCubeX - oldHorizontalViewDistance; cubeX <= playerCubeX + oldHorizontalViewDistance; cubeX++) {
for (int cubeZ = playerCubeZ - oldHorizontalViewDistance; cubeZ <= playerCubeZ + oldHorizontalViewDistance; cubeZ++) {
if (!isPointWithinCubeVolume(playerCubeX, 0, playerCubeZ, cubeX, 0, cubeZ, newHorizontalViewDistance, newVerticalViewDistance)) {
columnsToUnload.add(new ChunkPos(cubeX, cubeZ));
}
for (int cubeY = playerCubeY - oldVerticalViewDistance; cubeY <= playerCubeY + oldVerticalViewDistance; cubeY++) {
if (!isPointWithinCubeVolume(playerCubeX, playerCubeY, playerCubeZ, cubeX, cubeY, cubeZ, newHorizontalViewDistance, newVerticalViewDistance)) {
cubesToUnload.add(new CubePos(cubeX, cubeY, cubeZ));
}
}
}
}
}
private boolean isPointWithinCubeVolume(int cubeX, int cubeY, int cubeZ, int pointX, int pointY, int pointZ, int horizontal, int vertical) {
int dx = cubeX - pointX;
int dy = cubeY - pointY;
int dz = cubeZ - pointZ;
return dx >= -horizontal && dx <= horizontal
&& dy >= -vertical && dy <= vertical
&& dz >= -horizontal && dz <= horizontal;
}
}