ChunkLoadState class
Пакет: com.hypixel.hytale.server.core.universe.world.storage
Файл: com/hypixel/hytale/server/core/universe/world/storage/ChunkStore.java
extends: ChunkStore.LoadState
Поля (1)
| Модификаторы | Тип | Имя |
|---|---|---|
|
final AtomicInteger |
loadedSectionCount |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe.world.storage;
class="kw">import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.KeyedCodec;
class="kw">import com.hypixel.hytale.codec.builder.BuilderCodec;
class="kw">import com.hypixel.hytale.codec.store.CodecKey;
class="kw">import com.hypixel.hytale.codec.store.CodecStore;
class="kw">import com.hypixel.hytale.common.util.FormatUtil;
class="kw">import com.hypixel.hytale.component.AddReason;
class="kw">import com.hypixel.hytale.component.Component;
class="kw">import com.hypixel.hytale.component.ComponentRegistry;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.Holder;
class="kw">import com.hypixel.hytale.component.IResourceStorage;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.RemoveReason;
class="kw">import com.hypixel.hytale.component.Resource;
class="kw">import com.hypixel.hytale.component.ResourceType;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.component.SystemGroup;
class="kw">import com.hypixel.hytale.component.SystemType;
class="kw">import com.hypixel.hytale.component.system.StoreSystem;
class="kw">import com.hypixel.hytale.component.system.data.EntityDataSystem;
class="kw">import com.hypixel.hytale.event.IEventDispatcher;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.math.data.Int3ObjectOpenHashMap;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.metrics.MetricProvider;
class="kw">import com.hypixel.hytale.metrics.MetricsRegistry;
class="kw">import com.hypixel.hytale.protocol.ToClientPacket;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.WorldProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.ChunkFlag;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.ChunkSection;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.section.EntitySection;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.ChunkSectionPreLoadProcessEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.component.ChunkSavingSystems;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.component.ChunkUnloadingSystem;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.component.SectionUnloadingSystem;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.IChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.GeneratedChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.IWorldGen;
class="kw">import com.hypixel.hytale.sneakythrow.SneakyThrow;
class="kw">import it.unimi.dsi.fastutil.longs.LongPredicate;
class="kw">import it.unimi.dsi.fastutil.longs.LongSet;
class="kw">import it.unimi.dsi.fastutil.longs.LongSets;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectIterator;
class="kw">import java.io.IOException;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.atomic.AtomicInteger;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class ChunkStore class="kw">implements WorldProvider {
@Nonnull
class="kw">public class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
class="kw">public class="kw">static class="kw">final MetricsRegistry<ChunkStore> METRICS_REGISTRY = new MetricsRegistry<ChunkStore>()
.register("Store", ChunkStore::getStore, Store.METRICS_REGISTRY)
.register("ChunkLoader", MetricProvider.maybe(ChunkStore::getLoader))
.register("ChunkSaver", MetricProvider.maybe(ChunkStore::getSaver))
.register("WorldGen", MetricProvider.maybe(ChunkStore::getGenerator))
.register("SaveQueue", var0 -> var0.getStore().getResource(ChunkStore.SAVE_RESOURCE), ChunkSavingSystems.Data.METRICS_REGISTRY)
.register("TotalGeneratedChunkCount", var0 -> (long)var0.totalGeneratedChunksCount.get(), Codec.LONG)
.register("TotalLoadedChunkCount", var0 -> (long)var0.totalLoadedChunksCount.get(), Codec.LONG);
class="kw">public class="kw">static class="kw">final long MAX_FAILURE_BACKOFF_NANOS = TimeUnit.SECONDS.toNanos(10L);
class="kw">public class="kw">static class="kw">final long FAILURE_BACKOFF_NANOS = TimeUnit.MILLISECONDS.toNanos(1L);
class="kw">public class="kw">static class="kw">final ComponentRegistry<ChunkStore> REGISTRY = new ComponentRegistry<>();
class="kw">public class="kw">static class="kw">final CodecKey<Holder<ChunkStore>> HOLDER_CODEC_KEY = new CodecKey<>("ChunkHolder");
@Nonnull
class="kw">public class="kw">static class="kw">final SystemType<ChunkStore, ChunkStore.LoadPacketDataQuerySystem> LOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE = REGISTRY.registerSystemType(
ChunkStore.LoadPacketDataQuerySystem.class
);
@Nonnull
class="kw">public class="kw">static class="kw">final SystemType<ChunkStore, ChunkStore.LoadFuturePacketDataQuerySystem> LOAD_FUTURE_PACKETS_DATA_QUERY_SYSTEM_TYPE = REGISTRY.registerSystemType(
ChunkStore.LoadFuturePacketDataQuerySystem.class
);
@Nonnull
class="kw">public class="kw">static class="kw">final SystemType<ChunkStore, ChunkStore.UnloadPacketDataQuerySystem> UNLOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE = REGISTRY.registerSystemType(
ChunkStore.UnloadPacketDataQuerySystem.class
);
@Nonnull
class="kw">public class="kw">static class="kw">final ResourceType<ChunkStore, ChunkUnloadingSystem.Data> UNLOAD_RESOURCE = REGISTRY.registerResource(
ChunkUnloadingSystem.Data.class, ChunkUnloadingSystem.Data::new
);
@Nonnull
class="kw">public class="kw">static class="kw">final ResourceType<ChunkStore, SectionUnloadingSystem.Data> SECTION_UNLOAD_RESOURCE = REGISTRY.registerResource(
SectionUnloadingSystem.Data.class, SectionUnloadingSystem.Data::new
);
@Nonnull
class="kw">public class="kw">static class="kw">final ResourceType<ChunkStore, ChunkSavingSystems.Data> SAVE_RESOURCE = REGISTRY.registerResource(
ChunkSavingSystems.Data.class, ChunkSavingSystems.Data::new
);
class="kw">public class="kw">static class="kw">final SystemGroup<ChunkStore> INIT_GROUP = REGISTRY.registerSystemGroup();
@Nonnull
class="kw">private class="kw">final World world;
@Nonnull
class="kw">private class="kw">final Long2ObjectConcurrentHashMap<ChunkStore.ChunkLoadState> chunks = new Long2ObjectConcurrentHashMap<>(true, ChunkUtil.NOT_FOUND);
class="kw">private class="kw">final StampedLock lock = new StampedLock();
class="kw">private class="kw">final Int3ObjectOpenHashMap<ChunkStore.LoadState> chunkSections = new Int3ObjectOpenHashMap<>();
class="kw">private Store<ChunkStore> store;
class="kw">private Object storageData;
@Nullable
class="kw">private Runnable pendingStorageMigration;
@Nullable
class="kw">private IChunkLoader loader;
@Nullable
class="kw">private IChunkSaver saver;
@Nullable
class="kw">private IWorldGen generator;
@Nonnull
class="kw">private CompletableFuture<Void> generatorLoaded = new CompletableFuture<>();
class="kw">private class="kw">final StampedLock generatorLock = new StampedLock();
class="kw">private class="kw">final AtomicInteger totalGeneratedChunksCount = new AtomicInteger();
class="kw">private class="kw">final AtomicInteger totalLoadedChunksCount = new AtomicInteger();
class="kw">public ChunkStore(@Nonnull World var1) {
this.world = var1;
}
@Nonnull
@Override
class="kw">public World getWorld() {
class="kw">return this.world;
}
@Nonnull
class="kw">public Store<ChunkStore> getStore() {
class="kw">return this.store;
}
class="kw">public Object getStorageData() {
class="kw">return this.storageData;
}
@Nullable
class="kw">public IChunkLoader getLoader() {
class="kw">return this.loader;
}
@Nullable
class="kw">public IChunkSaver getSaver() {
class="kw">return this.saver;
}
@Nullable
class="kw">public IWorldGen getGenerator() {
long var1 = this.generatorLock.readLock();
try {
class="kw">return this.generator;
} class="kw">finally {
this.generatorLock.unlockRead(var1);
}
}
class="kw">public boolean supportsCubicSections() {
if (this.loader class="kw">instanceof IChunkLoader.Cubic) {
class="kw">return true;
}
long var1 = this.generatorLock.readLock();
try {
class="kw">return this.generator class="kw">instanceof IWorldGen.Cubic;
} class="kw">finally {
this.generatorLock.unlockRead(var1);
}
}
class="kw">public void shutdownGenerator() {
this.setGenerator(null);
}
class="kw">public void setGenerator(@Nullable IWorldGen var1) {
long var2 = this.generatorLock.writeLock();
try {
if (this.generator != null) {
this.generator.shutdown();
}
this.totalGeneratedChunksCount.set(0);
this.generator = var1;
if (var1 != null) {
this.generatorLoaded.complete(null);
this.generatorLoaded = new CompletableFuture<>();
}
} class="kw">finally {
this.generatorLock.unlockWrite(var2);
}
}
@Nonnull
class="kw">public LongSet getChunkIndexes() {
class="kw">return LongSets.unmodifiable(this.chunks.keySet());
}
class="kw">public int getLoadedChunksCount() {
class="kw">return this.chunks.size();
}
class="kw">public int getTotalGeneratedChunksCount() {
class="kw">return this.totalGeneratedChunksCount.get();
}
class="kw">public int getTotalLoadedChunksCount() {
class="kw">return this.totalLoadedChunksCount.get();
}
class="kw">public void start(@Nonnull IResourceStorage var1) {
this.store = REGISTRY.addStore(this, var1, var1x -> this.store = var1x);
if (this.pendingStorageMigration != null) {
Runnable var2 = this.pendingStorageMigration;
this.pendingStorageMigration = null;
var2.run();
}
}
class="kw">public void waitForLoadingChunks() {
long var1 = System.nanoTime();
boolean var3;
do {
this.world.consumeTaskQueue();
Thread.yield();
var3 = false;
ObjectIterator var4 = this.chunks.long2ObjectEntrySet().iterator();
while (var4.hasNext()) {
Entry var5 = (Entry<ChunkStore.ChunkLoadState>)var4.next();
ChunkStore.ChunkLoadState var6 = (ChunkStore.ChunkLoadState)var5.getValue();
long var7 = var6.lock.readLock();
try {
CompletableFuture var9 = var6.future;
if (var9 != null && !var9.isDone()) {
var3 = true;
break;
}
} class="kw">finally {
var6.lock.unlockRead(var7);
}
}
} while (var3 && System.nanoTime() - var1 <= 5000000000L);
this.world.consumeTaskQueue();
}
class="kw">public void shutdown() {
this.store.shutdown();
this.chunks.clear();
}
@Nonnull
class="kw">private Ref<ChunkStore> add(@Nonnull Holder<ChunkStore> var1) {
this.world.debugAssertInTickingThread();
WorldChunk var2 = var1.getComponent(WorldChunk.getComponentType());
assert var2 != null;
ChunkStore.ChunkLoadState var3 = this.chunks.get(var2.getIndex());
if (var3 == null) {
throw new IllegalStateException("Expected the ChunkLoadState to exist!");
}
Ref var4 = null;
long var5 = var3.lock.writeLock();
try {
if (var3.future == null) {
throw new IllegalStateException("Expected the ChunkLoadState to have a future!");
}
if (var3.reference != null) {
var4 = var3.reference;
var3.reference = null;
}
} class="kw">finally {
var3.lock.unlockWrite(var5);
}
if (var4 != null) {
WorldChunk var7 = this.store.getComponent(var4, WorldChunk.getComponentType());
assert var7 != null;
if (var3.loadedSectionCount.get() > 10) {
int var8 = var2.getX();
int var9 = var2.getZ();
ObjectArrayList var10 = new ObjectArrayList();
long var11 = this.lock.readLock();
try {
this.chunkSections.forEach((var3x, var4x, var5x, var6x) -> {
if (var3x == var8 && var5x == var9 && (var4x < 0 || var4x >= 10)) {
Ref var7 = var6x.reference;
if (var7 != null && var7.isValid()) {
var10.add(var7);
}
}
});
} class="kw">finally {
this.lock.unlockRead(var11);
}
for (int var13 = 0; var13 < var10.size(); var13++) {
this.removeSection((Ref<ChunkStore>)var10.get(var13), RemoveReason.REMOVE);
}
}
var7.setFlag(ChunkFlag.TICKING, false);
this.store.removeEntity(var4, RemoveReason.REMOVE);
int var31 = var3.loadedSectionCount.addAndGet(-10);
if (var31 != 0) {
throw new IllegalStateException(
"Expected loadedSectionCount == 0 after column replacement at " + var2.getX() + ", " + var2.getZ() + ", got " + var31
);
}
this.world.getNotificationHandler().updateChunk(var2.getIndex());
}
ChunkColumn var28 = var1.ensureAndGetComponent(ChunkColumn.getComponentType());
Ref var29 = this.store.addEntity(var1, AddReason.SPAWN);
if (var29 == null) {
throw new UnsupportedOperationException("Unable to add the chunk to the world!");
}
Ref[] var6 = var28.getSections();
Holder[] var30 = var28.takeSectionHolders();
Holder[] var32 = new Holder[var6.length];
boolean var33 = var2.is(ChunkFlag.TICKING);
boolean var34 = var2.is(ChunkFlag.NEEDS_FORMAT_REWRITE);
for (int var35 = 0; var35 < var6.length; var35++) {
Holder var12 = var30[var35];
var32[var35] = var12;
var6[var35] = this.postLoadChunkSection(var29, var2.getX(), var35, var2.getZ(), var12, var2.is(ChunkFlag.NEWLY_GENERATED), var33);
if (var34 && var6[var35] != null && var6[var35].isValid()) {
ChunkSection var38 = this.store.getComponent(var6[var35], ChunkSection.getComponentType());
if (var38 != null) {
var38.markNeedsSaving();
}
EntitySection var14 = this.store.getComponent(var6[var35], EntitySection.getComponentType());
if (var14 != null) {
var14.markNeedsSaving();
}
}
}
BlockChunk var36 = var1.getComponent(BlockChunk.getComponentType());
if (var36 != null) {
var36.refreshSectionRefs(var32);
}
if (var34) {
var2.markNeedsSaving();
var2.setFlag(ChunkFlag.NEEDS_FORMAT_REWRITE, false);
}
var2.setReference(var29);
long stampx = var3.lock.writeLock();
try {
var3.reference = var29;
var3.flags = 0;
var3.future = null;
var3.throwable = null;
var3.failedWhen = 0L;
var3.failedCounter = 0;
class="kw">return var29;
} class="kw">finally {
var3.lock.unlockWrite(stampx);
}
}
class="kw">public void remove(@Nonnull Ref<ChunkStore> var1, @Nonnull RemoveReason var2) {
this.world.debugAssertInTickingThread();
WorldChunk var3 = this.store.getComponent(var1, WorldChunk.getComponentType());
assert var3 != null;
long var4 = var3.getIndex();
ChunkStore.ChunkLoadState var6 = this.chunks.get(var4);
long var7 = var6.lock.writeLock();
try {
var3.setFlag(ChunkFlag.TICKING, false);
this.store.removeEntity(var1, var2);
var6.reference = null;
if (var6.future == null) {
this.chunks.remove(var4, var6);
}
long var9 = this.lock.writeLock();
try {
for (int var11 = 0; var11 < 10; var11++) {
ChunkStore.LoadState var12 = this.chunkSections.get(var3.getX(), var11, var3.getZ());
if (var12 != null) {
if (var12.reference != null && var12.reference.isValid()) {
throw new IllegalStateException("Section reference was failed to be removed");
}
var12.reference = null;
if (var12.future == null) {
this.chunkSections.remove(var3.getX(), var11, var3.getZ());
}
}
}
} class="kw">finally {
this.lock.unlockWrite(var9);
}
int var21 = var6.loadedSectionCount.addAndGet(-10);
if (var21 != 0) {
throw new IllegalStateException("Expected loadedSectionCount == 0 after column unload at " + var3.getX() + ", " + var3.getZ() + ", got " + var21);
}
} class="kw">finally {
var6.lock.unlockWrite(var7);
}
}
class="kw">public void removeSection(@Nonnull Ref<ChunkStore> var1, @Nonnull RemoveReason var2) {
this.world.debugAssertInTickingThread();
ChunkSection var3 = this.store.getComponent(var1, ChunkSection.getComponentType());
assert var3 != null;
int var4 = var3.getX();
int var5 = var3.getY();
int var6 = var3.getZ();
this.store.ensureComponent(var1, REGISTRY.getNonTickingComponentType());
long var8 = this.lock.readLock();
ChunkStore.LoadState var7;
try {
var7 = this.chunkSections.get(var4, var5, var6);
} class="kw">finally {
this.lock.unlockRead(var8);
}
if (var7 == null) {
this.store.removeEntity(var1, var2);
} else {
long var10 = var7.lock.writeLock();
try {
this.store.removeEntity(var1, var2);
var7.reference = null;
long var12 = this.lock.writeLock();
try {
assert var7.future == null : "removeSection raced an in-flight section load at " + var4 + ", " + var5 + ", " + var6;
this.chunkSections.remove(var4, var5, var6);
} class="kw">finally {
this.lock.unlockWrite(var12);
}
} class="kw">finally {
var7.lock.unlockWrite(var10);
}
}
ChunkStore.ChunkLoadState var28 = this.chunks.get(ChunkUtil.indexChunk(var4, var6));
if (var28 != null) {
var28.loadedSectionCount.decrementAndGet();
}
}
@Nullable
class="kw">public Ref<ChunkStore> getChunkReference(long var1) {
ChunkStore.ChunkLoadState var3 = this.chunks.get(var1);
if (var3 == null) {
class="kw">return null;
}
long var4 = var3.lock.tryOptimisticRead();
Ref var6 = var3.reference;
if (var3.lock.validate(var4)) {
class="kw">return var6;
}
var4 = var3.lock.readLock();
try {
class="kw">return var3.reference;
} class="kw">finally {
var3.lock.unlockRead(var4);
}
}
class="kw">public boolean hasLoadedSections(long var1) {
ChunkStore.ChunkLoadState var3 = this.chunks.get(var1);
class="kw">return var3 != null && var3.loadedSectionCount.get() > 10;
}
@Nullable
class="kw">public Ref<ChunkStore> getChunkSectionReference(int var1, int var2, int var3) {
long var4 = this.lock.readLock();
ChunkStore.LoadState var6;
try {
var6 = this.chunkSections.get(var1, var2, var3);
} class="kw">finally {
this.lock.unlockRead(var4);
}
if (var6 == null) {
class="kw">return null;
}
long var7 = var6.lock.tryOptimisticRead();
Ref var9 = var6.reference;
if (var6.lock.validate(var7)) {
class="kw">return var9;
}
var7 = var6.lock.readLock();
try {
class="kw">return var6.reference;
} class="kw">finally {
var6.lock.unlockRead(var7);
}
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkSectionReferenceAsync(int var1, int var2, int var3) {
class="kw">return this.getChunkSectionReferenceAsync(var1, var2, var3, 0);
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkSectionReferenceAsync(int var1, int var2, int var3, int var4) {
if ((var4 & 3) == 3) {
long var35 = this.lock.readLock();
ChunkStore.LoadState var7;
try {
var7 = this.chunkSections.get(var1, var2, var3);
} class="kw">finally {
this.lock.unlockRead(var35);
}
if (var7 == null) {
class="kw">return CompletableFuture.completedFuture(null);
}
long var36 = var7.lock.tryOptimisticRead();
Ref var10 = var7.reference;
if (var7.lock.validate(var36) && var10 != null) {
class="kw">return CompletableFuture.completedFuture(var10);
}
var36 = var7.lock.readLock();
try {
if (var7.reference != null) {
class="kw">return CompletableFuture.completedFuture(var7.reference);
} else {
class="kw">return var7.future == null ? CompletableFuture.completedFuture(null) : var7.future;
}
} class="kw">finally {
var7.lock.unlockRead(var36);
}
} else {
long var6 = this.lock.writeLock();
ChunkStore.LoadState var5;
try {
var5 = this.chunkSections.get(var1, var2, var3);
if (var5 == null) {
this.chunkSections.put(var1, var2, var3, var5 = new ChunkStore.LoadState());
}
} class="kw">finally {
this.lock.unlockWrite(var6);
}
ChunkStore.LoadState var8 = var5;
long var9 = var5.lock.writeLock();
try {
if (var5.checkAndResetBackoff()) {
class="kw">return CompletableFuture.failedFuture(new RuntimeException("Chunk section failure backoff", var5.throwable));
}
if (var5.future == null && var5.reference != null) {
Ref var38 = var5.reference;
if ((var4 & 4) == 0) {
class="kw">return CompletableFuture.completedFuture(var38);
}
var5.lock.unlockWrite(var9);
var9 = 0L;
if (this.world.isInThread() && (var4 & -2147483648) == 0) {
if (var38.isValid()) {
this.store.tryRemoveComponent(var38, REGISTRY.getNonTickingComponentType());
}
class="kw">return CompletableFuture.completedFuture(var38);
} else {
class="kw">return CompletableFuture.supplyAsync(() -> {
if (var38.isValid()) {
this.store.tryRemoveComponent(var38, REGISTRY.getNonTickingComponentType());
}
class="kw">return var38;
}, this.world);
}
} else {
boolean var11 = var5.future == null;
if (var11) {
var5.flags = var4;
}
if ((var4 & 32) != 0) {
var5.flags |= 32;
}
if (var11) {
var5.future = this.getChunkReferenceAsync(ChunkUtil.indexChunk(var1, var3), var4).thenApply(var1x -> var8.reference).exceptionally(var1x -> {
var8.fail(var1x);
throw SneakyThrow.sneakyThrow(var1x);
});
}
if ((var11 || (var5.flags & 1) != 0) && (var4 & 1) == 0) {
if (!var11) {
var5.flags &= -2;
}
var5.future = var5.future
.thenCompose(
var6x -> {
if (var6x != null) {
class="kw">return CompletableFuture.completedFuture((Ref<ChunkStore>)var6x);
} else {
class="kw">return this.loader class="kw">instanceof IChunkLoader.Cubic var7
? var7.loadSectionHolder(var1, var2, var3)
.thenApplyAsync(
var4x -> var4x != null && !this.store.isShutdown()
? this.preLoadChunkSectionAsync((Holder<ChunkStore>)var4x, var1, var2, var3, false)
: null
)
.thenApplyAsync(var5x -> {
if (var5x != null && !this.store.isShutdown()) {
boolean var6 = (var4 & 4) != 0;
class="kw">return this.postLoadChunkSection(null, var1, var2, var3, (Holder<ChunkStore>)var5x, false, var6);
} else {
class="kw">return null;
}
}, this.world)
.exceptionally(var4x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var4x))
.log("Failed to load chunk section! %d, %d, %d", var1, var2, var3);
var8.fail(var4x);
throw SneakyThrow.sneakyThrow(var4x);
})
: CompletableFuture.completedFuture(null);
}
}
);
}
if ((var11 || (var5.flags & 2) != 0) && (var4 & 2) == 0) {
if (!var11) {
var5.flags &= -3;
}
int var12 = (int)this.world.getWorldConfig().getSeed();
var5.future = var5.future
.thenCompose(
var7x -> {
if (var7x != null) {
class="kw">return CompletableFuture.completedFuture((Ref<ChunkStore>)var7x);
}
IWorldGen.StillNeededSection var8 = (var4 & 16) != 0 ? this::isSectionStillNeeded : null;
long var10 = this.generatorLock.readLock();
CompletableFuture var9;
try {
if (this.generator == null) {
var9 = this.generatorLoaded
.thenCompose(
var6x -> this.loader class="kw">instanceof IChunkLoader.Cubic && this.generator class="kw">instanceof IWorldGen.Cubic var7
? var7.generate(var12, var1, var2, var3, var8, this::fetchSectionPriority)
: CompletableFuture.completedFuture(null)
);
} else {
if (!(this.loader class="kw">instanceof IChunkLoader.Cubic && this.generator class="kw">instanceof IWorldGen.Cubic var12)) {
class="kw">return CompletableFuture.completedFuture(null);
}
var9 = var12.generate(var12, var1, var2, var3, var8, this::fetchSectionPriority);
}
} class="kw">finally {
this.generatorLock.unlockRead(var10);
}
class="kw">return var9.<Holder<ChunkStore>>thenApplyAsync(
var4x -> var4x != null && !this.store.isShutdown()
? this.preLoadChunkSectionAsync((Holder<ChunkStore>)var4x, var1, var2, var3, true)
: null
)
.thenApplyAsync(var5x -> {
if (var5x != null && !this.store.isShutdown()) {
boolean var6 = (var4 & 4) != 0;
class="kw">return this.postLoadChunkSection(null, var1, var2, var3, (Holder<ChunkStore>)var5x, true, var6);
} else {
class="kw">return null;
}
}, this.world)
.exceptionally(var4x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var4x))
.log("Failed to generate chunk section! %d, %d, %d", var1, var2, var3);
var8.fail(var4x);
throw SneakyThrow.sneakyThrow(var4x);
});
}
);
}
if ((var11 || (var5.flags & 4) == 0) && (var4 & 4) != 0) {
var5.flags |= 4;
var5.future = var5.future.thenApplyAsync(var0 -> {
if (var0 != null && var0.isValid()) {
var0.getStore().tryRemoveComponent((Ref<ChunkStore>)var0, REGISTRY.getNonTickingComponentType());
}
class="kw">return var0;
}, this.world);
}
if (!var5.cleanupAttached) {
var5.cleanupAttached = true;
var5.future = var5.future
.whenCompleteAsync(
(var5x, var6x) -> {
if (var6x == null && var5x == null) {
try {
long var7 = var8.lock.writeLock();
try {
if (var8.reference == null) {
long var9 = this.lock.writeLock();
try {
ChunkStore.LoadState var11 = this.chunkSections.get(var1, var2, var3);
if (var11 == var8) {
this.chunkSections.remove(var1, var2, var3);
var8.future = null;
}
class="kw">return;
} class="kw">finally {
this.lock.unlockWrite(var9);
}
}
} class="kw">finally {
var8.lock.unlockWrite(var7);
}
} catch (Throwable var22) {
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(var22))
.log("Failed to clean up empty section state %d, %d, %d", var1, var2, var3);
}
}
},
this.world
);
}
class="kw">return var5.future;
}
} class="kw">finally {
if (var9 != 0L) {
var5.lock.unlockWrite(var9);
}
}
}
}
@Nonnull
class="kw">private Holder<ChunkStore> preLoadChunkSectionAsync(@Nonnull Holder<ChunkStore> var1, int var2, int var3, int var4, boolean var5) {
if (!var1.getArchetype().contains(ChunkSection.getComponentType())) {
var1.putComponent(ChunkSection.getComponentType(), new ChunkSection(null, var2, var3, var4, var5 && this.world.getWorldConfig().shouldSaveNewChunks()));
}
long var6 = System.nanoTime();
IEventDispatcher var8 = HytaleServer.get().getEventBus().dispatchFor(ChunkSectionPreLoadProcessEvent.class, this.world.getName());
if (var8.hasListener()) {
ChunkSectionPreLoadProcessEvent var9 = var8.dispatch(new ChunkSectionPreLoadProcessEvent(this.world, var1, var5, var6));
if (!var9.didLog()) {
long var10 = System.nanoTime();
long var12 = var10 - var6;
if (var12 > this.world.getTickStepNanos()) {
LOGGER.at(Level.SEVERE)
.log(
"Took too long to pre-load process chunk section: %s > TICK_STEP, Has GC Run: %s, %s",
FormatUtil.nanosToString(var12),
this.world.consumeGCHasRun(),
var1
);
}
}
}
class="kw">return var1;
}
@Nullable
class="kw">private Ref<ChunkStore> postLoadChunkSection(
@Nullable Ref<ChunkStore> var1, int var2, int var3, int var4, @Nonnull Holder<ChunkStore> var5, boolean var6, boolean var7
) {
AddReason var8 = var6 ? AddReason.SPAWN : AddReason.LOAD;
if (var1 == null) {
var1 = this.getChunkReference(ChunkUtil.indexChunk(var2, var4));
}
if (var1 == null) {
class="kw">return null;
}
boolean var9 = this.world.getWorldConfig().shouldSaveNewChunks() && var8 == AddReason.SPAWN;
ChunkSection var10 = var5.getComponent(ChunkSection.getComponentType());
if (var10 != null) {
assert var10.getX() == var2;
assert var10.getY() == var3;
assert var10.getZ() == var4;
if (var9) {
var10.markNeedsSaving();
}
var10.updateChunkColumnReference(var1);
} else {
var5.putComponent(ChunkSection.getComponentType(), new ChunkSection(var1, var2, var3, var4, var9));
}
if (!var7) {
var5.ensureComponent(REGISTRY.getNonTickingComponentType());
} else {
var5.tryRemoveComponent(REGISTRY.getNonTickingComponentType());
}
Ref var11 = this.store.addEntity(var5, var8);
long var12 = this.lock.writeLock();
try {
ChunkStore.LoadState var14 = this.chunkSections.get(var2, var3, var4);
if (var14 == null) {
var14 = new ChunkStore.LoadState();
var14.reference = var11;
this.chunkSections.put(var2, var3, var4, var14);
} else {
var14.reference = var11;
var14.future = null;
var14.cleanupAttached = false;
}
} class="kw">finally {
this.lock.unlockWrite(var12);
}
ChunkStore.ChunkLoadState var19 = this.chunks.get(ChunkUtil.indexChunk(var2, var4));
if (var19 != null) {
var19.loadedSectionCount.incrementAndGet();
}
class="kw">return var11;
}
@Nullable
class="kw">public Ref<ChunkStore> getChunkSectionReferenceAtBlock(int var1, int var2, int var3) {
class="kw">return this.getChunkSectionReference(ChunkUtil.chunkCoordinate(var1), ChunkUtil.chunkCoordinate(var2), ChunkUtil.chunkCoordinate(var3));
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkSectionReferenceAtBlockAsync(int var1, int var2, int var3) {
class="kw">return this.getChunkSectionReferenceAsync(ChunkUtil.chunkCoordinate(var1), ChunkUtil.chunkCoordinate(var2), ChunkUtil.chunkCoordinate(var3));
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkSectionReferenceAtBlockAsync(int var1, int var2, int var3, int var4) {
class="kw">return this.getChunkSectionReferenceAsync(ChunkUtil.chunkCoordinate(var1), ChunkUtil.chunkCoordinate(var2), ChunkUtil.chunkCoordinate(var3), var4);
}
@Nullable
class="kw">public <T class="kw">extends Component<ChunkStore>> T getChunkComponent(long var1, @Nonnull ComponentType<ChunkStore, T> var3) {
Ref var4 = this.getChunkReference(var1);
class="kw">return var4 != null && var4.isValid() ? this.store.getComponent(var4, var3) : null;
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkReferenceAsync(long var1) {
class="kw">return this.getChunkReferenceAsync(var1, 0);
}
@Nonnull
class="kw">public CompletableFuture<Ref<ChunkStore>> getChunkReferenceAsync(long var1, int var3) {
if (this.store.isShutdown()) {
class="kw">return CompletableFuture.completedFuture(null);
}
ChunkStore.ChunkLoadState var4;
if ((var3 & 3) == 3) {
var4 = this.chunks.get(var1);
if (var4 == null) {
class="kw">return CompletableFuture.completedFuture(null);
}
long var5 = var4.lock.readLock();
try {
if ((var3 & 4) == 0 || (var4.flags & 4) != 0) {
if (var4.reference != null) {
class="kw">return CompletableFuture.completedFuture(var4.reference);
}
if (var4.future == null) {
class="kw">return CompletableFuture.completedFuture(null);
}
class="kw">return var4.future;
}
} class="kw">finally {
var4.lock.unlockRead(var5);
}
} else {
var4 = this.chunks.computeIfAbsent(var1, var0 -> new ChunkStore.ChunkLoadState());
}
long var28 = var4.lock.writeLock();
if (var4.future == null && var4.reference != null && (var3 & 8) == 0) {
Ref var29 = var4.reference;
if ((var3 & 4) == 0) {
var4.lock.unlockWrite(var28);
class="kw">return CompletableFuture.completedFuture(var29);
} else if (this.world.isInThread() && (var3 & -2147483648) == 0) {
var4.lock.unlockWrite(var28);
WorldChunk var30 = this.store.getComponent(var29, WorldChunk.getComponentType());
assert var30 != null;
var30.setFlag(ChunkFlag.TICKING, true);
class="kw">return CompletableFuture.completedFuture(var29);
} else {
var4.lock.unlockWrite(var28);
class="kw">return CompletableFuture.supplyAsync(() -> {
WorldChunk var2 = this.store.getComponent(var29, WorldChunk.getComponentType());
assert var2 != null;
var2.setFlag(ChunkFlag.TICKING, true);
class="kw">return var29;
}, this.world);
}
} else {
try {
if (var4.checkAndResetBackoff()) {
class="kw">return CompletableFuture.failedFuture(new RuntimeException("Chunk failure backoff", var4.throwable));
}
boolean var7 = var4.future == null;
if (var7) {
var4.flags = var3;
}
if ((var3 & 32) != 0) {
var4.flags |= 32;
}
int var8 = ChunkUtil.xOfChunkIndex(var1);
int var9 = ChunkUtil.zOfChunkIndex(var1);
if ((var7 || (var4.flags & 1) != 0) && (var3 & 1) == 0) {
if (var4.future == null) {
var4.future = this.loader.loadHolder(var8, var9).thenApplyAsync(var3x -> {
if (var3x != null && !this.store.isShutdown()) {
this.totalLoadedChunksCount.getAndIncrement();
class="kw">return this.preLoadChunkAsync(var1, (Holder<ChunkStore>)var3x, false);
} else {
class="kw">return null;
}
}).thenApplyAsync(this::postLoadChunk, this.world).exceptionally(var3x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3x)).log("Failed to load chunk! %s, %s", var8, var9);
var4.fail(var3x);
throw SneakyThrow.sneakyThrow(var3x);
});
} else {
var4.flags &= -2;
var4.future = var4.future
.thenCompose(
var6 -> var6 != null
? CompletableFuture.completedFuture((Ref<ChunkStore>)var6)
: this.loader.loadHolder(var8, var9).thenApplyAsync(var3x -> {
if (var3x != null && !this.store.isShutdown()) {
this.totalLoadedChunksCount.getAndIncrement();
class="kw">return this.preLoadChunkAsync(var1, (Holder<ChunkStore>)var3x, false);
} else {
class="kw">return null;
}
}).thenApplyAsync(this::postLoadChunk, this.world).exceptionally(var3x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3x)).log("Failed to load chunk! %s, %s", var8, var9);
var4.fail(var3x);
throw SneakyThrow.sneakyThrow(var3x);
})
);
}
}
if ((var7 || (var4.flags & 2) != 0) && (var3 & 2) == 0) {
int var10 = (int)this.world.getWorldConfig().getSeed();
if (var4.future == null) {
long var12 = this.generatorLock.readLock();
CompletableFuture var11;
try {
if (this.generator == null) {
var11 = this.generatorLoaded
.thenCompose(
var7x -> this.generator
.generate(var10, var1, var8, var9, (var3 & 16) != 0 ? this::isChunkStillNeeded : null, this::fetchColumnPriority)
);
} else {
var11 = this.generator.generate(var10, var1, var8, var9, (var3 & 16) != 0 ? this::isChunkStillNeeded : null, this::fetchColumnPriority);
}
} class="kw">finally {
this.generatorLock.unlockRead(var12);
}
var4.future = var11.<Holder<ChunkStore>>thenApplyAsync(var3x -> {
if (var3x != null && !this.store.isShutdown()) {
this.totalGeneratedChunksCount.getAndIncrement();
class="kw">return this.preLoadChunkAsync(var1, var3x.toHolder(this.world), true);
} else {
class="kw">return null;
}
}).thenApplyAsync(this::postLoadChunk, this.world).exceptionally(var3x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3x)).log("Failed to generate chunk! %s, %s", var8, var9);
var4.fail(var3x);
throw SneakyThrow.sneakyThrow(var3x);
});
} else {
var4.flags &= -3;
var4.future = var4.future.thenCompose(var7x -> {
if (var7x != null) {
class="kw">return CompletableFuture.completedFuture((Ref<ChunkStore>)var7x);
}
LongPredicate var8 = var1x -> this.world.isAlive();
long var10 = this.generatorLock.readLock();
CompletableFuture var9;
try {
if (this.generator == null) {
var9 = this.generatorLoaded.thenCompose(var7xx -> this.generator.generate(var10, var1, var8, var9, var8, this::fetchColumnPriority));
} else {
var9 = this.generator.generate(var10, var1, var8, var9, var8, this::fetchColumnPriority);
}
} class="kw">finally {
this.generatorLock.unlockRead(var10);
}
class="kw">return var9.<Holder<ChunkStore>>thenApplyAsync(var3x -> {
if (var3x != null && !this.store.isShutdown()) {
this.totalGeneratedChunksCount.getAndIncrement();
class="kw">return this.preLoadChunkAsync(var1, var3x.toHolder(this.world), true);
} else {
class="kw">return null;
}
}).thenApplyAsync(this::postLoadChunk, this.world).exceptionally(var3x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3x)).log("Failed to generate chunk! %s, %s", var8, var9);
var4.fail(var3x);
throw SneakyThrow.sneakyThrow(var3x);
});
});
}
}
if ((var7 || (var4.flags & 4) == 0) && (var3 & 4) != 0) {
var4.flags |= 4;
if (var4.future != null) {
var4.future = var4.future.<Ref<ChunkStore>>thenApplyAsync(var1x -> {
if (var1x != null) {
WorldChunk var2 = this.store.getComponent((Ref<ChunkStore>)var1x, WorldChunk.getComponentType());
assert var2 != null;
var2.setFlag(ChunkFlag.TICKING, true);
}
class="kw">return var1x;
}, this.world).exceptionally(var3x -> {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3x)).log("Failed to set chunk ticking! %s, %s", var8, var9);
var4.fail(var3x);
throw SneakyThrow.sneakyThrow(var3x);
});
}
}
class="kw">return var4.future == null ? CompletableFuture.completedFuture(null) : var4.future;
} class="kw">finally {
var4.lock.unlockWrite(var28);
}
}
}
class="kw">private boolean isSectionStillNeeded(int var1, int var2, int var3) {
if (var2 >= 0 && var2 < 10) {
class="kw">return this.isChunkStillNeeded(ChunkUtil.indexChunk(var1, var3));
}
for (PlayerRef var5 : this.world.getPlayerRefs()) {
if (var5.getChunkTracker().shouldBeVisible(var1, var2, var3)) {
class="kw">return true;
}
}
class="kw">return false;
}
class="kw">private boolean isChunkStillNeeded(long var1) {
for (PlayerRef var4 : this.world.getPlayerRefs()) {
if (var4.getChunkTracker().shouldBeVisible(var1)) {
class="kw">return true;
}
}
class="kw">return false;
}
class="kw">private float fetchSectionPriority(int var1, int var2, int var3) {
long var4 = this.lock.readLock();
try {
ChunkStore.LoadState var6 = this.chunkSections.get(var1, var2, var3);
if (var6 != null && (var6.flags & 32) != 0) {
class="kw">return -1.0F;
}
} class="kw">finally {
this.lock.unlockRead(var4);
}
float var11 = Float.MAX_VALUE;
for (PlayerRef var8 : this.world.getPlayerRefs()) {
if (var8.getChunkTracker().shouldBeVisible(var1, var2, var3)) {
var11 = Math.min(var11, var8.getChunkTracker().calculateSectionPriority(var1, var2, var3));
}
}
class="kw">return var11;
}
class="kw">private float fetchColumnPriority(long var1) {
ChunkStore.ChunkLoadState var3 = this.chunks.get(var1);
if (var3 != null && (var3.flags & 32) != 0) {
class="kw">return -1.0F;
}
float var4 = Float.MAX_VALUE;
int var5 = ChunkUtil.xOfChunkIndex(var1);
int var6 = ChunkUtil.zOfChunkIndex(var1);
for (PlayerRef var8 : this.world.getPlayerRefs()) {
if (var8.getChunkTracker().shouldBeVisible(var1)) {
var4 = Math.min(var4, var8.getChunkTracker().calculateColumnPriority(var5, var6));
}
}
class="kw">return var4;
}
class="kw">public boolean isChunkOnBackoff(long var1, long var3) {
ChunkStore.ChunkLoadState var5 = this.chunks.get(var1);
if (var5 == null) {
class="kw">return false;
}
long var6 = var5.lock.readLock();
try {
class="kw">return var5.isOnBackoff(var3);
} class="kw">finally {
var5.lock.unlockRead(var6);
}
}
class="kw">public boolean isChunkSectionOnBackoff(int var1, int var2, int var3, long var4) {
long var7 = this.lock.readLock();
ChunkStore.LoadState var6;
try {
var6 = this.chunkSections.get(var1, var2, var3);
} class="kw">finally {
this.lock.unlockRead(var7);
}
if (var6 == null) {
class="kw">return false;
}
long var9 = var6.lock.readLock();
try {
class="kw">return var6.isOnBackoff(var4);
} class="kw">finally {
var6.lock.unlockRead(var9);
}
}
@Nonnull
class="kw">private Holder<ChunkStore> preLoadChunkAsync(long var1, @Nonnull Holder<ChunkStore> var3, boolean var4) {
WorldChunk var5 = var3.getComponent(WorldChunk.getComponentType());
int var6 = ChunkUtil.xOfChunkIndex(var1);
int var7 = ChunkUtil.zOfChunkIndex(var1);
if (var5 == null) {
throw new IllegalStateException(String.format("Holder missing WorldChunk component! (%d, %d)", var6, var7));
}
if (var5.getIndex() != var1) {
throw new IllegalStateException(String.format("Incorrect chunk index! Got (%d, %d) expected (%d, %d)", var5.getX(), var5.getZ(), var6, var7));
}
BlockChunk var8 = var3.getComponent(BlockChunk.getComponentType());
if (var8 == null) {
throw new IllegalStateException(String.format("Holder missing BlockChunk component! (%d, %d)", var6, var7));
}
ChunkColumn var9 = var3.getComponent(ChunkColumn.getComponentType());
Holder[] var10 = var9.getSectionHolders();
if (var10 == null) {
var10 = new Holder[var9.getSections().length];
}
for (int var11 = 0; var11 < var10.length; var11++) {
Holder var12 = var10[var11] == null ? REGISTRY.newHolder() : var10[var11];
if (!var12.getArchetype().contains(ChunkSection.getComponentType())) {
var12.putComponent(
ChunkSection.getComponentType(), new ChunkSection(null, var6, var11, var7, var4 && this.world.getWorldConfig().shouldSaveNewChunks())
);
}
var10[var11] = var12;
}
var9.putSectionHolders(var10);
var8.loadFromHolder(var3);
var5.setFlag(ChunkFlag.NEWLY_GENERATED, var4);
var5.setFlag(ChunkFlag.ON_DISK, !var4);
var5.setLightingUpdatesEnabled(false);
if (var4 && this.world.getWorldConfig().shouldSaveNewChunks()) {
var5.markNeedsSaving();
}
try {
long var22 = System.nanoTime();
IEventDispatcher var13 = HytaleServer.get().getEventBus().dispatchFor(ChunkPreLoadProcessEvent.class, this.world.getName());
if (var13.hasListener()) {
ChunkPreLoadProcessEvent var14 = var13.dispatch(new ChunkPreLoadProcessEvent(var3, var5, var4, var22));
if (!var14.didLog()) {
long var15 = System.nanoTime();
long var17 = var15 - var22;
if (var17 > this.world.getTickStepNanos()) {
LOGGER.at(Level.SEVERE)
.log(
"Took too long to pre-load process chunk: %s > TICK_STEP, Has GC Run: %s, %s",
FormatUtil.nanosToString(var17),
this.world.consumeGCHasRun(),
var5
);
}
}
}
} class="kw">finally {
var5.setLightingUpdatesEnabled(true);
}
for (int var23 = 0; var23 < var10.length; var23++) {
Holder var24 = var10[var23];
var10[var23] = this.preLoadChunkSectionAsync(var24, var6, var23, var7, var5.is(ChunkFlag.NEWLY_GENERATED));
}
var9.putSectionHolders(var10);
class="kw">return var3;
}
@Nullable
class="kw">private Ref<ChunkStore> postLoadChunk(@Nullable Holder<ChunkStore> var1) {
this.world.debugAssertInTickingThread();
if (var1 != null && !this.store.isShutdown()) {
long var2 = System.nanoTime();
WorldChunk var4 = var1.getComponent(WorldChunk.getComponentType());
assert var4 != null;
var4.setFlag(ChunkFlag.START_INIT, true);
if (var4.is(ChunkFlag.TICKING)) {
var1.tryRemoveComponent(REGISTRY.getNonTickingComponentType());
} else {
var1.ensureComponent(REGISTRY.getNonTickingComponentType());
}
Ref var5 = this.add(var1);
var4.initFlags();
this.world.getChunkLighting().init(var4);
long var6 = System.nanoTime();
long var8 = var6 - var2;
if (var8 > this.world.getTickStepNanos()) {
LOGGER.at(Level.SEVERE)
.log(
"Took too long to post-load process chunk: %s > TICK_STEP, Has GC Run: %s, %s",
FormatUtil.nanosToString(var8),
this.world.consumeGCHasRun(),
var4
);
}
class="kw">return var5;
} else {
class="kw">return null;
}
}
class="kw">public void pauseBackgroundSaving(ChunkSavingSystems.Data var1) {
if (this.saver != null) {
this.saver.pauseBackgroundSaving(var1);
}
}
@Nonnull
class="kw">public CompletableFuture<Void> resumeBackgroundSaving() {
class="kw">return this.saver != null ? this.saver.resumeBackgroundSaving() : CompletableFuture.completedFuture(null);
}
class="kw">static {
CodecStore.STATIC.putCodecSupplier(HOLDER_CODEC_KEY, REGISTRY::getEntityCodec);
REGISTRY.registerSystem(new ChunkStore.ChunkLoaderSaverSetupSystem());
REGISTRY.registerSystem(new ChunkUnloadingSystem());
REGISTRY.registerSystem(new SectionUnloadingSystem());
REGISTRY.registerSystem(new ChunkSavingSystems.WorldRemoved());
REGISTRY.registerSystem(new ChunkSavingSystems.Ticking());
}
class="kw">private class="kw">static class ChunkLoadState class="kw">extends ChunkStore.LoadState {
class="kw">final AtomicInteger loadedSectionCount = new AtomicInteger();
class="kw">private ChunkLoadState() {
}
}
class="kw">public class="kw">static class ChunkLoaderSaverSetupSystem class="kw">extends StoreSystem<ChunkStore> {
class="kw">private class="kw">final ResourceType<ChunkStore, ChunkStore.ChunkStorage> chunkStorageResourceType = this.registerResource(
ChunkStore.ChunkStorage.class, "ChunkStorage", ChunkStore.ChunkStorage.CODEC
);
class="kw">public ChunkLoaderSaverSetupSystem() {
}
@Nullable
@Override
class="kw">public SystemGroup<ChunkStore> getGroup() {
class="kw">return ChunkStore.INIT_GROUP;
}
@Override
class="kw">public void onSystemAddedToStore(@Nonnull Store<ChunkStore> var1) {
ChunkStore var2 = var1.getExternalData();
World var3 = var2.getWorld();
IChunkStorageProvider var4 = var3.getWorldConfig().getChunkStorageProvider();
ChunkStore.ChunkStorage var5 = var1.getResource(this.chunkStorageResourceType);
if (var5.currentProvider != null && !var5.currentProvider.isSame(var4)) {
IChunkStorageProvider var6 = var5.currentProvider;
var2.pendingStorageMigration = () -> {
try {
var2.storageData = var4.migrateFrom(var1, var6);
var5.currentProvider = var4;
var2.loader = ((IChunkStorageProvider<Object>)var4).getLoader(var2.storageData, var1);
var2.saver = ((IChunkStorageProvider<Object>)var4).getSaver(var2.storageData, var1);
} catch (IOException var6) {
throw SneakyThrow.sneakyThrow(var6);
}
};
} else {
try {
var2.storageData = var4.initialize(var1);
var5.currentProvider = var4;
var2.loader = ((IChunkStorageProvider<Object>)var4).getLoader(var2.storageData, var1);
var2.saver = ((IChunkStorageProvider<Object>)var4).getSaver(var2.storageData, var1);
} catch (IOException var7) {
throw SneakyThrow.sneakyThrow(var7);
}
}
}
@Override
class="kw">public void onSystemRemovedFromStore(@Nonnull Store<ChunkStore> var1) {
ChunkStore var2 = var1.getExternalData();
try {
if (var2.loader != null) {
IChunkLoader var3 = var2.loader;
var2.loader = null;
var3.close();
}
if (var2.saver != null) {
IChunkSaver var6 = var2.saver;
var2.saver = null;
var6.close();
}
World var7 = var2.getWorld();
IChunkStorageProvider var4 = var7.getWorldConfig().getChunkStorageProvider();
((IChunkStorageProvider<Object>)var4).close(var2.storageData, var1);
} catch (IOException var5) {
((HytaleLogger.Api)ChunkStore.LOGGER.at(Level.SEVERE).withCause(var5)).log("Failed to close storage!");
}
}
}
class="kw">private class="kw">static class ChunkStorage class="kw">implements Resource<ChunkStore> {
class="kw">public class="kw">static class="kw">final BuilderCodec<ChunkStore.ChunkStorage> CODEC = BuilderCodec.builder(ChunkStore.ChunkStorage.class, ChunkStore.ChunkStorage::new)
.append(new KeyedCodec<>("CurrentProvider", IChunkStorageProvider.CODEC), (var0, var1) -> var0.currentProvider = var1, var0 -> var0.currentProvider)
.add()
.build();
@Nullable
class="kw">private IChunkStorageProvider<?> currentProvider;
class="kw">public ChunkStorage(@Nullable IChunkStorageProvider<?> var1) {
this.currentProvider = var1;
}
class="kw">public ChunkStorage() {
}
@Nullable
@Override
class="kw">public Resource<ChunkStore> clone() {
class="kw">return new ChunkStore.ChunkStorage(this.currentProvider);
}
}
class="kw">public class="kw">abstract class="kw">static class LoadFuturePacketDataQuerySystem class="kw">extends EntityDataSystem<ChunkStore, PlayerRef, CompletableFuture<ToClientPacket>> {
class="kw">public LoadFuturePacketDataQuerySystem() {
}
}
class="kw">public class="kw">abstract class="kw">static class LoadPacketDataQuerySystem class="kw">extends EntityDataSystem<ChunkStore, PlayerRef, ToClientPacket> {
class="kw">public LoadPacketDataQuerySystem() {
}
}
class="kw">private class="kw">static class LoadState {
class="kw">final StampedLock lock = new StampedLock();
int flags = 0;
@Nullable
CompletableFuture<Ref<ChunkStore>> future;
@Nullable
class="kw">volatile Ref<ChunkStore> reference;
@Nullable
Throwable throwable;
long failedWhen;
int failedCounter;
boolean cleanupAttached;
class="kw">private LoadState() {
}
void fail(Throwable var1) {
long var2 = this.lock.writeLock();
try {
this.flags = 0;
this.future = null;
this.cleanupAttached = false;
this.throwable = var1;
this.failedWhen = System.nanoTime();
this.failedCounter++;
} class="kw">finally {
this.lock.unlockWrite(var2);
}
}
boolean isOnBackoff(long var1) {
if (this.throwable == null) {
class="kw">return false;
}
long var3 = System.nanoTime() - this.failedWhen;
class="kw">return var3 < Math.min(var1, (long)this.failedCounter * this.failedCounter * ChunkStore.FAILURE_BACKOFF_NANOS);
}
boolean checkAndResetBackoff() {
if (this.isOnBackoff(ChunkStore.MAX_FAILURE_BACKOFF_NANOS)) {
class="kw">return true;
}
this.throwable = null;
this.failedWhen = 0L;
class="kw">return false;
}
}
class="kw">public class="kw">abstract class="kw">static class UnloadPacketDataQuerySystem class="kw">extends EntityDataSystem<ChunkStore, PlayerRef, ToClientPacket> {
class="kw">public UnloadPacketDataQuerySystem() {
}
}
}