Data class
Пакет: com.hypixel.hytale.server.core.universe.world.storage.component
Файл: com/hypixel/hytale/server/core/universe/world/storage/component/ChunkSavingSystems.java
implements: Resource<ChunkStore>
Поля (18)
| Модификаторы | Тип | Имя |
|---|---|---|
|
public static final int |
DEFAULT_MAX_IN_FLIGHT_SAVES |
|
public static final MetricsRegistry<ChunkSavingSystems.Data> |
METRICS_REGISTRY |
|
public static final float |
QUEUE_UPDATE_INTERVAL |
|
private final List<CompletableFuture<Void>> |
chunkSavingFutures |
|
private final AtomicInteger |
dirtyBlockComponentSectionsBacklog |
|
private final AtomicInteger |
dirtyEntitiesBacklog |
|
private final AtomicInteger |
dirtyEntitySectionsBacklog |
|
private final AtomicInteger |
dirtySectionsBacklog |
|
private final Semaphore |
inFlightPermits |
|
private final int |
maxInFlightSaves |
|
private final Deque<Ref<ChunkStore>> |
queue |
|
private final AtomicInteger |
savedCount |
|
private final Set<Ref<ChunkStore>> |
set |
|
private float |
time |
|
private final AtomicInteger |
toSaveTotal |
|
private final AtomicLong |
totalSaveCompletions |
|
private final AtomicLong |
totalSaveStarts |
|
Ref |
var1 |
Методы (26)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
|
public void |
awaitInFlightCapacitypublic void awaitInFlightCapacity() |
|
public boolean |
checkTimerpublic boolean checkTimer(float var1) |
|
public void |
clearSaveQueuepublic void clearSaveQueue() |
|
public Resource<ChunkStore> |
clonepublic Resource<ChunkStore> clone() |
|
public int |
getDirtyBlockComponentSectionsBacklogpublic int getDirtyBlockComponentSectionsBacklog() |
|
public int |
getDirtyEntitiesBacklogpublic int getDirtyEntitiesBacklog() |
|
public int |
getDirtyEntitySectionsBacklogpublic int getDirtyEntitySectionsBacklog() |
|
public int |
getDirtySectionsBacklogpublic int getDirtySectionsBacklog() |
|
public int |
getInFlightSaveCountpublic int getInFlightSaveCount() |
|
public int |
getMaxInFlightSavespublic int getMaxInFlightSaves() |
|
public int |
getPendingFutureCountpublic int getPendingFutureCount() |
|
public int |
getQueueDepthpublic int getQueueDepth() |
|
public long |
getTotalSaveCompletionspublic long getTotalSaveCompletions() |
|
public long |
getTotalSaveStartspublic long getTotalSaveStarts() |
|
|
if if(var1 == null) |
|
|
if if(this.time <= 0.0F) |
|
public Ref<ChunkStore> |
pollpublic Ref<ChunkStore> poll() |
|
public void |
pushpublic void push(@Nonnull Ref<ChunkStore> var1) |
|
public void |
pushSavingFuturepublic void pushSavingFuture(@Nonnull CompletableFuture<Void> var1) |
|
public void |
releaseInFlightpublic void releaseInFlight() |
|
public void |
setDirtyBlockComponentSectionsBacklogpublic void setDirtyBlockComponentSectionsBacklog(int var1) |
|
public void |
setDirtyEntitiesBacklogpublic void setDirtyEntitiesBacklog(int var1) |
|
public void |
setDirtyEntitySectionsBacklogpublic void setDirtyEntitySectionsBacklog(int var1) |
|
public void |
setDirtySectionsBacklogpublic void setDirtySectionsBacklog(int var1) |
|
public boolean |
tryReserveInFlightpublic boolean tryReserveInFlight() |
|
public CompletableFuture<Void> |
waitForSavingChunkspublic CompletableFuture<Void> waitForSavingChunks() |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe.world.storage.component;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.component.ArchetypeChunk;
class="kw">import com.hypixel.hytale.component.CommandBuffer;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Resource;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.component.dependency.Dependency;
class="kw">import com.hypixel.hytale.component.dependency.Order;
class="kw">import com.hypixel.hytale.component.dependency.RootDependency;
class="kw">import com.hypixel.hytale.component.dependency.SystemDependency;
class="kw">import com.hypixel.hytale.component.query.Query;
class="kw">import com.hypixel.hytale.component.system.StoreSystem;
class="kw">import com.hypixel.hytale.component.system.tick.RunWhenPausedSystem;
class="kw">import com.hypixel.hytale.component.system.tick.TickingSystem;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.metrics.MetricsRegistry;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.entity.EntitySavingSystem;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
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.BlockComponentSection;
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.ecs.ChunkSaveEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.IChunkSaver;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectListIterator;
class="kw">import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
class="kw">import java.util.Deque;
class="kw">import java.util.Iterator;
class="kw">import java.util.List;
class="kw">import java.util.Set;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.ConcurrentLinkedDeque;
class="kw">import java.util.concurrent.Executor;
class="kw">import java.util.concurrent.ForkJoinPool;
class="kw">import java.util.concurrent.Semaphore;
class="kw">import java.util.concurrent.atomic.AtomicInteger;
class="kw">import java.util.concurrent.atomic.AtomicLong;
class="kw">import java.util.function.BiConsumer;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class ChunkSavingSystems {
@Nonnull
class="kw">public class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
@Nonnull
class="kw">private class="kw">static class="kw">final ComponentType<ChunkStore, WorldChunk> WORLD_CHUNK_COMPONENT_TYPE = WorldChunk.getComponentType();
@Nonnull
class="kw">public class="kw">static class="kw">final Query<ChunkStore> QUERY = Query.and(WORLD_CHUNK_COMPONENT_TYPE, Query.not(ChunkStore.REGISTRY.getNonSerializedComponentType()));
class="kw">public ChunkSavingSystems() {
}
@Nonnull
class="kw">public class="kw">static CompletableFuture<Void> saveChunksInWorld(@Nonnull Store<ChunkStore> var0, @Nullable Executor var1) {
World var2 = var0.getExternalData().getWorld();
HytaleLogger var3 = var2.getLogger();
ChunkSavingSystems.Data var4 = var0.getResource(ChunkStore.SAVE_RESOURCE);
IChunkSaver var5 = var0.getExternalData().getSaver();
var3.at(Level.INFO).log("Queuing Chunks...");
var0.forEachChunk(QUERY, (var0x, var1x) -> {
for (int var2 = 0; var2 < var0x.size(); var2++) {
tryQueue(var2, var0x, var1x.getStore());
}
});
var3.at(Level.INFO).log("Saving All Chunks...");
Ref var6;
while ((var6 = var4.poll()) != null) {
saveChunk(var6, var4, true, var0, var1);
}
if (var5 class="kw">instanceof IChunkSaver.Cubic var7) {
var3.at(Level.INFO).log("Flushing Dirty Sections...");
SectionSavingSystem.flushAllDirty(var0, var7, var4, var1);
var3.at(Level.INFO).log("Flushing Dirty Entities...");
EntitySavingSystem.flushAllDirty(var2, var7, var4, var1);
}
var3.at(Level.INFO).log("Waiting for Saving Chunks...");
class="kw">return var4.waitForSavingChunks();
}
class="kw">public class="kw">static void tryQueue(int var0, @Nonnull ArchetypeChunk<ChunkStore> var1, @Nonnull Store<ChunkStore> var2) {
WorldChunk var3 = var1.getComponent(var0, WORLD_CHUNK_COMPONENT_TYPE);
assert var3 != null;
boolean var4 = var3.getNeedsSaving();
IChunkSaver var5 = var2.getExternalData().getSaver();
if (!(var5 class="kw">instanceof IChunkSaver.Cubic) && !var4) {
var4 = collectSectionDirtiness(var1.getComponent(var0, ChunkColumn.getComponentType()), var2, false);
}
if (var4 && !var3.isSaving()) {
Ref var6 = var1.getReferenceTo(var0);
ChunkSaveEvent var7 = new ChunkSaveEvent(var3);
var2.invoke(var6, var7);
if (!var7.isCancelled()) {
var2.getResource(ChunkStore.SAVE_RESOURCE).push(var6);
}
}
}
class="kw">public class="kw">static void tryQueueSync(@Nonnull ArchetypeChunk<ChunkStore> var0, @Nonnull CommandBuffer<ChunkStore> var1) {
Store var2 = var1.getStore();
ChunkSavingSystems.Data var3 = var2.getResource(ChunkStore.SAVE_RESOURCE);
IChunkSaver var4 = var2.getExternalData().getSaver();
for (int var5 = 0; var5 < var0.size(); var5++) {
WorldChunk var6 = var0.getComponent(var5, WORLD_CHUNK_COMPONENT_TYPE);
assert var6 != null;
boolean var7 = var6.getNeedsSaving();
if (!(var4 class="kw">instanceof IChunkSaver.Cubic) && !var7) {
var7 = collectSectionDirtiness(var0.getComponent(var5, ChunkColumn.getComponentType()), var2, false);
}
if (var7 && !var6.isSaving()) {
Ref var8 = var0.getReferenceTo(var5);
ChunkSaveEvent var9 = new ChunkSaveEvent(var6);
var2.invoke(var8, var9);
if (!var9.isCancelled()) {
var3.push(var8);
}
}
}
}
class="kw">static boolean collectSectionDirtiness(@Nullable ChunkColumn var0, @Nonnull ComponentAccessor<ChunkStore> var1, boolean var2) {
if (var0 == null) {
class="kw">return false;
}
for (Ref var6 : var0.getSections()) {
if (var6 != null && var6.isValid()) {
ChunkSection var7 = var1.getComponent(var6, ChunkSection.getComponentType());
if (var7 != null && (var7.needsSaving() || var2 && var7.isSaving())) {
class="kw">return true;
}
EntitySection var8 = var1.getComponent(var6, EntitySection.getComponentType());
if (var8 != null && (var8.needsSaving() || var2 && var8.isSaving())) {
class="kw">return true;
}
BlockComponentSection var9 = var1.getComponent(var6, BlockComponentSection.getComponentType());
if (var9 != null && (var9.needsSaving() || var2 && var9.isSaving())) {
class="kw">return true;
}
}
}
class="kw">return false;
}
class="kw">public class="kw">static void saveChunk(
@Nonnull Ref<ChunkStore> var0, @Nonnull ChunkSavingSystems.Data var1, boolean var2, @Nonnull Store<ChunkStore> var3, @Nullable Executor var4
) {
if (!var0.isValid()) {
LOGGER.at(Level.FINEST).log("Chunk reference in queue is for a chunk that has been removed!");
} else {
var1.awaitInFlightCapacity();
WorldChunk var5 = var3.getComponent(var0, WORLD_CHUNK_COMPONENT_TYPE);
assert var5 != null;
boolean var6 = false;
boolean var7 = false;
try {
var1.toSaveTotal.getAndIncrement();
ChunkStore var8 = var3.getExternalData();
World var9 = var8.getWorld();
IChunkSaver var10 = var8.getSaver();
CompletableFuture var11 = var10.saveChunkColumn(var5.getX(), var5.getZ(), var3, var0, var4, var1::releaseInFlight);
var7 = true;
var5.consumeNeedsSaving();
var1.chunkSavingFutures.add(var11);
BiConsumer var12 = (var1x, var2x) -> {
if (var2x != null) {
((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var2x)).log("Failed to save chunk (%d, %d):", var5.getX(), var5.getZ());
var5.markNeedsSaving();
} else {
var5.setFlag(ChunkFlag.ON_DISK, true);
LOGGER.at(Level.FINEST).log("Finished saving chunk (%d, %d)", var5.getX(), var5.getZ());
}
};
if (var4 != null) {
var11.whenCompleteAsync(var12, var4);
} else {
var11.whenComplete(var12);
}
var6 = true;
if (var2) {
var11.thenRunAsync(
() -> HytaleServer.get().reportSaveProgress(var9, var1.savedCount.incrementAndGet(), var1.toSaveTotal.get() + var1.queue.size())
);
}
} class="kw">finally {
if (!var6) {
var5.markNeedsSaving();
if (!var7) {
var1.releaseInFlight();
}
}
}
}
}
class="kw">public class="kw">static class Data class="kw">implements Resource<ChunkStore> {
class="kw">public class="kw">static class="kw">final float QUEUE_UPDATE_INTERVAL = 0.5F;
class="kw">public class="kw">static class="kw">final int DEFAULT_MAX_IN_FLIGHT_SAVES = Math.max(ForkJoinPool.getCommonPoolParallelism(), 8);
@Nonnull
class="kw">public class="kw">static class="kw">final MetricsRegistry<ChunkSavingSystems.Data> METRICS_REGISTRY = new MetricsRegistry<ChunkSavingSystems.Data>()
.register("ColumnQueueDepth", var0 -> (long)var0.queue.size(), Codec.LONG)
.register("DirtySectionsBacklog", var0 -> (long)var0.dirtySectionsBacklog.get(), Codec.LONG)
.register("DirtyEntitySectionsBacklog", var0 -> (long)var0.dirtyEntitySectionsBacklog.get(), Codec.LONG)
.register("DirtyBlockComponentSectionsBacklog", var0 -> (long)var0.dirtyBlockComponentSectionsBacklog.get(), Codec.LONG)
.register("DirtyEntitiesBacklog", var0 -> (long)var0.dirtyEntitiesBacklog.get(), Codec.LONG)
.register("InFlightSaves", var0 -> (long)var0.getInFlightSaveCount(), Codec.LONG)
.register("MaxInFlightSaves", var0 -> (long)var0.maxInFlightSaves, Codec.LONG)
.register("PendingFutures", var0 -> (long)var0.chunkSavingFutures.size(), Codec.LONG)
.register("TotalSaveStarts", var0 -> var0.totalSaveStarts.get(), Codec.LONG)
.register("TotalSaveCompletions", var0 -> var0.totalSaveCompletions.get(), Codec.LONG);
@Nonnull
class="kw">private class="kw">final Set<Ref<ChunkStore>> set = ConcurrentHashMap.newKeySet();
@Nonnull
class="kw">private class="kw">final Deque<Ref<ChunkStore>> queue = new ConcurrentLinkedDeque<>();
@Nonnull
class="kw">private class="kw">final List<CompletableFuture<Void>> chunkSavingFutures = new ObjectArrayList();
class="kw">private class="kw">final int maxInFlightSaves = DEFAULT_MAX_IN_FLIGHT_SAVES;
@Nonnull
class="kw">private class="kw">final Semaphore inFlightPermits = new Semaphore(this.maxInFlightSaves);
@Nonnull
class="kw">private class="kw">final AtomicLong totalSaveStarts = new AtomicLong();
@Nonnull
class="kw">private class="kw">final AtomicLong totalSaveCompletions = new AtomicLong();
@Nonnull
class="kw">private class="kw">final AtomicInteger dirtySectionsBacklog = new AtomicInteger();
@Nonnull
class="kw">private class="kw">final AtomicInteger dirtyEntitySectionsBacklog = new AtomicInteger();
@Nonnull
class="kw">private class="kw">final AtomicInteger dirtyBlockComponentSectionsBacklog = new AtomicInteger();
@Nonnull
class="kw">private class="kw">final AtomicInteger dirtyEntitiesBacklog = new AtomicInteger();
class="kw">private float time;
@Nonnull
class="kw">private class="kw">final AtomicInteger savedCount = new AtomicInteger();
@Nonnull
class="kw">private class="kw">final AtomicInteger toSaveTotal = new AtomicInteger();
class="kw">public Data() {
this.time = 0.5F;
}
class="kw">public Data(float var1) {
this.time = var1;
}
@Nonnull
@Override
class="kw">public Resource<ChunkStore> clone() {
class="kw">return new ChunkSavingSystems.Data(this.time);
}
class="kw">public void clearSaveQueue() {
this.queue.clear();
this.set.clear();
}
class="kw">public void push(@Nonnull Ref<ChunkStore> var1) {
if (this.set.add(var1)) {
this.queue.push(var1);
}
}
@Nullable
class="kw">public Ref<ChunkStore> poll() {
Ref var1 = this.queue.poll();
if (var1 == null) {
class="kw">return null;
}
this.set.remove(var1);
class="kw">return var1;
}
class="kw">public boolean checkTimer(float var1) {
this.time -= var1;
if (this.time <= 0.0F) {
this.time += 0.5F;
class="kw">return true;
} else {
class="kw">return false;
}
}
class="kw">public void pushSavingFuture(@Nonnull CompletableFuture<Void> var1) {
this.chunkSavingFutures.add(var1);
}
class="kw">public boolean tryReserveInFlight() {
if (!this.inFlightPermits.tryAcquire()) {
class="kw">return false;
}
this.totalSaveStarts.incrementAndGet();
class="kw">return true;
}
class="kw">public void awaitInFlightCapacity() {
this.inFlightPermits.acquireUninterruptibly();
this.totalSaveStarts.incrementAndGet();
}
class="kw">public void releaseInFlight() {
this.inFlightPermits.release();
this.totalSaveCompletions.incrementAndGet();
}
class="kw">public int getQueueDepth() {
class="kw">return this.queue.size();
}
class="kw">public int getInFlightSaveCount() {
class="kw">return this.maxInFlightSaves - this.inFlightPermits.availablePermits();
}
class="kw">public int getMaxInFlightSaves() {
class="kw">return this.maxInFlightSaves;
}
class="kw">public int getPendingFutureCount() {
class="kw">return this.chunkSavingFutures.size();
}
class="kw">public long getTotalSaveStarts() {
class="kw">return this.totalSaveStarts.get();
}
class="kw">public long getTotalSaveCompletions() {
class="kw">return this.totalSaveCompletions.get();
}
class="kw">public int getDirtySectionsBacklog() {
class="kw">return this.dirtySectionsBacklog.get();
}
class="kw">public void setDirtySectionsBacklog(int var1) {
this.dirtySectionsBacklog.set(var1);
}
class="kw">public int getDirtyEntitySectionsBacklog() {
class="kw">return this.dirtyEntitySectionsBacklog.get();
}
class="kw">public void setDirtyEntitySectionsBacklog(int var1) {
this.dirtyEntitySectionsBacklog.set(var1);
}
class="kw">public int getDirtyBlockComponentSectionsBacklog() {
class="kw">return this.dirtyBlockComponentSectionsBacklog.get();
}
class="kw">public void setDirtyBlockComponentSectionsBacklog(int var1) {
this.dirtyBlockComponentSectionsBacklog.set(var1);
}
class="kw">public int getDirtyEntitiesBacklog() {
class="kw">return this.dirtyEntitiesBacklog.get();
}
class="kw">public void setDirtyEntitiesBacklog(int var1) {
this.dirtyEntitiesBacklog.set(var1);
}
@Nonnull
class="kw">public CompletableFuture<Void> waitForSavingChunks() {
class="kw">return CompletableFuture.allOf(this.chunkSavingFutures.toArray(CompletableFuture[]::new));
}
}
class="kw">public class="kw">static class Ticking class="kw">extends TickingSystem<ChunkStore> class="kw">implements RunWhenPausedSystem<ChunkStore> {
class="kw">public Ticking() {
}
@Nonnull
@Override
class="kw">public Set<Dependency<ChunkStore>> getDependencies() {
class="kw">return RootDependency.lastSet();
}
@Override
class="kw">public void tick(float var1, int var2, @Nonnull Store<ChunkStore> var3) {
ChunkSavingSystems.Data var4 = var3.getResource(ChunkStore.SAVE_RESOURCE);
if (!var3.getExternalData().getWorld().isSavingLocked() && var3.getExternalData().getWorld().getWorldConfig().canSaveChunks()) {
var4.chunkSavingFutures.removeIf(CompletableFuture::isDone);
if (var4.checkTimer(var1)) {
var3.forEachChunk(ChunkSavingSystems.QUERY, ChunkSavingSystems::tryQueueSync);
}
World var5 = var3.getExternalData().getWorld();
IChunkSaver var6 = var3.getExternalData().getSaver();
int var7 = ForkJoinPool.commonPool().getParallelism();
for (int var8 = 0; var8 < var7; var8++) {
Ref var9 = var4.poll();
if (var9 == null) {
break;
}
if (!var4.tryReserveInFlight()) {
var4.push(var9);
break;
}
if (!var9.isValid()) {
var4.releaseInFlight();
ChunkSavingSystems.LOGGER.at(Level.FINEST).log("Chunk reference in queue is for a chunk that has been removed!");
} else {
WorldChunk var10 = var3.getComponent(var9, ChunkSavingSystems.WORLD_CHUNK_COMPONENT_TYPE);
var10.setSaving(true);
boolean var11 = false;
boolean var12 = false;
ReferenceArrayList var13 = null;
ReferenceArrayList var14 = null;
ReferenceArrayList var15 = null;
try {
ChunkColumn var16;
if (!(var6 class="kw">instanceof IChunkSaver.Cubic)) {
var16 = var3.getComponent(var9, ChunkColumn.getComponentType());
} else {
var16 = null;
}
var4.toSaveTotal.getAndIncrement();
var13 = var16 != null ? new ReferenceArrayList() : null;
var14 = var16 != null ? new ReferenceArrayList() : null;
var15 = var16 != null ? new ReferenceArrayList() : null;
CompletableFuture var17 = var6.saveChunkColumn(var10.getX(), var10.getZ(), var3, var9, var5, var4::releaseInFlight);
var12 = true;
var10.consumeNeedsSaving();
if (var16 != null) {
for (Ref var21 : var16.getSections()) {
if (var21 != null && var21.isValid()) {
ChunkSection var22 = var3.getComponent(var21, ChunkSection.getComponentType());
if (var22 != null && var22.consumeNeedsSaving()) {
var13.add(var22);
}
EntitySection var23 = var3.getComponent(var21, EntitySection.getComponentType());
if (var23 != null && var23.consumeNeedsSaving()) {
var14.add(var23);
}
BlockComponentSection var24 = var3.getComponent(var21, BlockComponentSection.getComponentType());
if (var24 != null && var24.consumeNeedsSaving()) {
var15.add(var24);
var24.takeDirtyBlocks();
var24.takeRemovedBlocks();
}
}
}
}
var4.chunkSavingFutures.add(var17);
ReferenceArrayList var30 = var13;
ReferenceArrayList var31 = var14;
ReferenceArrayList var32 = var15;
var17.whenCompleteAsync(
(var4x, var5x) -> {
if (var5x != null) {
((HytaleLogger.Api)ChunkSavingSystems.LOGGER.at(Level.SEVERE).withCause(var5x))
.log("Failed to save chunk (%d, %d):", var10.getX(), var10.getZ());
var10.markNeedsSaving();
if (var30 != null) {
Iterator var6 = var30.iterator();
while (var6.hasNext()) {
ChunkSection var7 = (ChunkSection)var6.next();
var7.markNeedsSaving();
}
}
if (var31 != null) {
Iterator var8 = var31.iterator();
while (var8.hasNext()) {
EntitySection var10 = (EntitySection)var8.next();
var10.markNeedsSaving();
}
}
if (var32 != null) {
Iterator var9 = var32.iterator();
while (var9.hasNext()) {
BlockComponentSection var11 = (BlockComponentSection)var9.next();
var11.markNeedsSaving();
}
}
} else {
var10.setFlag(ChunkFlag.ON_DISK, true);
ChunkSavingSystems.LOGGER.at(Level.FINEST).log("Finished saving chunk (%d, %d)", var10.getX(), var10.getZ());
}
var10.setSaving(false);
},
var5
);
var11 = true;
} class="kw">finally {
if (!var11) {
var10.setSaving(false);
var10.markNeedsSaving();
if (var13 != null) {
ObjectListIterator var26 = var13.iterator();
while (var26.hasNext()) {
ChunkSection var27 = (ChunkSection)var26.next();
var27.markNeedsSaving();
}
}
if (var14 != null) {
ObjectListIterator var33 = var14.iterator();
while (var33.hasNext()) {
EntitySection var35 = (EntitySection)var33.next();
var35.markNeedsSaving();
}
}
if (var15 != null) {
ObjectListIterator var34 = var15.iterator();
while (var34.hasNext()) {
BlockComponentSection var36 = (BlockComponentSection)var34.next();
var36.markNeedsSaving();
}
}
if (!var12) {
var4.releaseInFlight();
}
}
}
}
}
}
}
}
class="kw">public class="kw">static class WorldRemoved class="kw">extends StoreSystem<ChunkStore> {
@Nonnull
class="kw">private class="kw">final Set<Dependency<ChunkStore>> dependencies = Set.of(new SystemDependency<>(Order.AFTER, ChunkStore.ChunkLoaderSaverSetupSystem.class));
class="kw">public WorldRemoved() {
}
@Nonnull
@Override
class="kw">public Set<Dependency<ChunkStore>> getDependencies() {
class="kw">return this.dependencies;
}
@Override
class="kw">public void onSystemAddedToStore(@Nonnull Store<ChunkStore> var1) {
}
@Override
class="kw">public void onSystemRemovedFromStore(@Nonnull Store<ChunkStore> var1) {
World var2 = var1.getExternalData().getWorld();
var2.getLogger().at(Level.INFO).log("Shutting down chunk generator...");
var2.getChunkStore().shutdownGenerator();
if (!var2.getWorldConfig().canSaveChunks()) {
var2.getLogger().at(Level.INFO).log("This world has opted to disable chunk saving so it will not be saved on shutdown");
} else {
var2.getLogger().at(Level.INFO).log("Saving Chunks...");
ChunkSavingSystems.Data var3 = var1.getResource(ChunkStore.SAVE_RESOURCE);
var3.savedCount.set(0);
var3.toSaveTotal.set(0);
ChunkSavingSystems.saveChunksInWorld(var1, null).join();
var2.getLogger().at(Level.INFO).log("Done Saving Chunks!");
}
}
}
}