43 private static array $instances = [];
49 $worldId = spl_object_id($world);
50 $compressorId = spl_object_id($compressor);
51 if(!isset(self::$instances[$worldId])){
52 self::$instances[$worldId] = [];
54 foreach(self::$instances[$worldId] as $cache){
57 unset(self::$instances[$worldId]);
58 \GlobalLogger::get()->debug(
"Destroyed chunk packet caches for world#$worldId");
61 if(!isset(self::$instances[$worldId][$compressorId])){
62 \GlobalLogger::get()->debug(
"Created new chunk packet cache (world#$worldId, compressor#$compressorId)");
63 self::$instances[$worldId][$compressorId] =
new self($world, $compressor);
65 return self::$instances[$worldId][$compressorId];
68 public static function pruneCaches() : void{
69 foreach(self::$instances as $compressorMap){
70 foreach($compressorMap as $chunkCache){
71 foreach($chunkCache->caches as $chunkHash => $promise){
72 if($promise->hasResult()){
74 unset($chunkCache->caches[$chunkHash]);
82 private array $caches = [];
84 private int $hits = 0;
85 private int $misses = 0;
87 private function __construct(
89 private Compressor $compressor
98 $this->world->registerChunkListener($this, $chunkX, $chunkZ);
99 $chunk = $this->world->getChunk($chunkX, $chunkZ);
101 throw new \InvalidArgumentException(
"Cannot request an unloaded chunk");
103 $chunkHash = World::chunkHash($chunkX, $chunkZ);
105 if(isset($this->caches[$chunkHash])){
107 return $this->caches[$chunkHash];
112 $this->world->timings->syncChunkSendPrepare->startTiming();
116 $this->world->getServer()->getAsyncPool()->submitTask(
120 DimensionIds::OVERWORLD,
122 $this->caches[$chunkHash],
127 return $this->caches[$chunkHash];
129 $this->world->timings->syncChunkSendPrepare->stopTiming();
133 private function destroy(
int $chunkX,
int $chunkZ) : bool{
134 $chunkHash = World::chunkHash($chunkX, $chunkZ);
135 $existing = $this->caches[$chunkHash] ??
null;
136 unset($this->caches[$chunkHash]);
138 return $existing !==
null;
144 private function destroyOrRestart(
int $chunkX,
int $chunkZ) : void{
145 $chunkPosHash = World::chunkHash($chunkX, $chunkZ);
146 $cache = $this->caches[$chunkPosHash] ??
null;
148 if(!$cache->hasResult()){
151 unset($this->caches[$chunkPosHash]);
153 $this->request($chunkX, $chunkZ)->onResolve(...$cache->getResolveCallbacks());
156 $this->destroy($chunkX, $chunkZ);
161 use ChunkListenerNoOpTrait {
163 onChunkChanged as
private;
164 onBlockChanged as
private;
165 onChunkUnloaded as
private;
172 $this->destroyOrRestart($chunkX, $chunkZ);
181 $this->destroy($block->getFloorX() >>
Chunk::COORD_BIT_SIZE, $block->getFloorZ() >>
Chunk::COORD_BIT_SIZE);
188 $this->destroy($chunkX, $chunkZ);
189 $this->world->unregisterChunkListener($this, $chunkX, $chunkZ);
198 foreach($this->caches as $cache){
199 if($cache->hasResult()){
200 $result += strlen($cache->getResult());
210 $total = $this->hits + $this->misses;
211 return $total > 0 ? $this->hits / $total : 0.0;