Renderer/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java
austin d2ccf3c479
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
rewrite client side chunks + transvoxel integration
2024-11-04 13:51:04 -05:00

153 lines
4.8 KiB
Java

package electrosphere.client.terrain.cache;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3i;
import io.github.studiorailgun.HashUtils;
/**
* Acts as a cache in front of terrain model to streamline receiving chunks
*/
public class ClientTerrainCache {
//cache capacity
int cacheSize;
//the map of chunk key -> chunk data
Map<Long,ChunkData> cacheMap = new ConcurrentHashMap<Long,ChunkData>();
//the list of keys in the cache
List<Long> cacheList = new CopyOnWriteArrayList<Long>();
//A map of chunk to its world position
Map<ChunkData,Vector3i> chunkPositionMap = new ConcurrentHashMap<ChunkData,Vector3i>();
/**
* The map tracking chunks that have been requested
*/
Map<Long,Boolean> requestedChunks = new ConcurrentHashMap<Long,Boolean>();
/**
* Constructor
* @param cacheSize The capacity of the cache
*/
public ClientTerrainCache(int cacheSize){
this.cacheSize = cacheSize;
}
/**
* Adds a chunk data to the terrain cache
* @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @param chunkData The chunk data to add at the specified positions
*/
public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){
cacheMap.put(getKey(worldX,worldY,worldZ),chunkData);
chunkPositionMap.put(chunkData,new Vector3i(worldX,worldY,worldZ));
while(cacheList.size() > cacheSize){
Long currentChunk = cacheList.remove(0);
ChunkData data = cacheMap.remove(currentChunk);
Vector3i worldPos = data.getWorldPos();
requestedChunks.remove(getKey(worldPos.x,worldPos.y,worldPos.z));
}
}
/**
* Evicts all chunks from the cache
*/
public void evictAll(){
this.cacheList.clear();
this.cacheMap.clear();
this.chunkPositionMap.clear();
}
/**
* Generates a key for the cache based on the position provided
* @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @return The cache key
*/
public long getKey(int worldX, int worldY, int worldZ){
return HashUtils.cantorHash(worldX, worldY, worldZ);
}
/**
* Checks whether the cache contains chunk data at a given world point
* @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @return True if the cache contains chunk data at the specified point, false otherwise
*/
public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
return cacheMap.containsKey(getKey(worldX,worldY,worldZ));
}
/**
* Gets chunk data at the given world point
* @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @return The chunk data if it exists, null otherwise
*/
public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ){
return cacheMap.get(getKey(worldX,worldY,worldZ));
}
/**
* Gets the list of all chunks in the cache
* @return The list of all chunks in the cache
*/
public Collection<ChunkData> getAllChunks(){
return this.cacheMap.values();
}
/**
* Gets the world position of a chunk
* @param chunk The chunk
* @return The world position of the chunk
*/
public Vector3i getChunkPosition(ChunkData chunk){
return chunkPositionMap.get(chunk);
}
/**
* Gets the number of cells that have been requested
* @return The number of cells that have been requested
*/
public int getRequestedCellCount(){
return this.requestedChunks.size();
}
/**
* Checks if a chunk has been requested or not
* @param worldX The x coordinate in the world
* @param worldY The y coordinate in the world
* @param worldZ The z coordinate in the world
* @return true if it has been requested, false otherwise
*/
public boolean hasRequested(int worldX, int worldY, int worldZ){
return this.requestedChunks.containsKey(getKey(worldX, worldY, worldZ));
}
/**
* Marks a chunk as requested
* @param worldX The x coordinate in the world
* @param worldY The y coordinate in the world
* @param worldZ The z coordinate in the world
*/
public void markAsRequested(int worldX, int worldY, int worldZ){
this.requestedChunks.put(getKey(worldX, worldY, worldZ),true);
}
}