Skip to content

Commit

Permalink
Potential fix for actions on chunks not finishing when disabling the …
Browse files Browse the repository at this point in the history
…plugin (#1377)
  • Loading branch information
OmerBenGera committed Sep 30, 2022
1 parent 13172a8 commit d183663
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 3 deletions.
Expand Up @@ -369,6 +369,9 @@ public void onDisable() {
SuperiorSkyblockPlugin.log("Shutting down executor");
BukkitExecutor.close();

if (nmsChunks != null)
nmsChunks.shutdown();

SuperiorSkyblockPlugin.log("Closing database. This may hang the server. Do not shut it down, or data may get lost.");
//pluginDebugger.cancel();
dataHandler.closeConnection();
Expand Down
Expand Up @@ -33,4 +33,6 @@ CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chu

void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCropGrowthMultiplier);

void shutdown();

}
Expand Up @@ -281,6 +281,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down
Expand Up @@ -36,9 +36,11 @@

import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

Expand All @@ -51,6 +53,8 @@ public class NMSUtils {
private static final ReflectField<Map<Long, ChunkHolder>> VISIBLE_CHUNKS = new ReflectField<>(
ChunkMap.class, Map.class, Modifier.PUBLIC | Modifier.VOLATILE, 1);

private static final List<CompletableFuture<Void>> PENDING_CHUNK_ACTIONS = new LinkedList<>();

private NMSUtils() {

}
Expand Down Expand Up @@ -100,6 +104,9 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
Runnable onFinish) {
ChunkMap chunkMap = serverLevel.getChunkSource().chunkMap;

CompletableFuture<Void> pendingTask = new CompletableFuture<>();
PENDING_CHUNK_ACTIONS.add(pendingTask);

BukkitExecutor.createTask().runAsync(v -> {
chunks.forEach(chunkCoords -> {
try {
Expand All @@ -124,9 +131,16 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
}).runSync(v -> {
if (onFinish != null)
onFinish.run();

pendingTask.complete(null);
PENDING_CHUNK_ACTIONS.remove(pendingTask);
});
}

public static List<CompletableFuture<Void>> getPendingChunkActions() {
return Collections.unmodifiableList(PENDING_CHUNK_ACTIONS);
}

public static ProtoChunk createProtoChunk(ChunkPos chunkPos, ServerLevel serverLevel) {
try {
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, serverLevel, serverLevel);
Expand Down
Expand Up @@ -383,6 +383,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down
Expand Up @@ -40,10 +40,12 @@
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public class NMSUtils {
Expand All @@ -55,6 +57,8 @@ public class NMSUtils {
private static final ReflectField<Map<Long, ChunkHolder>> VISIBLE_CHUNKS = new ReflectField<>(
ChunkMap.class, Map.class, Modifier.PUBLIC | Modifier.VOLATILE, 1);

private static final List<CompletableFuture<Void>> PENDING_CHUNK_ACTIONS = new LinkedList<>();

private NMSUtils() {

}
Expand Down Expand Up @@ -104,6 +108,9 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
Runnable onFinish) {
ChunkMap chunkMap = serverLevel.getChunkSource().chunkMap;

CompletableFuture<Void> pendingTask = new CompletableFuture<>();
PENDING_CHUNK_ACTIONS.add(pendingTask);

BukkitExecutor.createTask().runAsync(v -> {
List<Pair<ChunkPos, net.minecraft.nbt.CompoundTag>> chunkCompounds = new LinkedList<>();

Expand Down Expand Up @@ -142,9 +149,16 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,

if (onFinish != null)
onFinish.run();

pendingTask.complete(null);
PENDING_CHUNK_ACTIONS.remove(pendingTask);
});
}

public static List<CompletableFuture<Void>> getPendingChunkActions() {
return Collections.unmodifiableList(PENDING_CHUNK_ACTIONS);
}

public static ProtoChunk createProtoChunk(ChunkPos chunkPos, ServerLevel serverLevel) {
return new ProtoChunk(chunkPos,
UpgradeData.EMPTY,
Expand Down
Expand Up @@ -385,6 +385,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down
Expand Up @@ -40,10 +40,12 @@
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public class NMSUtils {
Expand All @@ -55,6 +57,8 @@ public class NMSUtils {
private static final ReflectField<Map<Long, ChunkHolder>> VISIBLE_CHUNKS = new ReflectField<>(
ChunkMap.class, Map.class, Modifier.PUBLIC | Modifier.VOLATILE, 1);

private static final List<CompletableFuture<Void>> PENDING_CHUNK_ACTIONS = new LinkedList<>();

private NMSUtils() {

}
Expand Down Expand Up @@ -104,6 +108,9 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
Runnable onFinish) {
ChunkMap chunkMap = serverLevel.getChunkSource().chunkMap;

CompletableFuture<Void> pendingTask = new CompletableFuture<>();
PENDING_CHUNK_ACTIONS.add(pendingTask);

BukkitExecutor.createTask().runAsync(v -> {
List<Pair<ChunkPos, net.minecraft.nbt.CompoundTag>> chunkCompounds = new LinkedList<>();

Expand Down Expand Up @@ -142,9 +149,16 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,

if (onFinish != null)
onFinish.run();

pendingTask.complete(null);
PENDING_CHUNK_ACTIONS.remove(pendingTask);
});
}

public static List<CompletableFuture<Void>> getPendingChunkActions() {
return Collections.unmodifiableList(PENDING_CHUNK_ACTIONS);
}

public static ProtoChunk createProtoChunk(ChunkPos chunkPos, ServerLevel serverLevel) {
return new ProtoChunk(chunkPos,
UpgradeData.EMPTY,
Expand Down
Expand Up @@ -392,6 +392,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down
Expand Up @@ -40,10 +40,12 @@
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public class NMSUtils {
Expand All @@ -55,6 +57,8 @@ public class NMSUtils {
private static final ReflectField<Map<Long, ChunkHolder>> VISIBLE_CHUNKS = new ReflectField<>(
ChunkMap.class, Map.class, Modifier.PUBLIC | Modifier.VOLATILE, 1);

private static final List<CompletableFuture<Void>> PENDING_CHUNK_ACTIONS = new LinkedList<>();

private NMSUtils() {

}
Expand Down Expand Up @@ -104,6 +108,9 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
Runnable onFinish) {
ChunkMap chunkMap = serverLevel.getChunkSource().chunkMap;

CompletableFuture<Void> pendingTask = new CompletableFuture<>();
PENDING_CHUNK_ACTIONS.add(pendingTask);

BukkitExecutor.createTask().runAsync(v -> {
List<Pair<ChunkPos, net.minecraft.nbt.CompoundTag>> chunkCompounds = new LinkedList<>();

Expand Down Expand Up @@ -142,9 +149,16 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,

if (onFinish != null)
onFinish.run();

pendingTask.complete(null);
PENDING_CHUNK_ACTIONS.remove(pendingTask);
});
}

public static List<CompletableFuture<Void>> getPendingChunkActions() {
return Collections.unmodifiableList(PENDING_CHUNK_ACTIONS);
}

public static ProtoChunk createProtoChunk(ChunkPos chunkPos, ServerLevel serverLevel) {
return new ProtoChunk(chunkPos,
UpgradeData.EMPTY,
Expand Down
Expand Up @@ -387,6 +387,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down
Expand Up @@ -40,10 +40,12 @@
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public class NMSUtils {
Expand All @@ -55,6 +57,8 @@ public class NMSUtils {
private static final ReflectField<Map<Long, ChunkHolder>> VISIBLE_CHUNKS = new ReflectField<>(
ChunkMap.class, Map.class, Modifier.PUBLIC | Modifier.VOLATILE, 1);

private static final List<CompletableFuture<Void>> PENDING_CHUNK_ACTIONS = new LinkedList<>();

private NMSUtils() {

}
Expand Down Expand Up @@ -104,6 +108,9 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,
Runnable onFinish) {
ChunkMap chunkMap = serverLevel.getChunkSource().chunkMap;

CompletableFuture<Void> pendingTask = new CompletableFuture<>();
PENDING_CHUNK_ACTIONS.add(pendingTask);

BukkitExecutor.createTask().runAsync(v -> {
List<Pair<ChunkPos, net.minecraft.nbt.CompoundTag>> chunkCompounds = new LinkedList<>();

Expand Down Expand Up @@ -142,9 +149,16 @@ public static void runActionOnUnloadedChunks(ServerLevel serverLevel,

if (onFinish != null)
onFinish.run();

pendingTask.complete(null);
PENDING_CHUNK_ACTIONS.remove(pendingTask);
});
}

public static List<CompletableFuture<Void>> getPendingChunkActions() {
return Collections.unmodifiableList(PENDING_CHUNK_ACTIONS);
}

public static ProtoChunk createProtoChunk(ChunkPos chunkPos, ServerLevel serverLevel) {
return new ProtoChunk(chunkPos,
UpgradeData.EMPTY,
Expand Down
Expand Up @@ -387,6 +387,18 @@ public void updateCropsTicker(List<ChunkPosition> chunkPositions, double newCrop
cropsBlockEntity.setCropGrowthMultiplier(newCropGrowthMultiplier));
}

@Override
public void shutdown() {
List<CompletableFuture<Void>> pendingTasks = NMSUtils.getPendingChunkActions();

if (pendingTasks.isEmpty())
return;

SuperiorSkyblockPlugin.log("Waiting for chunk tasks to complete.");

CompletableFuture.allOf(pendingTasks.toArray(new CompletableFuture[0])).join();
}

private static CalculatedChunk calculateChunk(ChunkPosition chunkPosition, LevelChunkSection[] chunkSections) {
KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Set<Location> spawnersLocations = new HashSet<>();
Expand Down

0 comments on commit d183663

Please sign in to comment.