animated-chunks/src/main/java/me/topchetoeu/animatedchunks/animation/ProgressManager.java

147 lines
4.8 KiB
Java

package me.topchetoeu.animatedchunks.animation;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
public final class ProgressManager {
public static class ChunkLoc {
public final int x;
public final int y;
public final int z;
@Override
public boolean equals(Object obj) {
return obj instanceof ChunkLoc && ((ChunkLoc)obj).x == x && ((ChunkLoc)obj).y == y && ((ChunkLoc)obj).z == z;
}
@Override
public int hashCode() {
return 137 * x + 149 * y + 163 * z;
}
public ChunkLoc(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
private Hashtable<ChunkLoc, Float> chunkToStage = new Hashtable<>();
private HashSet<ChunkLoc> chunks = new HashSet<>();
private float duration = 1;
public ProgressManager() {
}
public float getDuration() {
return duration;
}
public void setDuration(float duration) {
this.duration = duration;
}
/**
* Removes all loaded chunks (called when a world is unloaded and loaded)
*/
public void reset() {
chunkToStage.clear();
chunks.clear();
}
/**
* Advances the animation for all tracked chunks, according to the duration and the specified delta
* @param delta The second delta to advance the animation by
*/
public void tick(float delta) {
for (ChunkLoc loc : new ArrayList<>(chunkToStage.keySet())) {
float val = chunkToStage.get(loc);
val += delta / duration;
if (val > 1f) chunkToStage.remove(loc);
chunkToStage.put(loc, val);
}
}
/**
* Loads a specified chunk (starts tracking its animation)
* @param x The x of the chunk
* @param y The y of the chunk
* @param y The z of the chunk
*/
public void load(int x, int y, int z) {
if (isChunkLoaded(x, y, z)) return;
ChunkLoc loc = new ChunkLoc(x, y, z);
chunks.add(loc);
chunkToStage.put(loc, 0f);
}
/**
* Unloads a specified chunk (stops tracking its animation)
* @param x The x of the chunk
* @param y The y of the chunk
* @param y The z of the chunk
*/
public void unload(int x, int y, int z) {
ChunkLoc loc = new ChunkLoc(x, y, z);
chunkToStage.remove(loc);
chunks.remove(loc);
}
/**
* Unloads all loaded chunks
*/
public void unloadAll() {
chunkToStage.clear();
chunks.clear();
}
/**
* Unloads all the chunks that are outside the render distance specified
* @param viewDistance The view distance (in chunks, radius)
* @param playerChunkX The x coordinate of the chunk in which the player stands
* @param playerChunkY The y coordinate of the chunk in which the player stands
* @param playerChunkZ The z coordinate of the chunk in which the player stands
*/
public void unloadAllFar(int viewDistance, int playerChunkX, int playerChunkY, int playerChunkZ) {
float circleVD = viewDistance + 1.38f;
int squareVD = viewDistance;
for (ChunkLoc loc : new ArrayList<>(chunks)) {
int chunkX = loc.x / 16;
int chunkZ = loc.z / 16;
int diffSquareX = playerChunkX - chunkX ;
int diffSquareZ = playerChunkZ - chunkZ;
int diffCircleX = playerChunkX - chunkX;
int diffCircleZ = playerChunkZ - chunkZ;
int dist = diffCircleX * diffCircleX + diffCircleZ * diffCircleZ;
if (dist > circleVD * circleVD) unload(loc.x, loc.y, loc.z);
if (Math.abs(diffSquareX) > squareVD || Math.abs(diffSquareZ) > squareVD) unload(loc.x, loc.y, loc.z);
}
}
/**
* Checks whether or not a chunk is loaded
* @param x The x of the chunk
* @param y The y of the chunk
* @param y The z of the chunk
* @return A value indicating whether or not the specified chunk is tracked
*/
public boolean isChunkLoaded(int x, int y, int z) {
return chunks.contains(new ChunkLoc(x, y, z));
}
/**
* Gets the animation progress of the specified chunk
* @param x The x of the chunk
* @param y The y of the chunk
* @param y The z of the chunk
* @return A float value from 0 to 1 (0 if the chunk is not tracked), indicating the animation progress of the specified chunk
*/
public float getChunkProgress(int x, int y, int z) {
if (!isChunkLoaded(x, y, z)) return 0f;
if (!chunkToStage.containsKey(new ChunkLoc(x, y, z))) return 1f;
return chunkToStage.get(new ChunkLoc(x, y, z));
}
}