Skip to content

Commit

Permalink
Added cache for calculation of unloaded chunks so they are not done m…
Browse files Browse the repository at this point in the history
…ore than once
  • Loading branch information
OmerBenGera committed Jul 9, 2022
1 parent 66b8052 commit 65ec818
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 63 deletions.
Expand Up @@ -53,7 +53,7 @@ public static List<ChunkPosition> getChunkCoords(Island island, World world, boo
}
}

return Collections.unmodifiableList(chunkCoords);
return chunkCoords;
}

public static Map<World, List<ChunkPosition>> getChunkCoords(Island island, boolean onlyProtected, boolean noEmptyChunks) {
Expand Down Expand Up @@ -98,6 +98,7 @@ public static List<CompletableFuture<Chunk>> getAllChunksAsync(Island island,
ChunkLoadReason chunkLoadReason,
BiConsumer<Chunk, Throwable> whenComplete) {
return new SequentialListBuilder<CompletableFuture<Chunk>>()
.mutable()
.build(IslandUtils.getChunkCoords(island, world, onlyProtected, noEmptyChunks), chunkPosition -> {
CompletableFuture<Chunk> completableFuture = ChunksProvider.loadChunk(chunkPosition, chunkLoadReason, null);
return whenComplete == null ? completableFuture : completableFuture.whenComplete(whenComplete);
Expand All @@ -111,6 +112,7 @@ public static List<CompletableFuture<Chunk>> getAllChunksAsync(Island island,
ChunkLoadReason chunkLoadReason,
Consumer<Chunk> onChunkLoad) {
return new SequentialListBuilder<CompletableFuture<Chunk>>()
.mutable()
.build(IslandUtils.getChunkCoords(island, world, onlyProtected, noEmptyChunks), chunkPosition ->
ChunksProvider.loadChunk(chunkPosition, chunkLoadReason, onChunkLoad));
}
Expand Down Expand Up @@ -143,7 +145,7 @@ public static List<CompletableFuture<Chunk>> getAllChunksAsync(Island island,
chunkCoords.addAll(getAllChunksAsync(island, registeredWorld, onlyProtected, noEmptyChunks, chunkLoadReason, onChunkLoad));
}

return Collections.unmodifiableList(chunkCoords);
return chunkCoords;
}

public static void updateIslandFly(Island island, SuperiorPlayer superiorPlayer) {
Expand Down
Expand Up @@ -6,18 +6,18 @@
import com.bgsoftware.superiorskyblock.api.key.Key;
import com.bgsoftware.superiorskyblock.api.key.KeyMap;
import com.bgsoftware.superiorskyblock.api.objects.Pair;
import com.bgsoftware.superiorskyblock.core.threads.BukkitExecutor;
import com.bgsoftware.superiorskyblock.core.CalculatedChunk;
import com.bgsoftware.superiorskyblock.core.ChunkPosition;
import com.bgsoftware.superiorskyblock.core.Materials;
import com.bgsoftware.superiorskyblock.core.collections.CompletableFutureList;
import com.bgsoftware.superiorskyblock.core.debug.PluginDebugger;
import com.bgsoftware.superiorskyblock.core.key.ConstantKeys;
import com.bgsoftware.superiorskyblock.core.key.KeyImpl;
import com.bgsoftware.superiorskyblock.core.key.KeyMapImpl;
import com.bgsoftware.superiorskyblock.core.collections.CompletableFutureList;
import com.bgsoftware.superiorskyblock.core.debug.PluginDebugger;
import com.bgsoftware.superiorskyblock.island.IslandUtils;
import com.bgsoftware.superiorskyblock.core.Materials;
import com.bgsoftware.superiorskyblock.core.stackedblocks.StackedBlock;
import com.bgsoftware.superiorskyblock.core.CalculatedChunk;
import com.bgsoftware.superiorskyblock.core.threads.BukkitExecutor;
import com.bgsoftware.superiorskyblock.island.IslandUtils;
import com.bgsoftware.superiorskyblock.world.chunk.ChunkLoadReason;
import com.bgsoftware.superiorskyblock.core.ChunkPosition;
import org.bukkit.Location;
import org.bukkit.block.CreatureSpawner;

Expand All @@ -29,9 +29,12 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultIslandCalculationAlgorithm implements IslandCalculationAlgorithm {

public static final Map<ChunkPosition, CalculatedChunk> CACHED_CALCULATED_CHUNKS = new ConcurrentHashMap<>();

private static final SuperiorSkyblockPlugin plugin = SuperiorSkyblockPlugin.getPlugin();

private static final DefaultIslandCalculationAlgorithm INSTANCE = new DefaultIslandCalculationAlgorithm();
Expand All @@ -50,13 +53,13 @@ public CompletableFuture<IslandCalculationResult> calculateIsland(Island island)

if (!plugin.getProviders().hasSnapshotsSupport()) {
IslandUtils.getChunkCoords(island, true, true).values().forEach(worldChunks ->
chunksToLoad.add(plugin.getNMSChunks().calculateChunks(worldChunks)));
chunksToLoad.add(plugin.getNMSChunks().calculateChunks(worldChunks, CACHED_CALCULATED_CHUNKS)));
} else {
IslandUtils.getAllChunksAsync(island, true, true, ChunkLoadReason.BLOCKS_RECALCULATE,
plugin.getProviders()::takeSnapshots).forEach(completableFuture -> {
CompletableFuture<List<CalculatedChunk>> calculateCompletable = new CompletableFuture<>();
completableFuture.whenComplete((chunk, ex) -> plugin.getNMSChunks()
.calculateChunks(Collections.singletonList(ChunkPosition.of(chunk))).whenComplete(
.calculateChunks(Collections.singletonList(ChunkPosition.of(chunk)), CACHED_CALCULATED_CHUNKS).whenComplete(
(pair, ex2) -> calculateCompletable.complete(pair)));
chunksToLoad.add(calculateCompletable);
});
Expand Down
Expand Up @@ -11,6 +11,7 @@
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

public interface NMSChunks {
Expand All @@ -19,7 +20,8 @@ public interface NMSChunks {

void deleteChunks(Island island, List<ChunkPosition> chunkPositions, Runnable onFinish);

CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions);
CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions,
Map<ChunkPosition, CalculatedChunk> unloadedChunksCache);

void injectChunkSections(Chunk chunk);

Expand Down
Expand Up @@ -3,12 +3,14 @@
import com.bgsoftware.superiorskyblock.SuperiorSkyblockPlugin;
import com.bgsoftware.superiorskyblock.api.island.Island;
import com.bgsoftware.superiorskyblock.api.world.event.WorldEventsManager;
import com.bgsoftware.superiorskyblock.core.ChunkPosition;
import com.bgsoftware.superiorskyblock.core.Singleton;
import com.bgsoftware.superiorskyblock.core.threads.BukkitExecutor;
import com.bgsoftware.superiorskyblock.island.algorithm.DefaultIslandCalculationAlgorithm;
import com.bgsoftware.superiorskyblock.listener.EntityTrackingListener;
import com.bgsoftware.superiorskyblock.module.BuiltinModules;
import com.bgsoftware.superiorskyblock.module.upgrades.type.UpgradeTypeCropGrowth;
import com.bgsoftware.superiorskyblock.module.upgrades.type.UpgradeTypeEntityLimits;
import com.bgsoftware.superiorskyblock.core.Singleton;
import com.bgsoftware.superiorskyblock.world.chunk.ChunksTracker;
import com.google.common.base.Preconditions;
import org.bukkit.Chunk;
Expand Down Expand Up @@ -50,8 +52,10 @@ public void loadChunk(Chunk chunk) {
if (cropGrowthEnabled && island.isInsideRange(chunk))
plugin.getNMSChunks().startTickingChunk(island, chunk, false);

ChunkPosition chunkPosition = ChunkPosition.of(chunk.getWorld(), chunk.getX(), chunk.getZ());

if (!plugin.getNMSChunks().isChunkEmpty(chunk))
ChunksTracker.markDirty(island, chunk, true);
ChunksTracker.markDirty(island, chunkPosition, true);

BukkitExecutor.sync(() -> {
// We want to delete old holograms of stacked blocks + count entities for the chunk
Expand Down Expand Up @@ -79,6 +83,8 @@ public void loadChunk(Chunk chunk) {
}
}

DefaultIslandCalculationAlgorithm.CACHED_CALCULATED_CHUNKS.remove(chunkPosition);

plugin.getStackedBlocks().updateStackedBlockHolograms(chunk);
}

Expand Down
Expand Up @@ -49,6 +49,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -99,7 +100,7 @@ public void setBiome(List<ChunkPosition> chunkPositions, Biome biome, Collection
WorldServer worldServer = ((CraftWorld) chunkPositions.get(0).getWorld()).getHandle();
byte biomeBase = (byte) BiomeBase.REGISTRY_ID.a(CraftBlock.biomeToBiomeBase(biome));

NMSUtils.runActionOnChunks(worldServer, chunksCoords, true, null, chunk -> {
NMSUtils.runActionOnChunks(worldServer, chunksCoords, true, null, (chunk, isLoaded) -> {
Arrays.fill(chunk.getBiomeIndex(), biomeBase);
chunk.markDirty();
}, chunk -> {
Expand All @@ -126,7 +127,7 @@ public void deleteChunks(Island island, List<ChunkPosition> chunkPositions, Runn

WorldServer worldServer = ((CraftWorld) chunkPositions.get(0).getWorld()).getHandle();

NMSUtils.runActionOnChunks(worldServer, chunksCoords, true, onFinish, chunk -> {
NMSUtils.runActionOnChunks(worldServer, chunksCoords, true, onFinish, (chunk, isLoaded) -> {
Arrays.fill(chunk.getSections(), Chunk.a);

removeEntities(chunk);
Expand All @@ -143,18 +144,33 @@ public void deleteChunks(Island island, List<ChunkPosition> chunkPositions, Runn
}

@Override
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions) {
CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions,
Map<ChunkPosition, CalculatedChunk> unloadedChunksCache) {
List<CalculatedChunk> allCalculatedChunks = new LinkedList<>();
List<ChunkCoordIntPair> chunksCoords = new LinkedList<>();

Iterator<ChunkPosition> chunkPositionsIterator = chunkPositions.iterator();
while (chunkPositionsIterator.hasNext()) {
ChunkPosition chunkPosition = chunkPositionsIterator.next();
CalculatedChunk cachedCalculatedChunk = unloadedChunksCache.get(chunkPosition);
if (cachedCalculatedChunk != null) {
allCalculatedChunks.add(cachedCalculatedChunk);
chunkPositionsIterator.remove();
} else {
chunksCoords.add(new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
}
}

List<ChunkCoordIntPair> chunksCoords = new SequentialListBuilder<ChunkCoordIntPair>()
.build(chunkPositions, chunkPosition -> new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
if (chunkPositions.isEmpty())
return CompletableFuture.completedFuture(allCalculatedChunks);

CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();

WorldServer worldServer = ((CraftWorld) chunkPositions.get(0).getWorld()).getHandle();

NMSUtils.runActionOnChunks(worldServer, chunksCoords, false, () -> {
completableFuture.complete(allCalculatedChunks);
}, chunk -> {
}, (chunk, isLoaded) -> {
ChunkPosition chunkPosition = ChunkPosition.of(worldServer.getWorld(), chunk.locX, chunk.locZ);

KeyMap<Integer> blockCounts = KeyMapImpl.createHashMap();
Expand Down Expand Up @@ -194,7 +210,10 @@ public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPositi
}
}

allCalculatedChunks.add(new CalculatedChunk(chunkPosition, blockCounts, spawnersLocations));
CalculatedChunk calculatedChunk = new CalculatedChunk(chunkPosition, blockCounts, spawnersLocations);
allCalculatedChunks.add(calculatedChunk);
if (!isLoaded)
unloadedChunksCache.put(chunkPosition, calculatedChunk);
}, null);

return completableFuture;
Expand Down
Expand Up @@ -29,6 +29,7 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class NMSUtils {
Expand All @@ -50,7 +51,7 @@ private NMSUtils() {
}

public static void runActionOnChunks(WorldServer worldServer, Collection<ChunkCoordIntPair> chunksCoords,
boolean saveChunks, Runnable onFinish, Consumer<Chunk> chunkConsumer,
boolean saveChunks, Runnable onFinish, BiConsumer<Chunk, Boolean> chunkConsumer,
Consumer<Chunk> updateChunk) {
List<ChunkCoordIntPair> unloadedChunks = new LinkedList<>();
List<Chunk> loadedChunks = new LinkedList<>();
Expand All @@ -67,7 +68,7 @@ public static void runActionOnChunks(WorldServer worldServer, Collection<ChunkCo

boolean hasUnloadedChunks = !unloadedChunks.isEmpty();

loadedChunks.forEach(chunkConsumer);
loadedChunks.forEach(loadedChunk -> chunkConsumer.accept(loadedChunk, true));

if (updateChunk != null)
loadedChunks.forEach(updateChunk);
Expand All @@ -80,7 +81,7 @@ public static void runActionOnChunks(WorldServer worldServer, Collection<ChunkCo
}

public static void runActionOnUnloadedChunks(WorldServer worldServer, Collection<ChunkCoordIntPair> chunks,
boolean saveChunks, Consumer<Chunk> chunkConsumer,
boolean saveChunks, BiConsumer<Chunk, Boolean> chunkConsumer,
Runnable onFinish) {
IChunkLoader chunkLoader = chunkLoadersMap.computeIfAbsent(worldServer.getDataManager().getUUID(),
uuid -> CHUNK_LOADER.get(worldServer.getChunkProvider()));
Expand All @@ -94,7 +95,7 @@ public static void runActionOnUnloadedChunks(WorldServer worldServer, Collection
Chunk loadedChunk = chunkLoader.a(worldServer, chunkCoords.x, chunkCoords.z);

if (loadedChunk != null) {
chunkConsumer.accept(loadedChunk);
chunkConsumer.accept(loadedChunk, false);

if (saveChunks) {
if (SAVE_CHUNK.isValid())
Expand Down
Expand Up @@ -65,6 +65,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -198,12 +199,27 @@ public void deleteChunks(Island island, List<ChunkPosition> chunkPositions, Runn
}

@Override
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions) {
CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions,
Map<ChunkPosition, CalculatedChunk> unloadedChunksCache) {
List<CalculatedChunk> allCalculatedChunks = new LinkedList<>();
List<ChunkCoordIntPair> chunksCoords = new LinkedList<>();

Iterator<ChunkPosition> chunkPositionsIterator = chunkPositions.iterator();
while (chunkPositionsIterator.hasNext()) {
ChunkPosition chunkPosition = chunkPositionsIterator.next();
CalculatedChunk cachedCalculatedChunk = unloadedChunksCache.get(chunkPosition);
if (cachedCalculatedChunk != null) {
allCalculatedChunks.add(cachedCalculatedChunk);
chunkPositionsIterator.remove();
} else {
chunksCoords.add(new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
}
}

List<ChunkCoordIntPair> chunksCoords = new SequentialListBuilder<ChunkCoordIntPair>()
.build(chunkPositions, chunkPosition -> new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
if (chunkPositions.isEmpty())
return CompletableFuture.completedFuture(allCalculatedChunks);

CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();

WorldServer worldServer = ((CraftWorld) chunkPositions.get(0).getWorld()).getHandle();

Expand All @@ -227,7 +243,9 @@ public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPositi
}

ChunkPosition chunkPosition = ChunkPosition.of(worldServer.getWorld(), chunkCoords.x, chunkCoords.z);
allCalculatedChunks.add(calculateChunk(chunkPosition, chunkSections));
CalculatedChunk calculatedChunk = calculateChunk(chunkPosition, chunkSections);
allCalculatedChunks.add(calculatedChunk);
unloadedChunksCache.put(chunkPosition, calculatedChunk);
});

return completableFuture;
Expand Down
Expand Up @@ -72,6 +72,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -200,12 +201,27 @@ public void deleteChunks(Island island, List<ChunkPosition> chunkPositions, Runn
}

@Override
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions) {
CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();
public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPosition> chunkPositions,
Map<ChunkPosition, CalculatedChunk> unloadedChunksCache) {
List<CalculatedChunk> allCalculatedChunks = new LinkedList<>();
List<ChunkCoordIntPair> chunksCoords = new LinkedList<>();

Iterator<ChunkPosition> chunkPositionsIterator = chunkPositions.iterator();
while (chunkPositionsIterator.hasNext()) {
ChunkPosition chunkPosition = chunkPositionsIterator.next();
CalculatedChunk cachedCalculatedChunk = unloadedChunksCache.get(chunkPosition);
if (cachedCalculatedChunk != null) {
allCalculatedChunks.add(cachedCalculatedChunk);
chunkPositionsIterator.remove();
} else {
chunksCoords.add(new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
}
}

List<ChunkCoordIntPair> chunksCoords = new SequentialListBuilder<ChunkCoordIntPair>()
.build(chunkPositions, chunkPosition -> new ChunkCoordIntPair(chunkPosition.getX(), chunkPosition.getZ()));
if (chunkPositions.isEmpty())
return CompletableFuture.completedFuture(allCalculatedChunks);

CompletableFuture<List<CalculatedChunk>> completableFuture = new CompletableFuture<>();

WorldServer worldServer = ((CraftWorld) chunkPositions.get(0).getWorld()).getHandle();

Expand All @@ -229,7 +245,9 @@ public CompletableFuture<List<CalculatedChunk>> calculateChunks(List<ChunkPositi
}

ChunkPosition chunkPosition = ChunkPosition.of(worldServer.getWorld(), chunkCoords.b, chunkCoords.c);
allCalculatedChunks.add(calculateChunk(chunkPosition, chunkSections));
CalculatedChunk calculatedChunk = calculateChunk(chunkPosition, chunkSections);
allCalculatedChunks.add(calculatedChunk);
unloadedChunksCache.put(chunkPosition, calculatedChunk);
});

return completableFuture;
Expand Down

0 comments on commit 65ec818

Please sign in to comment.