PlayerManagerCommon.java
package team.aura_dev.auraban.platform.common.player;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import lombok.Data;
import lombok.NonNull;
import org.slf4j.Logger;
import team.aura_dev.auraban.api.player.PlayerData;
import team.aura_dev.auraban.api.player.PlayerManager;
import team.aura_dev.auraban.platform.common.AuraBanBase;
import team.aura_dev.auraban.platform.common.storage.StorageEngine;
public abstract class PlayerManagerCommon implements PlayerManager {
protected static final Logger logger = AuraBanBase.logger;
protected final StorageEngine storageEngine;
protected final LoadingCache<UUID, CompletableFuture<Optional<PlayerData>>> playerCache;
protected PlayerManagerCommon(@Nonnull @NonNull StorageEngine storageEngine) {
this.storageEngine = storageEngine;
playerCache =
Caffeine.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build(storageEngine::loadPlayerData);
}
@SuppressFBWarnings(
value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE",
justification = "SpotBugs is incorrect in this case")
@Override
public Optional<PlayerData> getPlayerData(@Nonnull @NonNull UUID uuid) {
try {
return playerCache.get(uuid).get();
} catch (InterruptedException | ExecutionException e) {
logger.warn("Exception while trying to load player " + uuid, e);
return Optional.empty();
}
}
@Override
public PlayerData fromNativePlayer(@Nonnull @NonNull Object player)
throws IllegalArgumentException {
final BasePlayerData playerData = nativePlayerToBasePlayerData(player);
final UUID uuid = playerData.getUuid();
CompletableFuture<Optional<PlayerData>> cacheData = playerCache.getIfPresent(uuid);
if (cacheData != null) {
try {
Optional<PlayerData> optionalPlayerData = cacheData.get();
if (optionalPlayerData.isPresent()) {
return optionalPlayerData.get();
}
} catch (InterruptedException | ExecutionException e) {
logger.warn("Exception while trying to load player " + uuid, e);
}
}
CompletableFuture<PlayerData> newData =
storageEngine.loadAndUpdatePlayerData(uuid, playerData.getPlayerName());
playerCache.put(uuid, newData.thenApply(Optional::of));
try {
return newData.get();
} catch (InterruptedException | ExecutionException e) {
logger.warn("Exception while trying to load player " + uuid, e);
return null;
}
}
/**
* This method removes the specified player from the cache
*
* @param uuid The {@link UUID} of the player to remove
*/
public void unloadPlayer(@Nonnull @NonNull UUID uuid) {
playerCache.invalidate(uuid);
}
/**
* This method removes the specified player from the cache
*
* @param player The player to remove
*/
public void unloadPlayer(@Nonnull @NonNull PlayerData player) {
unloadPlayer(player.getUuid());
}
/**
* Collects the {@link UUID} and player name of a native player
*
* @param player The native player object to convert
* @return A {@link BasePlayerData} object that contains the data from the native player.
* @throws IllegalArgumentException when the object is not a native player object.
*/
protected abstract BasePlayerData nativePlayerToBasePlayerData(@Nonnull Object player)
throws IllegalArgumentException;
@Data
public static class BasePlayerData {
@NonNull private final UUID uuid;
@NonNull private final String playerName;
}
}