BlockTintCache.java
net.minecraft.client.color.block.BlockTintCache
信息
- 全限定名:net.minecraft.client.color.block.BlockTintCache
- 类型:public class
- 包:net.minecraft.client.color.block
- 源码路径:src/main/java/net/minecraft/client/color/block/BlockTintCache.java
- 起始行号:L17
- 职责:
TODO
字段/常量
-
MAX_CACHE_ENTRIES- 类型:
int - 修饰符:
private static final - 源码定位:
L18 - 说明:
TODO
- 类型:
-
latestChunkOnThread- 类型:
ThreadLocal<BlockTintCache.LatestCacheInfo> - 修饰符:
private final - 源码定位:
L19 - 说明:
TODO
- 类型:
-
cache- 类型:
Long2ObjectLinkedOpenHashMap<BlockTintCache.CacheData> - 修饰符:
private final - 源码定位:
L20 - 说明:
TODO
- 类型:
-
lock- 类型:
ReentrantReadWriteLock - 修饰符:
private final - 源码定位:
L21 - 说明:
TODO
- 类型:
-
source- 类型:
ToIntFunction<BlockPos> - 修饰符:
private final - 源码定位:
L22 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.color.block.BlockTintCache.CacheData- 类型:
class - 修饰符:
private static - 源码定位:
L120 - 说明:
TODO
- 类型:
-
net.minecraft.client.color.block.BlockTintCache.LatestCacheInfo- 类型:
class - 修饰符:
private static - 源码定位:
L166 - 说明:
TODO
- 类型:
构造器
public BlockTintCache(ToIntFunction<BlockPos> source) @ L24
- 构造器名:BlockTintCache
- 源码定位:L24
- 修饰符:public
参数:
- source: ToIntFunction
说明:
TODO
方法
下面的方法块按源码顺序生成。
public int getColor(BlockPos pos) @ L28
- 方法名:getColor
- 源码定位:L28
- 返回类型:int
- 修饰符:public
参数:
- pos: BlockPos
说明:
TODO
public void invalidateForChunk(int chunkX, int chunkZ) @ L52
- 方法名:invalidateForChunk
- 源码定位:L52
- 返回类型:void
- 修饰符:public
参数:
- chunkX: int
- chunkZ: int
说明:
TODO
public void invalidateAll() @ L70
- 方法名:invalidateAll
- 源码定位:L70
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
private BlockTintCache.CacheData findOrCreateChunkCache(int x, int z) @ L80
- 方法名:findOrCreateChunkCache
- 源码定位:L80
- 返回类型:BlockTintCache.CacheData
- 修饰符:private
参数:
- x: int
- z: int
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class BlockTintCache {
private static final int MAX_CACHE_ENTRIES = 256;
private final ThreadLocal<BlockTintCache.LatestCacheInfo> latestChunkOnThread = ThreadLocal.withInitial(BlockTintCache.LatestCacheInfo::new);
private final Long2ObjectLinkedOpenHashMap<BlockTintCache.CacheData> cache = new Long2ObjectLinkedOpenHashMap<>(256, 0.25F);
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ToIntFunction<BlockPos> source;
public BlockTintCache(ToIntFunction<BlockPos> source) {
this.source = source;
}
public int getColor(BlockPos pos) {
int chunkX = SectionPos.blockToSectionCoord(pos.getX());
int chunkZ = SectionPos.blockToSectionCoord(pos.getZ());
BlockTintCache.LatestCacheInfo chunkInfo = this.latestChunkOnThread.get();
if (chunkInfo.x != chunkX || chunkInfo.z != chunkZ || chunkInfo.cache == null || chunkInfo.cache.isInvalidated()) {
chunkInfo.x = chunkX;
chunkInfo.z = chunkZ;
chunkInfo.cache = this.findOrCreateChunkCache(chunkX, chunkZ);
}
int[] layer = chunkInfo.cache.getLayer(pos.getY());
int x = pos.getX() & 15;
int z = pos.getZ() & 15;
int index = z << 4 | x;
int cached = layer[index];
if (cached != -1) {
return cached;
} else {
int calculated = this.source.applyAsInt(pos);
layer[index] = calculated;
return calculated;
}
}
public void invalidateForChunk(int chunkX, int chunkZ) {
try {
this.lock.writeLock().lock();
for (int offsetX = -1; offsetX <= 1; offsetX++) {
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
long key = ChunkPos.pack(chunkX + offsetX, chunkZ + offsetZ);
BlockTintCache.CacheData removed = this.cache.remove(key);
if (removed != null) {
removed.invalidate();
}
}
}
} finally {
this.lock.writeLock().unlock();
}
}
public void invalidateAll() {
try {
this.lock.writeLock().lock();
this.cache.values().forEach(BlockTintCache.CacheData::invalidate);
this.cache.clear();
} finally {
this.lock.writeLock().unlock();
}
}
private BlockTintCache.CacheData findOrCreateChunkCache(int x, int z) {
long key = ChunkPos.pack(x, z);
this.lock.readLock().lock();
try {
BlockTintCache.CacheData existing = this.cache.get(key);
if (existing != null) {
return existing;
}
} finally {
this.lock.readLock().unlock();
}
this.lock.writeLock().lock();
BlockTintCache.CacheData newCache;
try {
BlockTintCache.CacheData existingNow = this.cache.get(key);
if (existingNow == null) {
newCache = new BlockTintCache.CacheData();
if (this.cache.size() >= 256) {
BlockTintCache.CacheData cacheData = this.cache.removeFirst();
if (cacheData != null) {
cacheData.invalidate();
}
}
this.cache.put(key, newCache);
return newCache;
}
newCache = existingNow;
} finally {
this.lock.writeLock().unlock();
}
return newCache;
}
@OnlyIn(Dist.CLIENT)
private static class CacheData {
private final Int2ObjectArrayMap<int[]> cache = new Int2ObjectArrayMap<>(16);
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private static final int BLOCKS_PER_LAYER = Mth.square(16);
private volatile boolean invalidated;
public int[] getLayer(int y) {
this.lock.readLock().lock();
try {
int[] existing = this.cache.get(y);
if (existing != null) {
return existing;
}
} finally {
this.lock.readLock().unlock();
}
this.lock.writeLock().lock();
int[] var12;
try {
var12 = this.cache.computeIfAbsent(y, n -> this.allocateLayer());
} finally {
this.lock.writeLock().unlock();
}
return var12;
}
private int[] allocateLayer() {
int[] newCache = new int[BLOCKS_PER_LAYER];
Arrays.fill(newCache, -1);
return newCache;
}
public boolean isInvalidated() {
return this.invalidated;
}
public void invalidate() {
this.invalidated = true;
}
}
@OnlyIn(Dist.CLIENT)
private static class LatestCacheInfo {
public int x = Integer.MIN_VALUE;
public int z = Integer.MIN_VALUE;
BlockTintCache.@Nullable CacheData cache;
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SectionPos.blockToSectionCoord()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.square()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ChunkPos.pack()
- 引用位置: