Skip to content
Merged
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ dependencies {
exclude group: 'junit', module: 'junit'
}

// Caching
shadowed("com.github.ben-manes.caffeine:caffeine:3.2.0")

// Other plugins for import
compileOnly('uk.co:MultiInv:3.0.6') {
exclude group: '*', module: '*'
Expand All @@ -64,6 +67,8 @@ shadowJar {
relocate 'com.dumptruckman.minecraft.util.DebugLog', 'org.mvplugins.multiverse.inventories.utils.DebugFileLogger'
relocate 'com.dumptruckman.bukkit.configuration', 'org.mvplugins.multiverse.inventories.utils.configuration'
relocate 'net.minidev', 'org.mvplugins.multiverse.inventories.utils.minidev'
relocate 'com.github.benmanes', 'org.mvplugins.multiverse.inventories.utils.benmanes'
relocate 'com.google.errorprone', 'org.mvplugins.multiverse.inventories.utils.errorprone'

dependencies {
exclude(dependency {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.mvplugins.multiverse.inventories.commands;

import com.google.common.cache.CacheStats;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import org.bukkit.entity.Player;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
Expand Down Expand Up @@ -38,7 +38,6 @@ void onCacheStatsCommand(MVCommandIssuer issuer) {
issuer.sendMessage(" hits count: " + entry.getValue().hitCount());
issuer.sendMessage(" misses count: " + entry.getValue().missCount());
issuer.sendMessage(" loads count: " + entry.getValue().loadCount());
issuer.sendMessage(" exceptions: " + entry.getValue().loadExceptionCount());
issuer.sendMessage(" evictions: " + entry.getValue().evictionCount());
issuer.sendMessage(" hit rate: " + entry.getValue().hitRate() * 100 + "%");
issuer.sendMessage(" miss rate: " + entry.getValue().missRate() * 100 + "%");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.List;

/**
* Provides methods for interacting with the configuration of Multiverse-Inventories.
Expand Down Expand Up @@ -200,6 +201,21 @@ public Try<Void> setAlwaysWriteWorldProfile(boolean alwaysWriteWorldProfile) {
return this.configHandle.set(configNodes.alwaysWriteWorldProfile, alwaysWriteWorldProfile);
}

public List<String> getPreloadDataOnJoinWorlds() {
return this.configHandle.get(configNodes.preloadDataOnJoinWorlds);
}

public Try<Void> setPreloadDataOnJoinWorlds(List<String> preloadDataOnJoinWorlds) {
return this.configHandle.set(configNodes.preloadDataOnJoinWorlds, preloadDataOnJoinWorlds);
}

public List<String> getPreloadDataOnJoinGroups() {
return this.configHandle.get(configNodes.preloadDataOnJoinGroups);
}

public Try<Void> setPreloadDataOnJoinGroups(List<String> preloadDataOnJoinGroups) {
return this.configHandle.set(configNodes.preloadDataOnJoinGroups, preloadDataOnJoinGroups);
}

public int getPlayerFileCacheSize() {
return this.configHandle.get(configNodes.playerFileCacheSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import org.mvplugins.multiverse.core.configuration.functions.NodeSerializer;
import org.mvplugins.multiverse.core.configuration.node.ConfigHeaderNode;
import org.mvplugins.multiverse.core.configuration.node.ConfigNode;
import org.mvplugins.multiverse.core.configuration.node.ListConfigNode;
import org.mvplugins.multiverse.core.configuration.node.Node;
import org.mvplugins.multiverse.core.configuration.node.NodeGroup;
import org.mvplugins.multiverse.inventories.share.Sharables;
import org.mvplugins.multiverse.inventories.share.Shares;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -160,6 +162,20 @@ public Object serialize(Shares sharables, Class<Shares> aClass) {
.name("always-write-world-profile")
.build());

private final ConfigHeaderNode preloadHeader = node(ConfigHeaderNode.builder("performance.preload-data-on-join")
.comment("")
.build());

final ListConfigNode<String> preloadDataOnJoinWorlds = node(ListConfigNode.listBuilder("performance.preload-data-on-join.worlds", String.class)
.defaultValue(ArrayList::new)
.name("preload-data-on-join-worlds")
.build());

final ListConfigNode<String> preloadDataOnJoinGroups = node(ListConfigNode.listBuilder("performance.preload-data-on-join.groups", String.class)
.defaultValue(ArrayList::new)
.name("preload-data-on-join-groups")
.build());

private final ConfigHeaderNode cacheHeader = node(ConfigHeaderNode.builder("performance.cache")
.comment("")
.comment("NOTE: Cache options require a server restart to take effect.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ private void mergeData(OfflinePlayer player, MIPlayerFileLoader playerFileLoader
Logging.warning("Could not import player data for group: " + dataName);
return;
}
playerProfile = group.getGroupProfileContainer().getPlayerData(ProfileTypes.SURVIVAL, player);
playerProfile = group.getGroupProfileContainer().getPlayerDataNow(ProfileTypes.SURVIVAL, player);
} else {
playerProfile = profileContainerStoreProvider.getStore(type)
.getContainer(dataName).getPlayerData(ProfileTypes.SURVIVAL, player);
.getContainer(dataName).getPlayerDataNow(ProfileTypes.SURVIVAL, player);
}
MIInventoryInterface inventoryInterface =
playerFileLoader.getInventory(GameMode.SURVIVAL.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private void saveMVDataForGroup(Group group) throws DataImportException {
}

private void saveMVDataForPlayer(Group group, OfflinePlayer offlinePlayer) throws DataImportException {
GlobalProfile globalProfile = profileDataSource.getGlobalProfile(offlinePlayer);
GlobalProfile globalProfile = profileDataSource.getGlobalProfileNow(offlinePlayer);
globalProfile.setLoadOnLogin(pwiSettings.getProperty(PluginSettings.LOAD_DATA_ON_JOIN));
profileDataSource.updateGlobalProfile(globalProfile);
for (GameMode gameMode : GameMode.values()) {
Expand All @@ -205,10 +205,10 @@ private void saveMVDataForPlayer(Group group, OfflinePlayer offlinePlayer) throw
private List<PlayerProfile> getMVPlayerData(
@NotNull OfflinePlayer offlinePlayer, @NotNull Group group, @NotNull GameMode gameMode) {
List<PlayerProfile> profiles = new ArrayList<>();
profiles.add(profileDataSource.getPlayerData(org.mvplugins.multiverse.inventories.profile.ProfileKey
profiles.add(profileDataSource.getPlayerDataNow(org.mvplugins.multiverse.inventories.profile.ProfileKey
.create(ContainerType.GROUP, group.getName(), ProfileTypes.forGameMode(gameMode), offlinePlayer.getUniqueId())));
for (var worldName : group.getWorlds()) {
profiles.add(profileDataSource.getPlayerData(org.mvplugins.multiverse.inventories.profile.ProfileKey
profiles.add(profileDataSource.getPlayerDataNow(org.mvplugins.multiverse.inventories.profile.ProfileKey
.create(ContainerType.WORLD, worldName, ProfileTypes.forGameMode(gameMode), offlinePlayer.getUniqueId())));
}
return profiles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ private Set<ProfileContainer> getWorldsWithoutGroups() {
}

private void transferData(OfflinePlayer player, Group wiGroup, ProfileContainer profileContainer) {
PlayerProfile playerProfile = profileContainer.getPlayerData(ProfileTypes.SURVIVAL, player);
PlayerProfile playerProfile = profileContainer.getPlayerDataNow(ProfileTypes.SURVIVAL, player);
WIPlayerInventory wiInventory = this.loadPlayerInventory(player, wiGroup);
WIPlayerStats wiStats = this.loadPlayerStats(player, wiGroup);
if (wiInventory != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ public abstract class ShareHandlingEvent extends Event implements Cancellable {
private boolean cancelled;

private final Player player;
private final PersistingProfile alwaysWriteProfile;
private final List<PersistingProfile> writeProfiles;
private final List<PersistingProfile> readProfiles;

ShareHandlingEvent(Player player, AffectedProfiles affectedProfiles) {
this.player = player;
this.alwaysWriteProfile = affectedProfiles.getAlwaysWriteProfile();
this.writeProfiles = affectedProfiles.getWriteProfiles();
this.readProfiles = affectedProfiles.getReadProfiles();
}
Expand All @@ -44,17 +42,7 @@ public void setCancelled(boolean cancel) {
}

/**
* Returns the profile that will always be saved to. By default, this is a profile for the world the player was in.
*
* @return The profile that will always be saved to when this event occurs.
*/
public PersistingProfile getAlwaysWriteProfile() {
return alwaysWriteProfile;
}

/**
* @return The profiles for the world/groups the player is coming from that data will be saved to in addition to
* the profile returned by {@link #getAlwaysWriteProfile()}.
* @return The profiles for the world/groups the player is coming from that data will be saved to.
*/
public List<PersistingProfile> getWriteProfiles() {
return this.writeProfiles;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,32 @@

import java.util.LinkedList;
import java.util.List;

import static org.mvplugins.multiverse.inventories.share.Sharables.enabled;
import java.util.concurrent.CompletableFuture;

public final class AffectedProfiles {

private PersistingProfile alwaysWriteProfile;
private final List<PersistingProfile> writeProfiles = new LinkedList<>();
private final List<PersistingProfile> readProfiles = new LinkedList<>();

AffectedProfiles() {
}

void setAlwaysWriteProfile(PlayerProfile profile) {
alwaysWriteProfile = new PersistingProfile(enabled(), profile);
}

/**
* @param profile The player profile that will need data saved to.
* @param shares What from this group needs to be saved.
*/
void addWriteProfile(PlayerProfile profile, Shares shares) {
void addWriteProfile(CompletableFuture<PlayerProfile> profile, Shares shares) {
writeProfiles.add(new PersistingProfile(shares, profile));
}

/**
* @param profile The player profile that will need data loaded from.
* @param shares What from this group needs to be loaded.
*/
void addReadProfile(PlayerProfile profile, Shares shares) {
void addReadProfile(CompletableFuture<PlayerProfile> profile, Shares shares) {
readProfiles.add(new PersistingProfile(shares, profile));
}

public PersistingProfile getAlwaysWriteProfile() {
return alwaysWriteProfile;
}

public List<PersistingProfile> getWriteProfiles() {
return writeProfiles;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.mvplugins.multiverse.inventories.profile.ProfileTypes;
import org.mvplugins.multiverse.inventories.profile.container.ProfileContainer;
import org.mvplugins.multiverse.inventories.share.Sharables;
import org.mvplugins.multiverse.inventories.share.Shares;
import org.mvplugins.multiverse.inventories.util.Perm;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
Expand Down Expand Up @@ -49,13 +50,19 @@ protected ShareHandlingEvent createEvent() {

@Override
protected void prepareProfiles() {
Logging.finer("=== " + player.getName() + " changing game mode from: " + fromType
Logging.fine("=== " + player.getName() + " changing game mode from: " + fromType
+ " to: " + toType + " for world: " + world + " ===");

affectedProfiles.setAlwaysWriteProfile(worldProfileContainerStore.getContainer(world).getPlayerData(fromType, player));

if (isPlayerAffectedByChange()) {
addProfiles();
} else if (inventoriesConfig.getAlwaysWriteWorldProfile()) {
// Write to world profile to ensure data is saved incase bypass is removed
affectedProfiles.addWriteProfile(
worldProfileContainerStore.getContainer(world).getPlayerData(player),
(worldGroups.isEmpty() && !inventoriesConfig.getUseOptionalsForUngroupedWorlds())
? Sharables.standard()
: Sharables.enabled()
);
}
}

Expand All @@ -73,22 +80,28 @@ private boolean isPlayerBypassingChange() {
}

private void addProfiles() {
if (hasWorldGroups()) {
worldGroups.forEach(this::addProfilesForWorldGroup);
} else {
Logging.finer("No groups for world.");
affectedProfiles.addReadProfile(worldProfileContainerStore.getContainer(world).getPlayerData(toType, player),
inventoriesConfig.getUseOptionalsForUngroupedWorlds() ? Sharables.enabled() : Sharables.standardOf());
Shares handledShares = Sharables.noneOf();
worldGroups.forEach(worldGroup -> addProfilesForWorldGroup(handledShares,worldGroup));
Shares unhandledShares = Sharables.enabledOf().setSharing(handledShares, false);
if (!unhandledShares.isEmpty()) {
affectedProfiles.addReadProfile(worldProfileContainerStore.getContainer(world).getPlayerData(fromType, player), unhandledShares);
}
}

private boolean hasWorldGroups() {
return !worldGroups.isEmpty();
if (inventoriesConfig.getAlwaysWriteWorldProfile()) {
affectedProfiles.addWriteProfile(worldProfileContainerStore.getContainer(world).getPlayerData(toType, player),
inventoriesConfig.getUseOptionalsForUngroupedWorlds() ? Sharables.enabled() : Sharables.standard());
} else {
if (!unhandledShares.isEmpty()) {
affectedProfiles.addWriteProfile(worldProfileContainerStore.getContainer(world).getPlayerData(toType, player), unhandledShares);
}
}
}

private void addProfilesForWorldGroup(WorldGroup worldGroup) {
private void addProfilesForWorldGroup(Shares handledShares, WorldGroup worldGroup) {
ProfileContainer container = worldGroup.getGroupProfileContainer();
affectedProfiles.addWriteProfile(container.getPlayerData(fromType, player), Sharables.enabled());
affectedProfiles.addReadProfile(container.getPlayerData(toType, player), Sharables.enabled());
affectedProfiles.addWriteProfile(container.getPlayerData(fromType, player), worldGroup.getApplicableShares());
affectedProfiles.addReadProfile(container.getPlayerData(toType, player), worldGroup.getApplicableShares());
handledShares.addAll(worldGroup.getApplicableShares());
handledShares.addAll(worldGroup.getDisabledShares());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,33 @@
import org.mvplugins.multiverse.inventories.profile.PlayerProfile;
import org.mvplugins.multiverse.inventories.share.Shares;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
* Simple class for groups that are going to be saved/loaded. This is used specifically for when a user's world
* change is being handled.
*/
public record PersistingProfile(Shares shares, PlayerProfile profile) {
public final class PersistingProfile {
private final Shares shares;
private final CompletableFuture<PlayerProfile> profile;

public PersistingProfile(Shares shares, PlayerProfile profile) {
this(shares, CompletableFuture.completedFuture(profile));
}

public PersistingProfile(Shares shares, CompletableFuture<PlayerProfile> profile) {
this.shares = shares;
this.profile = profile;
}

/**
* Gets the shares that will be saved/loaded for the profile.
*
* @return The shares that will be saved/loaded for the profile. This is the set of all Sharables that will be acted
* upon when passed through the ShareHandler class, or any of its subclasses.
*/
@Override
public Shares shares() {
public Shares getShares() {
return this.shares;
}

Expand All @@ -25,8 +38,7 @@ public Shares shares() {
*
* @return The player profile for the world/group that will be saved/loaded for.
*/
@Override
public PlayerProfile profile() {
public CompletableFuture<PlayerProfile> getProfile() {
return this.profile;
}
}
Expand Down
Loading