Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package org.mvplugins.multiverse.inventories.profile;

import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
import org.mvplugins.multiverse.inventories.util.DataStrings;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
Expand All @@ -15,7 +19,7 @@ public final class GlobalProfile {
* @param player the player to create the profile object for.
* @return a new GlobalProfile for the given player.
*/
public static GlobalProfile createGlobalProfile(OfflinePlayer player) {
static GlobalProfile createGlobalProfile(OfflinePlayer player) {
return new GlobalProfile(player.getName(), player.getUniqueId());
}

Expand All @@ -26,7 +30,7 @@ public static GlobalProfile createGlobalProfile(OfflinePlayer player) {
* @param playerUUID the UUID of the player to create the profile for.
* @return a new GlobalProfile for the given player.
*/
public static GlobalProfile createGlobalProfile(String playerName, UUID playerUUID) {
static GlobalProfile createGlobalProfile(String playerName, UUID playerUUID) {
return new GlobalProfile(playerName, playerUUID);
}

Expand All @@ -40,6 +44,13 @@ private GlobalProfile(String name, UUID uuid) {
this.lastKnownName = name;
}

public GlobalProfile(UUID uuid, String lastWorld, String lastKnownName, boolean loadOnLogin) {
this.uuid = uuid;
this.lastWorld = lastWorld;
this.lastKnownName = lastKnownName;
this.loadOnLogin = loadOnLogin;
}

/**
* Returns the name of the player.
*
Expand Down Expand Up @@ -127,4 +138,37 @@ public String toString() {
", loadOnLogin=" + loadOnLogin +
'}';
}

/**
* Converts a global profile to a map that can be serialized into the profile data file.
*
* @param profile The global profile data.
* @return The serialized profile map.
*/
Map<String, Object> serialize(GlobalProfile profile) {
Map<String, Object> result = new HashMap<>(3);
if (profile.getLastWorld() != null) {
result.put(DataStrings.PLAYER_LAST_WORLD, profile.getLastWorld());
}
result.put(DataStrings.PLAYER_SHOULD_LOAD, profile.shouldLoadOnLogin());
result.put(DataStrings.PLAYER_LAST_KNOWN_NAME, profile.getLastKnownName());
return result;
}

/**
* Converts a configuration section to a global profile.
*
* @param playerName The player name.
* @param playerUUID The player UUID.
* @param data The configuration section to convert.
* @return The global profile.
*/
static GlobalProfile deserialize(String playerName, UUID playerUUID, ConfigurationSection data) {
return new GlobalProfile(
playerUUID,
data.getString(DataStrings.PLAYER_LAST_WORLD, null),
data.getString(DataStrings.PLAYER_LAST_KNOWN_NAME, playerName),
data.getBoolean(DataStrings.PLAYER_SHOULD_LOAD, false)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package org.mvplugins.multiverse.inventories.profile;

import org.mvplugins.multiverse.inventories.share.Sharable;
import org.mvplugins.multiverse.inventories.share.SharableEntry;
import org.mvplugins.multiverse.inventories.profile.container.ContainerType;
import org.bukkit.OfflinePlayer;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* Contains all the world/group specific data for a player.
*/
public final class PlayerProfile implements Cloneable, Iterable<SharableEntry> {
public final class PlayerProfile implements Cloneable {

public static PlayerProfile createPlayerProfile(ContainerType containerType, String containerName,
static PlayerProfile createPlayerProfile(ContainerType containerType, String containerName,
ProfileType profileType, OfflinePlayer player) {
return new PlayerProfile(containerType, containerName, profileType, player);
}

private Map<Sharable, SharableEntry> data = new HashMap<Sharable, SharableEntry>();
private final Map<Sharable, Object> data = new HashMap<>();

private final OfflinePlayer player;
private final ContainerType containerType;
Expand Down Expand Up @@ -69,8 +67,7 @@ public ProfileType getProfileType() {
* @return The value of the sharable for this profile. Null if no value is set.
*/
public <T> T get(Sharable<T> sharable) {
SharableEntry entry = this.data.get(sharable);
return sharable.getType().cast(entry != null ? entry.getValue() : null);
return sharable.getType().cast(this.data.get(sharable));
}

/**
Expand All @@ -81,7 +78,7 @@ public <T> T get(Sharable<T> sharable) {
* @param <T> The type of value to be expected.
*/
public <T> void set(Sharable<T> sharable, T value) {
this.data.put(sharable, new SharableEntry<T>(sharable, value));
this.data.put(sharable, value);
}

public PlayerProfile clone() {
Expand All @@ -92,33 +89,7 @@ public PlayerProfile clone() {
}
}

@Override
public Iterator<SharableEntry> iterator() {
return new SharablesIterator(data.values().iterator());
}

private static class SharablesIterator implements Iterator<SharableEntry> {

private final Iterator<SharableEntry> backingIterator;

private SharablesIterator(Iterator<SharableEntry> backingIterator) {
this.backingIterator = backingIterator;
}

@Override
public boolean hasNext() {
return backingIterator.hasNext();
}

@Override
public SharableEntry next() {
return backingIterator.next();
}

@Override
public void remove() {
throw new UnsupportedOperationException();
}
public Map<Sharable, Object> getData() {
return data;
}
}

Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.mvplugins.multiverse.inventories.profile;

import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Contract;
import org.mvplugins.multiverse.external.vavr.control.Option;
import org.mvplugins.multiverse.inventories.profile.container.ContainerType;

import java.io.IOException;
import java.util.UUID;
import java.util.function.Predicate;

/**
* A source for updating and retrieving player profiles via persistence.
Expand Down Expand Up @@ -40,10 +43,10 @@ public sealed interface ProfileDataSource permits FlatFileProfileDataSource {
* @param dataName The name of the world/group the player's data is associated with.
* @param profileType The type of profile we're removing, as per {@link ProfileType}. If null, this will remove
* remove all profile types.
* @param playerName The name of the player whose data is being removed.
* @param playerUUID The UUID of the player whose data is being removed.
* @return True if successfully removed.
*/
boolean removePlayerData(ContainerType containerType, String dataName, ProfileType profileType, String playerName);
boolean removePlayerData(ContainerType containerType, String dataName, ProfileType profileType, UUID playerUUID);

/**
* Retrieves the global profile for a player which contains meta-data for the player.
Expand All @@ -63,12 +66,22 @@ public sealed interface ProfileDataSource permits FlatFileProfileDataSource {

/**
* Retrieves the global profile for a player which contains meta-data for the player.
* Creates the profile if it doesn't exist.
*
* @param playerName The name of the player.
* @param playerUUID The UUID of the player.
* @return The global profile for the specified player.
*/
GlobalProfile getGlobalProfile(String playerName, UUID playerUUID);
@NotNull GlobalProfile getGlobalProfile(String playerName, UUID playerUUID);

/**
* Retrieves the global profile for a player which contains meta-data for the player if it exists.
*
* @param playerName The name of the player.
* @param playerUUID The UUID of the player.
* @return The global profile for the specified player or empty if it doesn't exist.
*/
@NotNull Option<GlobalProfile> getExistingGlobalProfile(String playerName, UUID playerUUID);

/**
* Update the file for a player's global profile.
Expand Down Expand Up @@ -109,6 +122,11 @@ public sealed interface ProfileDataSource permits FlatFileProfileDataSource {
*/
void clearProfileCache(ProfileKey key);

/**
* Clears a single profile in cache.
*/
void clearProfileCache(Predicate<ProfileKey> predicate);

/**
* Clears all profiles in cache.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.mvplugins.multiverse.inventories.profile;

import com.dumptruckman.bukkit.configuration.json.JsonConfiguration;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.external.jakarta.inject.Inject;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@Service
final class ProfileFileIO {

private final ExecutorService fileIOExecutorService = Executors.newSingleThreadExecutor();

@Inject
public ProfileFileIO() {
}

FileConfiguration waitForConfigHandle(File file) {
Future<FileConfiguration> future = fileIOExecutorService.submit(new ConfigLoader(file));
try {
return future.get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
}

FileConfiguration getConfigHandleNow(File file) throws IOException, InvalidConfigurationException {
JsonConfiguration jsonConfiguration = new JsonConfiguration();
jsonConfiguration.options().continueOnSerializationError(true);
jsonConfiguration.load(file);
return jsonConfiguration;
}

private class ConfigLoader implements Callable<FileConfiguration> {
private final File file;

private ConfigLoader(File file) {
this.file = file;
}

@Override
public FileConfiguration call() throws Exception {
return getConfigHandleNow(file);
}
}

void queueAction(Runnable action) {
fileIOExecutorService.submit(action);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void addPlayerData(PlayerProfile playerProfile) {
*/
public void removeAllPlayerData(OfflinePlayer player) {
this.getPlayerData(player.getName()).clear();
profileDataSource.removePlayerData(getContainerType(), getContainerName(), null, player.getName());
profileDataSource.removePlayerData(getContainerType(), getContainerName(), null, player.getUniqueId());
}

/**
Expand All @@ -112,7 +112,7 @@ public void removeAllPlayerData(OfflinePlayer player) {
*/
public void removePlayerData(ProfileType profileType, OfflinePlayer player) {
this.getPlayerData(player.getName()).remove(profileType);
profileDataSource.removePlayerData(getContainerType(), getContainerName(), profileType, player.getName());
profileDataSource.removePlayerData(getContainerType(), getContainerName(), profileType, player.getUniqueId());
}

/**
Expand All @@ -139,11 +139,8 @@ public ContainerType getContainerType() {
* Clears all cached data in the container.
*/
public void clearContainer() {
for (Map<ProfileType, PlayerProfile> profiles : playerData.values()) {
for (PlayerProfile profile : profiles.values()) {
profileDataSource.clearProfileCache(ProfileKey.createProfileKey(profile));
}
}
profileDataSource.clearProfileCache(key ->
key.getContainerType().equals(type) && key.getDataName().equals(name));
this.playerData.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public class DataStrings {
* Player last location identifier.
*/
public static final String PLAYER_LAST_LOCATION = "lastLocation";
/**
* Player global profile data
*/
public static final String PLAYER_DATA = "playerData";
/**
* Player last world identifier.
*/
Expand Down
Loading