Skip to content

Commit

Permalink
Optimized the way islands are cached in memory
Browse files Browse the repository at this point in the history
  • Loading branch information
OmerBenGera committed Jun 11, 2022
1 parent d24181d commit a5a5cfe
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 39 deletions.
@@ -1,6 +1,5 @@
package com.bgsoftware.superiorskyblock.api.handlers;

import com.bgsoftware.superiorskyblock.api.data.DatabaseBridge;
import com.bgsoftware.superiorskyblock.api.data.IDatabaseBridgeHolder;
import com.bgsoftware.superiorskyblock.api.island.Island;
import com.bgsoftware.superiorskyblock.api.island.IslandPreview;
Expand Down Expand Up @@ -119,8 +118,10 @@ void createIsland(SuperiorPlayer superiorPlayer, String schemName, BigDecimal bo
*
* @param superiorPlayer The player to check.
* @return The island of the player. May be null.
* @deprecated See {@link SuperiorPlayer#getIsland()}
*/
@Nullable
@Deprecated
Island getIsland(SuperiorPlayer superiorPlayer);

/**
Expand Down Expand Up @@ -149,8 +150,10 @@ void createIsland(SuperiorPlayer superiorPlayer, String schemName, BigDecimal bo
*
* @param uuid The uuid of the owner.
* @return The island of the owner. May be null.
* @deprecated See {@link SuperiorPlayer#getIsland()}
*/
@Nullable
@Deprecated
Island getIsland(UUID uuid);

/**
Expand Down
@@ -1,5 +1,6 @@
package com.bgsoftware.superiorskyblock.api.island.container;

import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI;
import com.bgsoftware.superiorskyblock.api.island.Island;
import com.bgsoftware.superiorskyblock.api.island.SortingType;
import com.bgsoftware.superiorskyblock.api.wrappers.SuperiorPlayer;
Expand Down Expand Up @@ -37,9 +38,13 @@ public interface IslandsContainer {
* Get an island by its leader's uuid.
*
* @param uuid The uuid of the island's leader.
* @deprecated Not supported anymore.
*/
@Nullable
Island getIslandByLeader(UUID uuid);
@Deprecated
default Island getIslandByLeader(UUID uuid) {
return SuperiorSkyblockAPI.getGrid().getIsland(uuid);
}

/**
* Get an island by its position in the top-islands.
Expand Down Expand Up @@ -78,8 +83,12 @@ public interface IslandsContainer {
*
* @param oldLeader The uuid of the current leader.
* @param newLeader The uuid of the new leader.
* @deprecated Not supported anymore.
*/
void transferIsland(UUID oldLeader, UUID newLeader);
@Deprecated
default void transferIsland(UUID oldLeader, UUID newLeader) {

}

/**
* Sort islands for the top-islands.
Expand Down
Expand Up @@ -65,7 +65,7 @@ public void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, String[
return;
}
} else {
if ((island = plugin.getGrid().getIsland(targetPlayer)) == null || !island.isInvited(superiorPlayer)) {
if ((island = targetPlayer.getIsland()) == null || !island.isInvited(superiorPlayer)) {
Message.NO_ISLAND_INVITE.send(superiorPlayer);
return;
}
Expand Down
Expand Up @@ -98,7 +98,6 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -1304,8 +1303,6 @@ public boolean transferIsland(SuperiorPlayer superiorPlayer) {
IslandsDatabaseBridge.saveIslandLeader(this);
IslandsDatabaseBridge.addMember(this, previousOwner, getCreationTime());

plugin.getGrid().transferIsland(previousOwner.getUniqueId(), owner.getUniqueId());

plugin.getMissions().getAllMissions().forEach(mission -> mission.transferData(previousOwner, owner));

return true;
Expand All @@ -1319,7 +1316,6 @@ public void replacePlayers(SuperiorPlayer originalPlayer, SuperiorPlayer newPlay
if (owner == originalPlayer) {
owner = newPlayer;
IslandsDatabaseBridge.saveIslandLeader(this);
plugin.getGrid().transferIsland(originalPlayer.getUniqueId(), owner.getUniqueId());
} else if (isMember(originalPlayer)) {
members.write(members -> {
members.remove(originalPlayer);
Expand Down
Expand Up @@ -5,7 +5,10 @@
import com.bgsoftware.superiorskyblock.api.island.SortingType;
import com.bgsoftware.superiorskyblock.api.island.container.IslandsContainer;
import com.bgsoftware.superiorskyblock.island.IslandPosition;
import com.bgsoftware.superiorskyblock.structure.SortedRegistry;
import com.bgsoftware.superiorskyblock.threads.Executor;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.jetbrains.annotations.Nullable;
Expand All @@ -14,19 +17,19 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Predicate;

public final class DefaultIslandsContainer implements IslandsContainer {

private static final Predicate<Island> ISLANDS_PREDICATE = island -> !island.isIgnored();

private final SortedRegistry<UUID, Island, SortingType> sortedIslands = new SortedRegistry<>(ISLANDS_PREDICATE);
private final Map<IslandPosition, Island> islandsByPositions = new ConcurrentHashMap<>();
private final Map<UUID, Island> islandsByUUID = new ConcurrentHashMap<>();

private final Map<SortingType, Set<Island>> sortedIslands = new ConcurrentHashMap<>();

private final SuperiorSkyblockPlugin plugin;

public DefaultIslandsContainer(SuperiorSkyblockPlugin plugin) {
Expand All @@ -48,17 +51,19 @@ public void addIsland(Island island) {
}

this.islandsByUUID.put(island.getUniqueId(), island);
this.sortedIslands.put(island.getOwner().getUniqueId(), island);

sortedIslands.values().forEach(sortedIslands -> sortedIslands.add(island));
}

@Override
public void removeIsland(Island island) {
Location islandLocation = island.getCenter(plugin.getSettings().getWorlds().getDefaultWorld());

sortedIslands.remove(island.getOwner().getUniqueId());
islandsByUUID.remove(island.getUniqueId());
islandsByPositions.remove(IslandPosition.of(islandLocation));

sortedIslands.values().forEach(sortedIslands -> sortedIslands.remove(island));

if (plugin.getProviders().hasCustomWorldsSupport()) {
runWithCustomWorld(islandLocation, island, World.Environment.NORMAL,
location -> islandsByPositions.remove(IslandPosition.of(location)));
Expand All @@ -75,21 +80,27 @@ public Island getIslandByUUID(UUID uuid) {
return this.islandsByUUID.get(uuid);
}

@Nullable
@Override
public Island getIslandByLeader(UUID uuid) {
return this.sortedIslands.get(uuid);
}

@Nullable
@Override
public Island getIslandAtPosition(int position, SortingType sortingType) {
return position < 0 || position > getIslandsAmount() ? null : this.sortedIslands.get(position, sortingType);
ensureSortingType(sortingType);

if (position < 0 || position > getIslandsAmount()) {
return null;
}

Set<Island> sortedIslands = this.sortedIslands.get(sortingType);

return Iterables.get(sortedIslands, position);
}

@Override
public int getIslandPosition(Island island, SortingType sortingType) {
return this.sortedIslands.indexOf(island, sortingType);
ensureSortingType(sortingType);

Set<Island> sortedIslands = this.sortedIslands.get(sortingType);

return Iterables.indexOf(sortedIslands, island::equals);
}

@Override
Expand All @@ -104,26 +115,34 @@ public Island getIslandAt(Location location) {
return island == null || !island.isInside(location) ? null : island;
}

@Override
public void transferIsland(UUID oldOwner, UUID newOwner) {
Island island = sortedIslands.get(oldOwner);
sortedIslands.remove(oldOwner);
sortedIslands.put(newOwner, island);
}

@Override
public void sortIslands(SortingType sortingType, Runnable onFinish) {
this.sortIslands(sortingType, false, onFinish);
}

@Override
public void sortIslands(SortingType sortingType, boolean forceSort, Runnable onFinish) {
this.sortedIslands.sort(sortingType, forceSort, onFinish);
ensureSortingType(sortingType);

Set<Island> sortedIslands = this.sortedIslands.get(sortingType);

if (!forceSort && sortedIslands.size() <= 1) {
if (onFinish != null)
onFinish.run();
return;
}

if (Bukkit.isPrimaryThread()) {
Executor.async(() -> sortIslandsInternal(sortingType, onFinish));
} else {
sortIslandsInternal(sortingType, onFinish);
}
}

@Override
public List<Island> getSortedIslands(SortingType sortingType) {
return this.sortedIslands.getIslands(sortingType);
ensureSortingType(sortingType);
return Collections.unmodifiableList(new ArrayList<>(this.sortedIslands.get(sortingType)));
}

@Override
Expand All @@ -133,7 +152,8 @@ public List<Island> getIslandsUnsorted() {

@Override
public void addSortingType(SortingType sortingType, boolean sort) {
this.sortedIslands.registerSortingType(sortingType, sort);
Preconditions.checkArgument(!sortedIslands.containsKey(sortingType), "You cannot register an existing sorting type to the database.");
sortIslandsInternal(sortingType, null);
}

private void runWithCustomWorld(Location islandLocation, Island island, World.Environment environment, Consumer<Location> onSuccess) {
Expand All @@ -145,4 +165,22 @@ private void runWithCustomWorld(Location islandLocation, Island island, World.En
}
}

private void ensureSortingType(SortingType sortingType) {
Preconditions.checkState(sortedIslands.containsKey(sortingType), "The sorting-type " + sortingType + " doesn't exist in the database. Please contact author!");
}

private void sortIslandsInternal(SortingType sortingType, Runnable onFinish) {
Set<Island> newSortedTree = new TreeSet<>(sortingType);

for (Island island : islandsByUUID.values()) {
if (!island.isIgnored())
newSortedTree.add(island);
}

this.sortedIslands.put(sortingType, newSortedTree);

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

}
Expand Up @@ -332,7 +332,7 @@ public void deleteIsland(Island island) {
@Override
public Island getIsland(SuperiorPlayer superiorPlayer) {
Preconditions.checkNotNull(superiorPlayer, "superiorPlayer parameter cannot be null.");
return getIsland(superiorPlayer.getIslandLeader().getUniqueId());
return superiorPlayer.getIsland();
}

@Override
Expand All @@ -351,7 +351,8 @@ public int getIslandPosition(Island island, SortingType sortingType) {
@Override
public Island getIsland(UUID uuid) {
Preconditions.checkNotNull(uuid, "uuid parameter cannot be null.");
return this.islandsContainer.getIslandByLeader(uuid);
SuperiorPlayer superiorPlayer = plugin.getPlayers().getPlayersContainer().getSuperiorPlayer(uuid);
return superiorPlayer == null ? null : getIsland(superiorPlayer);
}

@Override
Expand Down Expand Up @@ -406,9 +407,7 @@ public Island getIslandAt(Chunk chunk) {

@Override
public void transferIsland(UUID oldOwner, UUID newOwner) {
Preconditions.checkNotNull(oldOwner, "oldOwner parameter cannot be null.");
Preconditions.checkNotNull(newOwner, "newOwner parameter cannot be null.");
this.islandsContainer.transferIsland(oldOwner, newOwner);
// Do nothing.
}

@Override
Expand Down Expand Up @@ -631,7 +630,7 @@ public UUID generateIslandUUID() {

do {
uuid = UUID.randomUUID();
} while (getIslandByUUID(uuid) != null || getIsland(uuid) != null);
} while (getIslandByUUID(uuid) != null || plugin.getPlayers().getPlayersContainer().getSuperiorPlayer(uuid) != null);

return uuid;
}
Expand Down

0 comments on commit a5a5cfe

Please sign in to comment.